From dcdfb169ace5b41d71374a4f9f513a6a5f842fcb Mon Sep 17 00:00:00 2001 From: Fraser Hutchison Date: Tue, 21 Jul 2020 22:40:28 +0100 Subject: [PATCH 1/3] NDRS-157: get block limits from the chainspec --- Cargo.lock | 4 +- Makefile | 17 +- node/Cargo.toml | 3 + node/src/components/chainspec_handler.rs | 1 + .../components/chainspec_handler/chainspec.rs | 38 ++- .../components/chainspec_handler/config.rs | 31 +- node/src/components/consensus.rs | 6 +- node/src/components/deploy_buffer.rs | 278 ++++++++++-------- node/src/components/storage.rs | 10 +- node/src/effect.rs | 28 +- node/src/effect/announcements.rs | 11 +- node/src/effect/requests.rs | 50 +--- node/src/reactor/validator.rs | 42 +-- resources/local/chainspec.toml | 4 + resources/production/chainspec.toml | 4 + resources/test/valid/chainspec.toml | 6 +- 16 files changed, 296 insertions(+), 237 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc95c3ba38..03f026b48f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4409,9 +4409,9 @@ checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" [[package]] name = "tracing" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e2a2de6b0d5cbb13fc21193a2296888eaab62b6044479aafb3c54c01c29fcd" +checksum = "dbdf4ccd1652592b01286a5dbe1e2a77d78afaa34beadd9872a5f7396f92aaa9" dependencies = [ "cfg-if", "log 0.4.11", diff --git a/Makefile b/Makefile index d5ea8cca53..a529cae4e6 100644 --- a/Makefile +++ b/Makefile @@ -57,16 +57,10 @@ TOOL_TARGET_DIR = grpc/cargo-casperlabs/target TOOL_WASM_DIR = grpc/cargo-casperlabs/wasm CRATES_WITH_DOCS_RS_MANIFEST_TABLE = \ - contract \ - engine-core \ - engine-grpc-server \ - engine-shared \ - engine-storage \ - engine-test-support \ - engine-wasm-prep \ - mint \ - proof-of-stake \ - standard-payment \ + grpc/server \ + grpc/test_support \ + node \ + smart_contracts/contract \ types CRATES_WITH_DOCS_RS_MANIFEST_TABLE := $(patsubst %, doc-stable/%, $(CRATES_WITH_DOCS_RS_MANIFEST_TABLE)) @@ -87,7 +81,7 @@ build-contract-rs/%: build-system-contract-featured-rs/%: $(CARGO) build \ --release $(filter-out --release, $(CARGO_FLAGS)) \ - --manifest-path "contracts/system/$*/Cargo.toml" $(if $(FEATURES),$(if $(filter $(HIGHWAY_CONTRACTS), $*),--features $(FEATURES))) \ + --manifest-path "smart_contracts/contracts/system/$*/Cargo.toml" $(if $(FEATURES),$(if $(filter $(HIGHWAY_CONTRACTS), $*),--features $(FEATURES))) \ --target wasm32-unknown-unknown build-contracts-rs: \ @@ -191,6 +185,7 @@ check-rs: \ .PHONY: check check: \ + build-docs-stable-rs \ build \ check-format \ lint \ diff --git a/node/Cargo.toml b/node/Cargo.toml index a9e2429e87..ae7fb6afc0 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -114,3 +114,6 @@ assets = [ ["./target/release/casperlabs-node","/usr/bin/casperlabs-node", "755"], ["./target/release/casperlabs-client","/usr/bin/casperlabs-client", "755"] ] + +[package.metadata.docs.rs] +features = ["no-unstable-features"] diff --git a/node/src/components/chainspec_handler.rs b/node/src/components/chainspec_handler.rs index 9a6869cb32..6aa3310109 100644 --- a/node/src/components/chainspec_handler.rs +++ b/node/src/components/chainspec_handler.rs @@ -23,6 +23,7 @@ use crate::{ EffectBuilder, EffectExt, Effects, }, }; +pub(crate) use chainspec::DeployConfig; // False positive. #[allow(unreachable_pub)] pub use chainspec::{Chainspec, GenesisAccount}; diff --git a/node/src/components/chainspec_handler/chainspec.rs b/node/src/components/chainspec_handler/chainspec.rs index 271d1634d4..0b25665fb1 100644 --- a/node/src/components/chainspec_handler/chainspec.rs +++ b/node/src/components/chainspec_handler/chainspec.rs @@ -10,6 +10,7 @@ use std::{ time::Duration, }; +use num_traits::Zero; use rand::{ distributions::{Distribution, Standard}, Rng, @@ -101,6 +102,21 @@ pub(crate) struct DeployConfig { pub(crate) max_ttl: Duration, pub(crate) max_dependencies: u8, pub(crate) max_block_size: u32, + pub(crate) block_gas_limit: u64, + pub(crate) block_max_deploy_count: u32, +} + +impl Default for DeployConfig { + fn default() -> Self { + DeployConfig { + max_payment_cost: Motes::zero(), + max_ttl: Duration::from_millis(86_400_000), // 1 day + max_dependencies: 10, + max_block_size: 10_485_760, + block_gas_limit: 10_000_000_000_000, + block_max_deploy_count: 3, + } + } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -115,6 +131,19 @@ pub(crate) struct HighwayConfig { pub(crate) finality_threshold_percent: u8, } +impl Default for HighwayConfig { + fn default() -> Self { + HighwayConfig { + genesis_era_start_timestamp: 1_583_712_000_000, + era_duration: Duration::from_millis(604_800_000), // 1 week + booking_duration: Duration::from_millis(864_000_000), // 10 days + entropy_duration: Duration::from_millis(10_800_000), // 3 hours + voting_period_duration: Duration::from_millis(172_800_000), // 2 days + finality_threshold_percent: 10, + } + } +} + #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] // Disallow unknown fields to ensure config files and command-line overrides contain valid keys. #[serde(deny_unknown_fields)] @@ -311,6 +340,8 @@ mod tests { ); assert_eq!(spec.genesis.deploy_config.max_dependencies, 11); assert_eq!(spec.genesis.deploy_config.max_block_size, 12); + assert_eq!(spec.genesis.deploy_config.block_gas_limit, 13); + assert_eq!(spec.genesis.deploy_config.block_max_deploy_count, 14); assert_eq!(spec.genesis.costs.regular, 13); assert_eq!(spec.genesis.costs.div, 14); @@ -353,9 +384,14 @@ mod tests { ); assert_eq!(upgrade0.new_deploy_config.unwrap().max_dependencies, 36); assert_eq!(upgrade0.new_deploy_config.unwrap().max_block_size, 37); + assert_eq!(upgrade0.new_deploy_config.unwrap().block_gas_limit, 38); + assert_eq!( + upgrade0.new_deploy_config.unwrap().block_max_deploy_count, + 39 + ); let upgrade1 = &spec.upgrades[1]; - assert_eq!(upgrade1.activation_point, ActivationPoint { rank: 38 }); + assert_eq!(upgrade1.activation_point, ActivationPoint { rank: 40 }); assert_eq!(upgrade1.protocol_version, Version::from((0, 3, 0))); assert!(upgrade1.upgrade_installer_bytes.is_none()); assert!(upgrade1.upgrade_installer_args.is_none()); diff --git a/node/src/components/chainspec_handler/config.rs b/node/src/components/chainspec_handler/config.rs index ad6746202b..fafeb3ce70 100644 --- a/node/src/components/chainspec_handler/config.rs +++ b/node/src/components/chainspec_handler/config.rs @@ -41,16 +41,13 @@ struct DeployConfig { max_ttl_millis: u64, max_dependencies: u8, max_block_size: u32, + block_gas_limit: u64, + block_max_deploy_count: u32, } impl Default for DeployConfig { fn default() -> Self { - DeployConfig { - max_payment_cost: String::from("0"), - max_ttl_millis: 86_400_000, // 1 day - max_dependencies: 10, - max_block_size: 10_485_760, - } + chainspec::DeployConfig::default().into() } } @@ -61,6 +58,8 @@ impl From for DeployConfig { max_ttl_millis: cfg.max_ttl.as_millis() as u64, max_dependencies: cfg.max_dependencies, max_block_size: cfg.max_block_size, + block_gas_limit: cfg.block_gas_limit, + block_max_deploy_count: cfg.block_max_deploy_count, } } } @@ -75,6 +74,8 @@ impl TryFrom for chainspec::DeployConfig { max_ttl: Duration::from_millis(cfg.max_ttl_millis), max_dependencies: cfg.max_dependencies, max_block_size: cfg.max_block_size, + block_gas_limit: cfg.block_gas_limit, + block_max_deploy_count: cfg.block_max_deploy_count, }) } } @@ -118,13 +119,19 @@ struct HighwayConfig { impl Default for HighwayConfig { fn default() -> Self { + chainspec::HighwayConfig::default().into() + } +} + +impl From for HighwayConfig { + fn from(cfg: chainspec::HighwayConfig) -> Self { HighwayConfig { - genesis_era_start_timestamp: 1_583_712_000_000, - era_duration_millis: 604_800_000, // 1 week - booking_duration_millis: 864_000_000, // 10 days - entropy_duration_millis: 10_800_000, // 3 hours - voting_period_duration_millis: 172_800_000, // 2 days - finality_threshold_percent: 10, + genesis_era_start_timestamp: cfg.genesis_era_start_timestamp, + era_duration_millis: cfg.era_duration.as_millis() as u64, + booking_duration_millis: cfg.booking_duration.as_millis() as u64, + entropy_duration_millis: cfg.entropy_duration.as_millis() as u64, + voting_period_duration_millis: cfg.voting_period_duration.as_millis() as u64, + finality_threshold_percent: cfg.finality_threshold_percent, } } } diff --git a/node/src/components/consensus.rs b/node/src/components/consensus.rs index 9d204458e8..1c4549f1d4 100644 --- a/node/src/components/consensus.rs +++ b/node/src/components/consensus.rs @@ -20,7 +20,7 @@ use crate::{ components::Component, effect::{ announcements::ConsensusAnnouncement, - requests::{BlockExecutorRequest, DeployQueueRequest, NetworkRequest}, + requests::{BlockExecutorRequest, DeployBufferRequest, NetworkRequest}, EffectBuilder, EffectExt, Effects, }, types::{ExecutedBlock, ProtoBlock, Timestamp}, @@ -127,7 +127,7 @@ pub trait ReactorEventT: From> + Send + From> - + From + + From + From + From { @@ -137,7 +137,7 @@ impl ReactorEventT for REv where REv: From> + Send + From> - + From + + From + From + From { diff --git a/node/src/components/deploy_buffer.rs b/node/src/components/deploy_buffer.rs index ab27503d1c..843fda7af9 100644 --- a/node/src/components/deploy_buffer.rs +++ b/node/src/components/deploy_buffer.rs @@ -9,14 +9,71 @@ use std::{ }; use derive_more::From; -use tracing::error; +use semver::Version; +use tracing::{error, info}; use crate::{ - components::Component, - effect::{requests::DeployQueueRequest, EffectBuilder, EffectExt, Effects}, + components::{ + chainspec_handler::DeployConfig, + storage::{self, Storage}, + Component, + }, + effect::{ + requests::{DeployBufferRequest, StorageRequest}, + EffectBuilder, EffectExt, Effects, Responder, + }, types::{BlockHash, DeployHash, DeployHeader, ProtoBlock}, + Chainspec, }; +/// An event for when using the deploy buffer as a component. +#[derive(Debug, From)] +pub enum Event { + #[from] + Request(DeployBufferRequest), + /// A new deploy should be buffered. + Buffer { + hash: DeployHash, + header: Box, + }, + /// A proto block has been proposed. We should not propose duplicates of its deploys. + ProposedProtoBlock(ProtoBlock), + /// A proto block has been finalized. We should never propose its deploys again. + FinalizedProtoBlock(ProtoBlock), + /// A proto block has been orphaned. Its deploys should be re-proposed. + OrphanedProtoBlock(ProtoBlock), + /// The result of the `DeployBuffer` getting the chainspec from the storage component. + GetChainspecResult { + result: Box>, + current_instant: u64, + past_blocks: HashSet, + responder: Responder>, + }, +} + +impl Display for Event { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + Event::Request(req) => write!(f, "deploy-buffer request: {}", req), + Event::Buffer { hash, .. } => write!(f, "deploy-buffer add {}", hash), + Event::ProposedProtoBlock(block) => { + write!(f, "deploy-buffer proposed proto block {}", block) + } + Event::FinalizedProtoBlock(block) => { + write!(f, "deploy-buffer finalized proto block {}", block) + } + Event::OrphanedProtoBlock(block) => { + write!(f, "deploy-buffer orphaned proto block {}", block) + } + Event::GetChainspecResult { result, .. } => write!( + f, + "deploy-buffer get chainspec - succeeded: {}", + result.is_ok() + ), + } + } +} + /// Deploy buffer. #[derive(Debug, Clone, Default)] pub(crate) struct DeployBuffer { @@ -25,19 +82,6 @@ pub(crate) struct DeployBuffer { finalized: HashMap>, } -/// Limits for how many deploys to include in a block. -#[derive(Debug, Clone)] -pub struct BlockLimits { - /// Maximum block size in bytes. - /// - /// The total size of the deploys must not exceed this. - pub size_bytes: u64, - /// Gas limit for sum of deploys. - pub gas: u64, - // The maximum number of deploys. - pub deploy_count: u32, -} - impl DeployBuffer { /// Creates a new, empty deploy buffer instance. pub(crate) fn new() -> Self { @@ -47,50 +91,66 @@ impl DeployBuffer { /// Adds a deploy to the deploy buffer. /// /// Returns `false` if the deploy has been rejected. - pub(crate) fn add_deploy(&mut self, hash: DeployHash, deploy: DeployHeader) -> bool { + fn add_deploy(&mut self, hash: DeployHash, header: DeployHeader) { // only add the deploy if it isn't contained in a finalized block if !self .finalized .values() .any(|block| block.contains_key(&hash)) { - self.collected_deploys.insert(hash, deploy); - true + self.collected_deploys.insert(hash, header); + info!("added deploy {} to the buffer", hash); } else { - false + info!("deploy {} rejected from the buffer", hash); } } + /// Gets the chainspec from storage in order to call `remaining_deploys()`. + fn get_chainspec_from_storage( + &mut self, + effect_builder: EffectBuilder, + current_instant: u64, + past_blocks: HashSet, + responder: Responder>, + ) -> Effects + where + REv: From> + Send, + { + // TODO - should the current protocol version be passed in here? + let version = Version::from((1, 0, 0)); + effect_builder + .get_chainspec(version) + .event(move |result| Event::GetChainspecResult { + result: Box::new(result), + current_instant, + past_blocks, + responder, + }) + } + /// Returns a list of candidates for inclusion into a block. - pub(crate) fn remaining_deploys( + fn remaining_deploys( &mut self, + deploy_config: DeployConfig, current_instant: u64, - max_ttl: u32, - limits: BlockLimits, - max_dependencies: u8, - past: &HashSet, + past_blocks: HashSet, ) -> HashSet { - let past_deploys = past + let past_deploys = past_blocks .iter() .filter_map(|block_hash| self.processed.get(block_hash)) .chain(self.finalized.values()) .flat_map(|deploys| deploys.keys()) .collect::>(); // deploys_to_return = all deploys in collected_deploys that aren't in finalized blocks or - // processed blocks from the set `past` + // processed blocks from the set `past_blocks` self.collected_deploys .iter() .filter(|&(hash, deploy)| { - self.is_deploy_valid( - deploy, - current_instant, - max_ttl, - max_dependencies, - &past_deploys, - ) && !past_deploys.contains(hash) + self.is_deploy_valid(deploy, current_instant, &deploy_config, &past_deploys) + && !past_deploys.contains(hash) }) .map(|(hash, _deploy)| *hash) - .take(limits.deploy_count as usize) + .take(deploy_config.block_max_deploy_count as usize) .collect::>() // TODO: check gas and block size limits } @@ -100,8 +160,7 @@ impl DeployBuffer { &self, deploy: &DeployHeader, current_instant: u64, - max_ttl: u32, - max_dependencies: u8, + deploy_config: &DeployConfig, past_deploys: &HashSet<&DeployHash>, ) -> bool { let all_deps_resolved = || { @@ -110,16 +169,16 @@ impl DeployBuffer { .iter() .all(|dep| past_deploys.contains(dep)) }; - let ttl_valid = deploy.ttl_millis <= max_ttl; + let ttl_valid = deploy.ttl_millis as u128 <= deploy_config.max_ttl.as_millis(); let timestamp_valid = deploy.timestamp <= current_instant; let deploy_valid = deploy.timestamp + deploy.ttl_millis as u64 >= current_instant; - let num_deps_valid = deploy.dependencies.len() <= max_dependencies as usize; + let num_deps_valid = deploy.dependencies.len() <= deploy_config.max_dependencies as usize; ttl_valid && timestamp_valid && deploy_valid && num_deps_valid && all_deps_resolved() } /// Notifies the deploy buffer of a new block that has been proposed, so that the block's /// deploys are not returned again by `remaining_deploys`. - pub(crate) fn added_block(&mut self, block: BlockHash, deploys: I) + fn added_block(&mut self, block: BlockHash, deploys: I) where I: IntoIterator, { @@ -139,7 +198,7 @@ impl DeployBuffer { } /// Notifies the deploy buffer that a block has been finalized. - pub(crate) fn finalized_block(&mut self, block: BlockHash) { + fn finalized_block(&mut self, block: BlockHash) { if let Some(deploys) = self.processed.remove(&block) { self.collected_deploys .retain(|deploy_hash, _| !deploys.contains_key(deploy_hash)); @@ -151,7 +210,7 @@ impl DeployBuffer { } /// Notifies the deploy buffer that a block has been orphaned. - pub(crate) fn orphaned_block(&mut self, block: BlockHash) { + fn orphaned_block(&mut self, block: BlockHash) { if let Some(deploys) = self.processed.remove(&block) { self.collected_deploys.extend(deploys); } else { @@ -161,65 +220,49 @@ impl DeployBuffer { } } -/// An event for when using the deploy buffer as a component. -#[derive(Debug, From)] -pub enum Event { - #[from] - QueueRequest(DeployQueueRequest), - /// A proto block has been proposed. We should not propose duplicates of its deploys. - ProposedProtoBlock(ProtoBlock), - /// A proto block has been finalized. We should never propose its deploys again. - FinalizedProtoBlock(ProtoBlock), - /// A proto block has been orphaned. Its deploys should be re-proposed. - OrphanedProtoBlock(ProtoBlock), -} - -impl Display for Event { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - Event::QueueRequest(req) => write!(f, "dq request: {}", req), - Event::ProposedProtoBlock(block) => write!(f, "dq proposed proto block {}", block), - Event::FinalizedProtoBlock(block) => write!(f, "dq finalized proto block {}", block), - Event::OrphanedProtoBlock(block) => write!(f, "dq orphaned proto block {}", block), - } - } -} - -impl Component for DeployBuffer { +impl Component for DeployBuffer +where + REv: From> + Send, +{ type Event = Event; fn handle_event( &mut self, - _effect_builder: EffectBuilder, + effect_builder: EffectBuilder, _rng: &mut R, event: Self::Event, ) -> Effects { match event { - Event::QueueRequest(DeployQueueRequest::QueueDeploy { - hash, - header, - responder, - }) => return responder.respond(self.add_deploy(hash, header)).ignore(), - Event::QueueRequest(DeployQueueRequest::RequestForInclusion { + Event::Request(DeployBufferRequest::ListForInclusion { current_instant, - max_ttl, - limits, - max_dependencies, - past, + past_blocks, responder, }) => { - let deploys = self.remaining_deploys( + return self.get_chainspec_from_storage( + effect_builder, current_instant, - max_ttl, - limits, - max_dependencies, - &past, + past_blocks, + responder, ); - return responder.respond(deploys).ignore(); } + Event::Buffer { hash, header } => self.add_deploy(hash, *header), Event::ProposedProtoBlock(block) => self.added_block(block.hash(), block.deploys), Event::FinalizedProtoBlock(block) => self.finalized_block(block.hash()), Event::OrphanedProtoBlock(block) => self.orphaned_block(block.hash()), + Event::GetChainspecResult { + result, + current_instant, + past_blocks, + responder, + } => { + let chainspec = result.expect("should return chainspec"); + let deploys = self.remaining_deploys( + chainspec.genesis.deploy_config, + current_instant, + past_blocks, + ); + return responder.respond(deploys).ignore(); + } } Effects::new() } @@ -231,7 +274,7 @@ mod tests { use rand::random; - use super::{BlockLimits, DeployBuffer}; + use super::*; use crate::{ crypto::{asymmetric_key::PublicKey, hash::hash}, types::{BlockHash, DeployHash, DeployHeader}, @@ -251,23 +294,6 @@ mod tests { (deploy_hash, deploy) } - fn remaining_deploys( - buffer: &mut DeployBuffer, - time: u64, - blocks: &HashSet, - ) -> HashSet { - let max_ttl = 200u32; - // TODO: - let limits = BlockLimits { - size_bytes: 0u64, - gas: 0u64, - deploy_count: 3u32, - }; - let max_dependencies = 1u8; - - buffer.remaining_deploys(time, max_ttl, limits, max_dependencies, blocks) - } - #[test] fn add_and_take_deploys() { let creation_time = 100u64; @@ -283,7 +309,9 @@ mod tests { let (hash3, deploy3) = generate_deploy(creation_time, ttl); let (hash4, deploy4) = generate_deploy(creation_time, ttl); - assert!(remaining_deploys(&mut buffer, block_time2, &no_blocks).is_empty()); + assert!(buffer + .remaining_deploys(DeployConfig::default(), block_time2, no_blocks.clone()) + .is_empty()); // add two deploys buffer.add_deploy(hash1, deploy1); @@ -291,41 +319,59 @@ mod tests { // if we try to create a block with a timestamp that is too early, we shouldn't get any // deploys - assert!(remaining_deploys(&mut buffer, block_time1, &no_blocks).is_empty()); + assert!(buffer + .remaining_deploys(DeployConfig::default(), block_time1, no_blocks.clone()) + .is_empty()); // if we try to create a block with a timestamp that is too late, we shouldn't get any // deploys, either - assert!(remaining_deploys(&mut buffer, block_time3, &no_blocks).is_empty()); + assert!(buffer + .remaining_deploys(DeployConfig::default(), block_time3, no_blocks.clone()) + .is_empty()); // take the deploys out - let deploys = remaining_deploys(&mut buffer, block_time2, &no_blocks); + let deploys = + buffer.remaining_deploys(DeployConfig::default(), block_time2, no_blocks.clone()); assert_eq!(deploys.len(), 2); assert!(deploys.contains(&hash1)); assert!(deploys.contains(&hash2)); // the deploys should not have been removed yet - assert!(!remaining_deploys(&mut buffer, block_time2, &no_blocks).is_empty()); + assert!(!buffer + .remaining_deploys(DeployConfig::default(), block_time2, no_blocks.clone()) + .is_empty()); // the two deploys will be included in block 1 let block_hash1 = BlockHash::new(hash(random::<[u8; 16]>())); buffer.added_block(block_hash1, deploys); // the deploys should have been removed now - assert!(remaining_deploys(&mut buffer, block_time2, &no_blocks).is_empty()); + assert!(buffer + .remaining_deploys(DeployConfig::default(), block_time2, no_blocks.clone()) + .is_empty()); let mut blocks = HashSet::new(); blocks.insert(block_hash1); - assert!(remaining_deploys(&mut buffer, block_time2, &blocks).is_empty()); + assert!(buffer + .remaining_deploys(DeployConfig::default(), block_time2, blocks.clone()) + .is_empty()); // try adding the same deploy again buffer.add_deploy(hash2, deploy2.clone()); // it shouldn't be returned if we include block 1 in the past blocks - assert!(remaining_deploys(&mut buffer, block_time2, &blocks).is_empty()); + assert!(buffer + .remaining_deploys(DeployConfig::default(), block_time2, blocks) + .is_empty()); // ...but it should be returned if we don't include it - assert!(remaining_deploys(&mut buffer, block_time2, &no_blocks).len() == 1); + assert!( + buffer + .remaining_deploys(DeployConfig::default(), block_time2, no_blocks.clone()) + .len() + == 1 + ); // the previous check removed the deploy from the buffer, let's re-add it buffer.add_deploy(hash2, deploy2); @@ -337,7 +383,7 @@ mod tests { buffer.add_deploy(hash3, deploy3); buffer.add_deploy(hash4, deploy4); - let deploys = remaining_deploys(&mut buffer, block_time2, &no_blocks); + let deploys = buffer.remaining_deploys(DeployConfig::default(), block_time2, no_blocks); // since block 1 is now finalized, deploy2 shouldn't be among the ones returned assert_eq!(deploys.len(), 2); @@ -363,12 +409,14 @@ mod tests { buffer.add_deploy(hash2, deploy2); // deploy2 has an unsatisfied dependency - assert!(remaining_deploys(&mut buffer, block_time, &blocks).is_empty()); + assert!(buffer + .remaining_deploys(DeployConfig::default(), block_time, blocks.clone()) + .is_empty()); // add deploy1 buffer.add_deploy(hash1, deploy1); - let deploys = remaining_deploys(&mut buffer, block_time, &blocks); + let deploys = buffer.remaining_deploys(DeployConfig::default(), block_time, blocks.clone()); // only deploy1 should be returned, as it has no dependencies assert_eq!(deploys.len(), 1); assert!(deploys.contains(&hash1)); @@ -378,7 +426,7 @@ mod tests { buffer.added_block(block_hash1, deploys); blocks.insert(block_hash1); - let deploys2 = remaining_deploys(&mut buffer, block_time, &blocks); + let deploys2 = buffer.remaining_deploys(DeployConfig::default(), block_time, blocks); // `blocks` contains a block that contains deploy1 now, so we should get deploy2 assert_eq!(deploys2.len(), 1); assert!(deploys2.contains(&hash2)); diff --git a/node/src/components/storage.rs b/node/src/components/storage.rs index a45753fee4..098fca08ca 100644 --- a/node/src/components/storage.rs +++ b/node/src/components/storage.rs @@ -166,20 +166,20 @@ where let deploy_store = self.deploy_store(); async move { // Create the effect, but do not return it. - let announce_success = effect_builder.announce_deploy_stored(&deploy); + let announce_new_deploy = effect_builder.announce_deploy_stored(&deploy); let result = task::spawn_blocking(move || deploy_store.put(*deploy)) .await .expect("should run"); - let was_ok = result.is_ok(); + let stored_new_deploy = *result.as_ref().unwrap_or_else(|_| &false); - // Tell the requestor the result of storing the deploy. + // Tell the requester the result of storing the deploy. responder.respond(result).await; - if was_ok { + if stored_new_deploy { // Now that we have stored the deploy, we also want to announce it. - announce_success.await; + announce_new_deploy.await; } } .ignore() diff --git a/node/src/effect.rs b/node/src/effect.rs index 459c020079..6973859b8e 100644 --- a/node/src/effect.rs +++ b/node/src/effect.rs @@ -82,7 +82,6 @@ use crate::{ shared::{additive_map::AdditiveMap, transform::Transform}, storage::global_state::CommitResult, }, - deploy_buffer::BlockLimits, storage::{self, DeployHashes, DeployHeaderResults, DeployResults, StorageType, Value}, }, crypto::hash::Digest, @@ -96,7 +95,7 @@ use announcements::{ use casperlabs_types::{Key, ProtocolVersion}; use engine_state::{execute_request::ExecuteRequest, execution_result::ExecutionResults}; use requests::{ - BlockExecutorRequest, ContractRuntimeRequest, DeployQueueRequest, MetricsRequest, + BlockExecutorRequest, ContractRuntimeRequest, DeployBufferRequest, MetricsRequest, NetworkRequest, StorageRequest, }; @@ -410,7 +409,7 @@ impl EffectBuilder { .await; } - /// Announce that the HTTP API server has received a deploy. + /// Announces that the HTTP API server has received a deploy. pub(crate) async fn announce_deploy_received(self, deploy: Box) where REv: From, @@ -423,17 +422,17 @@ impl EffectBuilder { .await; } - /// Announces that a (not necessarily new) deploy has been added to the store. + /// Announces that a deploy not previously stored has now been stored. pub(crate) fn announce_deploy_stored(self, deploy: &S::Deploy) -> impl Future where S: StorageType, REv: From>, { let deploy_hash = *deploy.id(); - let deploy_header = deploy.header().clone(); + let deploy_header = Box::new(deploy.header().clone()); self.0.schedule( - StorageAnnouncement::StoredDeploy { + StorageAnnouncement::StoredNewDeploy { deploy_hash, deploy_header, }, @@ -579,22 +578,13 @@ impl EffectBuilder { * type than the context in the return value in the future */ ) -> (ProtoBlock, BlockContext) where - REv: From, + REv: From, { - // TODO: The `EffectBuilder` shouldn't contain that much logic. Move to deploy buffer. - let limits = BlockLimits { - size_bytes: u64::MAX, - gas: u64::MAX, - deploy_count: 3, // TODO - }; let deploys = self .make_request( - |responder| DeployQueueRequest::RequestForInclusion { + |responder| DeployBufferRequest::ListForInclusion { current_instant: block_context.timestamp().millis(), - max_ttl: u32::MAX, - limits, - max_dependencies: u8::MAX, - past: Default::default(), // TODO + past_blocks: Default::default(), // TODO responder, }, QueueKind::Regular, @@ -713,8 +703,6 @@ impl EffectBuilder { } /// Gets the requested chainspec from the chainspec store. - // TODO: remove once method is used. - #[allow(dead_code)] pub(crate) async fn get_chainspec(self, version: Version) -> storage::Result where S: StorageType + 'static, diff --git a/node/src/effect/announcements.rs b/node/src/effect/announcements.rs index 42544feabf..c2f3bcf45c 100644 --- a/node/src/effect/announcements.rs +++ b/node/src/effect/announcements.rs @@ -61,13 +61,12 @@ impl Display for ApiServerAnnouncement { /// A storage layer announcement. #[derive(Debug)] pub enum StorageAnnouncement { - /// A deploy has been stored. - StoredDeploy { + /// A deploy which wasn't previously stored has been stored. + StoredNewDeploy { /// ID or "hash" of the deploy that was added to the store. deploy_hash: ::Id, - /// The header of the deploy that was added to the store. - deploy_header: ::Header, + deploy_header: Box<::Header>, }, } @@ -78,8 +77,8 @@ where { fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { match self { - StorageAnnouncement::StoredDeploy { deploy_hash, .. } => { - write!(formatter, "stored deploy {}", deploy_hash) + StorageAnnouncement::StoredNewDeploy { deploy_hash, .. } => { + write!(formatter, "stored new deploy {}", deploy_hash) } } } diff --git a/node/src/effect/requests.rs b/node/src/effect/requests.rs index 51eb7f99b9..190ce5b859 100644 --- a/node/src/effect/requests.rs +++ b/node/src/effect/requests.rs @@ -26,11 +26,10 @@ use crate::{ shared::{additive_map::AdditiveMap, transform::Transform}, storage::global_state::CommitResult, }, - deploy_buffer::BlockLimits, storage::{self, DeployHashes, DeployHeaderResults, DeployResults, StorageType, Value}, }, crypto::hash::Digest, - types::{BlockHash, Deploy, DeployHash, DeployHeader, ExecutedBlock, FinalizedBlock}, + types::{BlockHash, Deploy, DeployHash, ExecutedBlock, FinalizedBlock}, utils::DisplayIter, Chainspec, }; @@ -245,62 +244,33 @@ impl Display for StorageRequest { } } -#[allow(dead_code)] // FIXME: Remove once in use. -/// Deploy-queue related requests. +/// A `DeployBuffer` request. #[derive(Debug)] #[must_use] -pub enum DeployQueueRequest { - /// Add a deploy to the queue for inclusion into an upcoming block. - QueueDeploy { - /// Hash of deploy to store. - hash: DeployHash, - /// Header of the deploy to store. - header: DeployHeader, - /// Responder to call with the result. - responder: Responder, - }, - +pub enum DeployBufferRequest { /// Request a list of deploys to propose in a new block. - RequestForInclusion { + ListForInclusion { /// The instant for which the deploy is requested. current_instant: u64, // TODO: timestamp: Timestamp, - /// Maximum time to live. - max_ttl: u32, - /// Gas, size and count limits for deploys in a block. - limits: BlockLimits, - /// Maximum number of dependencies. - max_dependencies: u8, /// Set of block hashes pointing to blocks whose deploys should be excluded. - past: HashSet, + past_blocks: HashSet, /// Responder to call with the result. responder: Responder>, }, } -impl Display for DeployQueueRequest { +impl Display for DeployBufferRequest { fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { match self { - DeployQueueRequest::QueueDeploy { hash, .. } => { - write!(formatter, "add deploy {} to queue", hash) - } - DeployQueueRequest::RequestForInclusion { + DeployBufferRequest::ListForInclusion { current_instant, - max_ttl, - limits, - max_dependencies, - past, + past_blocks, responder: _, } => write!( formatter, - "request for inclusion: instant {} ttl {} block_size {} gas_limit {} \ - max_deps {} max_deploy_count {} #past {}", + "list for inclusion: instant {} past {}", current_instant, - max_ttl, - limits.size_bytes, - limits.gas, - max_dependencies, - limits.deploy_count, - past.len() + past_blocks.len() ), } } diff --git a/node/src/reactor/validator.rs b/node/src/reactor/validator.rs index 171fd2b17a..a1d8294a8f 100644 --- a/node/src/reactor/validator.rs +++ b/node/src/reactor/validator.rs @@ -7,12 +7,12 @@ mod error; use std::fmt::{self, Display, Formatter}; -use casperlabs_types::U512; use derive_more::From; use prometheus::Registry; use rand::Rng; use serde::{Deserialize, Serialize}; -use tracing::info; + +use casperlabs_types::U512; use crate::{ components::{ @@ -32,7 +32,7 @@ use crate::{ ApiServerAnnouncement, ConsensusAnnouncement, NetworkAnnouncement, StorageAnnouncement, }, requests::{ - ApiRequest, BlockExecutorRequest, ContractRuntimeRequest, DeployQueueRequest, + ApiRequest, BlockExecutorRequest, ContractRuntimeRequest, DeployBufferRequest, MetricsRequest, NetworkRequest, StorageRequest, }, EffectBuilder, Effects, @@ -76,9 +76,9 @@ pub enum Event { /// Network event. #[from] Network(small_network::Event), - /// Deploy queue event. + /// Deploy buffer event. #[from] - DeployQueue(deploy_buffer::Event), + DeployBuffer(deploy_buffer::Event), /// Pinger event. #[from] Pinger(pinger::Event), @@ -105,9 +105,9 @@ pub enum Event { /// Network request. #[from] NetworkRequest(NetworkRequest), - /// Deploy queue request. + /// Deploy buffer request. #[from] - DeployQueueRequest(DeployQueueRequest), + DeployBufferRequest(DeployBufferRequest), /// Block executor request. #[from] BlockExecutorRequest(BlockExecutorRequest), @@ -164,7 +164,7 @@ impl Display for Event { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Event::Network(event) => write!(f, "network: {}", event), - Event::DeployQueue(event) => write!(f, "deploy queue: {}", event), + Event::DeployBuffer(event) => write!(f, "deploy buffer: {}", event), Event::Pinger(event) => write!(f, "pinger: {}", event), Event::Storage(event) => write!(f, "storage: {}", event), Event::ApiServer(event) => write!(f, "api server: {}", event), @@ -173,7 +173,7 @@ impl Display for Event { Event::ContractRuntime(event) => write!(f, "contract runtime: {}", event), Event::BlockExecutor(event) => write!(f, "block executor: {}", event), Event::NetworkRequest(req) => write!(f, "network request: {}", req), - Event::DeployQueueRequest(req) => write!(f, "deploy queue request: {}", req), + Event::DeployBufferRequest(req) => write!(f, "deploy buffer request: {}", req), Event::BlockExecutorRequest(req) => write!(f, "block executor request: {}", req), Event::MetricsRequest(req) => write!(f, "metrics request: {}", req), Event::NetworkAnnouncement(ann) => write!(f, "network announcement: {}", ann), @@ -282,8 +282,8 @@ impl reactor::Reactor for Reactor { Event::Network, self.net.handle_event(effect_builder, rng, event), ), - Event::DeployQueue(event) => reactor::wrap_effects( - Event::DeployQueue, + Event::DeployBuffer(event) => reactor::wrap_effects( + Event::DeployBuffer, self.deploy_buffer.handle_event(effect_builder, rng, event), ), Event::Pinger(event) => reactor::wrap_effects( @@ -316,14 +316,15 @@ impl reactor::Reactor for Reactor { Event::BlockExecutor, self.block_executor.handle_event(effect_builder, rng, event), ), + // Requests: Event::NetworkRequest(req) => self.dispatch_event( effect_builder, rng, Event::Network(small_network::Event::from(req)), ), - Event::DeployQueueRequest(req) => { - self.dispatch_event(effect_builder, rng, Event::DeployQueue(req.into())) + Event::DeployBufferRequest(req) => { + self.dispatch_event(effect_builder, rng, Event::DeployBuffer(req.into())) } Event::BlockExecutorRequest(req) => self.dispatch_event( effect_builder, @@ -360,7 +361,7 @@ impl reactor::Reactor for Reactor { self.dispatch_event(effect_builder, rng, Event::DeployGossiper(event)) } Event::ConsensusAnnouncement(consensus_announcement) => { - let reactor_event = Event::DeployQueue(match consensus_announcement { + let reactor_event = Event::DeployBuffer(match consensus_announcement { ConsensusAnnouncement::Proposed(block) => { deploy_buffer::Event::ProposedProtoBlock(block) } @@ -373,16 +374,15 @@ impl reactor::Reactor for Reactor { }); self.dispatch_event(effect_builder, rng, reactor_event) } - Event::StorageAnnouncement(StorageAnnouncement::StoredDeploy { + Event::StorageAnnouncement(StorageAnnouncement::StoredNewDeploy { deploy_hash, deploy_header, }) => { - if self.deploy_buffer.add_deploy(deploy_hash, deploy_header) { - info!("Added deploy {} to the buffer.", deploy_hash); - } else { - info!("Deploy {} rejected from the buffer.", deploy_hash); - } - Effects::new() + let event = deploy_buffer::Event::Buffer { + hash: deploy_hash, + header: deploy_header, + }; + self.dispatch_event(effect_builder, rng, Event::DeployBuffer(event)) } } } diff --git a/resources/local/chainspec.toml b/resources/local/chainspec.toml index aa919ad12a..fd8afaee0f 100644 --- a/resources/local/chainspec.toml +++ b/resources/local/chainspec.toml @@ -52,6 +52,10 @@ max_ttl_millis = 86400000 max_dependencies = 10 # Maximum block size in bytes. 0 means unlimited. max_block_size = 10485760 +# The upper limit of total gas of all deploys in a block. +block_gas_limit = 10000000000000 +# The maximum number of deploys permitted in a single block. +block_max_deploy_count = 3 [wasm_costs] # Default opcode cost. diff --git a/resources/production/chainspec.toml b/resources/production/chainspec.toml index 487500f331..ee2b501f80 100644 --- a/resources/production/chainspec.toml +++ b/resources/production/chainspec.toml @@ -52,6 +52,10 @@ max_ttl_millis = 86400000 max_dependencies = 10 # Maximum block size in bytes. 0 means unlimited. max_block_size = 10485760 +# The upper limit of total gas of all deploys in a block. +block_gas_limit = 10000000000000 +# The maximum number of deploys permitted in a single block. +block_max_deploy_count = 3 [wasm_costs] # Default opcode cost. diff --git a/resources/test/valid/chainspec.toml b/resources/test/valid/chainspec.toml index ca284b9778..288224c9c5 100644 --- a/resources/test/valid/chainspec.toml +++ b/resources/test/valid/chainspec.toml @@ -20,6 +20,8 @@ max_payment_cost = '9' max_ttl_millis = 10 max_dependencies = 11 max_block_size = 12 +block_gas_limit = 13 +block_max_deploy_count = 14 [wasm_costs] regular = 13 @@ -57,9 +59,11 @@ max_payment_cost = '34' max_ttl_millis = 35 max_dependencies = 36 max_block_size = 37 +block_gas_limit = 38 +block_max_deploy_count = 39 [[upgrade]] protocol_version = '0.3.0' [upgrade.activation_point] -rank = 38 +rank = 40 From 34f58e0716948879bf234627f10f9db79a1ade64 Mon Sep 17 00:00:00 2001 From: Fraser Hutchison Date: Thu, 23 Jul 2020 16:07:46 +0100 Subject: [PATCH 2/3] NDRS-157: remove block_max_deploy_count from DeployConfig --- node/src/components/chainspec_handler/chainspec.rs | 9 +-------- node/src/components/chainspec_handler/config.rs | 3 --- node/src/components/deploy_buffer.rs | 1 - resources/local/chainspec.toml | 2 -- resources/production/chainspec.toml | 2 -- resources/test/valid/chainspec.toml | 4 +--- 6 files changed, 2 insertions(+), 19 deletions(-) diff --git a/node/src/components/chainspec_handler/chainspec.rs b/node/src/components/chainspec_handler/chainspec.rs index 0b25665fb1..edee9b2e45 100644 --- a/node/src/components/chainspec_handler/chainspec.rs +++ b/node/src/components/chainspec_handler/chainspec.rs @@ -103,7 +103,6 @@ pub(crate) struct DeployConfig { pub(crate) max_dependencies: u8, pub(crate) max_block_size: u32, pub(crate) block_gas_limit: u64, - pub(crate) block_max_deploy_count: u32, } impl Default for DeployConfig { @@ -114,7 +113,6 @@ impl Default for DeployConfig { max_dependencies: 10, max_block_size: 10_485_760, block_gas_limit: 10_000_000_000_000, - block_max_deploy_count: 3, } } } @@ -341,7 +339,6 @@ mod tests { assert_eq!(spec.genesis.deploy_config.max_dependencies, 11); assert_eq!(spec.genesis.deploy_config.max_block_size, 12); assert_eq!(spec.genesis.deploy_config.block_gas_limit, 13); - assert_eq!(spec.genesis.deploy_config.block_max_deploy_count, 14); assert_eq!(spec.genesis.costs.regular, 13); assert_eq!(spec.genesis.costs.div, 14); @@ -385,13 +382,9 @@ mod tests { assert_eq!(upgrade0.new_deploy_config.unwrap().max_dependencies, 36); assert_eq!(upgrade0.new_deploy_config.unwrap().max_block_size, 37); assert_eq!(upgrade0.new_deploy_config.unwrap().block_gas_limit, 38); - assert_eq!( - upgrade0.new_deploy_config.unwrap().block_max_deploy_count, - 39 - ); let upgrade1 = &spec.upgrades[1]; - assert_eq!(upgrade1.activation_point, ActivationPoint { rank: 40 }); + assert_eq!(upgrade1.activation_point, ActivationPoint { rank: 39 }); assert_eq!(upgrade1.protocol_version, Version::from((0, 3, 0))); assert!(upgrade1.upgrade_installer_bytes.is_none()); assert!(upgrade1.upgrade_installer_args.is_none()); diff --git a/node/src/components/chainspec_handler/config.rs b/node/src/components/chainspec_handler/config.rs index fafeb3ce70..efdedc007e 100644 --- a/node/src/components/chainspec_handler/config.rs +++ b/node/src/components/chainspec_handler/config.rs @@ -42,7 +42,6 @@ struct DeployConfig { max_dependencies: u8, max_block_size: u32, block_gas_limit: u64, - block_max_deploy_count: u32, } impl Default for DeployConfig { @@ -59,7 +58,6 @@ impl From for DeployConfig { max_dependencies: cfg.max_dependencies, max_block_size: cfg.max_block_size, block_gas_limit: cfg.block_gas_limit, - block_max_deploy_count: cfg.block_max_deploy_count, } } } @@ -75,7 +73,6 @@ impl TryFrom for chainspec::DeployConfig { max_dependencies: cfg.max_dependencies, max_block_size: cfg.max_block_size, block_gas_limit: cfg.block_gas_limit, - block_max_deploy_count: cfg.block_max_deploy_count, }) } } diff --git a/node/src/components/deploy_buffer.rs b/node/src/components/deploy_buffer.rs index 843fda7af9..c1936df6ae 100644 --- a/node/src/components/deploy_buffer.rs +++ b/node/src/components/deploy_buffer.rs @@ -150,7 +150,6 @@ impl DeployBuffer { && !past_deploys.contains(hash) }) .map(|(hash, _deploy)| *hash) - .take(deploy_config.block_max_deploy_count as usize) .collect::>() // TODO: check gas and block size limits } diff --git a/resources/local/chainspec.toml b/resources/local/chainspec.toml index fd8afaee0f..0a6921f9fb 100644 --- a/resources/local/chainspec.toml +++ b/resources/local/chainspec.toml @@ -54,8 +54,6 @@ max_dependencies = 10 max_block_size = 10485760 # The upper limit of total gas of all deploys in a block. block_gas_limit = 10000000000000 -# The maximum number of deploys permitted in a single block. -block_max_deploy_count = 3 [wasm_costs] # Default opcode cost. diff --git a/resources/production/chainspec.toml b/resources/production/chainspec.toml index ee2b501f80..39a6490314 100644 --- a/resources/production/chainspec.toml +++ b/resources/production/chainspec.toml @@ -54,8 +54,6 @@ max_dependencies = 10 max_block_size = 10485760 # The upper limit of total gas of all deploys in a block. block_gas_limit = 10000000000000 -# The maximum number of deploys permitted in a single block. -block_max_deploy_count = 3 [wasm_costs] # Default opcode cost. diff --git a/resources/test/valid/chainspec.toml b/resources/test/valid/chainspec.toml index 288224c9c5..3c9b8f83ee 100644 --- a/resources/test/valid/chainspec.toml +++ b/resources/test/valid/chainspec.toml @@ -21,7 +21,6 @@ max_ttl_millis = 10 max_dependencies = 11 max_block_size = 12 block_gas_limit = 13 -block_max_deploy_count = 14 [wasm_costs] regular = 13 @@ -60,10 +59,9 @@ max_ttl_millis = 35 max_dependencies = 36 max_block_size = 37 block_gas_limit = 38 -block_max_deploy_count = 39 [[upgrade]] protocol_version = '0.3.0' [upgrade.activation_point] -rank = 40 +rank = 39 From 9d92381a1952c59c88f64804f63c8cc9488041e6 Mon Sep 17 00:00:00 2001 From: Fraser Hutchison Date: Thu, 23 Jul 2020 17:30:41 +0100 Subject: [PATCH 3/3] NDRS_157: add block_max_deploy_count to NodeConfig --- node/src/components/deploy_buffer.rs | 19 +++++++++++++------ node/src/reactor/validator.rs | 2 +- node/src/types/node_config.rs | 4 ++++ resources/local/config.toml | 3 +++ 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/node/src/components/deploy_buffer.rs b/node/src/components/deploy_buffer.rs index c1936df6ae..b5d7e4425c 100644 --- a/node/src/components/deploy_buffer.rs +++ b/node/src/components/deploy_buffer.rs @@ -75,8 +75,9 @@ impl Display for Event { } /// Deploy buffer. -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone)] pub(crate) struct DeployBuffer { + block_max_deploy_count: usize, collected_deploys: HashMap, processed: HashMap>, finalized: HashMap>, @@ -84,8 +85,13 @@ pub(crate) struct DeployBuffer { impl DeployBuffer { /// Creates a new, empty deploy buffer instance. - pub(crate) fn new() -> Self { - Default::default() + pub(crate) fn new(block_max_deploy_count: usize) -> Self { + DeployBuffer { + block_max_deploy_count, + collected_deploys: HashMap::new(), + processed: HashMap::new(), + finalized: HashMap::new(), + } } /// Adds a deploy to the deploy buffer. @@ -150,6 +156,7 @@ impl DeployBuffer { && !past_deploys.contains(hash) }) .map(|(hash, _deploy)| *hash) + .take(self.block_max_deploy_count) .collect::>() // TODO: check gas and block size limits } @@ -276,7 +283,7 @@ mod tests { use super::*; use crate::{ crypto::{asymmetric_key::PublicKey, hash::hash}, - types::{BlockHash, DeployHash, DeployHeader}, + types::{BlockHash, DeployHash, DeployHeader, NodeConfig}, }; fn generate_deploy(timestamp: u64, ttl: u32) -> (DeployHash, DeployHeader) { @@ -302,7 +309,7 @@ mod tests { let block_time3 = 220u64; let no_blocks = HashSet::new(); - let mut buffer = DeployBuffer::new(); + let mut buffer = DeployBuffer::new(NodeConfig::default().block_max_deploy_count as usize); let (hash1, deploy1) = generate_deploy(creation_time, ttl); let (hash2, deploy2) = generate_deploy(creation_time, ttl); let (hash3, deploy3) = generate_deploy(creation_time, ttl); @@ -402,7 +409,7 @@ mod tests { deploy2.dependencies = vec![hash1]; let mut blocks = HashSet::new(); - let mut buffer = DeployBuffer::new(); + let mut buffer = DeployBuffer::new(NodeConfig::default().block_max_deploy_count as usize); // add deploy2 buffer.add_deploy(hash2, deploy2); diff --git a/node/src/reactor/validator.rs b/node/src/reactor/validator.rs index a1d8294a8f..0eab1f811d 100644 --- a/node/src/reactor/validator.rs +++ b/node/src/reactor/validator.rs @@ -243,7 +243,7 @@ impl reactor::Reactor for Reactor { validator_stakes, )?; let deploy_gossiper = DeployGossiper::new(config.gossip); - let deploy_buffer = DeployBuffer::new(); + let deploy_buffer = DeployBuffer::new(config.node.block_max_deploy_count as usize); // Post state hash is expected to be present let post_state_hash = chainspec_handler .post_state_hash() diff --git a/node/src/types/node_config.rs b/node/src/types/node_config.rs index d80b776410..988830af44 100644 --- a/node/src/types/node_config.rs +++ b/node/src/types/node_config.rs @@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize}; use std::path::PathBuf; const DEFAULT_CHAINSPEC_CONFIG_PATH: &str = "chainspec.toml"; +const DEFAULT_BLOCK_MAX_DEPLOY_COUNT: u32 = 3; /// Node configuration. #[derive(Debug, Deserialize, Serialize)] @@ -10,12 +11,15 @@ const DEFAULT_CHAINSPEC_CONFIG_PATH: &str = "chainspec.toml"; pub struct NodeConfig { /// Path to chainspec config file. pub chainspec_config_path: PathBuf, + /// The maximum number of deploys permitted in a single block. + pub block_max_deploy_count: u32, } impl Default for NodeConfig { fn default() -> Self { NodeConfig { chainspec_config_path: PathBuf::from(DEFAULT_CHAINSPEC_CONFIG_PATH), + block_max_deploy_count: DEFAULT_BLOCK_MAX_DEPLOY_COUNT, } } } diff --git a/resources/local/config.toml b/resources/local/config.toml index 54452e7540..dcf7581f5c 100644 --- a/resources/local/config.toml +++ b/resources/local/config.toml @@ -6,6 +6,9 @@ # Path (absolute, or relative to this config.toml) to the chainspec configuration file. chainspec_config_path = 'chainspec.toml' +# The maximum number of deploys permitted in a single block. +block_max_deploy_count = 3 + # ==================================== # Configuration options for consensus