From 3e9cc6fb524e6997e7992c337e8a5621f9db1498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marin=20Ver=C5=A1i=C4=87?= Date: Tue, 27 Aug 2024 10:47:45 +0200 Subject: [PATCH] feat: bounded discrete time (#4928) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marin Veršić --- cli/src/lib.rs | 4 +- client/benches/torii.rs | 4 +- client/examples/million_accounts_genesis.rs | 2 +- client/examples/register_1000_triggers.rs | 2 +- .../integration/triggers/time_trigger.rs | 2 +- config/src/parameters/actual.rs | 2 - config/src/parameters/defaults.rs | 5 +- config/src/parameters/user.rs | 5 - config/tests/fixtures.rs | 3 +- config/tests/fixtures/full.toml | 1 - core/benches/blocks/common.rs | 8 +- core/benches/kura.rs | 33 ++-- core/benches/validation.rs | 48 +++-- core/src/block.rs | 180 ++++++++++++------ core/src/gossiper.rs | 15 +- core/src/kura.rs | 87 ++++----- core/src/metrics.rs | 2 +- core/src/queue.rs | 153 +++++---------- core/src/smartcontracts/isi/mod.rs | 9 +- core/src/smartcontracts/isi/query.rs | 35 ++-- core/src/smartcontracts/isi/world.rs | 1 + core/src/smartcontracts/wasm.rs | 5 +- core/src/state.rs | 21 +- core/src/sumeragi/main_loop.rs | 46 +++-- core/src/tx.rs | 82 ++++---- crypto/src/lib.rs | 32 ++-- data_model/src/block.rs | 167 ++++++++++------ data_model/src/parameter.rs | 35 +++- data_model/src/transaction.rs | 2 +- defaults/executor.wasm | Bin 0 -> 400985 bytes defaults/genesis.json | 5 + docs/source/references/peer.template.toml | 1 - docs/source/references/schema.json | 9 + genesis/src/lib.rs | 10 +- primitives/src/time.rs | 2 +- telemetry/derive/src/lib.rs | 9 +- torii/src/routing.rs | 15 +- 37 files changed, 570 insertions(+), 472 deletions(-) create mode 100644 defaults/executor.wasm diff --git a/cli/src/lib.rs b/cli/src/lib.rs index bef162f0dde..23c43a1ccc9 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -832,10 +832,10 @@ mod tests { let genesis_key_pair = KeyPair::random(); let genesis = GenesisBuilder::default().build_and_sign( - dummy_executor(), ChainId::from("00000000-0000-0000-0000-000000000000"), - &genesis_key_pair, + dummy_executor(), vec![], + &genesis_key_pair, ); let mut config = config_factory(genesis_key_pair.public_key()); diff --git a/client/benches/torii.rs b/client/benches/torii.rs index efdd8ec5dc1..b7e04595e2f 100644 --- a/client/benches/torii.rs +++ b/client/benches/torii.rs @@ -38,7 +38,7 @@ fn query_requests(criterion: &mut Criterion) { .domain("wonderland".parse().expect("Valid")) .account(get_key_pair(test_network::Signatory::Alice).into_parts().0) .finish_domain() - .build_and_sign(executor, chain_id, &genesis_key_pair, topology); + .build_and_sign(chain_id, executor, topology, &genesis_key_pair); let builder = PeerBuilder::new() .with_config(configuration) @@ -135,7 +135,7 @@ fn instruction_submits(criterion: &mut Criterion) { .domain("wonderland".parse().expect("Valid")) .account(configuration.common.key_pair.public_key().clone()) .finish_domain() - .build_and_sign(executor, chain_id, &genesis_key_pair, topology); + .build_and_sign(chain_id, executor, topology, &genesis_key_pair); let builder = PeerBuilder::new() .with_config(configuration) .with_genesis(genesis); diff --git a/client/examples/million_accounts_genesis.rs b/client/examples/million_accounts_genesis.rs index 4c6f8622fac..18fe51f3197 100644 --- a/client/examples/million_accounts_genesis.rs +++ b/client/examples/million_accounts_genesis.rs @@ -36,7 +36,7 @@ fn generate_genesis( let executor = construct_executor("../wasm_samples/default_executor") .expect("Failed to construct executor"); - builder.build_and_sign(executor, chain_id, genesis_key_pair, topology) + builder.build_and_sign(chain_id, executor, topology, genesis_key_pair) } fn main_genesis() { diff --git a/client/examples/register_1000_triggers.rs b/client/examples/register_1000_triggers.rs index e1fbc844c67..e4d7533c8b1 100644 --- a/client/examples/register_1000_triggers.rs +++ b/client/examples/register_1000_triggers.rs @@ -65,7 +65,7 @@ fn generate_genesis( let executor = construct_executor("../wasm_samples/default_executor") .expect("Failed to construct executor"); - Ok(builder.build_and_sign(executor, chain_id, genesis_key_pair, topology)) + Ok(builder.build_and_sign(chain_id, executor, topology, genesis_key_pair)) } fn main() -> Result<(), Box> { diff --git a/client/tests/integration/triggers/time_trigger.rs b/client/tests/integration/triggers/time_trigger.rs index fead56dc6bf..76672d5adbc 100644 --- a/client/tests/integration/triggers/time_trigger.rs +++ b/client/tests/integration/triggers/time_trigger.rs @@ -36,7 +36,7 @@ fn curr_time() -> core::time::Duration { SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) - .expect("Failed to get the current system time") + .unwrap() } /// Macro to abort compilation, if `e` isn't `true` diff --git a/config/src/parameters/actual.rs b/config/src/parameters/actual.rs index 0c589175441..60331067941 100644 --- a/config/src/parameters/actual.rs +++ b/config/src/parameters/actual.rs @@ -94,7 +94,6 @@ pub struct Queue { pub capacity: NonZeroUsize, pub capacity_per_user: NonZeroUsize, pub transaction_time_to_live: Duration, - pub future_threshold: Duration, } #[allow(missing_docs)] @@ -109,7 +108,6 @@ impl Default for Queue { fn default() -> Self { Self { transaction_time_to_live: defaults::queue::TRANSACTION_TIME_TO_LIVE, - future_threshold: defaults::queue::FUTURE_THRESHOLD, capacity: defaults::queue::CAPACITY, capacity_per_user: defaults::queue::CAPACITY_PER_USER, } diff --git a/config/src/parameters/defaults.rs b/config/src/parameters/defaults.rs index 1fb3928fff2..df4d8305587 100644 --- a/config/src/parameters/defaults.rs +++ b/config/src/parameters/defaults.rs @@ -17,7 +17,6 @@ pub mod queue { pub const CAPACITY_PER_USER: NonZeroUsize = nonzero!(2_usize.pow(16)); // 24 hours pub const TRANSACTION_TIME_TO_LIVE: Duration = Duration::from_secs(24 * 60 * 60); - pub const FUTURE_THRESHOLD: Duration = Duration::from_secs(1); } pub mod kura { @@ -40,8 +39,8 @@ pub mod snapshot { use super::*; pub const STORE_DIR: &str = "./storage/snapshot"; - // The default frequency of making snapshots is 1 minute, need to be adjusted for larger world state view size - pub const CREATE_EVERY: Duration = Duration::from_secs(60); + // 10 mins + pub const CREATE_EVERY: Duration = Duration::from_secs(10 * 60); } pub mod torii { diff --git a/config/src/parameters/user.rs b/config/src/parameters/user.rs index 8cdb29c2695..db88c729bbc 100644 --- a/config/src/parameters/user.rs +++ b/config/src/parameters/user.rs @@ -324,9 +324,6 @@ pub struct Queue { /// The transaction will be dropped after this time if it is still in the queue. #[config(default = "defaults::queue::TRANSACTION_TIME_TO_LIVE.into()")] pub transaction_time_to_live_ms: DurationMs, - /// The threshold to determine if a transaction has been tampered to have a future timestamp. - #[config(default = "defaults::queue::FUTURE_THRESHOLD.into()")] - pub future_threshold_ms: DurationMs, } impl Queue { @@ -335,13 +332,11 @@ impl Queue { capacity, capacity_per_user, transaction_time_to_live_ms: transaction_time_to_live, - future_threshold_ms: future_threshold, } = self; actual::Queue { capacity, capacity_per_user, transaction_time_to_live: transaction_time_to_live.0, - future_threshold: future_threshold.0, } } } diff --git a/config/tests/fixtures.rs b/config/tests/fixtures.rs index 4065fd76af4..ce9b2af7bac 100644 --- a/config/tests/fixtures.rs +++ b/config/tests/fixtures.rs @@ -181,12 +181,11 @@ fn minimal_config_snapshot() { capacity: 65536, capacity_per_user: 65536, transaction_time_to_live: 86400s, - future_threshold: 1s, }, snapshot: Snapshot { mode: ReadWrite, create_every_ms: DurationMs( - 60s, + 600s, ), store_dir: WithOrigin { value: "./storage/snapshot", diff --git a/config/tests/fixtures/full.toml b/config/tests/fixtures/full.toml index a333af4e541..c21bc715ee6 100644 --- a/config/tests/fixtures/full.toml +++ b/config/tests/fixtures/full.toml @@ -45,7 +45,6 @@ format = "compact" capacity = 65_536 capacity_per_user = 65_536 transaction_time_to_live_ms = 100 -future_threshold_ms = 50 [snapshot] mode = "read_write" diff --git a/core/benches/blocks/common.rs b/core/benches/blocks/common.rs index 5bbfcb0628b..9b4edabbc83 100644 --- a/core/benches/blocks/common.rs +++ b/core/benches/blocks/common.rs @@ -36,12 +36,16 @@ pub fn create_block( let transaction = TransactionBuilder::new(chain_id.clone(), account_id) .with_instructions(instructions) .sign(account_private_key); - let limits = state.transaction_executor().limits; + let (max_clock_drift, tx_limits) = { + let params = state.world.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) + }; let block = BlockBuilder::new(vec![AcceptedTransaction::accept( transaction, &chain_id, - limits, + max_clock_drift, + tx_limits, ) .unwrap()]) .chain(0, state) diff --git a/core/benches/kura.rs b/core/benches/kura.rs index 061d8de8532..b01a5dcfd56 100644 --- a/core/benches/kura.rs +++ b/core/benches/kura.rs @@ -14,13 +14,22 @@ use iroha_core::{ sumeragi::network_topology::Topology, }; use iroha_crypto::KeyPair; -use iroha_data_model::{parameter::TransactionParameters, prelude::*}; -use nonzero_ext::nonzero; +use iroha_data_model::prelude::*; use test_samples::gen_account_in; use tokio::{fs, runtime::Runtime}; async fn measure_block_size_for_n_executors(n_executors: u32) { + let dir = tempfile::tempdir().expect("Could not create tempfile."); + let cfg = Config { + init_mode: iroha_config::kura::InitMode::Strict, + debug_output_new_blocks: false, + store_dir: WithOrigin::inline(dir.path().to_path_buf()), + }; let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); + let (kura, _) = iroha_core::kura::Kura::new(&cfg).unwrap(); + let _thread_handle = iroha_core::kura::Kura::start(kura.clone()); + let query_handle = LiveQueryStore::test().start(); + let state = State::new(World::new(), kura, query_handle); let (alice_id, alice_keypair) = gen_account_in("test"); let (bob_id, _bob_keypair) = gen_account_in("test"); @@ -30,23 +39,13 @@ async fn measure_block_size_for_n_executors(n_executors: u32) { let tx = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions([transfer]) .sign(alice_keypair.private_key()); - let txn_limits = TransactionParameters { - max_instructions: nonzero!(4096_u64), - smart_contract_size: nonzero!(1_u64), + let (max_clock_drift, tx_limits) = { + let state_view = state.world.view(); + let params = state_view.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) }; - let tx = AcceptedTransaction::accept(tx, &chain_id, txn_limits) + let tx = AcceptedTransaction::accept(tx, &chain_id, max_clock_drift, tx_limits) .expect("Failed to accept Transaction."); - let dir = tempfile::tempdir().expect("Could not create tempfile."); - let cfg = Config { - init_mode: iroha_config::kura::InitMode::Strict, - debug_output_new_blocks: false, - store_dir: WithOrigin::inline(dir.path().to_path_buf()), - }; - let (kura, _) = iroha_core::kura::Kura::new(&cfg).unwrap(); - let _thread_handle = iroha_core::kura::Kura::start(kura.clone()); - - let query_handle = LiveQueryStore::test().start(); - let state = State::new(World::new(), kura, query_handle); let (peer_public_key, peer_private_key) = KeyPair::random().into_parts(); let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), peer_public_key); let topology = Topology::new(vec![peer_id]); diff --git a/core/benches/validation.rs b/core/benches/validation.rs index ff7cc119d1e..40c999b8579 100644 --- a/core/benches/validation.rs +++ b/core/benches/validation.rs @@ -7,13 +7,10 @@ use iroha_core::{ query::store::LiveQueryStore, smartcontracts::{isi::Registrable as _, Execute}, state::{State, World}, - tx::TransactionExecutor, }; use iroha_data_model::{ - account::AccountId, isi::InstructionBox, parameter::TransactionParameters, prelude::*, - transaction::TransactionBuilder, + account::AccountId, isi::InstructionBox, prelude::*, transaction::TransactionBuilder, }; -use nonzero_ext::nonzero; use once_cell::sync::Lazy; use test_samples::gen_account_in; @@ -22,9 +19,6 @@ static STARTER_KEYPAIR: Lazy = Lazy::new(KeyPair::random); static STARTER_ID: Lazy = Lazy::new(|| AccountId::new(STARTER_DOMAIN.clone(), STARTER_KEYPAIR.public_key().clone())); -const TRANSACTION_LIMITS: TransactionParameters = - TransactionParameters::new(nonzero!(4096_u64), nonzero!(1_u64)); - fn build_test_transaction(chain_id: ChainId) -> TransactionBuilder { let domain_id: DomainId = "domain".parse().unwrap(); let create_domain = Register::domain(Domain::new(domain_id.clone())); @@ -75,13 +69,24 @@ fn build_test_and_transient_state() -> State { fn accept_transaction(criterion: &mut Criterion) { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); + let state = build_test_and_transient_state(); + let (max_clock_drift, tx_limits) = { + let state_view = state.world.view(); + let params = state_view.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) + }; let transaction = build_test_transaction(chain_id.clone()).sign(STARTER_KEYPAIR.private_key()); let mut success_count = 0; let mut failures_count = 0; let _ = criterion.bench_function("accept", |b| { b.iter(|| { - match AcceptedTransaction::accept(transaction.clone(), &chain_id, TRANSACTION_LIMITS) { + match AcceptedTransaction::accept( + transaction.clone(), + &chain_id, + max_clock_drift, + tx_limits, + ) { Ok(_) => success_count += 1, Err(_) => failures_count += 1, } @@ -111,21 +116,26 @@ fn sign_transaction(criterion: &mut Criterion) { fn validate_transaction(criterion: &mut Criterion) { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); + let state = build_test_and_transient_state(); + let (max_clock_drift, tx_limits) = { + let state_view = state.world.view(); + let params = state_view.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) + }; let transaction = AcceptedTransaction::accept( build_test_transaction(chain_id.clone()).sign(STARTER_KEYPAIR.private_key()), &chain_id, - TRANSACTION_LIMITS, + max_clock_drift, + tx_limits, ) .expect("Failed to accept transaction."); let mut success_count = 0; let mut failure_count = 0; - let state = build_test_and_transient_state(); let _ = criterion.bench_function("validate", move |b| { - let transaction_executor = TransactionExecutor::new(TRANSACTION_LIMITS); b.iter(|| { let mut state_block = state.block(); - match transaction_executor.validate(transaction.clone(), &mut state_block) { + match state_block.validate(transaction.clone()) { Ok(_) => success_count += 1, Err(_) => failure_count += 1, } @@ -136,16 +146,22 @@ fn validate_transaction(criterion: &mut Criterion) { fn sign_blocks(criterion: &mut Criterion) { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); + let kura = iroha_core::kura::Kura::blank_kura_for_testing(); + let query_handle = LiveQueryStore::test().start(); + let state = State::new(World::new(), kura, query_handle); + let (max_clock_drift, tx_limits) = { + let state_view = state.world.view(); + let params = state_view.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) + }; let transaction = AcceptedTransaction::accept( build_test_transaction(chain_id.clone()).sign(STARTER_KEYPAIR.private_key()), &chain_id, - TRANSACTION_LIMITS, + max_clock_drift, + tx_limits, ) .expect("Failed to accept transaction."); - let kura = iroha_core::kura::Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); - let state = State::new(World::new(), kura, query_handle); let (_, peer_private_key) = KeyPair::random().into_parts(); let mut count = 0; diff --git a/core/src/block.rs b/core/src/block.rs index 96c35475c45..8af28da8704 100644 --- a/core/src/block.rs +++ b/core/src/block.rs @@ -4,7 +4,7 @@ //! 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 _; +use std::{error::Error as _, time::Duration}; use iroha_crypto::{HashOf, KeyPair, MerkleTree}; use iroha_data_model::{ @@ -71,6 +71,10 @@ pub enum BlockValidationError { ViewChangeIndexTooLarge, /// Invalid genesis block: {0} InvalidGenesis(#[from] InvalidGenesisError), + /// Block's creation time is earlier than that of the previous block + BlockInThePast, + /// Block's creation time is later than the current node local time + BlockInTheFuture, } /// Error during signature verification @@ -112,12 +116,10 @@ pub enum InvalidGenesisError { pub struct BlockBuilder(B); mod pending { - use std::{ - num::NonZeroUsize, - time::{Duration, SystemTime}, - }; + use std::time::SystemTime; use iroha_data_model::transaction::CommittedTransaction; + use nonzero_ext::nonzero; use super::*; use crate::state::StateBlock; @@ -134,6 +136,8 @@ mod pending { } impl BlockBuilder { + const TIME_PADDING: Duration = Duration::from_millis(1); + /// Create [`Self`] /// /// # Panics @@ -141,35 +145,61 @@ mod pending { /// if the given list of transaction is empty #[inline] pub fn new(transactions: Vec) -> Self { + assert!( + !transactions.is_empty(), + "Block must contain at least 1 transaction" + ); + Self(Pending { transactions }) } fn make_header( - prev_height: usize, - prev_block_hash: Option>, + prev_block: Option<&SignedBlock>, view_change_index: usize, transactions: &[CommittedTransaction], consensus_estimation: Duration, ) -> 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()) + .max() + .expect("INTERNAL BUG: Block empty"); + + let now = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap(); + + // NOTE: Lower time bound must always be upheld for a valid block + // If the clock has drifted too far this block will be rejected + let creation_time = [ + now, + latest_txn_time + Self::TIME_PADDING, + prev_block_time + Self::TIME_PADDING, + ] + .into_iter() + .max() + .unwrap(); + BlockHeader { - height: NonZeroUsize::new( - prev_height - .checked_add(1) - .expect("INTERNAL BUG: Blockchain height exceeds usize::MAX"), - ) - .expect("INTERNAL BUG: block height must not be 0") - .try_into() - .expect("INTERNAL BUG: Number of blocks exceeds u64::MAX"), - prev_block_hash, + height: prev_block + .map(|block| block.header().height) + .map(|height| { + height + .checked_add(1) + .expect("INTERNAL BUG: Blockchain height exceeds usize::MAX") + }) + .unwrap_or(nonzero!(1_u64)), + prev_block_hash: prev_block.map(SignedBlock::hash), transactions_hash: transactions .iter() .map(|value| value.as_ref().hash()) .collect::>() .hash() .expect("INTERNAL BUG: Empty block created"), - creation_time_ms: SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .expect("INTERNAL BUG: Failed to get the current system time") + creation_time_ms: creation_time .as_millis() .try_into() .expect("Time should fit into u64"), @@ -189,25 +219,23 @@ mod pending { ) -> Vec { transactions .into_iter() - .map( - |tx| match state_block.transaction_executor().validate(tx, state_block) { - Ok(tx) => CommittedTransaction { + .map(|tx| match state_block.validate(tx) { + Ok(tx) => CommittedTransaction { + value: tx, + error: None, + }, + Err((tx, error)) => { + iroha_logger::warn!( + reason = %error, + caused_by = ?error.source(), + "Transaction validation failed", + ); + CommittedTransaction { value: tx, - error: None, - }, - Err((tx, error)) => { - iroha_logger::warn!( - reason = %error, - caused_by = ?error.source(), - "Transaction validation failed", - ); - CommittedTransaction { - value: tx, - error: Some(error), - } + error: Some(error), } - }, - ) + } + }) .collect() } @@ -223,8 +251,7 @@ mod pending { BlockBuilder(Chained(BlockPayload { header: Self::make_header( - state.height(), - state.latest_block_hash(), + state.latest_block().as_deref(), view_change_index, &transactions, state.world.parameters().sumeragi.consensus_estimation(), @@ -251,6 +278,8 @@ mod chained { } mod valid { + use std::time::SystemTime; + use commit::CommittedBlock; use indexmap::IndexMap; use iroha_data_model::{account::AccountId, events::pipeline::PipelineEventBox, ChainId}; @@ -497,6 +526,14 @@ mod valid { }); } + let now = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap(); + let max_clock_drift = state.world().parameters().sumeragi.max_clock_drift(); + if block.header().creation_time().saturating_sub(now) > max_clock_drift { + return Err(BlockValidationError::BlockInTheFuture); + } + let expected_prev_block_hash = if soft_fork { state.prev_block_hash() } else { @@ -514,6 +551,19 @@ mod valid { if block.header().is_genesis() { check_genesis_block(block, genesis_account)?; } else { + let prev_block_time = if soft_fork { + state.prev_block() + } else { + state.latest_block() + } + .expect("INTERNAL BUG: Genesis not committed") + .header() + .creation_time(); + + if block.header().creation_time() <= prev_block_time { + return Err(BlockValidationError::BlockInThePast); + } + Self::verify_leader_signature(block, topology)?; Self::verify_validator_signatures(block, topology)?; Self::verify_no_undefined_signatures(block, topology)?; @@ -540,35 +590,40 @@ mod valid { ) -> Result<(), TransactionValidationError> { let is_genesis = block.header().is_genesis(); + let (max_clock_drift, tx_limits) = { + let params = state_block.world().parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) + }; + block .transactions() // TODO: Unnecessary clone? .cloned() .try_for_each(|CommittedTransaction { value, error }| { - let transaction_executor = state_block.transaction_executor(); - let tx = if is_genesis { AcceptedTransaction::accept_genesis( value, expected_chain_id, + max_clock_drift, genesis_account, ) } else { AcceptedTransaction::accept( value, expected_chain_id, - transaction_executor.limits, + max_clock_drift, + tx_limits, ) }?; if error.is_some() { - match transaction_executor.validate(tx, state_block) { + match state_block.validate(tx) { Err(rejected_transaction) => Ok(rejected_transaction), Ok(_) => Err(TransactionValidationError::RejectedIsValid), }?; } else { - transaction_executor - .validate(tx, state_block) + state_block + .validate(tx) .map_err(|(_tx, error)| TransactionValidationError::NotValid(error))?; } @@ -1095,6 +1150,11 @@ mod tests { let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = State::new(world, kura, query_handle); + let (max_clock_drift, tx_limits) = { + let state_view = state.world.view(); + let params = state_view.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) + }; let mut state_block = state.block(); // Creating an instruction @@ -1103,11 +1163,11 @@ mod tests { Register::asset_definition(AssetDefinition::numeric(asset_definition_id)); // Making two transactions that have the same instruction - let transaction_limits = state_block.transaction_executor().limits; let tx = TransactionBuilder::new(chain_id.clone(), alice_id) .with_instructions([create_asset_definition]) .sign(alice_keypair.private_key()); - let tx = AcceptedTransaction::accept(tx, &chain_id, transaction_limits).expect("Valid"); + let tx = + AcceptedTransaction::accept(tx, &chain_id, max_clock_drift, tx_limits).expect("Valid"); // Creating a block of two identical transactions and validating it let transactions = vec![tx.clone(), tx]; @@ -1148,6 +1208,11 @@ mod tests { let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = State::new(world, kura, query_handle); + let (max_clock_drift, tx_limits) = { + let state_view = state.world.view(); + let params = state_view.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) + }; let mut state_block = state.block(); // Creating an instruction @@ -1156,11 +1221,11 @@ mod tests { Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone())); // Making two transactions that have the same instruction - let transaction_limits = state_block.transaction_executor().limits; let tx = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions([create_asset_definition]) .sign(alice_keypair.private_key()); - let tx = AcceptedTransaction::accept(tx, &chain_id, transaction_limits).expect("Valid"); + let tx = + AcceptedTransaction::accept(tx, &chain_id, max_clock_drift, tx_limits).expect("Valid"); let fail_mint = Mint::asset_numeric( 20u32, @@ -1173,12 +1238,14 @@ mod tests { let tx0 = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions([fail_mint]) .sign(alice_keypair.private_key()); - let tx0 = AcceptedTransaction::accept(tx0, &chain_id, transaction_limits).expect("Valid"); + let tx0 = + AcceptedTransaction::accept(tx0, &chain_id, max_clock_drift, tx_limits).expect("Valid"); let tx2 = TransactionBuilder::new(chain_id.clone(), alice_id) .with_instructions([succeed_mint]) .sign(alice_keypair.private_key()); - let tx2 = AcceptedTransaction::accept(tx2, &chain_id, transaction_limits).expect("Valid"); + let tx2 = + AcceptedTransaction::accept(tx2, &chain_id, max_clock_drift, tx_limits).expect("Valid"); // Creating a block of two identical transactions and validating it let transactions = vec![tx0, tx, tx2]; @@ -1219,8 +1286,12 @@ mod tests { let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = State::new(world, kura, query_handle); + let (max_clock_drift, tx_limits) = { + let state_view = state.world.view(); + let params = state_view.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) + }; let mut state_block = state.block(); - let transaction_limits = state_block.transaction_executor().limits; let domain_id = DomainId::from_str("domain").expect("Valid"); let create_domain = Register::domain(Domain::new(domain_id)); @@ -1231,13 +1302,14 @@ mod tests { let tx_fail = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions::([create_domain.clone().into(), fail_isi.into()]) .sign(alice_keypair.private_key()); - let tx_fail = - AcceptedTransaction::accept(tx_fail, &chain_id, transaction_limits).expect("Valid"); + let tx_fail = AcceptedTransaction::accept(tx_fail, &chain_id, max_clock_drift, tx_limits) + .expect("Valid"); let tx_accept = TransactionBuilder::new(chain_id.clone(), alice_id) .with_instructions::([create_domain.into(), create_asset.into()]) .sign(alice_keypair.private_key()); let tx_accept = - AcceptedTransaction::accept(tx_accept, &chain_id, transaction_limits).expect("Valid"); + AcceptedTransaction::accept(tx_accept, &chain_id, max_clock_drift, tx_limits) + .expect("Valid"); // Creating a block of where first transaction must fail and second one fully executed let transactions = vec![tx_fail, tx_accept]; diff --git a/core/src/gossiper.rs b/core/src/gossiper.rs index 70c1bc73b17..247d9b717d5 100644 --- a/core/src/gossiper.rs +++ b/core/src/gossiper.rs @@ -10,7 +10,7 @@ use tokio::sync::mpsc; use crate::{ queue::Queue, state::State, tx::AcceptedTransaction, IrohaNetwork, NetworkMessage, - StateReadOnly, WorldReadOnly, + WorldReadOnly, }; /// [`Gossiper`] actor handle. @@ -108,12 +108,15 @@ impl TransactionGossiper { fn handle_transaction_gossip(&self, TransactionGossip { txs }: TransactionGossip) { iroha_logger::trace!(size = txs.len(), "Received new transaction gossip"); - let state_view = self.state.view(); for tx in txs { - let transaction_limits = state_view.world().parameters().transaction; - - match AcceptedTransaction::accept(tx, &self.chain_id, transaction_limits) { - Ok(tx) => match self.queue.push(tx, &state_view) { + let (max_clock_drift, tx_limits) = { + let state_view = self.state.world.view(); + let params = state_view.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) + }; + + match AcceptedTransaction::accept(tx, &self.chain_id, max_clock_drift, tx_limits) { + Ok(tx) => match self.queue.push(tx, self.state.view()) { Ok(()) => {} Err(crate::queue::Failure { tx, diff --git a/core/src/kura.rs b/core/src/kura.rs index bc6278f6ee1..8366e7c69ad 100644 --- a/core/src/kura.rs +++ b/core/src/kura.rs @@ -808,7 +808,7 @@ mod tests { smartcontracts::Registrable, state::State, sumeragi::network_topology::Topology, - StateReadOnly, World, + World, }; fn indices(value: [(u64, u64); N]) -> [BlockIndex; N] { @@ -1001,33 +1001,10 @@ mod tests { let _logger = iroha_logger::test_logger(); } - let temp_dir = TempDir::new().unwrap(); - - let [block_genesis, block, block_soft_fork, block_next] = - create_blocks(&rt).try_into().unwrap(); - // Create kura and write some blocks - { - let (kura, block_count) = Kura::new(&Config { - init_mode: InitMode::Strict, - store_dir: iroha_config::base::WithOrigin::inline( - temp_dir.path().to_str().unwrap().into(), - ), - debug_output_new_blocks: false, - }) - .unwrap(); - // Starting with empty block store - assert_eq!(block_count.0, 0); - - let _handle = Kura::start(kura.clone()); - - kura.store_block(block_genesis.clone()); - kura.store_block(block); - // Add wait so that previous block is written to the block store - thread::sleep(Duration::from_secs(1)); - kura.replace_top_block(block_soft_fork.clone()); - kura.store_block(block_next.clone()); - } + let temp_dir = TempDir::new().unwrap(); + let [block_genesis, _block, block_soft_fork, block_next] = + create_blocks(&rt, &temp_dir).try_into().unwrap(); // Reinitialize kura and check that correct blocks are loaded { @@ -1058,7 +1035,7 @@ mod tests { } #[allow(clippy::too_many_lines)] - fn create_blocks(rt: &tokio::runtime::Runtime) -> Vec { + fn create_blocks(rt: &tokio::runtime::Runtime, temp_dir: &TempDir) -> Vec { let mut blocks = Vec::new(); let (leader_public_key, leader_private_key) = KeyPair::random().into_parts(); @@ -1081,9 +1058,23 @@ mod tests { let _rt_guard = rt.enter(); live_query_store.start() }; + + let (kura, block_count) = Kura::new(&Config { + init_mode: InitMode::Strict, + store_dir: iroha_config::base::WithOrigin::inline( + temp_dir.path().to_str().unwrap().into(), + ), + debug_output_new_blocks: false, + }) + .unwrap(); + // Starting with empty block store + assert_eq!(block_count.0, 0); + + let _handle = Kura::start(kura.clone()); + let state = State::new( World::with([domain, genesis_domain], [account, genesis_account], []), - Kura::blank_kura_for_testing(), + Arc::clone(&kura), live_query_store, ); @@ -1092,10 +1083,10 @@ mod tests { Executor::new(WasmSmartContract::from_compiled(executor_blob)) }; let genesis = GenesisBuilder::default().build_and_sign( - executor, chain_id.clone(), - &genesis_key_pair, + executor, topology.as_ref().to_owned(), + &genesis_key_pair, ); { @@ -1115,9 +1106,14 @@ mod tests { let _events = state_block.apply_without_execution(&block_genesis, topology.as_ref().to_owned()); state_block.commit(); - blocks.push(block_genesis); + blocks.push(block_genesis.clone()); + kura.store_block(block_genesis); } + let (max_clock_drift, tx_limits) = { + let params = state.view().world.parameters; + (params.sumeragi().max_clock_drift(), params.transaction) + }; let tx1 = TransactionBuilder::new(chain_id.clone(), account_id.clone()) .with_instructions([Log::new(Level::INFO, "msg1".to_string())]) .sign(account_keypair.private_key()); @@ -1125,18 +1121,10 @@ mod tests { let tx2 = TransactionBuilder::new(chain_id.clone(), account_id) .with_instructions([Log::new(Level::INFO, "msg2".to_string())]) .sign(account_keypair.private_key()); - let tx1 = crate::AcceptedTransaction::accept( - tx1, - &chain_id, - state.view().transaction_executor().limits, - ) - .unwrap(); - let tx2 = crate::AcceptedTransaction::accept( - tx2, - &chain_id, - state.view().transaction_executor().limits, - ) - .unwrap(); + let tx1 = + crate::AcceptedTransaction::accept(tx1, &chain_id, max_clock_drift, tx_limits).unwrap(); + let tx2 = + crate::AcceptedTransaction::accept(tx2, &chain_id, max_clock_drift, tx_limits).unwrap(); { let mut state_block = state.block(); @@ -1149,8 +1137,11 @@ mod tests { .unwrap(); let _events = state_block.apply_without_execution(&block, topology.as_ref().to_owned()); state_block.commit(); - blocks.push(block); + blocks.push(block.clone()); + kura.store_block(block); } + // Add wait so that previous block is written to the block store + thread::sleep(Duration::from_secs(1)); { let mut state_block = state.block_and_revert(); @@ -1164,7 +1155,8 @@ mod tests { let _events = state_block.apply_without_execution(&block_soft_fork, topology.as_ref().to_owned()); state_block.commit(); - blocks.push(block_soft_fork); + blocks.push(block_soft_fork.clone()); + kura.replace_top_block(block_soft_fork); } { @@ -1179,7 +1171,8 @@ mod tests { let _events = state_block.apply_without_execution(&block_next, topology.as_ref().to_owned()); state_block.commit(); - blocks.push(block_next); + blocks.push(block_next.clone()); + kura.store_block(block_next); } blocks diff --git a/core/src/metrics.rs b/core/src/metrics.rs index 379690e74a1..da9fec96d73 100644 --- a/core/src/metrics.rs +++ b/core/src/metrics.rs @@ -116,7 +116,7 @@ impl MetricsReporter { if let Some(timestamp) = state_view.genesis_timestamp() { let curr_time = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) - .expect("Failed to get the current system time"); + .unwrap(); // this will overflow in 584942417years. self.metrics.uptime_since_genesis_ms.set( diff --git a/core/src/queue.rs b/core/src/queue.rs index 48ed31ad9bc..4b7b074c2da 100644 --- a/core/src/queue.rs +++ b/core/src/queue.rs @@ -37,7 +37,7 @@ pub struct Queue { /// The queue for transactions tx_hashes: ArrayQueue>, /// [`AcceptedTransaction`]s addressed by `Hash` - accepted_txs: DashMap, AcceptedTransaction>, + txs: DashMap, AcceptedTransaction>, /// Amount of transactions per user in the queue txs_per_user: DashMap, /// The maximum number of transactions in the queue @@ -50,9 +50,6 @@ pub struct Queue { time_source: TimeSource, /// Length of time after which transactions are dropped. pub tx_time_to_live: Duration, - /// A point in time that is considered `Future` we cannot use - /// current time, because of network time synchronisation issues - future_threshold: Duration, } /// Queue push error @@ -61,8 +58,6 @@ pub struct Queue { pub enum Error { /// Queue is full Full, - /// Transaction is regarded to have been tampered to have a future timestamp - InFuture, /// Transaction expired Expired, /// Transaction is already applied @@ -110,20 +105,18 @@ impl Queue { capacity, capacity_per_user, transaction_time_to_live, - future_threshold, }: Config, events_sender: EventsSender, ) -> Self { Self { events_sender, tx_hashes: ArrayQueue::new(capacity.get()), - accepted_txs: DashMap::new(), + txs: DashMap::new(), txs_per_user: DashMap::new(), capacity, capacity_per_user, time_source: TimeSource::new_system(), tx_time_to_live: transaction_time_to_live, - future_threshold, } } @@ -144,19 +137,12 @@ impl Queue { curr_time.saturating_sub(tx_creation_time) > time_limit } - /// If `true`, this transaction is regarded to have been tampered to have a future timestamp. - fn is_in_future(&self, tx: &AcceptedTransaction) -> bool { - let tx_timestamp = tx.as_ref().creation_time(); - let curr_time = self.time_source.get_unix_time(); - tx_timestamp.saturating_sub(curr_time) > self.future_threshold - } - /// Returns all pending transactions. pub fn all_transactions<'state>( &'state self, state_view: &'state StateView, ) -> impl Iterator + 'state { - self.accepted_txs.iter().filter_map(|tx| { + self.txs.iter().filter_map(|tx| { if self.is_pending(tx.value(), state_view) { return Some(tx.value().clone()); } @@ -171,7 +157,7 @@ impl Queue { n: u32, state_view: &StateView, ) -> Vec { - self.accepted_txs + self.txs .iter() .filter(|e| self.is_pending(e.value(), state_view)) .map(|e| e.value().clone()) @@ -182,9 +168,7 @@ impl Queue { } fn check_tx(&self, tx: &AcceptedTransaction, state_view: &StateView) -> Result<(), Error> { - if self.is_in_future(tx) { - Err(Error::InFuture) - } else if self.is_expired(tx) { + if self.is_expired(tx) { Err(Error::Expired) } else if tx.is_in_blockchain(state_view) { Err(Error::InBlockchain) @@ -197,16 +181,17 @@ impl Queue { /// /// # Errors /// See [`enum@Error`] - pub fn push(&self, tx: AcceptedTransaction, state_view: &StateView) -> Result<(), Failure> { + pub fn push(&self, tx: AcceptedTransaction, state_view: StateView) -> Result<(), Failure> { trace!(tx=%tx.as_ref().hash(), "Pushing to the queue"); - if let Err(err) = self.check_tx(&tx, state_view) { + if let Err(err) = self.check_tx(&tx, &state_view) { return Err(Failure { tx, err }); } + drop(state_view); // Get `txs_len` before entry to avoid deadlock - let txs_len = self.accepted_txs.len(); + let txs_len = self.txs.len(); let hash = tx.as_ref().hash(); - let entry = match self.accepted_txs.entry(hash) { + let entry = match self.txs.entry(hash) { Entry::Occupied(_) => { return Err(Failure { tx, @@ -236,7 +221,7 @@ impl Queue { self.tx_hashes.push(hash).map_err(|err_hash| { warn!("Queue is full"); let (_, err_tx) = self - .accepted_txs + .txs .remove(&err_hash) .expect("Inserted just before match"); self.decrease_per_user_tx_count(err_tx.as_ref().authority()); @@ -266,7 +251,7 @@ impl Queue { loop { let hash = self.tx_hashes.pop()?; - let entry = match self.accepted_txs.entry(hash) { + let entry = match self.txs.entry(hash) { Entry::Occupied(entry) => entry, // FIXME: Reachable under high load. Investigate, see if it's a problem. // As practice shows this code is not `unreachable!()`. @@ -297,7 +282,7 @@ impl Queue { /// Return the number of transactions in the queue. pub fn tx_len(&self) -> usize { - self.accepted_txs.len() + self.txs.len() } /// Gets transactions till they fill whole block or till the end of queue. @@ -360,7 +345,7 @@ impl Queue { /// (either because it was expired, or because transaction is commited to blockchain), /// we should remove transaction from [`Queue::accepted_tx`]. fn remove_stale_transaction(&self, tx: &AcceptedTransaction) { - let removed = self.accepted_txs.remove(&tx.as_ref().hash()); + let removed = self.txs.remove(&tx.as_ref().hash()); if removed.is_some() { self.decrease_per_user_tx_count(tx.as_ref().authority()); @@ -436,13 +421,12 @@ pub mod tests { Self { events_sender: tokio::sync::broadcast::Sender::new(1), tx_hashes: ArrayQueue::new(cfg.capacity.get()), - accepted_txs: DashMap::new(), + txs: DashMap::new(), txs_per_user: DashMap::new(), capacity: cfg.capacity, capacity_per_user: cfg.capacity_per_user, time_source: time_source.clone(), tx_time_to_live: cfg.transaction_time_to_live, - future_threshold: cfg.future_threshold, } } } @@ -466,11 +450,12 @@ pub mod tests { TransactionBuilder::new_with_time_source(chain_id.clone(), account_id, time_source) .with_instructions(instructions) .sign(key_pair.private_key()); - let limits = TransactionParameters { + let tx_limits = TransactionParameters { max_instructions: nonzero!(4096_u64), smart_contract_size: nonzero!(1024_u64), }; - AcceptedTransaction::accept(tx, &chain_id, limits).expect("Failed to accept Transaction.") + AcceptedTransaction::accept(tx, &chain_id, Duration::from_millis(10), tx_limits) + .expect("Failed to accept Transaction.") } pub fn world_with_test_domains() -> World { @@ -494,14 +479,13 @@ pub mod tests { let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); - let state_view = state.view(); let (_time_handle, time_source) = TimeSource::new_mock(Duration::default()); let queue = Queue::test(config_factory(), &time_source); queue - .push(accepted_tx_by_someone(&time_source), &state_view) + .push(accepted_tx_by_someone(&time_source), state.view()) .expect("Failed to push tx into queue"); } @@ -512,7 +496,6 @@ pub mod tests { let kura: Arc = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); - let state_view = state.view(); let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -527,13 +510,13 @@ pub mod tests { for _ in 0..capacity.get() { queue - .push(accepted_tx_by_someone(&time_source), &state_view) + .push(accepted_tx_by_someone(&time_source), state.view()) .expect("Failed to push tx into queue"); time_handle.advance(Duration::from_millis(10)); } assert!(matches!( - queue.push(accepted_tx_by_someone(&time_source), &state_view), + queue.push(accepted_tx_by_someone(&time_source), state.view()), Err(Failure { err: Error::Full, .. @@ -547,7 +530,6 @@ pub mod tests { let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); - let state_view = state.view(); let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -561,12 +543,12 @@ pub mod tests { let queue = Arc::new(queue); for _ in 0..5 { queue - .push(accepted_tx_by_someone(&time_source), &state_view) + .push(accepted_tx_by_someone(&time_source), state.view()) .expect("Failed to push tx into queue"); time_handle.advance(Duration::from_millis(10)); } - let available = queue.collect_transactions_for_block(&state_view, max_txs_in_block); + let available = queue.collect_transactions_for_block(&state.view(), max_txs_in_block); assert_eq!(available.len(), max_txs_in_block.get()); } @@ -582,16 +564,15 @@ pub mod tests { .transactions .insert(tx.as_ref().hash(), nonzero!(1_usize)); state_block.commit(); - let state_view = state.view(); let queue = Queue::test(config_factory(), &time_source); assert!(matches!( - queue.push(tx, &state_view), + queue.push(tx, state.view()), Err(Failure { err: Error::InBlockchain, .. }) )); - assert_eq!(queue.accepted_txs.len(), 0); + assert_eq!(queue.txs.len(), 0); } #[test] @@ -604,7 +585,7 @@ pub mod tests { let tx = accepted_tx_by_someone(&time_source); let queue = Queue::test(config_factory(), &time_source); let queue = Arc::new(queue); - queue.push(tx.clone(), &state.view()).unwrap(); + queue.push(tx.clone(), state.view()).unwrap(); let mut state_block = state.block(); state_block .transactions @@ -616,7 +597,7 @@ pub mod tests { .len(), 0 ); - assert_eq!(queue.accepted_txs.len(), 0); + assert_eq!(queue.txs.len(), 0); } #[test] @@ -625,7 +606,6 @@ pub mod tests { let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); - let state_view = state.view(); let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -639,29 +619,29 @@ pub mod tests { let queue = Arc::new(queue); for _ in 0..(max_txs_in_block.get() - 1) { queue - .push(accepted_tx_by_someone(&time_source), &state_view) + .push(accepted_tx_by_someone(&time_source), state.view()) .expect("Failed to push tx into queue"); time_handle.advance(Duration::from_millis(100)); } queue - .push(accepted_tx_by_someone(&time_source), &state_view) + .push(accepted_tx_by_someone(&time_source), state.view()) .expect("Failed to push tx into queue"); time_handle.advance(Duration::from_millis(101)); assert_eq!( queue - .collect_transactions_for_block(&state_view, max_txs_in_block) + .collect_transactions_for_block(&state.view(), max_txs_in_block) .len(), 1 ); queue - .push(accepted_tx_by_someone(&time_source), &state_view) + .push(accepted_tx_by_someone(&time_source), state.view()) .expect("Failed to push tx into queue"); time_handle.advance(Duration::from_millis(210)); assert_eq!( queue - .collect_transactions_for_block(&state_view, max_txs_in_block) + .collect_transactions_for_block(&state.view(), max_txs_in_block) .len(), 0 ); @@ -678,7 +658,11 @@ pub mod tests { let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); - let state_view = state.view(); + let (max_clock_drift, tx_limits) = { + let state_view = state.world.view(); + let params = state_view.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) + }; let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); let mut queue = Queue::test(config_factory(), &time_source); @@ -691,15 +675,11 @@ pub mod tests { .with_instructions(instructions); tx.set_ttl(Duration::from_millis(TTL_MS)); let tx = tx.sign(alice_keypair.private_key()); - let limits = TransactionParameters { - max_instructions: nonzero!(4096_u64), - smart_contract_size: nonzero!(1024_u64), - }; let tx_hash = tx.hash(); - let tx = AcceptedTransaction::accept(tx, &chain_id, limits) + let tx = AcceptedTransaction::accept(tx, &chain_id, max_clock_drift, tx_limits) .expect("Failed to accept Transaction."); queue - .push(tx.clone(), &state_view) + .push(tx.clone(), state.view()) .expect("Failed to push tx into queue"); let queued_tx_event = event_receiver.recv().await.unwrap(); @@ -716,7 +696,7 @@ pub mod tests { let mut txs = Vec::new(); time_handle.advance(Duration::from_millis(TTL_MS + 1)); let queue = Arc::new(queue); - queue.get_transactions_for_block(&state_view, max_txs_in_block, &mut txs); + queue.get_transactions_for_block(&state.view(), max_txs_in_block, &mut txs); let expired_tx_event = event_receiver.recv().await.unwrap(); assert!(txs.is_empty()); @@ -760,7 +740,7 @@ pub mod tests { thread::spawn(move || { while start_time.elapsed() < run_for { let tx = accepted_tx_by_someone(&time_source); - match queue_arc_clone.push(tx, &state.view()) { + match queue_arc_clone.push(tx, state.view()) { Ok(()) | Err(Failure { err: Error::Full | Error::MaximumTransactionsPerUser, @@ -800,48 +780,12 @@ pub mod tests { // Validate the queue state. let array_queue: Vec<_> = core::iter::from_fn(|| queue.tx_hashes.pop()).collect(); - assert_eq!(array_queue.len(), queue.accepted_txs.len()); + assert_eq!(array_queue.len(), queue.txs.len()); for tx in array_queue { - assert!(queue.accepted_txs.contains_key(&tx)); + assert!(queue.txs.contains_key(&tx)); } } - #[test] - async fn push_tx_in_future() { - let future_threshold = Duration::from_secs(1); - - let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); - let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); - let state_view = state.view(); - - let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); - let queue = Queue::test( - Config { - future_threshold, - ..Config::default() - }, - &time_source, - ); - - let tx = accepted_tx_by_someone(&time_source); - assert!(queue.push(tx.clone(), &state_view).is_ok()); - - // create the same tx but with timestamp in the future - time_handle.advance(future_threshold * 2); - let tx = accepted_tx_by_someone(&time_source); - time_handle.rewind(future_threshold * 2); - - assert!(matches!( - queue.push(tx, &state_view), - Err(Failure { - err: Error::InFuture, - .. - }) - )); - assert_eq!(queue.accepted_txs.len(), 1); - } - #[test] async fn queue_throttling() { let kura = Kura::blank_kura_for_testing(); @@ -864,7 +808,6 @@ pub mod tests { transaction_time_to_live: Duration::from_secs(100), capacity: 100.try_into().unwrap(), capacity_per_user: 1.try_into().unwrap(), - ..Config::default() }, &time_source, ); @@ -874,14 +817,14 @@ pub mod tests { queue .push( accepted_tx_by(alice_id.clone(), &alice_keypair, &time_source), - &state.view(), + state.view(), ) .expect("Failed to push tx into queue"); // Second push by Alice excide limit and will be rejected let result = queue.push( accepted_tx_by(alice_id.clone(), &alice_keypair, &time_source), - &state.view(), + state.view(), ); assert!( matches!( @@ -898,7 +841,7 @@ pub mod tests { queue .push( accepted_tx_by(bob_id.clone(), &bob_keypair, &time_source), - &state.view(), + state.view(), ) .expect("Failed to push tx into queue"); @@ -920,14 +863,14 @@ pub mod tests { queue .push( accepted_tx_by(alice_id, &alice_keypair, &time_source), - &state.view(), + state.view(), ) .expect("Failed to push tx into queue"); queue .push( accepted_tx_by(bob_id, &bob_keypair, &time_source), - &state.view(), + state.view(), ) .expect("Failed to push tx into queue"); } diff --git a/core/src/smartcontracts/isi/mod.rs b/core/src/smartcontracts/isi/mod.rs index e1d92e2a97d..670b30aa8d5 100644 --- a/core/src/smartcontracts/isi/mod.rs +++ b/core/src/smartcontracts/isi/mod.rs @@ -434,14 +434,17 @@ mod tests { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); let kura = Kura::blank_kura_for_testing(); let state = state_with_test_domains(&kura)?; - let state_block = state.block(); + let (max_clock_drift, tx_limits) = { + let state_view = state.world.view(); + let params = state_view.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) + }; let tx = TransactionBuilder::new(chain_id.clone(), SAMPLE_GENESIS_ACCOUNT_ID.clone()) .with_instructions::([]) .sign(SAMPLE_GENESIS_ACCOUNT_KEYPAIR.private_key()); - let tx_limits = state_block.transaction_executor().limits; assert!(matches!( - AcceptedTransaction::accept(tx, &chain_id, tx_limits), + AcceptedTransaction::accept(tx, &chain_id, max_clock_drift, tx_limits), Err(AcceptTransactionFail::UnexpectedGenesisAccountSignature) )); Ok(()) diff --git a/core/src/smartcontracts/isi/query.rs b/core/src/smartcontracts/isi/query.rs index 172e831206a..40de08eae93 100644 --- a/core/src/smartcontracts/isi/query.rs +++ b/core/src/smartcontracts/isi/query.rs @@ -124,8 +124,7 @@ pub fn apply_query_postprocessing( }: &QueryParams, ) -> Result where - I: Iterator, - I::Item: SortableQueryOutput + Send + Sync + 'static, + I: Iterator, QueryOutputBatchBox: From>, { // validate the fetch (aka batch) size @@ -358,10 +357,7 @@ mod tests { use std::str::FromStr as _; use iroha_crypto::{Hash, HashOf, KeyPair}; - use iroha_data_model::{ - parameter::TransactionParameters, - query::{error::FindError, predicate::CompoundPredicate}, - }; + use iroha_data_model::query::{error::FindError, predicate::CompoundPredicate}; use iroha_primitives::json::JsonString; use nonzero_ext::nonzero; use test_samples::{gen_account_in, ALICE_ID, ALICE_KEYPAIR}; @@ -429,30 +425,25 @@ mod tests { let query_handle = LiveQueryStore::test().start(); let state = State::new(world_with_test_domains(), kura.clone(), query_handle); { - let mut state_block = state.block(); - let limits = TransactionParameters { - max_instructions: nonzero!(1000_u64), - smart_contract_size: nonzero!(1024_u64), - }; - let huge_limits = TransactionParameters { - max_instructions: nonzero!(1000_u64), - smart_contract_size: nonzero!(1024_u64), + let (max_clock_drift, tx_limits) = { + let state_view = state.world.view(); + let params = state_view.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) }; - state_block.world.parameters.transaction = limits; - + let mut state_block = state.block(); let valid_tx = { let tx = TransactionBuilder::new(chain_id.clone(), ALICE_ID.clone()) .with_instructions::([]) .sign(ALICE_KEYPAIR.private_key()); - AcceptedTransaction::accept(tx, &chain_id, limits)? + AcceptedTransaction::accept(tx, &chain_id, max_clock_drift, tx_limits)? }; let invalid_tx = { let fail_isi = Unregister::domain("dummy".parse().unwrap()); let tx = TransactionBuilder::new(chain_id.clone(), ALICE_ID.clone()) .with_instructions([fail_isi.clone(), fail_isi]) .sign(ALICE_KEYPAIR.private_key()); - AcceptedTransaction::accept(tx, &chain_id, huge_limits)? + AcceptedTransaction::accept(tx, &chain_id, max_clock_drift, tx_limits)? }; let mut transactions = vec![valid_tx; valid_tx_per_block]; @@ -602,14 +593,18 @@ mod tests { let kura = Kura::blank_kura_for_testing(); let query_handle = LiveQueryStore::test().start(); let state = State::new(world_with_test_domains(), kura.clone(), query_handle); + let (max_clock_drift, tx_limits) = { + let state_view = state.world.view(); + let params = state_view.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) + }; let mut state_block = state.block(); let tx = TransactionBuilder::new(chain_id.clone(), ALICE_ID.clone()) .with_instructions::([]) .sign(ALICE_KEYPAIR.private_key()); - let tx_limits = state_block.transaction_executor().limits; - let va_tx = AcceptedTransaction::accept(tx, &chain_id, tx_limits)?; + let va_tx = AcceptedTransaction::accept(tx, &chain_id, max_clock_drift, tx_limits)?; let (peer_public_key, _) = KeyPair::random().into_parts(); let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), peer_public_key); diff --git a/core/src/smartcontracts/isi/world.rs b/core/src/smartcontracts/isi/world.rs index fffe50369a7..d631e11b0ec 100644 --- a/core/src/smartcontracts/isi/world.rs +++ b/core/src/smartcontracts/isi/world.rs @@ -376,6 +376,7 @@ pub mod isi { } set_parameter!( + Sumeragi(sumeragi.max_clock_drift_ms) => SumeragiParameter::MaxClockDriftMs, Sumeragi(sumeragi.block_time_ms) => SumeragiParameter::BlockTimeMs, Sumeragi(sumeragi.commit_time_ms) => SumeragiParameter::CommitTimeMs, diff --git a/core/src/smartcontracts/wasm.rs b/core/src/smartcontracts/wasm.rs index 269735c2c77..751ae3b19cf 100644 --- a/core/src/smartcontracts/wasm.rs +++ b/core/src/smartcontracts/wasm.rs @@ -815,10 +815,7 @@ where let authority = state.authority(); let state_ro = state.state.state(); - let state_ro = state_ro.borrow(); - - let live_query_store = state_ro.query_handle(); - + let live_query_store = state_ro.borrow().query_handle(); let response = query.execute(live_query_store, state_ro, authority)?; // store the output cursor if there is one diff --git a/core/src/state.rs b/core/src/state.rs index 6e23260c8b8..80a6077e5b8 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -56,7 +56,6 @@ use crate::{ }, wasm, Execute, }, - tx::TransactionExecutor, PeersIds, }; @@ -1200,6 +1199,18 @@ pub trait StateReadOnly { fn query_handle(&self) -> &LiveQueryStoreHandle; fn new_tx_amounts(&self) -> &Mutex>; + /// Get a reference to the block one before the latest block. + /// Returns None if at least 2 blocks are not committed. + /// + /// If you only need hash of the latest block prefer using [`Self::prev_block_hash`]. + #[inline] + fn prev_block(&self) -> Option> { + self.height() + .checked_sub(1) + .and_then(NonZeroUsize::new) + .and_then(|height| self.kura().get_block_by_height(height)) + } + /// Get a reference to the latest block. Returns none if genesis is not committed. /// /// If you only need hash of the latest block prefer using [`Self::latest_block_hash`] @@ -1213,7 +1224,8 @@ pub trait StateReadOnly { self.block_hashes().iter().nth_back(0).copied() } - /// Return the hash of the block one before the latest block + /// Return the hash of the block one before the latest block. + /// Returns None if at least 2 blocks are not committed. fn prev_block_hash(&self) -> Option> { self.block_hashes().iter().nth_back(1).copied() } @@ -1295,11 +1307,6 @@ pub trait StateReadOnly { fn has_transaction(&self, hash: HashOf) -> bool { self.transactions().get(&hash).is_some() } - - /// Get transaction executor - fn transaction_executor(&self) -> TransactionExecutor { - TransactionExecutor::new(self.world().parameters().transaction) - } } macro_rules! impl_state_ro { diff --git a/core/src/sumeragi/main_loop.rs b/core/src/sumeragi/main_loop.rs index 79d4ba866ac..30f77b9809b 100644 --- a/core/src/sumeragi/main_loop.rs +++ b/core/src/sumeragi/main_loop.rs @@ -127,19 +127,21 @@ impl Sumeragi { let mut should_sleep = true; for _ in 0..MAX_CONTROL_MSG_IN_A_ROW { - if let Ok(msg) = self.control_message_receiver + if let Ok(msg) = self + .control_message_receiver .try_recv() .map_err(|recv_error| { assert!( recv_error != mpsc::TryRecvError::Disconnected, - "Sumeragi control message pump disconnected. This is not a recoverable error." + "INTERNAL ERROR: Sumeragi control message pump disconnected" ) - }) { + }) + { should_sleep = false; if let Err(error) = view_change_proof_chain.merge( msg.view_change_proofs, &self.topology, - latest_block + latest_block, ) { trace!(%error, "Failed to add proofs into view change proof chain") } @@ -170,7 +172,7 @@ impl Sumeragi { .map_err(|recv_error| { assert!( recv_error != mpsc::TryRecvError::Disconnected, - "Sumeragi message pump disconnected. This is not a recoverable error." + "INTERNAL ERROR: Sumeragi message pump disconnected" ) }) .ok()?; @@ -1406,14 +1408,19 @@ mod tests { // Creating an instruction let fail_isi = Unregister::domain("dummy".parse().unwrap()); + let (max_clock_drift, tx_limits) = { + let state_view = state.world.view(); + let params = state_view.parameters(); + (params.sumeragi().max_clock_drift(), params.transaction) + }; let mut state_block = state.block(); + // Making two transactions that have the same instruction let tx = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions([fail_isi]) .sign(alice_keypair.private_key()); let tx = - AcceptedTransaction::accept(tx, chain_id, state_block.transaction_executor().limits) - .expect("Valid"); + AcceptedTransaction::accept(tx, chain_id, max_clock_drift, tx_limits).expect("Valid"); // NOTE: imitate peer registration in the genesis block let peers = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) @@ -1426,9 +1433,8 @@ mod tests { .map(InstructionBox::from), ) .sign(alice_keypair.private_key()); - let peers = - AcceptedTransaction::accept(peers, chain_id, state_block.transaction_executor().limits) - .expect("Valid"); + let peers = AcceptedTransaction::accept(peers, chain_id, max_clock_drift, tx_limits) + .expect("Valid"); // Creating a block of two identical transactions and validating it let block = BlockBuilder::new(vec![peers, tx.clone(), tx]) @@ -1457,23 +1463,15 @@ mod tests { let tx1 = TransactionBuilder::new(chain_id.clone(), alice_id.clone()) .with_instructions([create_asset_definition1]) .sign(alice_keypair.private_key()); - let tx1 = AcceptedTransaction::accept( - tx1, - chain_id, - state_block.transaction_executor().limits, - ) - .map(Into::into) - .expect("Valid"); + let tx1 = AcceptedTransaction::accept(tx1, chain_id, max_clock_drift, tx_limits) + .map(Into::into) + .expect("Valid"); let tx2 = TransactionBuilder::new(chain_id.clone(), alice_id) .with_instructions([create_asset_definition2]) .sign(alice_keypair.private_key()); - let tx2 = AcceptedTransaction::accept( - tx2, - chain_id, - state_block.transaction_executor().limits, - ) - .map(Into::into) - .expect("Valid"); + let tx2 = AcceptedTransaction::accept(tx2, chain_id, max_clock_drift, tx_limits) + .map(Into::into) + .expect("Valid"); // Creating a block of two identical transactions and validating it BlockBuilder::new(vec![tx1, tx2]) diff --git a/core/src/tx.rs b/core/src/tx.rs index 1218707ff4b..c3b2c5c1c10 100644 --- a/core/src/tx.rs +++ b/core/src/tx.rs @@ -8,6 +8,8 @@ //! This is also where the actual execution of instructions, as well //! as various forms of validation are performed. +use std::time::{Duration, SystemTime}; + use eyre::Result; use iroha_crypto::SignatureOf; pub use iroha_data_model::prelude::*; @@ -58,9 +60,34 @@ pub enum AcceptTransactionFail { UnexpectedGenesisAccountSignature, /// Chain id doesn't correspond to the id of current blockchain: {0} ChainIdMismatch(Mismatch), + /// Transaction creation time is in the future + TransactionInTheFuture, } impl AcceptedTransaction { + fn validate( + tx: &SignedTransaction, + expected_chain_id: &ChainId, + max_clock_drift: Duration, + ) -> Result<(), AcceptTransactionFail> { + let actual_chain_id = tx.chain(); + + if expected_chain_id != actual_chain_id { + return Err(AcceptTransactionFail::ChainIdMismatch(Mismatch { + expected: expected_chain_id.clone(), + actual: actual_chain_id.clone(), + })); + } + + let now = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap(); + if tx.creation_time().saturating_sub(now) > max_clock_drift { + return Err(AcceptTransactionFail::TransactionInTheFuture); + } + + Ok(()) + } /// Accept genesis transaction. Transition from [`SignedTransaction`] to [`AcceptedTransaction`]. /// /// # Errors @@ -69,16 +96,10 @@ impl AcceptedTransaction { pub fn accept_genesis( tx: SignedTransaction, expected_chain_id: &ChainId, + max_clock_drift: Duration, genesis_account: &AccountId, ) -> Result { - let actual_chain_id = tx.chain(); - - if expected_chain_id != actual_chain_id { - return Err(AcceptTransactionFail::ChainIdMismatch(Mismatch { - expected: expected_chain_id.clone(), - actual: actual_chain_id.clone(), - })); - } + Self::validate(&tx, expected_chain_id, max_clock_drift)?; if genesis_account != tx.authority() { return Err(AcceptTransactionFail::UnexpectedGenesisAccountSignature); @@ -95,16 +116,10 @@ impl AcceptedTransaction { pub fn accept( tx: SignedTransaction, expected_chain_id: &ChainId, + max_clock_drift: Duration, limits: TransactionParameters, ) -> Result { - let actual_chain_id = tx.chain(); - - if expected_chain_id != actual_chain_id { - return Err(AcceptTransactionFail::ChainIdMismatch(Mismatch { - expected: expected_chain_id.clone(), - actual: actual_chain_id.clone(), - })); - } + Self::validate(&tx, expected_chain_id, max_clock_drift)?; if *iroha_genesis::GENESIS_DOMAIN_ID == *tx.authority().domain() { return Err(AcceptTransactionFail::UnexpectedGenesisAccountSignature); @@ -178,23 +193,7 @@ impl AsRef for AcceptedTransaction { } } -/// Used to validate transaction and thus move transaction lifecycle forward -/// -/// Validation is skipped for genesis. -#[derive(Clone, Copy)] -pub struct TransactionExecutor { - /// [`TransactionParameters`] field - pub limits: TransactionParameters, -} - -impl TransactionExecutor { - /// Construct [`TransactionExecutor`] - pub fn new(transaction_limits: TransactionParameters) -> Self { - Self { - limits: transaction_limits, - } - } - +impl StateBlock<'_> { /// Move transaction lifecycle forward by checking if the /// instructions can be applied to the [`StateBlock`]. /// @@ -203,12 +202,11 @@ impl TransactionExecutor { /// # Errors /// Fails if validation of instruction fails (e.g. permissions mismatch). pub fn validate( - &self, + &mut self, tx: AcceptedTransaction, - state_block: &mut StateBlock<'_>, ) -> Result { - let mut state_transaction = state_block.transaction(); - if let Err(rejection_reason) = self.validate_internal(tx.clone(), &mut state_transaction) { + let mut state_transaction = self.transaction(); + if let Err(rejection_reason) = Self::validate_internal(tx.clone(), &mut state_transaction) { return Err((tx.0, rejection_reason)); } state_transaction.apply(); @@ -217,7 +215,6 @@ impl TransactionExecutor { } fn validate_internal( - &self, tx: AcceptedTransaction, state_transaction: &mut StateTransaction<'_, '_>, ) -> Result<(), TransactionRejectionReason> { @@ -233,7 +230,7 @@ impl TransactionExecutor { Self::validate_with_runtime_executor(tx.clone(), state_transaction)?; if let (authority, Executable::Wasm(bytes)) = tx.into() { - self.validate_wasm(authority, state_transaction, bytes)? + Self::validate_wasm(authority, state_transaction, bytes)? } debug!("Validation successful"); @@ -241,7 +238,6 @@ impl TransactionExecutor { } fn validate_wasm( - &self, authority: AccountId, state_transaction: &mut StateTransaction<'_, '_>, wasm: WasmSmartContract, @@ -255,7 +251,11 @@ impl TransactionExecutor { state_transaction, authority, wasm, - self.limits.max_instructions, + state_transaction + .world + .parameters + .transaction + .max_instructions, ) }) .map_err(|error| WasmExecutionFail { diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs index 3f2b2c16c2a..e9c872a1a59 100755 --- a/crypto/src/lib.rs +++ b/crypto/src/lib.rs @@ -1013,21 +1013,19 @@ mod tests { "ed012059C8A4DA1EBB5380F74ABA51F502714652FDCCE9611FAFB9904E4A3C4D382774" .parse() .expect("Public key not in mulithash format"), - PrivateKey::from_hex( - Algorithm::Ed25519, - "93CA389FC2979F3F7D2A7F8B76C70DE6D5EAF5FA58D4F93CB8B0FB298D398ACC", - ) - .expect("Private key not hex encoded"), + "80262093CA389FC2979F3F7D2A7F8B76C70DE6D5EAF5FA58D4F93CB8B0FB298D398ACC" + .parse() + .expect("Private key not in mulithash format"), ) .unwrap(); KeyPair::new("ea01309060D021340617E9554CCBC2CF3CC3DB922A9BA323ABDF7C271FCC6EF69BE7A8DEBCA7D9E96C0F0089ABA22CDAADE4A2" .parse() .expect("Public key not in multihash format"), - PrivateKey::from_hex( - Algorithm::BlsNormal, - "1ca347641228c3b79aa43839dedc85fa51c0e8b9b6a00f6b0d6b0423e902973f", - ).expect("Private key not hex encoded")).unwrap(); + "8926201ca347641228c3b79aa43839dedc85fa51c0e8b9b6a00f6b0d6b0423e902973f" + .parse() + .expect("Private key not in multihash format") + ).unwrap(); } #[test] @@ -1074,21 +1072,19 @@ mod tests { "ed012059C8A4DA1EBB5380F74ABA51F502714652FDCCE9611FAFB9904E4A3C4D382774" .parse() .expect("Public key not in mulithash format"), - PrivateKey::from_hex( - Algorithm::Ed25519, - "3A7991AF1ABB77F3FD27CC148404A6AE4439D095A63591B77C788D53F708A02A", - ) - .expect("Private key not valid"), + "8026203A7991AF1ABB77F3FD27CC148404A6AE4439D095A63591B77C788D53F708A02A" + .parse() + .expect("Public key not in mulithash format"), ) .unwrap_err(); KeyPair::new("ea01309060D021340617E9554CCBC2CF3CC3DB922A9BA323ABDF7C271FCC6EF69BE7A8DEBCA7D9E96C0F0089ABA22CDAADE4A2" .parse() .expect("Public key not in mulithash format"), - PrivateKey::from_hex( - Algorithm::BlsNormal, - "CC176E44C41AA144FD1BEE4E0BCD2EF43F06D0C7BC2988E89A799951D240E503", - ).expect("Private key not valid")).unwrap_err(); + "892620CC176E44C41AA144FD1BEE4E0BCD2EF43F06D0C7BC2988E89A799951D240E503" + .parse() + .expect("Private key not in mulithash format"), + ).unwrap_err(); } #[test] diff --git a/data_model/src/block.rs b/data_model/src/block.rs index 99c1a839f0e..e24faa5c7d0 100644 --- a/data_model/src/block.rs +++ b/data_model/src/block.rs @@ -5,16 +5,15 @@ //! starts from `PendingBlock`. #[cfg(not(feature = "std"))] -use alloc::{boxed::Box, format, string::String, vec, vec::Vec}; +use alloc::{boxed::Box, format, string::String, vec::Vec}; use core::{fmt::Display, time::Duration}; use derive_more::Display; -use iroha_crypto::{HashOf, MerkleTree, PrivateKey, Signature, SignatureOf}; +use iroha_crypto::{HashOf, MerkleTree, SignatureOf}; use iroha_data_model_derive::model; use iroha_macro::FromVariant; use iroha_schema::IntoSchema; use iroha_version::{declare_versioned, version_with_scale}; -use nonzero_ext::nonzero; use parity_scale_codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; @@ -73,18 +72,7 @@ mod model { } #[derive( - Debug, - Display, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, + Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Serialize, IntoSchema, )] #[display(fmt = "({header})")] #[allow(missing_docs)] @@ -157,7 +145,7 @@ impl BlockHeader { /// Calculate block hash #[inline] pub fn hash(&self) -> HashOf { - iroha_crypto::HashOf::new(&self) + iroha_crypto::HashOf::new(self) } } @@ -269,18 +257,26 @@ 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: &PrivateKey, + genesis_private_key: &iroha_crypto::PrivateKey, ) -> SignedBlock { + use std::time::SystemTime; + + use nonzero_ext::nonzero; + let transactions_hash = genesis_transactions .iter() .map(SignedTransaction::hash) .collect::>() .hash() .expect("Tree is not empty"); - let first_transaction = &genesis_transactions[0]; - let creation_time_ms = u64::try_from(first_transaction.creation_time().as_millis()) + let creation_time_ms = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_millis() + .try_into() .expect("INTERNAL BUG: Unix timestamp exceedes u64::MAX"); let header = BlockHeader { height: nonzero!(1_u64), @@ -319,7 +315,7 @@ impl BlockSignature { } /// Signature itself - pub fn payload(&self) -> &Signature { + pub fn payload(&self) -> &SignatureOf { &self.1 } } @@ -335,12 +331,59 @@ mod candidate { payload: BlockPayload, } + #[derive(Decode, Deserialize)] + struct BlockPayloadCandidate { + header: BlockHeader, + transactions: Vec, + } + + impl BlockPayloadCandidate { + fn validate(self) -> Result { + #[cfg(not(target_family = "wasm"))] + { + self.validate_header()?; + } + + Ok(BlockPayload { + header: self.header, + transactions: self.transactions, + }) + } + + #[cfg(not(target_family = "wasm"))] + fn validate_header(&self) -> Result<(), &'static str> { + let actual_txs_hash = self.header.transactions_hash; + + let expected_txs_hash = self + .transactions + .iter() + .map(|value| value.as_ref().hash()) + .collect::>() + .hash() + .ok_or("Block is empty")?; + + if expected_txs_hash != actual_txs_hash { + return Err("Transactions' hash incorrect"); + } + + self.transactions.iter().try_for_each(|tx| { + if tx.value.creation_time() >= self.header.creation_time() { + return Err("Transaction creation time is ahead of block creation time"); + } + + Ok(()) + })?; + + Ok(()) + } + } + impl SignedBlockCandidate { fn validate(self) -> Result { #[cfg(not(target_family = "wasm"))] { self.validate_signatures()?; - self.validate_header()?; + if self.payload.header.height.get() == 1 { self.validate_genesis()?; } @@ -352,6 +395,31 @@ mod candidate { }) } + #[cfg(not(target_family = "wasm"))] + fn validate_signatures(&self) -> Result<(), &'static str> { + #[cfg(not(feature = "std"))] + use alloc::collections::BTreeSet; + #[cfg(feature = "std")] + use std::collections::BTreeSet; + + if self.signatures.is_empty() && self.payload.header.height.get() != 1 { + return Err("Block missing signatures"); + } + + self.signatures + .iter() + .map(|signature| signature.0) + .try_fold(BTreeSet::new(), |mut acc, elem| { + if !acc.insert(elem) { + return Err("Duplicate signature in block"); + } + + Ok(acc) + })?; + + Ok(()) + } + #[cfg(not(target_family = "wasm"))] fn validate_genesis(&self) -> Result<(), &'static str> { use crate::isi::InstructionBox; @@ -388,50 +456,26 @@ mod candidate { Ok(()) } + } - #[cfg(not(target_family = "wasm"))] - fn validate_signatures(&self) -> Result<(), &'static str> { - #[cfg(not(feature = "std"))] - use alloc::collections::BTreeSet; - #[cfg(feature = "std")] - use std::collections::BTreeSet; - - if self.signatures.is_empty() && self.payload.header.height.get() != 1 { - return Err("Block missing signatures"); - } - - self.signatures - .iter() - .map(|signature| signature.0) - .try_fold(BTreeSet::new(), |mut acc, elem| { - if !acc.insert(elem) { - return Err("Duplicate signature in block"); - } - - Ok(acc) - })?; - - Ok(()) + impl Decode for super::BlockPayload { + fn decode(input: &mut I) -> Result { + BlockPayloadCandidate::decode(input)? + .validate() + .map_err(Into::into) } + } - #[cfg(not(target_family = "wasm"))] - fn validate_header(&self) -> Result<(), &'static str> { - let actual_txs_hash = self.payload.header.transactions_hash; - - let expected_txs_hash = self - .payload - .transactions - .iter() - .map(|value| value.as_ref().hash()) - .collect::>() - .hash() - .ok_or("Block is empty")?; - - if expected_txs_hash != actual_txs_hash { - return Err("Transactions' hash incorrect. Expected: {expected_txs_hash:?}, actual: {actual_txs_hash:?}"); - } + impl<'de> Deserialize<'de> for super::BlockPayload { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + use serde::de::Error as _; - Ok(()) + BlockPayloadCandidate::deserialize(deserializer)? + .validate() + .map_err(D::Error::custom) } } @@ -442,6 +486,7 @@ mod candidate { .map_err(Into::into) } } + impl<'de> Deserialize<'de> for SignedBlockV1 { fn deserialize(deserializer: D) -> Result where diff --git a/data_model/src/parameter.rs b/data_model/src/parameter.rs index 546bb4a2455..4bc47bea3c2 100644 --- a/data_model/src/parameter.rs +++ b/data_model/src/parameter.rs @@ -64,7 +64,7 @@ mod model { Serialize, IntoSchema, )] - #[display(fmt = "{block_time_ms},{commit_time_ms}_SL")] + #[display(fmt = "{block_time_ms},{commit_time_ms}{max_clock_drift_ms}_SL")] pub struct SumeragiParameters { /// Maximal amount of time (in milliseconds) a peer will wait before forcing creation of a new block. /// @@ -75,6 +75,12 @@ mod model { /// /// If this period expires the block will request a view change pub commit_time_ms: u64, + /// Maximal allowed random deviation from the nominal rate + /// + /// # Warning + /// + /// This value should be kept as low as possible to not affect soundness of the consensus + pub max_clock_drift_ms: u64, } /// Single Sumeragi parameter @@ -98,6 +104,7 @@ mod model { pub enum SumeragiParameter { BlockTimeMs(u64), CommitTimeMs(u64), + MaxClockDriftMs(u64), } /// Limits that a block must obey to be accepted. @@ -300,6 +307,15 @@ impl core::fmt::Display for Parameter { } impl SumeragiParameters { + /// Maximal allowed random deviation from the nominal rate + /// + /// # Warning + /// + /// This value should be kept as low as possible to not affect soundness of the consensus + pub fn max_clock_drift(&self) -> Duration { + Duration::from_millis(self.max_clock_drift_ms) + } + /// Maximal amount of time (in milliseconds) a peer will wait before forcing creation of a new block. /// /// A block is created if this limit or [`BlockParameters::max_transactions`] limit is reached, @@ -330,12 +346,14 @@ impl SumeragiParameters { impl Default for SumeragiParameters { fn default() -> Self { - pub const DEFAULT_BLOCK_TIME: u64 = 2_000; - pub const DEFAULT_COMMIT_TIME: u64 = 4_000; + pub const DEFAULT_BLOCK_TIME_MS: u64 = 2_000; + pub const DEFAULT_COMMIT_TIME_MS: u64 = 4_000; + pub const DEFAULT_MAX_CLOCK_DRIFT_MS: u64 = 1_000; Self { - block_time_ms: DEFAULT_BLOCK_TIME, - commit_time_ms: DEFAULT_COMMIT_TIME, + block_time_ms: DEFAULT_BLOCK_TIME_MS, + commit_time_ms: DEFAULT_COMMIT_TIME_MS, + max_clock_drift_ms: DEFAULT_MAX_CLOCK_DRIFT_MS, } } } @@ -389,7 +407,7 @@ impl Parameters { impl SumeragiParameters { /// Construct [`Self`] - pub fn new(block_time: Duration, commit_time: Duration) -> Self { + pub fn new(block_time: Duration, commit_time: Duration, max_clock_drift: Duration) -> Self { Self { block_time_ms: block_time .as_millis() @@ -399,6 +417,10 @@ impl SumeragiParameters { .as_millis() .try_into() .expect("INTERNAL BUG: Time should fit into u64"), + max_clock_drift_ms: max_clock_drift + .as_millis() + .try_into() + .expect("INTERNAL BUG: Time should fit into u64"), } } @@ -407,6 +429,7 @@ impl SumeragiParameters { [ SumeragiParameter::BlockTimeMs(self.block_time_ms), SumeragiParameter::CommitTimeMs(self.commit_time_ms), + SumeragiParameter::MaxClockDriftMs(self.max_clock_drift_ms), ] .into_iter() } diff --git a/data_model/src/transaction.rs b/data_model/src/transaction.rs index ab1a2505a6a..e268e46c13c 100644 --- a/data_model/src/transaction.rs +++ b/data_model/src/transaction.rs @@ -660,7 +660,7 @@ mod http { // can't delegate to `new_with_time_source`, because it's gated behind "transparent_api" let creation_time_ms = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) - .expect("Failed to get the current system time") + .unwrap() .as_millis() .try_into() .expect("INTERNAL BUG: Unix timestamp exceedes u64::MAX"); diff --git a/defaults/executor.wasm b/defaults/executor.wasm new file mode 100644 index 0000000000000000000000000000000000000000..086cf28ac215a8c7951f225618deff4c330d5ec1 GIT binary patch literal 400985 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∓-wMR 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

bJQHB+3jDN$Cr?7&P+=+S*|i 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

*&;;;I)Ty+QNT=Gbz0lsCn!VGU{ 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 YI8Ze?4pW<|OdI%2GT2A=T0<$uU#p87>;M1& literal 0 HcmV?d00001 diff --git a/defaults/genesis.json b/defaults/genesis.json index feb8c89b0eb..c96cd79dc16 100644 --- a/defaults/genesis.json +++ b/defaults/genesis.json @@ -12,6 +12,11 @@ "CommitTimeMs": 4000 } }, + { + "Sumeragi": { + "MaxClockDriftMs": 1000 + } + }, { "Block": { "MaxTransactions": 512 diff --git a/docs/source/references/peer.template.toml b/docs/source/references/peer.template.toml index 70006d228e4..af87ad35638 100644 --- a/docs/source/references/peer.template.toml +++ b/docs/source/references/peer.template.toml @@ -50,7 +50,6 @@ # capacity = 65536 # capacity_per_user = 65536 # transaction_time_to_live_ms = 86_400_000 # 1 day -# future_threshold_ms = 1_000 [snapshot] # mode = "read_write" diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index 2335b2e4930..19ba62a4cf1 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -4258,6 +4258,11 @@ "tag": "CommitTimeMs", "discriminant": 1, "type": "u64" + }, + { + "tag": "MaxClockDriftMs", + "discriminant": 2, + "type": "u64" } ] }, @@ -4270,6 +4275,10 @@ { "name": "commit_time_ms", "type": "u64" + }, + { + "name": "max_clock_drift_ms", + "type": "u64" } ] }, diff --git a/genesis/src/lib.rs b/genesis/src/lib.rs index 6f37b655ff2..326db3050d3 100644 --- a/genesis/src/lib.rs +++ b/genesis/src/lib.rs @@ -259,10 +259,10 @@ impl GenesisBuilder { /// Finish building, sign, and produce a [`GenesisBlock`]. pub fn build_and_sign( self, - executor_blob: Executor, chain_id: ChainId, - genesis_key_pair: &KeyPair, + executor_blob: Executor, topology: Vec, + genesis_key_pair: &KeyPair, ) -> GenesisBlock { build_and_sign_genesis( self.instructions, @@ -361,7 +361,7 @@ mod tests { .domain("wonderland".parse()?) .account(alice_public_key) .finish_domain() - .build_and_sign(dummy_executor(), chain_id, &genesis_key_pair, vec![]); + .build_and_sign(chain_id, dummy_executor(), vec![], &genesis_key_pair); Ok(()) } @@ -396,10 +396,10 @@ mod tests { // In real cases executor should be constructed from a wasm blob let finished_genesis = genesis_builder.build_and_sign( - dummy_executor(), ChainId::from("00000000-0000-0000-0000-000000000000"), - &KeyPair::random(), + dummy_executor(), vec![], + &KeyPair::random(), ); let transactions = &finished_genesis.0.transactions().collect::>(); diff --git a/primitives/src/time.rs b/primitives/src/time.rs index 2e6ccc84075..f6c34185943 100644 --- a/primitives/src/time.rs +++ b/primitives/src/time.rs @@ -51,7 +51,7 @@ impl TimeSource { match &self.0 { TimeSourceInner::SystemTime => SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) - .expect("Failed to get the current system time"), + .unwrap(), TimeSourceInner::MockTime(time) => *time.lock(), } } diff --git a/telemetry/derive/src/lib.rs b/telemetry/derive/src/lib.rs index ae41e9f6e5c..15c434f4598 100644 --- a/telemetry/derive/src/lib.rs +++ b/telemetry/derive/src/lib.rs @@ -242,15 +242,10 @@ fn impl_metrics(emitter: &mut Emitter, _specs: &MetricSpecs, func: &syn::ItemFn) quote!( #(#attrs)* #vis #sig { let _closure = || #block; - let start_time = std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .expect("Failed to get the current system time"); + let started_at = std::time::Instant::now(); #totals let res = _closure(); - let end_time = std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .expect("Failed to get the current system time"); #times if let Ok(_) = res { @@ -288,7 +283,7 @@ fn write_metrics( .metrics .isi_times .with_label_values( &[#spec]) - .observe((end_time.as_millis() - start_time.as_millis()) as f64); + .observe(started_at.elapsed().as_millis() as f64); ) }; let totals: TokenStream = specs diff --git a/torii/src/routing.rs b/torii/src/routing.rs index bd296074b8b..5881f4c2a2f 100644 --- a/torii/src/routing.rs +++ b/torii/src/routing.rs @@ -29,14 +29,19 @@ pub async fn handle_transaction( chain_id: Arc, queue: Arc, state: Arc, - transaction: SignedTransaction, + tx: SignedTransaction, ) -> Result<()> { - let state_view = state.view(); - let transaction_limits = state_view.world().parameters().transaction; - let transaction = AcceptedTransaction::accept(transaction, &chain_id, transaction_limits) + let (max_clock_drift, tx_limits) = { + let state_view = state.world.view(); + let params = state_view.parameters(); + (params.sumeragi.max_clock_drift(), params.transaction) + }; + + let accepted_tx = AcceptedTransaction::accept(tx, &chain_id, max_clock_drift, tx_limits) .map_err(Error::AcceptTransaction)?; + queue - .push(transaction, &state_view) + .push(accepted_tx, state.view()) .map_err(|queue::Failure { tx, err }| { iroha_logger::warn!( tx_hash=%tx.as_ref().hash(), ?err,