From 8872bfececda746cea3cfdf78507aa22a09c6680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marin=20Ver=C5=A1i=C4=87?= Date: Thu, 3 Oct 2024 17:03:03 +0900 Subject: [PATCH] refactor!: move transaction error out of block payload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marin Veršić --- crates/iroha/benches/tps/utils.rs | 9 +- crates/iroha/tests/integration/tx_history.rs | 18 +- crates/iroha_core/benches/blocks/common.rs | 4 +- crates/iroha_core/src/block.rs | 167 +++++++++--------- crates/iroha_core/src/metrics.rs | 11 +- .../src/smartcontracts/isi/query.rs | 31 ++-- .../iroha_core/src/smartcontracts/isi/tx.rs | 36 ++-- crates/iroha_core/src/state.rs | 12 +- crates/iroha_core/src/sumeragi/main_loop.rs | 8 +- crates/iroha_data_model/src/block.rs | 110 ++++++++---- crates/iroha_data_model/src/query/mod.rs | 22 +-- .../query/predicate/predicate_atoms/block.rs | 90 ++++------ .../src/query/predicate/projectors.rs | 9 +- .../src/query/predicate/prototypes/block.rs | 30 ++-- crates/iroha_data_model/src/transaction.rs | 37 +--- crates/iroha_genesis/src/lib.rs | 4 +- crates/iroha_primitives/src/const_vec.rs | 2 +- crates/iroha_schema_gen/src/lib.rs | 113 ++++++------ docs/source/references/schema.json | 119 ++++++------- 19 files changed, 386 insertions(+), 446 deletions(-) diff --git a/crates/iroha/benches/tps/utils.rs b/crates/iroha/benches/tps/utils.rs index 08a95111946..e6937bb693c 100644 --- a/crates/iroha/benches/tps/utils.rs +++ b/crates/iroha/benches/tps/utils.rs @@ -110,15 +110,14 @@ impl Config { .view(); let mut blocks = state_view.all_blocks(NonZeroUsize::new(blocks_out_of_measure as usize + 1).unwrap()); - let (txs_accepted, txs_rejected) = (0..self.blocks) + let (txs_rejected, txs_accepted) = (0..self.blocks) .map(|_| { let block = blocks .next() .expect("The block is not yet in state. Need more sleep?"); - ( - block.transactions().filter(|tx| tx.error.is_none()).count(), - block.transactions().filter(|tx| tx.error.is_some()).count(), - ) + + let rejected = block.errors().count(); + (rejected, block.transactions().count() - rejected) }) .fold((0, 0), |acc, pair| (acc.0 + pair.0, acc.1 + pair.1)); #[allow(clippy::float_arithmetic, clippy::cast_precision_loss)] diff --git a/crates/iroha/tests/integration/tx_history.rs b/crates/iroha/tests/integration/tx_history.rs index 1b20be0054f..8c2b85f14a6 100644 --- a/crates/iroha/tests/integration/tx_history.rs +++ b/crates/iroha/tests/integration/tx_history.rs @@ -50,7 +50,7 @@ fn client_has_rejected_and_acepted_txs_should_return_tx_history() -> Result<()> let transactions = client .query(transaction::all()) - .filter_with(|tx| tx.transaction.value.authority.eq(account_id.clone())) + .filter_with(|tx| tx.value.authority.eq(account_id.clone())) .with_pagination(Pagination { limit: Some(nonzero!(50_u64)), offset: 1, @@ -59,15 +59,11 @@ fn client_has_rejected_and_acepted_txs_should_return_tx_history() -> Result<()> assert_eq!(transactions.len(), 50); let mut prev_creation_time = core::time::Duration::from_millis(0); - transactions - .iter() - .map(AsRef::as_ref) - .map(AsRef::as_ref) - .for_each(|tx| { - assert_eq!(tx.authority(), &account_id); - //check sorted - assert!(tx.creation_time() >= prev_creation_time); - prev_creation_time = tx.creation_time(); - }); + transactions.iter().map(AsRef::as_ref).for_each(|tx| { + assert_eq!(tx.authority(), &account_id); + //check sorted + assert!(tx.creation_time() >= prev_creation_time); + prev_creation_time = tx.creation_time(); + }); Ok(()) } diff --git a/crates/iroha_core/benches/blocks/common.rs b/crates/iroha_core/benches/blocks/common.rs index d7d3959e7e1..7936831a19a 100644 --- a/crates/iroha_core/benches/blocks/common.rs +++ b/crates/iroha_core/benches/blocks/common.rs @@ -56,9 +56,7 @@ pub fn create_block( .unwrap(); // Verify that transactions are valid - for tx in block.as_ref().transactions() { - assert_eq!(tx.error, None); - } + assert_eq!(block.as_ref().errors().count(), 0); block } diff --git a/crates/iroha_core/src/block.rs b/crates/iroha_core/src/block.rs index 4634c4c9bd4..33d82c2f992 100644 --- a/crates/iroha_core/src/block.rs +++ b/crates/iroha_core/src/block.rs @@ -4,14 +4,14 @@ //! 2. If a block is received, i.e. deserialized: //! `SignedBlock` -> `ValidBlock` -> `CommittedBlock` //! [`Block`]s are organised into a linear sequence over time (also known as the block chain). -use std::{error::Error as _, time::Duration}; +use std::{collections::BTreeMap, error::Error as _, time::Duration}; use iroha_crypto::{HashOf, KeyPair, MerkleTree}; use iroha_data_model::{ block::*, events::prelude::*, peer::PeerId, - transaction::{error::TransactionRejectionReason, prelude::*}, + transaction::{error::TransactionRejectionReason, SignedTransaction}, }; use thiserror::Error; @@ -118,7 +118,6 @@ pub struct BlockBuilder(B); mod pending { use std::time::SystemTime; - use iroha_data_model::transaction::CommittedTransaction; use nonzero_ext::nonzero; use super::*; @@ -156,14 +155,22 @@ mod pending { fn make_header( prev_block: Option<&SignedBlock>, view_change_index: usize, +<<<<<<< HEAD transactions: &[CommittedTransaction], +||||||| parent of 6b8c96ce9 (refactor!: move transaction error out of block payload) + transactions: &[CommittedTransaction], + consensus_estimation: Duration, +======= + transactions: &[SignedTransaction], + consensus_estimation: Duration, +>>>>>>> 6b8c96ce9 (refactor!: move transaction error out of block payload) ) -> BlockHeader { let prev_block_time = prev_block.map_or(Duration::ZERO, |block| block.header().creation_time()); let latest_txn_time = transactions .iter() - .map(|tx| tx.as_ref().creation_time()) + .map(SignedTransaction::creation_time) .max() .expect("INTERNAL BUG: Block empty"); @@ -194,7 +201,7 @@ mod pending { prev_block_hash: prev_block.map(SignedBlock::hash), transactions_hash: transactions .iter() - .map(|value| value.as_ref().hash()) + .map(SignedTransaction::hash) .collect::>() .hash() .expect("INTERNAL BUG: Empty block created"), @@ -211,27 +218,31 @@ mod pending { fn categorize_transactions( transactions: Vec, state_block: &mut StateBlock<'_>, - ) -> Vec { - transactions + ) -> ( + Vec, + BTreeMap, + ) { + let mut errors = BTreeMap::new(); + + let transactions = transactions .into_iter() - .map(|tx| match state_block.validate(tx) { - Ok(tx) => CommittedTransaction { - value: tx, - error: None, - }, + .enumerate() + .map(|(idx, tx)| match state_block.validate(tx) { + Ok(tx) => tx, Err((tx, error)) => { iroha_logger::warn!( reason = %error, caused_by = ?error.source(), "Transaction validation failed", ); - CommittedTransaction { - value: tx, - error: Some(Box::new(error)), - } + errors.insert(idx, error); + + tx } }) - .collect() + .collect(); + + (transactions, errors) } /// Chain the block with existing blockchain. @@ -242,8 +253,9 @@ mod pending { view_change_index: usize, state: &mut StateBlock<'_>, ) -> BlockBuilder { - let transactions = Self::categorize_transactions(self.0.transactions, state); + let (transactions, errors) = Self::categorize_transactions(self.0.transactions, state); +<<<<<<< HEAD BlockBuilder(Chained(BlockPayload { header: Self::make_header( state.latest_block().as_deref(), @@ -252,6 +264,30 @@ mod pending { ), transactions, })) +||||||| parent of 6b8c96ce9 (refactor!: move transaction error out of block payload) + BlockBuilder(Chained(BlockPayload { + header: Self::make_header( + state.latest_block().as_deref(), + view_change_index, + &transactions, + state.world.parameters().sumeragi.consensus_estimation(), + ), + transactions, + })) +======= + BlockBuilder(Chained( + BlockPayload { + header: Self::make_header( + state.latest_block().as_deref(), + view_change_index, + &transactions, + state.world.parameters().sumeragi.consensus_estimation(), + ), + transactions, + }, + errors, + )) +>>>>>>> 6b8c96ce9 (refactor!: move transaction error out of block payload) } } } @@ -261,12 +297,17 @@ mod chained { /// When a [`Pending`] block is chained with the blockchain it becomes [`Chained`] block. #[derive(Debug, Clone)] - pub struct Chained(pub(super) BlockPayload); + pub struct Chained( + pub(super) BlockPayload, + pub(super) BTreeMap, + ); impl BlockBuilder { /// Sign this block and get [`SignedBlock`]. pub fn sign(self, private_key: &PrivateKey) -> WithEvents { - WithEvents::new(ValidBlock(self.0 .0.sign(private_key))) + let mut block = self.0 .0.sign(private_key); + block.categorize_transactions(self.0 .1); + WithEvents::new(ValidBlock(block)) } } } @@ -566,7 +607,7 @@ mod valid { if block.transactions().any(|tx| { state .transactions() - .get(&tx.as_ref().hash()) + .get(&tx.hash()) // In case of soft-fork transaction is check if it was added at the same height as candidate block .is_some_and(|height| height.get() < expected_block_height) }) { @@ -593,7 +634,8 @@ mod valid { .transactions() // TODO: Unnecessary clone? .cloned() - .try_for_each(|CommittedTransaction { value, error }| { + .enumerate() + .try_for_each(|(idx, value)| { let tx = if is_genesis { AcceptedTransaction::accept_genesis( value, @@ -610,7 +652,7 @@ mod valid { ) }?; - if error.is_some() { + if block.error(idx).is_some() { match state_block.validate(tx) { Err(rejected_transaction) => Ok(rejected_transaction), Ok(_) => Err(TransactionValidationError::RejectedIsValid), @@ -776,11 +818,11 @@ mod valid { leader_private_key: &PrivateKey, f: impl FnOnce(&mut BlockPayload), ) -> Self { - use nonzero_ext::nonzero; + let (transactions, errors) = (Vec::new(), BTreeMap::new()); let mut payload = BlockPayload { header: BlockHeader { - height: nonzero!(2_u64), + height: nonzero_ext::nonzero!(2_u64), prev_block_hash: None, transactions_hash: HashOf::from_untyped_unchecked(Hash::prehashed( [1; Hash::LENGTH], @@ -788,10 +830,10 @@ mod valid { creation_time_ms: 0, view_change_index: 0, }, - transactions: Vec::new(), + transactions, }; f(&mut payload); - BlockBuilder(Chained(payload)) + BlockBuilder(Chained(payload, errors)) .sign(leader_private_key) .unpack(|_| {}) } @@ -825,7 +867,7 @@ mod valid { let transactions = block.payload().transactions.as_slice(); for transaction in transactions { - if transaction.value.authority() != genesis_account { + if transaction.authority() != genesis_account { return Err(InvalidGenesisError::UnexpectedAuthority); } } @@ -1048,15 +1090,16 @@ mod event { fn produce_events(&self) -> impl Iterator { let block_height = self.as_ref().header().height; - let tx_events = self.as_ref().transactions().map(move |tx| { - let status = tx.error.as_ref().map_or_else( + let block = self.as_ref(); + let tx_events = block.transactions().enumerate().map(move |(idx, tx)| { + let status = block.error(idx).map_or_else( || TransactionStatus::Approved, |error| TransactionStatus::Rejected(error.clone().into()), ); TransactionEvent { block_height: Some(block_height), - hash: tx.as_ref().hash(), + hash: tx.hash(), status, } }); @@ -1167,23 +1210,8 @@ mod tests { .sign(alice_keypair.private_key()) .unpack(|_| {}); - // The first transaction should be confirmed - assert!(valid_block - .as_ref() - .transactions() - .next() - .unwrap() - .error - .is_none()); - - // The second transaction should be rejected - assert!(valid_block - .as_ref() - .transactions() - .nth(1) - .unwrap() - .error - .is_some()); + // The 1st transaction should be confirmed and the 2nd rejected + assert_eq!(*valid_block.as_ref().errors().next().unwrap().0, 1); } #[tokio::test] @@ -1247,23 +1275,10 @@ mod tests { .sign(alice_keypair.private_key()) .unpack(|_| {}); - // The first transaction should fail - assert!(valid_block - .as_ref() - .transactions() - .next() - .unwrap() - .error - .is_some()); - - // The third transaction should succeed - assert!(valid_block - .as_ref() - .transactions() - .nth(2) - .unwrap() - .error - .is_none()); + // The 1st transaction should fail and 2nd succeed + let mut errors = valid_block.as_ref().errors(); + assert_eq!(0, *errors.next().unwrap().0); + assert!(errors.next().is_none()); } #[tokio::test] @@ -1311,27 +1326,17 @@ mod tests { .sign(alice_keypair.private_key()) .unpack(|_| {}); - // The first transaction should be rejected - assert!( - valid_block - .as_ref() - .transactions() - .next() - .unwrap() - .error - .is_some(), + let mut errors = valid_block.as_ref().errors(); + // The 1st transaction should be rejected + assert_eq!( + 0, + *errors.next().unwrap().0, "The first transaction should be rejected, as it contains `Fail`." ); // The second transaction should be accepted assert!( - valid_block - .as_ref() - .transactions() - .nth(1) - .unwrap() - .error - .is_none(), + errors.next().is_none(), "The second transaction should be accepted." ); } diff --git a/crates/iroha_core/src/metrics.rs b/crates/iroha_core/src/metrics.rs index b377cd1986a..93f8ead17c0 100644 --- a/crates/iroha_core/src/metrics.rs +++ b/crates/iroha_core/src/metrics.rs @@ -75,15 +75,8 @@ impl MetricsReporter { break; }; block_index += 1; - let mut block_txs_accepted = 0; - let mut block_txs_rejected = 0; - for tx in block.transactions() { - if tx.error.is_none() { - block_txs_accepted += 1; - } else { - block_txs_rejected += 1; - } - } + let block_txs_rejected = block.errors().count() as u64; + let block_txs_accepted = block.transactions().count() as u64 - block_txs_rejected; self.metrics .txs diff --git a/crates/iroha_core/src/smartcontracts/isi/query.rs b/crates/iroha_core/src/smartcontracts/isi/query.rs index 87404e97ff0..21c39d0cc46 100644 --- a/crates/iroha_core/src/smartcontracts/isi/query.rs +++ b/crates/iroha_core/src/smartcontracts/isi/query.rs @@ -6,9 +6,9 @@ use eyre::Result; use iroha_data_model::{ prelude::*, query::{ - error::QueryExecutionFail as Error, parameters::QueryParams, QueryBox, QueryOutputBatchBox, - QueryRequest, QueryRequestWithAuthority, QueryResponse, SingularQueryBox, - SingularQueryOutputBox, + error::QueryExecutionFail as Error, parameters::QueryParams, CommittedTransaction, + QueryBox, QueryOutputBatchBox, QueryRequest, QueryRequestWithAuthority, QueryResponse, + SingularQueryBox, SingularQueryOutputBox, }, }; @@ -68,7 +68,7 @@ impl SortableQueryOutput for RoleId { } } -impl SortableQueryOutput for TransactionQueryOutput { +impl SortableQueryOutput for CommittedTransaction { fn get_metadata_sorting_key(&self, _key: &Name) -> Option { None } @@ -567,15 +567,11 @@ mod tests { assert_eq!(txs.len() as u64, num_blocks * 2); assert_eq!( - txs.iter() - .filter(|txn| txn.transaction.error.is_some()) - .count() as u64, + txs.iter().filter(|txn| txn.error.is_some()).count() as u64, num_blocks ); assert_eq!( - txs.iter() - .filter(|txn| txn.transaction.error.is_none()) - .count() as u64, + txs.iter().filter(|txn| txn.error.is_none()).count() as u64, num_blocks ); @@ -626,9 +622,7 @@ mod tests { let not_found = FindTransactions::new() .execute( - TransactionQueryOutputPredicateBox::build(|tx| { - tx.transaction.value.hash.eq(wrong_hash) - }), + CommittedTransactionPredicateBox::build(|tx| tx.value.hash.eq(wrong_hash)), &state_view, ) .expect("Query execution should not fail") @@ -637,8 +631,8 @@ mod tests { let found_accepted = FindTransactions::new() .execute( - TransactionQueryOutputPredicateBox::build(|tx| { - tx.transaction.value.hash.eq(va_tx.as_ref().hash()) + CommittedTransactionPredicateBox::build(|tx| { + tx.value.hash.eq(va_tx.as_ref().hash()) }), &state_view, ) @@ -646,11 +640,8 @@ mod tests { .next() .expect("Query should return a transaction"); - if found_accepted.transaction.error.is_none() { - assert_eq!( - va_tx.as_ref().hash(), - found_accepted.as_ref().as_ref().hash() - ) + if found_accepted.error.is_none() { + assert_eq!(va_tx.as_ref().hash(), found_accepted.as_ref().hash()) } Ok(()) } diff --git a/crates/iroha_core/src/smartcontracts/isi/tx.rs b/crates/iroha_core/src/smartcontracts/isi/tx.rs index e12fd93073d..7567764c63a 100644 --- a/crates/iroha_core/src/smartcontracts/isi/tx.rs +++ b/crates/iroha_core/src/smartcontracts/isi/tx.rs @@ -9,12 +9,10 @@ use iroha_data_model::{ prelude::*, query::{ error::QueryExecutionFail, - predicate::{ - predicate_atoms::block::TransactionQueryOutputPredicateBox, CompoundPredicate, - }, - TransactionQueryOutput, + predicate::{predicate_atoms::block::CommittedTransactionPredicateBox, CompoundPredicate}, + CommittedTransaction, }, - transaction::CommittedTransaction, + transaction::error::TransactionRejectionReason, }; use iroha_telemetry::metrics; use nonzero_ext::nonzero; @@ -51,12 +49,15 @@ impl BlockTransactionRef { self.0.hash() } - fn value(&self) -> CommittedTransaction { - self.0 - .transactions() - .nth(self.1) - .expect("The transaction is not found") - .clone() + fn value(&self) -> (SignedTransaction, Option) { + ( + self.0 + .transactions() + .nth(self.1) + .expect("INTERNAL BUG: The transaction is not found") + .clone(), + self.0.error(self.1).cloned(), + ) } } @@ -64,15 +65,20 @@ impl ValidQuery for FindTransactions { #[metrics(+"find_transactions")] fn execute( self, - filter: CompoundPredicate, + filter: CompoundPredicate, state_ro: &impl StateReadOnly, ) -> Result, QueryExecutionFail> { Ok(state_ro .all_blocks(nonzero!(1_usize)) .flat_map(BlockTransactionIter::new) - .map(|tx| TransactionQueryOutput { - block_hash: tx.block_hash(), - transaction: tx.value(), + .map(|tx| { + let (value, error) = tx.value(); + + CommittedTransaction { + block_hash: tx.block_hash(), + value, + error, + } }) .filter(move |tx| filter.applies(tx))) } diff --git a/crates/iroha_core/src/state.rs b/crates/iroha_core/src/state.rs index 95b3439580d..4979182d560 100644 --- a/crates/iroha_core/src/state.rs +++ b/crates/iroha_core/src/state.rs @@ -1381,15 +1381,14 @@ impl<'state> StateBlock<'state> { /// # Errors /// Fails if transaction instruction execution fails fn execute_transactions(&mut self, block: &CommittedBlock) -> Result<()> { + let block = block.as_ref(); + // TODO: Should this block panic instead? - for tx in block.as_ref().transactions() { - if tx.error.is_none() { + for (idx, tx) in block.transactions().enumerate() { + if block.error(idx).is_none() { // Execute every tx in it's own transaction let mut transaction = self.transaction(); - transaction.process_executable( - tx.as_ref().instructions(), - tx.as_ref().authority().clone(), - )?; + transaction.process_executable(tx.instructions(), tx.authority().clone())?; transaction.apply(); } } @@ -1421,7 +1420,6 @@ impl<'state> StateBlock<'state> { block .as_ref() .transactions() - .map(|tx| &tx.value) .map(SignedTransaction::hash) .for_each(|tx_hash| { self.transactions.insert(tx_hash, block_height); diff --git a/crates/iroha_core/src/sumeragi/main_loop.rs b/crates/iroha_core/src/sumeragi/main_loop.rs index 5183728ef81..78ab259801c 100644 --- a/crates/iroha_core/src/sumeragi/main_loop.rs +++ b/crates/iroha_core/src/sumeragi/main_loop.rs @@ -134,7 +134,7 @@ impl Sumeragi { .map_err(|recv_error| { assert!( recv_error != mpsc::TryRecvError::Disconnected, - "INTERNAL ERROR: Sumeragi control message pump disconnected" + "INTERNAL BUG: Sumeragi control message pump disconnected" ) }) { @@ -173,7 +173,7 @@ impl Sumeragi { .map_err(|recv_error| { assert!( recv_error != mpsc::TryRecvError::Disconnected, - "INTERNAL ERROR: Sumeragi message pump disconnected" + "INTERNAL BUG: Sumeragi message pump disconnected" ) }) .ok()?; @@ -257,7 +257,7 @@ impl Sumeragi { } }; - if block.as_ref().transactions().any(|tx| tx.error.is_some()) { + if block.as_ref().errors().next().is_some() { error!( peer_id=%self.peer_id, role=%self.role(), @@ -305,7 +305,7 @@ impl Sumeragi { .expect("Genesis invalid"); assert!( - !genesis.as_ref().transactions().any(|tx| tx.error.is_some()), + !genesis.as_ref().errors().next().is_some(), "Genesis contains invalid transactions" ); diff --git a/crates/iroha_data_model/src/block.rs b/crates/iroha_data_model/src/block.rs index 4306fba2188..84f01acfc0d 100644 --- a/crates/iroha_data_model/src/block.rs +++ b/crates/iroha_data_model/src/block.rs @@ -3,8 +3,10 @@ //! `Block`s are organised into a linear sequence over time (also known as the block chain). #[cfg(not(feature = "std"))] -use alloc::{boxed::Box, format, string::String, vec::Vec}; +use alloc::{boxed::Box, collections::BTreeMap, format, string::String, vec::Vec}; use core::{fmt::Display, time::Duration}; +#[cfg(feature = "std")] +use std::collections::BTreeMap; use derive_more::Display; use iroha_crypto::{HashOf, MerkleTree, SignatureOf}; @@ -16,7 +18,7 @@ use parity_scale_codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; pub use self::model::*; -use crate::transaction::prelude::*; +use crate::transaction::{error::TransactionRejectionReason, prelude::*}; #[model] mod model { @@ -76,7 +78,7 @@ mod model { /// Block header pub header: BlockHeader, /// array of transactions, which successfully passed validation and consensus step. - pub transactions: Vec, + pub transactions: Vec, } /// Signature of a block @@ -112,6 +114,12 @@ mod model { pub(super) signatures: Vec, /// Block payload pub(super) payload: BlockPayload, + /// Collection of rejection reasons for every transaction if exists + /// + /// # Warning + /// + /// Transaction errors are not part of the block hash or protected by the block signature. + pub(super) errors: BTreeMap, } } @@ -141,8 +149,12 @@ impl BlockHeader { } impl BlockPayload { - /// Create new signed block, using `key_pair` to sign `payload` - #[cfg(feature = "transparent_api")] + /// Create new signed block, using `key_pair` to sign `payload`. + /// + /// # Warning + /// + /// All transactions are categorized as valid + #[cfg(feature = "std")] pub fn sign(self, private_key: &iroha_crypto::PrivateKey) -> SignedBlock { let signatures = vec![BlockSignature( 0, @@ -152,6 +164,7 @@ impl BlockPayload { SignedBlockV1 { signatures, payload: self, + errors: BTreeMap::new(), } .into() } @@ -164,6 +177,28 @@ impl SignedBlockV1 { } impl SignedBlock { + /// Return error for the transaction index + pub fn error(&self, tx: usize) -> Option<&TransactionRejectionReason> { + let SignedBlock::V1(block) = self; + block.errors.get(&(tx as u64)) + } + + /// Setter for transaction errors + #[cfg(feature = "transparent_api")] + pub fn categorize_transactions( + &mut self, + errors: impl IntoIterator, + ) -> &mut Self { + let SignedBlock::V1(block) = self; + + block.errors = errors + .into_iter() + .map(|(idx, error)| (idx as u64, error)) + .collect(); + + self + } + /// Block payload. Used for tests #[cfg(feature = "transparent_api")] pub fn payload(&self) -> &BlockPayload { @@ -180,11 +215,22 @@ impl SignedBlock { /// Block transactions #[inline] - pub fn transactions(&self) -> impl ExactSizeIterator { + pub fn transactions(&self) -> impl ExactSizeIterator { let SignedBlock::V1(block) = self; block.payload.transactions.iter() } + /// Collection of rejection reasons for every transaction if exists + /// + /// # Warning + /// + /// Transaction errors are not part of the block hash or protected by the block signature. + #[inline] + pub fn errors(&self) -> impl ExactSizeIterator { + let SignedBlock::V1(block) = self; + block.errors.iter() + } + /// Signatures of peers which approved this block. #[inline] pub fn signatures( @@ -250,18 +296,18 @@ impl SignedBlock { /// Creates genesis block signed with genesis private key (and not signed by any peer) #[cfg(feature = "std")] pub fn genesis( - genesis_transactions: Vec, - genesis_private_key: &iroha_crypto::PrivateKey, + transactions: Vec, + private_key: &iroha_crypto::PrivateKey, ) -> SignedBlock { use nonzero_ext::nonzero; - let transactions_hash = genesis_transactions + let transactions_hash = transactions .iter() .map(SignedTransaction::hash) .collect::>() .hash() .expect("Tree is not empty"); - let creation_time_ms = Self::get_genesis_block_creation_time(&genesis_transactions); + let creation_time_ms = Self::get_genesis_block_creation_time(&transactions); let header = BlockHeader { height: nonzero!(1_u64), prev_block_hash: None, @@ -269,34 +315,22 @@ impl SignedBlock { creation_time_ms, view_change_index: 0, }; - let transactions = genesis_transactions - .into_iter() - .map(|transaction| CommittedTransaction { - value: transaction, - error: None, - }) - .collect(); let payload = BlockPayload { header, transactions, }; - let signature = BlockSignature(0, SignatureOf::new(genesis_private_key, &payload.header)); - SignedBlockV1 { - signatures: vec![signature], - payload, - } - .into() + payload.sign(private_key) } #[cfg(feature = "std")] - fn get_genesis_block_creation_time(genesis_transactions: &[SignedTransaction]) -> u64 { + fn get_genesis_block_creation_time(transactions: &[SignedTransaction]) -> u64 { use std::time::SystemTime; - let latest_txn_time = genesis_transactions + let latest_txn_time = transactions .iter() - .map(|tx| tx.creation_time()) + .map(SignedTransaction::creation_time) .max() .expect("INTERNAL BUG: Block empty"); let now = SystemTime::now() @@ -333,12 +367,13 @@ mod candidate { struct SignedBlockCandidate { signatures: Vec, payload: BlockPayload, + errors: BTreeMap, } #[derive(Decode, Deserialize)] struct BlockPayloadCandidate { header: BlockHeader, - transactions: Vec, + transactions: Vec, } impl BlockPayloadCandidate { @@ -361,7 +396,7 @@ mod candidate { let expected_txs_hash = self .transactions .iter() - .map(|value| value.as_ref().hash()) + .map(SignedTransaction::hash) .collect::>() .hash() .ok_or("Block is empty")?; @@ -371,7 +406,7 @@ mod candidate { } self.transactions.iter().try_for_each(|tx| { - if tx.value.creation_time() >= self.header.creation_time() { + if tx.creation_time() >= self.header.creation_time() { return Err("Transaction creation time is ahead of block creation time"); } @@ -396,6 +431,7 @@ mod candidate { Ok(SignedBlockV1 { signatures: self.signatures, payload: self.payload, + errors: self.errors, }) } @@ -426,14 +462,14 @@ mod candidate { #[cfg(not(target_family = "wasm"))] fn validate_genesis(&self) -> Result<(), &'static str> { - use crate::isi::InstructionBox; - let transactions = self.payload.transactions.as_slice(); + + if !self.errors.is_empty() { + return Err("Genesis transaction must not contain errors"); + } + for transaction in transactions { - if transaction.error.is_some() { - return Err("Genesis transaction must not contain errors"); - } - let Executable::Instructions(_) = transaction.value.instructions() else { + let Executable::Instructions(_) = transaction.instructions() else { return Err("Genesis transaction must contain instructions"); }; } @@ -442,11 +478,11 @@ mod candidate { return Err("Genesis block must contain at least one transaction"); }; let Executable::Instructions(instructions_executor) = - transaction_executor.value.instructions() + transaction_executor.instructions() else { return Err("Genesis transaction must contain instructions"); }; - let [InstructionBox::Upgrade(_)] = instructions_executor.as_ref() else { + let [crate::isi::InstructionBox::Upgrade(_)] = instructions_executor.as_ref() else { return Err( "First transaction must contain single `Upgrade` instruction to set executor", ); diff --git a/crates/iroha_data_model/src/query/mod.rs b/crates/iroha_data_model/src/query/mod.rs index 40d0f3970b4..e6bb9e4d027 100644 --- a/crates/iroha_data_model/src/query/mod.rs +++ b/crates/iroha_data_model/src/query/mod.rs @@ -31,7 +31,7 @@ use crate::{ permission::Permission, role::{Role, RoleId}, seal::Sealed, - transaction::{CommittedTransaction, SignedTransaction}, + transaction::{error::TransactionRejectionReason, SignedTransaction}, trigger::{Trigger, TriggerId}, }; @@ -118,7 +118,7 @@ mod model { Role(Vec), Parameter(Vec), Permission(Vec), - Transaction(Vec), + Transaction(Vec), Peer(Vec), RoleId(Vec), TriggerId(Vec), @@ -153,7 +153,7 @@ mod model { JsonString(JsonString), Trigger(crate::trigger::Trigger), Parameters(Parameters), - Transaction(TransactionQueryOutput), + Transaction(CommittedTransaction), BlockHeader(BlockHeader), } @@ -240,12 +240,14 @@ mod model { )] #[getset(get = "pub")] #[ffi_type] - pub struct TransactionQueryOutput { + pub struct CommittedTransaction { /// The hash of the block to which `tx` belongs to pub block_hash: HashOf, /// Transaction #[getset(skip)] - pub transaction: CommittedTransaction, + pub value: SignedTransaction, + /// Reason of rejection, if any + pub error: Option, } } @@ -563,7 +565,7 @@ impl_iter_queries! { FindPeers => crate::peer::Peer, FindActiveTriggerIds => crate::trigger::TriggerId, FindTriggers => crate::trigger::Trigger, - FindTransactions => TransactionQueryOutput, + FindTransactions => CommittedTransaction, FindAccountsWithAsset => crate::account::Account, FindBlockHeaders => crate::block::BlockHeader, FindBlocks => SignedBlock, @@ -580,9 +582,9 @@ impl_singular_queries! { FindExecutorDataModel => crate::executor::ExecutorDataModel, } -impl AsRef for TransactionQueryOutput { - fn as_ref(&self) -> &CommittedTransaction { - &self.transaction +impl AsRef for CommittedTransaction { + fn as_ref(&self) -> &SignedTransaction { + &self.value } } @@ -1097,6 +1099,6 @@ pub mod prelude { account::prelude::*, asset::prelude::*, block::prelude::*, builder::prelude::*, domain::prelude::*, executor::prelude::*, parameters::prelude::*, peer::prelude::*, permission::prelude::*, predicate::prelude::*, role::prelude::*, transaction::prelude::*, - trigger::prelude::*, QueryBox, QueryRequest, SingularQueryBox, TransactionQueryOutput, + trigger::prelude::*, CommittedTransaction, QueryBox, QueryRequest, SingularQueryBox, }; } diff --git a/crates/iroha_data_model/src/query/predicate/predicate_atoms/block.rs b/crates/iroha_data_model/src/query/predicate/predicate_atoms/block.rs index c1d7ecb24b3..0ee4e0289e7 100644 --- a/crates/iroha_data_model/src/query/predicate/predicate_atoms/block.rs +++ b/crates/iroha_data_model/src/query/predicate/predicate_atoms/block.rs @@ -1,7 +1,7 @@ //! This module contains predicates for block-related objects, mirroring [`crate::block`]. #[cfg(not(feature = "std"))] -use alloc::{boxed::Box, format, string::String, vec::Vec}; +use alloc::{format, string::String, vec::Vec}; use iroha_crypto::HashOf; use iroha_schema::IntoSchema; @@ -19,9 +19,9 @@ use crate::{ projectors::BaseProjector, AstPredicate, CompoundPredicate, EvaluatePredicate, HasPredicateBox, HasPrototype, }, - TransactionQueryOutput, + CommittedTransaction, }, - transaction::{CommittedTransaction, SignedTransaction}, + transaction::SignedTransaction, }; /// A predicate that can be applied to a [`HashOf`] @@ -128,21 +128,22 @@ pub enum TransactionErrorPredicateBox { IsSome, } -impl_predicate_box!(Option>: TransactionErrorPredicateBox); +impl_predicate_box!(Option: TransactionErrorPredicateBox); -impl EvaluatePredicate>> for TransactionErrorPredicateBox { - fn applies(&self, input: &Option>) -> bool { +impl EvaluatePredicate> for TransactionErrorPredicateBox { + fn applies(&self, input: &Option) -> bool { match self { TransactionErrorPredicateBox::IsSome => input.is_some(), } } } -/// A predicate that can be applied to a [`CommittedTransaction`] +/// A predicate that can be applied to a [`CommittedTransaction`]. #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub enum CommittedTransactionPredicateBox { - // projections - /// Checks if a predicate applies to the signed transaction inside. + /// Checks if a predicate applies to the hash of the block the transaction was included in. + BlockHash(BlockHashPredicateBox), + /// Checks if a predicate applies to the committed transaction inside. Value(SignedTransactionPredicateBox), /// Checks if a predicate applies to the error of the transaction. Error(TransactionErrorPredicateBox), @@ -153,35 +154,13 @@ impl_predicate_box!(CommittedTransaction: CommittedTransactionPredicateBox); impl EvaluatePredicate for CommittedTransactionPredicateBox { fn applies(&self, input: &CommittedTransaction) -> bool { match self { - CommittedTransactionPredicateBox::Value(signed_transaction) => { - signed_transaction.applies(&input.value) - } - CommittedTransactionPredicateBox::Error(error) => error.applies(&input.error), - } - } -} - -/// A predicate that can be applied to a [`TransactionQueryOutput`]. -#[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] -pub enum TransactionQueryOutputPredicateBox { - // projections - /// Checks if a predicate applies to the committed transaction inside. - Transaction(CommittedTransactionPredicateBox), - /// Checks if a predicate applies to the hash of the block the transaction was included in. - BlockHash(BlockHashPredicateBox), -} - -impl_predicate_box!(TransactionQueryOutput: TransactionQueryOutputPredicateBox); - -impl EvaluatePredicate for TransactionQueryOutputPredicateBox { - fn applies(&self, input: &TransactionQueryOutput) -> bool { - match self { - TransactionQueryOutputPredicateBox::Transaction(committed_transaction) => { - committed_transaction.applies(&input.transaction) - } - TransactionQueryOutputPredicateBox::BlockHash(block_hash) => { + CommittedTransactionPredicateBox::BlockHash(block_hash) => { block_hash.applies(&input.block_hash) } + CommittedTransactionPredicateBox::Value(committed_transaction) => { + committed_transaction.applies(&input.value) + } + CommittedTransactionPredicateBox::Error(error) => error.applies(&input.error), } } } @@ -191,7 +170,7 @@ pub mod prelude { pub use super::{ BlockHashPredicateBox, BlockHeaderPredicateBox, CommittedTransactionPredicateBox, SignedBlockPredicateBox, SignedTransactionPredicateBox, TransactionErrorPredicateBox, - TransactionHashPredicateBox, TransactionQueryOutputPredicateBox, + TransactionHashPredicateBox, }; } @@ -203,7 +182,7 @@ mod test { account::AccountId, prelude::{ AccountIdPredicateBox, BlockHeaderPredicateBox, CompoundPredicate, - SignedBlockPredicateBox, TransactionQueryOutputPredicateBox, + SignedBlockPredicateBox, }, query::predicate::predicate_atoms::block::{ BlockHashPredicateBox, CommittedTransactionPredicateBox, SignedTransactionPredicateBox, @@ -219,37 +198,32 @@ mod test { .parse() .unwrap(); - let predicate = TransactionQueryOutputPredicateBox::build(|tx| { + let predicate = CommittedTransactionPredicateBox::build(|tx| { tx.block_hash.eq(HashOf::from_untyped_unchecked(hash)) - & tx.transaction.error.is_some() - & tx.transaction.value.authority.eq(account_id.clone()) - & tx.transaction - .value - .hash - .eq(HashOf::from_untyped_unchecked(hash)) + & tx.value.authority.eq(account_id.clone()) + & tx.value.hash.eq(HashOf::from_untyped_unchecked(hash)) + & tx.error.is_some() }); assert_eq!( predicate, CompoundPredicate::And(vec![ - CompoundPredicate::Atom(TransactionQueryOutputPredicateBox::BlockHash( + CompoundPredicate::Atom(CommittedTransactionPredicateBox::BlockHash( BlockHashPredicateBox::Equals(HashOf::from_untyped_unchecked(hash)) )), - CompoundPredicate::Atom(TransactionQueryOutputPredicateBox::Transaction( - CommittedTransactionPredicateBox::Error(TransactionErrorPredicateBox::IsSome) - )), - CompoundPredicate::Atom(TransactionQueryOutputPredicateBox::Transaction( - CommittedTransactionPredicateBox::Value( - SignedTransactionPredicateBox::Authority(AccountIdPredicateBox::Equals( - account_id.clone() - )) - ) + CompoundPredicate::Atom(CommittedTransactionPredicateBox::Value( + SignedTransactionPredicateBox::Authority(AccountIdPredicateBox::Equals( + account_id.clone() + )) )), - CompoundPredicate::Atom(TransactionQueryOutputPredicateBox::Transaction( - CommittedTransactionPredicateBox::Value(SignedTransactionPredicateBox::Hash( - TransactionHashPredicateBox::Equals(HashOf::from_untyped_unchecked(hash)) + CompoundPredicate::Atom(CommittedTransactionPredicateBox::Value( + SignedTransactionPredicateBox::Hash(TransactionHashPredicateBox::Equals( + HashOf::from_untyped_unchecked(hash) )) )), + CompoundPredicate::Atom(CommittedTransactionPredicateBox::Error( + TransactionErrorPredicateBox::IsSome + )), ]) ); } diff --git a/crates/iroha_data_model/src/query/predicate/projectors.rs b/crates/iroha_data_model/src/query/predicate/projectors.rs index 4fe3d194f8d..45ea67cba26 100644 --- a/crates/iroha_data_model/src/query/predicate/projectors.rs +++ b/crates/iroha_data_model/src/query/predicate/projectors.rs @@ -8,9 +8,7 @@ use core::marker::PhantomData; use super::{AstPredicate, CompoundPredicate}; use crate::{ - prelude::{ - BlockHeaderPredicateBox, SignedBlockPredicateBox, TransactionQueryOutputPredicateBox, - }, + prelude::{BlockHeaderPredicateBox, SignedBlockPredicateBox}, query::predicate::{ predicate_atoms::{ account::{AccountIdPredicateBox, AccountPredicateBox}, @@ -214,9 +212,6 @@ proj!(SignedTransactionHashProjector(SignedTransactionHashProjection): Transacti proj!(SignedTransactionAuthorityProjector(SignedTransactionAuthorityProjection): AccountIdPredicateBox => SignedTransactionPredicateBox::Authority); // projections on CommittedTransaction +proj!(CommittedTransactionBlockHashProjector(CommittedTransactionBlockHashProjection): BlockHashPredicateBox => CommittedTransactionPredicateBox::BlockHash); proj!(CommittedTransactionValueProjector(CommittedTransactionValueProjection): SignedTransactionPredicateBox => CommittedTransactionPredicateBox::Value); proj!(CommittedTransactionErrorProjector(CommittedTransactionErrorProjection): TransactionErrorPredicateBox => CommittedTransactionPredicateBox::Error); - -// projections on TransactionQueryOutput -proj!(TransactionQueryOutputTransactionProjector(TransactionQueryOutputTransactionProjection): CommittedTransactionPredicateBox => TransactionQueryOutputPredicateBox::Transaction); -proj!(TransactionQueryOutputBlockHashProjector(TransactionQueryOutputBlockHashProjection): BlockHashPredicateBox => TransactionQueryOutputPredicateBox::BlockHash); diff --git a/crates/iroha_data_model/src/query/predicate/prototypes/block.rs b/crates/iroha_data_model/src/query/predicate/prototypes/block.rs index 236d927446b..f72e59a0211 100644 --- a/crates/iroha_data_model/src/query/predicate/prototypes/block.rs +++ b/crates/iroha_data_model/src/query/predicate/prototypes/block.rs @@ -12,14 +12,14 @@ use crate::{ predicate_atoms::block::{ BlockHashPredicateBox, BlockHeaderPredicateBox, CommittedTransactionPredicateBox, SignedBlockPredicateBox, SignedTransactionPredicateBox, TransactionErrorPredicateBox, - TransactionHashPredicateBox, TransactionQueryOutputPredicateBox, + TransactionHashPredicateBox, }, predicate_combinators::NotAstPredicate, projectors::{ - BlockHeaderHashProjector, CommittedTransactionErrorProjector, - CommittedTransactionValueProjector, ObjectProjector, SignedBlockHeaderProjector, - SignedTransactionAuthorityProjector, SignedTransactionHashProjector, - TransactionQueryOutputBlockHashProjector, TransactionQueryOutputTransactionProjector, + BlockHeaderHashProjector, CommittedTransactionBlockHashProjector, + CommittedTransactionErrorProjector, CommittedTransactionValueProjector, + ObjectProjector, SignedBlockHeaderProjector, SignedTransactionAuthorityProjector, + SignedTransactionHashProjector, }, prototypes::account::AccountIdPrototype, AstPredicate, HasPrototype, @@ -123,25 +123,15 @@ where } } -/// A prototype of [`crate::transaction::CommittedTransaction`] -#[derive(Default, Copy, Clone)] +/// A prototype of [`crate::query::CommittedTransaction`] for predicate construction. +#[derive(Default, Clone)] pub struct CommittedTransactionPrototype { - /// Build a predicate on the signed transaction inside + /// Build a predicate on the block hash inside + pub block_hash: BlockHashPrototype>, + /// Build a predicate on the transaction inside pub value: SignedTransactionPrototype>, /// Build a predicate on the transaction error pub error: TransactionErrorPrototype>, } impl_prototype!(CommittedTransactionPrototype: CommittedTransactionPredicateBox); - -/// A prototype of [`crate::query::TransactionQueryOutput`] for predicate construction. -#[derive(Default, Copy, Clone)] -pub struct TransactionQueryOutputPrototype { - /// Build a predicate on the transaction inside - pub transaction: - CommittedTransactionPrototype>, - /// Build a predicate on the block hash inside - pub block_hash: BlockHashPrototype>, -} - -impl_prototype!(TransactionQueryOutputPrototype: TransactionQueryOutputPredicateBox); diff --git a/crates/iroha_data_model/src/transaction.rs b/crates/iroha_data_model/src/transaction.rs index 6bd5efb4cc5..53dadad5165 100644 --- a/crates/iroha_data_model/src/transaction.rs +++ b/crates/iroha_data_model/src/transaction.rs @@ -29,7 +29,6 @@ use crate::{ #[model] mod model { - use getset::Getters; use iroha_primitives::const_vec::ConstVec; use super::*; @@ -153,32 +152,6 @@ mod model { /// Payload of the transaction. pub(super) payload: TransactionPayload, } - - /// Transaction Value used in Instructions and Queries - #[derive( - Debug, - PartialOrd, - Ord, - Getters, - Clone, - PartialEq, - Eq, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[ffi_type] - #[getset(get = "pub")] - pub struct CommittedTransaction { - /// Committed transaction - #[getset(skip)] - pub value: SignedTransaction, - /// Reason of rejection - // NOTE: Using `Box` reduces memory use by 10% - pub error: Option>, - } } impl FromIterator for Executable { @@ -311,12 +284,6 @@ impl SignedTransactionV1 { } } -impl AsRef for CommittedTransaction { - fn as_ref(&self) -> &SignedTransaction { - &self.value - } -} - impl TransactionSignature { /// Signature itself pub fn payload(&self) -> &Signature { @@ -750,9 +717,7 @@ mod http { pub mod prelude { #[cfg(feature = "http")] pub use super::http::TransactionBuilder; - pub use super::{ - error::prelude::*, CommittedTransaction, Executable, SignedTransaction, WasmSmartContract, - }; + pub use super::{error::prelude::*, Executable, SignedTransaction, WasmSmartContract}; } #[cfg(test)] diff --git a/crates/iroha_genesis/src/lib.rs b/crates/iroha_genesis/src/lib.rs index 1bd448168a5..a6bc0fbde92 100644 --- a/crates/iroha_genesis/src/lib.rs +++ b/crates/iroha_genesis/src/lib.rs @@ -422,7 +422,7 @@ mod tests { // First transaction { let transaction = transactions[0]; - let instructions = transaction.value.instructions(); + let instructions = transaction.instructions(); let Executable::Instructions(instructions) = instructions else { panic!("Expected instructions"); }; @@ -433,7 +433,7 @@ mod tests { // Second transaction let transaction = transactions[1]; - let instructions = transaction.value.instructions(); + let instructions = transaction.instructions(); let Executable::Instructions(instructions) = instructions else { panic!("Expected instructions"); }; diff --git a/crates/iroha_primitives/src/const_vec.rs b/crates/iroha_primitives/src/const_vec.rs index 54f7c628b28..3cf7287cd5c 100644 --- a/crates/iroha_primitives/src/const_vec.rs +++ b/crates/iroha_primitives/src/const_vec.rs @@ -98,7 +98,7 @@ impl<'a, T> IntoIterator for &'a ConstVec { type IntoIter = <&'a [T] as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() + self.0.iter() } } diff --git a/crates/iroha_schema_gen/src/lib.rs b/crates/iroha_schema_gen/src/lib.rs index f310b40defb..8b0802a7b5b 100644 --- a/crates/iroha_schema_gen/src/lib.rs +++ b/crates/iroha_schema_gen/src/lib.rs @@ -130,6 +130,11 @@ types!( AssetType, AssetValue, AssetValuePredicateBox, + BTreeMap, + BTreeMap, + BTreeMap, + BTreeSet, + BTreeSet, BlockEvent, BlockEventFilter, BlockHashPredicateBox, @@ -147,23 +152,19 @@ types!( Box>, Box>, Box>, + Box>, Box>, Box>, Box>, Box>, Box>, Box>, - Box>, Box>, Box>, Box, - BTreeMap, - BTreeMap, - BTreeSet, - BTreeSet, - BurnBox, Burn, Burn, + BurnBox, ChainId, CommittedTransaction, CommittedTransactionPredicateBox, @@ -171,21 +172,21 @@ types!( CompoundPredicate, CompoundPredicate, CompoundPredicate, + CompoundPredicate, CompoundPredicate, CompoundPredicate, CompoundPredicate, CompoundPredicate, CompoundPredicate, CompoundPredicate, - CompoundPredicate, CompoundPredicate, CompoundPredicate, ConfigurationEvent, ConfigurationEventFilter, ConfigurationEventSet, ConstString, - ConstVec, ConstVec, + ConstVec, CustomInstruction, CustomParameter, CustomParameterId, @@ -217,37 +218,37 @@ types!( ExecutorUpgrade, FetchSize, FindAccountMetadata, - FindAccountsWithAsset, FindAccounts, + FindAccountsWithAsset, FindActiveTriggerIds, + FindAssetDefinitionMetadata, + FindAssetMetadata, + FindAssetQuantityById, FindAssets, FindAssetsDefinitions, FindBlockHeaders, FindBlocks, + FindDomainMetadata, FindDomains, + FindError, + FindExecutorDataModel, FindParameters, FindPeers, + FindPermissionsByAccountId, FindRoleIds, FindRoles, - FindTransactions, - FindTriggers, - FindAssetDefinitionMetadata, - FindAssetMetadata, - FindAssetQuantityById, - FindDomainMetadata, - FindError, - FindExecutorDataModel, - FindPermissionsByAccountId, FindRolesByAccountId, + FindTransactions, FindTriggerMetadata, + FindTriggers, ForwardCursor, - GrantBox, Grant, Grant, Grant, + GrantBox, Hash, - HashOf>, HashOf, + HashOf>, HashOf, IdBox, InstructionBox, @@ -259,26 +260,6 @@ types!( IpfsPath, Ipv4Addr, Ipv6Addr, - QueryBox, - QueryOutput, - QueryOutputBatchBox, - QueryParams, - QueryWithFilter, - QueryWithFilter, - QueryWithFilter, - QueryWithFilter, - QueryWithFilter, - QueryWithFilter, - QueryWithFilter, - QueryWithFilter, - QueryWithFilter, - QueryWithFilter, - QueryWithFilter, - QueryWithFilter, - QueryWithFilter, - QueryWithFilter, - QueryWithFilter, - QueryWithParams, JsonString, Level, Log, @@ -291,11 +272,11 @@ types!( MetadataChanged, MetadataChanged, MetadataPredicateBox, - MintabilityError, - Mintable, - MintBox, Mint, Mint, + MintBox, + MintabilityError, + Mintable, Mismatch, Name, NewAccount, @@ -323,7 +304,7 @@ types!( Option, Option, Option, - Option>, + Option, Option, Option, Option, @@ -345,31 +326,51 @@ types!( PipelineEventFilterBox, PublicKey, PublicKeyPredicateBox, + QueryBox, QueryExecutionFail, + QueryOutput, + QueryOutputBatchBox, + QueryParams, QueryRequest, QueryRequestWithAuthority, QueryResponse, QuerySignature, + QueryWithFilter, + QueryWithFilter, + QueryWithFilter, + QueryWithFilter, + QueryWithFilter, + QueryWithFilter, + QueryWithFilter, + QueryWithFilter, + QueryWithFilter, + QueryWithFilter, + QueryWithFilter, + QueryWithFilter, + QueryWithFilter, + QueryWithFilter, + QueryWithFilter, + QueryWithParams, Register, Register, Register, - RegisterBox, Register, Register, Register, Register, + RegisterBox, RemoveKeyValue, RemoveKeyValue, RemoveKeyValue, - RemoveKeyValueBox, RemoveKeyValue, RemoveKeyValue, + RemoveKeyValueBox, Repeats, RepetitionError, - RevokeBox, Revoke, Revoke, Revoke, + RevokeBox, Role, RoleEvent, RoleEventFilter, @@ -381,9 +382,9 @@ types!( SetKeyValue, SetKeyValue, SetKeyValue, - SetKeyValueBox, SetKeyValue, SetKeyValue, + SetKeyValueBox, SetParameter, Signature, SignatureOf, @@ -422,8 +423,6 @@ types!( TransactionParameter, TransactionParameters, TransactionPayload, - TransactionQueryOutput, - TransactionQueryOutputPredicateBox, TransactionRejectionReason, TransactionSignature, TransactionStatus, @@ -442,17 +441,17 @@ types!( TriggerEventSet, TriggerId, TriggerIdPredicateBox, - TriggerPredicateBox, TriggerNumberOfExecutionsChanged, + TriggerPredicateBox, TypeError, Unregister, Unregister, Unregister, - UnregisterBox, Unregister, Unregister, Unregister, Unregister, + UnregisterBox, Upgrade, ValidationFail, Vec, @@ -465,13 +464,13 @@ types!( Vec>, Vec>, Vec>, + Vec>, Vec>, Vec>, Vec>, Vec>, Vec>, Vec>, - Vec>, Vec>, Vec>, Vec, @@ -484,7 +483,7 @@ types!( Vec, Vec, Vec, - Vec, + Vec, Vec, Vec, Vec, @@ -538,9 +537,9 @@ pub mod complete_data_model { error::{FindError, QueryExecutionFail}, parameters::{ForwardCursor, QueryParams}, predicate::CompoundPredicate, - QueryOutput, QueryOutputBatchBox, QueryRequestWithAuthority, QueryResponse, - QuerySignature, QueryWithFilter, QueryWithParams, SignedQuery, SignedQueryV1, - SingularQueryOutputBox, + CommittedTransaction, QueryOutput, QueryOutputBatchBox, QueryRequestWithAuthority, + QueryResponse, QuerySignature, QueryWithFilter, QueryWithParams, SignedQuery, + SignedQueryV1, SingularQueryOutputBox, }, transaction::{ error::TransactionLimitError, SignedTransactionV1, TransactionPayload, diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index c010be2906f..4d47b35717a 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -720,7 +720,7 @@ }, { "name": "transactions", - "type": "Vec" + "type": "Vec" } ] }, @@ -981,6 +981,10 @@ "ChainId": "String", "CommittedTransaction": { "Struct": [ + { + "name": "block_hash", + "type": "HashOf" + }, { "name": "value", "type": "SignedTransaction" @@ -994,13 +998,18 @@ "CommittedTransactionPredicateBox": { "Enum": [ { - "tag": "Value", + "tag": "BlockHash", "discriminant": 0, + "type": "BlockHashPredicateBox" + }, + { + "tag": "Value", + "discriminant": 1, "type": "SignedTransactionPredicateBox" }, { "tag": "Error", - "discriminant": 1, + "discriminant": 2, "type": "TransactionErrorPredicateBox" } ] @@ -1107,6 +1116,30 @@ } ] }, + "CompoundPredicate": { + "Enum": [ + { + "tag": "Atom", + "discriminant": 0, + "type": "CommittedTransactionPredicateBox" + }, + { + "tag": "Not", + "discriminant": 1, + "type": "CompoundPredicate" + }, + { + "tag": "And", + "discriminant": 2, + "type": "Vec>" + }, + { + "tag": "Or", + "discriminant": 3, + "type": "Vec>" + } + ] + }, "CompoundPredicate": { "Enum": [ { @@ -1251,30 +1284,6 @@ } ] }, - "CompoundPredicate": { - "Enum": [ - { - "tag": "Atom", - "discriminant": 0, - "type": "TransactionQueryOutputPredicateBox" - }, - { - "tag": "Not", - "discriminant": 1, - "type": "CompoundPredicate" - }, - { - "tag": "And", - "discriminant": 2, - "type": "Vec>" - }, - { - "tag": "Or", - "discriminant": 3, - "type": "Vec>" - } - ] - }, "CompoundPredicate": { "Enum": [ { @@ -3002,7 +3011,7 @@ { "tag": "FindTransactions", "discriminant": 12, - "type": "QueryWithFilter" + "type": "QueryWithFilter" }, { "tag": "FindBlocks", @@ -3110,7 +3119,7 @@ { "tag": "Transaction", "discriminant": 7, - "type": "Vec" + "type": "Vec" }, { "tag": "Peer", @@ -3362,7 +3371,7 @@ } ] }, - "QueryWithFilter": { + "QueryWithFilter": { "Struct": [ { "name": "query", @@ -3370,7 +3379,7 @@ }, { "name": "predicate", - "type": "CompoundPredicate" + "type": "CompoundPredicate" } ] }, @@ -3960,6 +3969,10 @@ { "name": "payload", "type": "BlockPayload" + }, + { + "name": "errors", + "type": "SortedMap" } ] }, @@ -4093,7 +4106,7 @@ { "tag": "Transaction", "discriminant": 5, - "type": "TransactionQueryOutput" + "type": "CommittedTransaction" }, { "tag": "BlockHeader", @@ -4195,6 +4208,12 @@ "value": "JsonString" } }, + "SortedMap": { + "Map": { + "key": "u64", + "value": "TransactionRejectionReason" + } + }, "SortedVec": { "Vec": "Permission" }, @@ -4405,32 +4424,6 @@ } ] }, - "TransactionQueryOutput": { - "Struct": [ - { - "name": "block_hash", - "type": "HashOf" - }, - { - "name": "transaction", - "type": "CommittedTransaction" - } - ] - }, - "TransactionQueryOutputPredicateBox": { - "Enum": [ - { - "tag": "Transaction", - "discriminant": 0, - "type": "CommittedTransactionPredicateBox" - }, - { - "tag": "BlockHash", - "discriminant": 1, - "type": "BlockHashPredicateBox" - } - ] - }, "TransactionRejectionReason": { "Enum": [ { @@ -4920,6 +4913,9 @@ "Vec>": { "Vec": "CompoundPredicate" }, + "Vec>": { + "Vec": "CompoundPredicate" + }, "Vec>": { "Vec": "CompoundPredicate" }, @@ -4938,9 +4934,6 @@ "Vec>": { "Vec": "CompoundPredicate" }, - "Vec>": { - "Vec": "CompoundPredicate" - }, "Vec>": { "Vec": "CompoundPredicate" }, @@ -4977,8 +4970,8 @@ "Vec": { "Vec": "SignedBlock" }, - "Vec": { - "Vec": "TransactionQueryOutput" + "Vec": { + "Vec": "SignedTransaction" }, "Vec": { "Vec": "Trigger"