diff --git a/Cargo.lock b/Cargo.lock index 75179116be6..8ed1250c483 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7333,6 +7333,7 @@ dependencies = [ "const-hex", "constant_time_eq 0.4.2", "crc32fast", + "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", "crunchy", @@ -7405,7 +7406,7 @@ dependencies = [ "indexmap 2.13.0", "ipnet", "itertools 0.10.5", - "itertools 0.11.0", + "itertools 0.13.0", "js-sys", "jsonrpsee", "jsonrpsee-client-transport", @@ -7534,7 +7535,6 @@ dependencies = [ "signature", "slice-group-by", "smallvec", - "socket2 0.4.10", "soketto", "sp-allocator", "sp-api", diff --git a/ethexe/common/src/db.rs b/ethexe/common/src/db.rs index 1557b54f404..5cda0b19f4b 100644 --- a/ethexe/common/src/db.rs +++ b/ethexe/common/src/db.rs @@ -43,27 +43,14 @@ pub struct BlockMeta { /// Block has been prepared, meaning: /// all metadata is ready, all predecessors till start block are prepared too. pub prepared: bool, - // TODO: #4945 remove announces from here - /// Set of announces included in the block. - pub announces: Option>>, /// Queue of code ids waiting for validation status commitment on-chain. pub codes_queue: Option>, /// Last committed on-chain batch hash. pub last_committed_batch: Option, /// Last committed on-chain announce hash. pub last_committed_announce: Option>, -} - -impl BlockMeta { - pub fn default_prepared() -> Self { - Self { - prepared: true, - announces: Some(Default::default()), - codes_queue: Some(Default::default()), - last_committed_batch: Some(Default::default()), - last_committed_announce: Some(Default::default()), - } - } + /// Latest era with committed validators. + pub latest_era_validators_committed: u64, } #[auto_impl::auto_impl(&, Box)] @@ -112,8 +99,6 @@ pub trait OnChainStorageRO { fn code_blob_info(&self, code_id: CodeId) -> Option; fn block_synced(&self, block_hash: H256) -> bool; fn validators(&self, era_index: u64) -> Option; - // TODO kuzmindev: temporal solution - must move into block meta or something else. - fn block_validators_committed_for_era(&self, block_hash: H256) -> Option; } #[auto_impl::auto_impl(&)] @@ -122,7 +107,6 @@ pub trait OnChainStorageRW: OnChainStorageRO { fn set_block_events(&self, block_hash: H256, events: &[BlockEvent]); fn set_code_blob_info(&self, code_id: CodeId, code_info: CodeBlobInfo); fn set_validators(&self, era_index: u64, validator_set: ValidatorsVec); - fn set_block_validators_committed_for_era(&self, block_hash: H256, era_index: u64); fn set_block_synced(&self, block_hash: H256); } @@ -152,11 +136,13 @@ pub trait AnnounceStorageRO { fn announce_outcome(&self, announce_hash: HashOf) -> Option>; fn announce_schedule(&self, announce_hash: HashOf) -> Option; fn announce_meta(&self, announce_hash: HashOf) -> AnnounceMeta; + fn block_announces(&self, block_hash: H256) -> Option>>; } #[auto_impl::auto_impl(&)] pub trait AnnounceStorageRW: AnnounceStorageRO { fn set_announce(&self, announce: Announce) -> HashOf; + fn set_block_announces(&self, block_hash: H256, announces: BTreeSet>); fn set_announce_program_states( &self, announce_hash: HashOf, @@ -170,6 +156,11 @@ pub trait AnnounceStorageRW: AnnounceStorageRO { announce_hash: HashOf, f: impl FnOnce(&mut AnnounceMeta), ); + fn mutate_block_announces( + &self, + block_hash: H256, + f: impl FnOnce(&mut BTreeSet>), + ); } pub struct PreparedBlockData { @@ -260,7 +251,7 @@ mod tests { #[test] fn ensure_types_unchanged() { const EXPECTED_TYPE_INFO_HASH: &str = - "36d0e8436bb8fa8ea920012e1b4b079f9b6a83414e016771afc977568d30f29b"; + "4d2864a076a65fc8abf5a4d7a0def202bd3982b086e14751d04e4ff711bc536a"; let types = [ meta_type::(), diff --git a/ethexe/common/src/mock.rs b/ethexe/common/src/mock.rs index bc3a60ec452..f1386794b1a 100644 --- a/ethexe/common/src/mock.rs +++ b/ethexe/common/src/mock.rs @@ -225,36 +225,26 @@ pub struct PreparedBlockData { #[derive(Debug, Clone, PartialEq, Eq)] pub struct BlockFullData { pub hash: H256, - pub synced: Option, + pub synced: SyncedBlockData, pub prepared: Option, } impl BlockFullData { #[track_caller] - pub fn as_synced(&self) -> &SyncedBlockData { - self.synced.as_ref().expect("block not synced") + pub fn assert_prepared(&self) -> &PreparedBlockData { + self.prepared.as_ref().expect("block is not prepared") } #[track_caller] - pub fn as_prepared(&self) -> &PreparedBlockData { - self.prepared.as_ref().expect("block not prepared") - } - - #[track_caller] - pub fn as_synced_mut(&mut self) -> &mut SyncedBlockData { - self.synced.as_mut().expect("block not synced") - } - - #[track_caller] - pub fn as_prepared_mut(&mut self) -> &mut PreparedBlockData { - self.prepared.as_mut().expect("block not prepared") + pub fn assert_prepared_mut(&mut self) -> &mut PreparedBlockData { + self.prepared.as_mut().expect("block is not prepared") } #[track_caller] pub fn to_simple(&self) -> SimpleBlockData { SimpleBlockData { hash: self.hash, - header: self.as_synced().header, + header: self.synced.header, } } } @@ -336,7 +326,7 @@ impl BlockChain { self.blocks .get(block_index) .expect("block index overflow") - .as_prepared() + .assert_prepared() .announces .iter() .flatten() @@ -385,7 +375,7 @@ impl BlockChain { self.announces.insert(new_announce_hash, announce_data); self.blocks[block_index] - .as_prepared_mut() + .assert_prepared_mut() .announces .as_mut() .expect("block announces not found") @@ -418,19 +408,16 @@ impl BlockChain { for BlockFullData { hash, - synced, + synced: SyncedBlockData { header, events }, prepared, } in blocks { - if let Some(SyncedBlockData { header, events }) = synced { - db.set_block_header(hash, header); - db.set_block_events(hash, &events); - db.set_block_synced(hash); - - let block_era = config.timelines.era_from_ts(header.timestamp); - db.set_validators(block_era, validators.clone()); - db.set_block_validators_committed_for_era(hash, block_era); - } + db.set_block_header(hash, header); + db.set_block_events(hash, &events); + db.set_block_synced(hash); + + let block_era = config.timelines.era_from_ts(header.timestamp); + db.set_validators(block_era, validators.clone()); if let Some(PreparedBlockData { codes_queue, @@ -439,13 +426,17 @@ impl BlockChain { last_committed_announce, }) = prepared { + if let Some(announces) = announces { + db.set_block_announces(hash, announces); + } + db.mutate_block_meta(hash, |meta| { *meta = BlockMeta { prepared: true, - announces, codes_queue: Some(codes_queue), last_committed_batch: Some(last_committed_batch), last_committed_announce: Some(last_committed_announce), + latest_era_validators_committed: block_era, } }); } @@ -507,14 +498,14 @@ impl Mock<(u32, ValidatorsVec)> for BlockChain { |((parent_hash, _, _), (block_hash, block_height, block_timestamp))| { BlockFullData { hash: block_hash, - synced: Some(SyncedBlockData { + synced: SyncedBlockData { header: BlockHeader { height: block_height, timestamp: block_timestamp as u64, parent_hash, }, events: Default::default(), - }), + }, prepared: Some(PreparedBlockData { codes_queue: Default::default(), announces: Some(Default::default()), // empty here, filled below with announces @@ -601,7 +592,7 @@ pub trait DBMockExt { fn top_announce_hash(&self, block: H256) -> HashOf; } -impl DBMockExt for DB { +impl DBMockExt for DB { #[track_caller] fn simple_block_data(&self, block: H256) -> SimpleBlockData { let header = self.block_header(block).expect("block header not found"); @@ -613,8 +604,7 @@ impl DBMockExt for DB { #[track_caller] fn top_announce_hash(&self, block: H256) -> HashOf { - self.block_meta(block) - .announces + self.block_announces(block) .expect("block announces not found") .into_iter() .next() diff --git a/ethexe/common/src/utils.rs b/ethexe/common/src/utils.rs index be5be66e78f..b44215135f7 100644 --- a/ethexe/common/src/utils.rs +++ b/ethexe/common/src/utils.rs @@ -44,7 +44,7 @@ pub const fn u64_into_uint48_be_bytes_lossy(val: u64) -> [u8; 6] { [b1, b2, b3, b4, b5, b6] } -pub fn setup_block_in_db( +pub fn setup_block_in_db( db: &DB, block_hash: H256, block_data: PreparedBlockData, @@ -53,20 +53,17 @@ pub fn setup_block_in_db( db.set_block_events(block_hash, &block_data.events); db.set_block_synced(block_hash); + db.set_block_announces(block_hash, block_data.announces); + db.mutate_block_meta(block_hash, |meta| { *meta = BlockMeta { prepared: true, - announces: Some(block_data.announces), codes_queue: Some(block_data.codes_queue), last_committed_batch: Some(block_data.last_committed_batch), last_committed_announce: Some(block_data.last_committed_announce), + latest_era_validators_committed: block_data.latest_era_with_committed_validators, } }); - - db.set_block_validators_committed_for_era( - block_hash, - block_data.latest_era_with_committed_validators, - ); } pub fn setup_announce_in_db( diff --git a/ethexe/compute/src/prepare.rs b/ethexe/compute/src/prepare.rs index 24ae9634fee..6718c36dc7d 100644 --- a/ethexe/compute/src/prepare.rs +++ b/ethexe/compute/src/prepare.rs @@ -297,9 +297,7 @@ fn prepare_one_block Vec { // Return a map with `CodeId` and corresponding code bytes fn insert_code_events(chain: &mut BlockChain, events_in_block: u32) { let mut nonce = 0; - for data in chain.blocks.iter_mut().map(|data| data.as_synced_mut()) { + for BlockFullData { synced: data, .. } in &mut chain.blocks { data.events = (0..events_in_block) .map(|_| { nonce += 1; @@ -226,9 +226,10 @@ impl TestEnv { let computed_announce = event.unwrap_announce_computed(); assert_eq!(computed_announce, announce_hash); - self.db.mutate_block_meta(announce.block_hash, |meta| { - meta.announces.get_or_insert_default().insert(announce_hash); - }); + self.db + .mutate_block_announces(announce.block_hash, |announces| { + announces.insert(announce_hash); + }); } } @@ -273,11 +274,10 @@ async fn multiple_preparation_and_one_processing() -> Result<()> { // append announces to prepared blocks, except the last one, so that it can be computed for i in 1..3 { let announce = new_announce(&env.db, env.chain.blocks[i].hash, Some(100)); - env.db.mutate_block_meta(announce.block_hash, |meta| { - meta.announces - .get_or_insert_default() - .insert(announce.to_hash()); - }); + env.db + .mutate_block_announces(announce.block_hash, |announces| { + announces.insert(announce.to_hash()); + }); env.db.set_announce(announce); } @@ -309,7 +309,7 @@ async fn code_validation_request_does_not_block_preparation() -> Result<()> { let mut env = TestEnv::new(1, 3); - let mut block_events = env.chain.blocks[1].as_synced().events.clone(); + let mut block_events = env.chain.blocks[1].synced.events.clone(); // add invalid event which shouldn't stop block prepare block_events.push(BlockEvent::Router(RouterEvent::CodeValidationRequested( diff --git a/ethexe/consensus/src/announces.rs b/ethexe/consensus/src/announces.rs index 16509ca2211..668b6e527ba 100644 --- a/ethexe/consensus/src/announces.rs +++ b/ethexe/consensus/src/announces.rs @@ -147,7 +147,7 @@ impl< .block_header(current_block) .ok_or_else(|| anyhow!("header not found for block({current_block})"))?; - if self.block_meta(current_block).announces.is_some() { + if self.block_announces(current_block).is_some() { break; } @@ -168,11 +168,10 @@ impl< let announce_hash = self.set_announce(announce); let mut newly_included = None; - self.mutate_block_meta(block_hash, |meta| { - if let Some(announces) = &mut meta.announces { - newly_included = Some(announces.insert(announce_hash)); - } - }); + if let Some(mut announces) = self.block_announces(block_hash) { + newly_included = Some(announces.insert(announce_hash)); + self.set_block_announces(block_hash, announces); + } if let Some(newly_included) = newly_included { Ok((announce_hash, newly_included)) @@ -190,7 +189,7 @@ impl< } self.announce(announce_hash) - .and_then(|announce| self.block_meta(announce.block_hash).announces) + .and_then(|announce| self.block_announces(announce.block_hash)) .map(|announces| announces.contains(&announce_hash)) .unwrap_or(false) } @@ -225,7 +224,7 @@ pub fn propagate_announces( // iterate over the collected blocks from oldest to newest and propagate announces for block in chain { debug_assert!( - db.block_meta(block.hash).announces.is_none(), + db.block_announces(block.hash).is_none(), "Block {} should not have announces propagated yet", block.hash ); @@ -249,15 +248,14 @@ pub fn propagate_announces( )?; let mut new_base_announces = BTreeSet::new(); - for parent_announce_hash in db - .block_meta(block.header.parent_hash) - .announces - .ok_or_else(|| { - anyhow!( - "Parent block({}) announces are missing", - block.header.parent_hash - ) - })? + for parent_announce_hash in + db.block_announces(block.header.parent_hash) + .ok_or_else(|| { + anyhow!( + "Parent block({}) announces are missing", + block.header.parent_hash + ) + })? { if let Some(new_base_announce) = propagate_one_base_announce( db, @@ -278,14 +276,12 @@ pub fn propagate_announces( block.hash ); - db.mutate_block_meta(block.hash, |meta| { - debug_assert!( - meta.announces.is_none(), - "block({}) announces must be None before propagation", - block.hash - ); - meta.announces = Some(new_base_announces); - }); + debug_assert!( + db.block_announces(block.hash).is_none(), + "block({}) announces must be None before propagation", + block.hash + ); + db.set_block_announces(block.hash, new_base_announces); } Ok(()) @@ -446,8 +442,7 @@ fn propagate_one_base_announce( // Check neighbor announces to be last committed announce if db - .block_meta(current_announce.block_hash) - .announces + .block_announces(current_announce.block_hash) .ok_or_else(|| { anyhow!( "announces are missing for block({})", @@ -562,8 +557,7 @@ fn find_announces_common_predecessor( let start_announce_hash = db.globals().start_announce_hash; let mut announces = db - .block_meta(block_hash) - .announces + .block_announces(block_hash) .ok_or_else(|| anyhow!("announces not found for block {block_hash}"))?; for _ in 0..commitment_delay_limit { @@ -606,7 +600,7 @@ pub fn best_parent_announce( // so we take parents of all announces from `block_hash`, // to be sure that we take only not expired parent announces. let parent_announces = - db.announces_parents(db.block_meta(block_hash).announces.into_iter().flatten())?; + db.announces_parents(db.block_announces(block_hash).into_iter().flatten())?; best_announce(db, parent_announces, commitment_delay_limit) } @@ -796,7 +790,7 @@ mod tests { let mut chain = BlockChain::mock(last as u32); (fnp..=last).for_each(|i| { chain.blocks[i] - .as_prepared_mut() + .assert_prepared_mut() .announces .take() .iter() @@ -813,7 +807,7 @@ mod tests { ); let announce_hash = announce.to_hash(); chain.blocks[wta] - .as_prepared_mut() + .assert_prepared_mut() .announces .as_mut() .unwrap() @@ -836,8 +830,7 @@ mod tests { ) -> (H256, usize) { let block_hash = chain.blocks[idx].hash; let announces_amount = db - .block_meta(block_hash) - .announces + .block_announces(block_hash) .unwrap_or_else(|| panic!("announces not found for block {block_hash}")) .len(); (block_hash, announces_amount) @@ -929,7 +922,7 @@ mod tests { let mut chain = make_chain(last, fnp, wta); (fnp..=last).for_each(|i| { - chain.blocks[i].as_prepared_mut().last_committed_announce = + chain.blocks[i].assert_prepared_mut().last_committed_announce = chain.block_top_announce_hash(wta); }); @@ -969,7 +962,7 @@ mod tests { let committed_announce_hash = chain.block_top_announce(wta).announce.to_hash(); for i in committed_at..=last { - chain.blocks[i].as_prepared_mut().last_committed_announce = committed_announce_hash; + chain.blocks[i].assert_prepared_mut().last_committed_announce = committed_announce_hash; } let chain = chain.setup(&db); @@ -1009,7 +1002,7 @@ mod tests { let missing_announce_hash = missing_announce.to_hash(); (committed_at..=last).for_each(|i| { - chain.blocks[i].as_prepared_mut().last_committed_announce = missing_announce_hash; + chain.blocks[i].assert_prepared_mut().last_committed_announce = missing_announce_hash; }); let chain = chain.setup(&db); @@ -1063,21 +1056,20 @@ mod tests { let chain = BlockChain::mock(10) .tap_mut(|chain| { - chain.blocks[10].as_synced_mut().events = - (0..MAX_TOUCHED_PROGRAMS_PER_ANNOUNCE / 2 + 1) - .map(|i| BlockEvent::Mirror { - actor_id: ActorId::from(i as u64), - event: MirrorEvent::MessageQueueingRequested( - MessageQueueingRequestedEvent { - id: MessageId::zero(), - source: ActorId::zero(), - payload: vec![], - value: 0, - call_reply: false, - }, - ), - }) - .collect(); + chain.blocks[10].synced.events = (0..MAX_TOUCHED_PROGRAMS_PER_ANNOUNCE / 2 + 1) + .map(|i| BlockEvent::Mirror { + actor_id: ActorId::from(i as u64), + event: MirrorEvent::MessageQueueingRequested( + MessageQueueingRequestedEvent { + id: MessageId::zero(), + source: ActorId::zero(), + payload: vec![], + value: 0, + call_reply: false, + }, + ), + }) + .collect(); chain .block_top_announce_mut(9) diff --git a/ethexe/consensus/src/validator/batch/manager.rs b/ethexe/consensus/src/validator/batch/manager.rs index 5594d52649a..1de63e617d9 100644 --- a/ethexe/consensus/src/validator/batch/manager.rs +++ b/ethexe/consensus/src/validator/batch/manager.rs @@ -200,12 +200,7 @@ impl BatchCommitmentManager { }); } - let candidates = self - .db - .block_meta(block.hash) - .announces - .into_iter() - .flatten(); + let candidates = self.db.block_announces(block.hash).into_iter().flatten(); let best_announce_hash = announces::best_announce(&self.db, candidates, self.limits.commitment_delay_limit)?; @@ -326,13 +321,8 @@ impl BatchCommitmentManager { let latest_era_validators_committed = self .db - .block_validators_committed_for_era(block.hash) - .ok_or_else(|| { - anyhow!( - "not found latest_era_validators_committed in database for block: {}", - block.hash - ) - })?; + .block_meta(block.hash) + .latest_era_validators_committed; if latest_era_validators_committed == block_era + 1 { tracing::trace!( diff --git a/ethexe/consensus/src/validator/batch/tests.rs b/ethexe/consensus/src/validator/batch/tests.rs index 7288c94ed4f..2d246a3f6f4 100644 --- a/ethexe/consensus/src/validator/batch/tests.rs +++ b/ethexe/consensus/src/validator/batch/tests.rs @@ -250,7 +250,7 @@ async fn rejects_code_not_processed_yet() { let chain = BlockChain::mock(10) .tap_mut(|chain| { chain.blocks[10] - .as_prepared_mut() + .assert_prepared_mut() .codes_queue .push_front(code_id); chain.codes.insert( @@ -470,9 +470,9 @@ async fn test_aggregate_validators_commitment() { assert_eq!(commitment.era_index, 1); // Inside election period validators already committed - ctx.core - .db - .set_block_validators_committed_for_era(chain.blocks[7].hash, 1); + ctx.core.db.mutate_block_meta(chain.blocks[7].hash, |meta| { + meta.latest_era_validators_committed = 1; + }); let commitment = ctx .core .batch_manager @@ -484,7 +484,9 @@ async fn test_aggregate_validators_commitment() { // Election for era 2 but validators are not committed for era 1 ctx.core .db - .set_block_validators_committed_for_era(chain.blocks[15].hash, 0); + .mutate_block_meta(chain.blocks[15].hash, |meta| { + meta.latest_era_validators_committed = 0; + }); let commitment = ctx .core .batch_manager @@ -498,7 +500,9 @@ async fn test_aggregate_validators_commitment() { // Election for era 2 but validators for era 3 are already committed ctx.core .db - .set_block_validators_committed_for_era(chain.blocks[15].hash, 3); + .mutate_block_meta(chain.blocks[15].hash, |meta| { + meta.latest_era_validators_committed = 3; + }); ctx.core .batch_manager .aggregate_validators_commitment(&chain.blocks[15].to_simple()) diff --git a/ethexe/consensus/src/validator/batch/utils.rs b/ethexe/consensus/src/validator/batch/utils.rs index c8cd14ce6b4..aa449faa8a4 100644 --- a/ethexe/consensus/src/validator/batch/utils.rs +++ b/ethexe/consensus/src/validator/batch/utils.rs @@ -294,8 +294,9 @@ mod tests { .as_computed_mut() .outcome .push(StateTransition::mock(())); - chain.blocks[10].as_prepared_mut().last_committed_announce = - chain.block_top_announce_hash(3); + chain.blocks[10] + .assert_prepared_mut() + .last_committed_announce = chain.block_top_announce_hash(3); }) .setup(&db); let block = chain.blocks[10].to_simple(); @@ -419,7 +420,7 @@ mod tests { let chain = BlockChain::mock(10) .tap_mut(|c| { c.block_top_announce_mut(10).announce.gas_allowance = Some(10); - c.blocks[10].as_prepared_mut().announces = + c.blocks[10].assert_prepared_mut().announces = Some([c.block_top_announce(10).announce.to_hash()].into()); }) .setup(&db); diff --git a/ethexe/consensus/src/validator/initial.rs b/ethexe/consensus/src/validator/initial.rs index 8d0d0f5f03b..0160c5f4da3 100644 --- a/ethexe/consensus/src/validator/initial.rs +++ b/ethexe/consensus/src/validator/initial.rs @@ -346,7 +346,7 @@ mod tests { let last = 9; let mut chain = BlockChain::mock(last as u32); - chain.blocks[last].as_prepared_mut().announces = None; + chain.blocks[last].assert_prepared_mut().announces = None; // create 2 missing announces from blocks last - 2 and last - 1 let announce2 = Announce::with_default_gas( @@ -356,7 +356,9 @@ mod tests { let announce1 = Announce::with_default_gas(chain.blocks[last - 1].hash, announce2.to_hash()); - chain.blocks[last].as_prepared_mut().last_committed_announce = announce1.to_hash(); + chain.blocks[last] + .assert_prepared_mut() + .last_committed_announce = announce1.to_hash(); let chain = chain.setup(&ctx.core.db); ctx.core.timelines = chain.config.timelines; let block = chain.blocks[last].to_simple(); @@ -371,7 +373,7 @@ mod tests { let tail = chain.block_top_announce_hash(last - 4); let expected_request = AnnouncesRequest { - head: chain.blocks[last].as_prepared().last_committed_announce, + head: chain.blocks[last].assert_prepared().last_committed_announce, until: tail.into(), }; assert_eq!(state.context().output, vec![expected_request.into()]); @@ -407,7 +409,7 @@ mod tests { .tap_mut(|chain| { // remove announces from 5 latest blocks (last - 4..=last).for_each(|idx| { - chain.blocks[idx].as_prepared_mut().announces = None; + chain.blocks[idx].assert_prepared_mut().announces = None; }); // append one more announce to the block last - 5 @@ -416,7 +418,7 @@ mod tests { chain.block_top_announce_hash(last - 6), ); chain.blocks[last - 5] - .as_prepared_mut() + .assert_prepared_mut() .announces .as_mut() .unwrap() @@ -443,11 +445,11 @@ mod tests { let ctx = state.into_context(); assert_eq!(ctx.output, vec![]); for i in last - 5..last - 5 + ctx.core.commitment_delay_limit as usize { - let announces = ctx.core.db.block_meta(chain.blocks[i].hash).announces; + let announces = ctx.core.db.block_announces(chain.blocks[i].hash); assert_eq!(announces.unwrap().len(), 2); } for i in last - 5 + ctx.core.commitment_delay_limit as usize..=last { - let announces = ctx.core.db.block_meta(chain.blocks[i].hash).announces; + let announces = ctx.core.db.block_announces(chain.blocks[i].hash); assert_eq!(announces.unwrap().len(), 1); } } @@ -462,7 +464,7 @@ mod tests { .tap_mut(|chain| { // remove announces from 10 latest blocks (last - 9..=last).for_each(|idx| { - chain.blocks[idx].as_prepared_mut().announces = None; + chain.blocks[idx].assert_prepared_mut().announces = None; }); }) .setup(&ctx.core.db); @@ -480,7 +482,7 @@ mod tests { assert_eq!(ctx.output, vec![]); (last - 9..=last).for_each(|idx| { let block_hash = chain.blocks[idx].hash; - let announces = ctx.core.db.block_meta(block_hash).announces; + let announces = ctx.core.db.block_announces(block_hash); assert!( announces.is_some(), "expected announces to be propagated for block {block_hash}" @@ -549,10 +551,11 @@ mod tests { let (ctx, _, _) = mock_validator_context(); let block = BlockChain::mock(1) - .setup(&ctx.core.db) .tap_mut(|chain| { - chain.blocks[1].as_prepared_mut().announces = None; - chain.blocks[1].as_prepared_mut().last_committed_announce = HashOf::random(); + chain.blocks[1].assert_prepared_mut().announces = None; + chain.blocks[1] + .assert_prepared_mut() + .last_committed_announce = HashOf::random(); }) .setup(&ctx.core.db) .blocks[1] @@ -605,17 +608,19 @@ mod tests { // remove announces from 5 latest blocks for idx in last - 4..=last { chain.blocks[idx] - .as_prepared_mut() + .assert_prepared_mut() .announces .iter() .flatten() .for_each(|ah| { chain.announces.remove(ah); }); - chain.blocks[idx].as_prepared_mut().announces = None; + chain.blocks[idx].assert_prepared_mut().announces = None; // set unknown_announce as last committed announce - chain.blocks[idx].as_prepared_mut().last_committed_announce = unknown_announce_hash; + chain.blocks[idx] + .assert_prepared_mut() + .last_committed_announce = unknown_announce_hash; } let chain = chain.setup(&ctx.core.db); @@ -632,7 +637,7 @@ mod tests { assert!(state.is_initial(), "got {:?}", state); let expected_request = AnnouncesRequest { - head: chain.blocks[last].as_prepared().last_committed_announce, + head: chain.blocks[last].assert_prepared().last_committed_announce, until: chain.block_top_announce_hash(last - 8).into(), }; assert_eq!(state.context().output, vec![expected_request.into()]); diff --git a/ethexe/consensus/src/validator/tx_pool.rs b/ethexe/consensus/src/validator/tx_pool.rs index c7045ae7946..a7a6fab8066 100644 --- a/ethexe/consensus/src/validator/tx_pool.rs +++ b/ethexe/consensus/src/validator/tx_pool.rs @@ -309,7 +309,7 @@ mod tests { let chain = BlockChain::mock(10) .tap_mut(|chain| { - chain.blocks[10].as_synced_mut().events = (0..97) + chain.blocks[10].synced.events = (0..97) .map(|i| BlockEvent::Mirror { actor_id: ActorId::from(i), event: MirrorEvent::MessageQueueingRequested( diff --git a/ethexe/db/src/database.rs b/ethexe/db/src/database.rs index 13af1ada3fb..cb10ba05f79 100644 --- a/ethexe/db/src/database.rs +++ b/ethexe/db/src/database.rs @@ -48,6 +48,7 @@ use gear_core::{ }; use gprimitives::H256; use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; use std::{ collections::BTreeSet, mem::size_of, @@ -59,6 +60,7 @@ enum Key { // TODO (kuzmindev): use `HashOf` here BlockSmallData(H256) = 0, BlockEvents(H256) = 1, + BlockAnnounces(H256) = 13, ValidatorSet(u64) = 2, @@ -75,12 +77,8 @@ enum Key { InjectedTransaction(HashOf) = 12, - // TODO kuzmindev: make keys prefixes consistent. We don't change it to avoid corrupting existing key layout. Globals = 14, Config = 15, - - // TODO kuzmindev: temporal solution - must move into block meta or something else. - LatestEraValidatorsCommitted(H256), } impl Key { @@ -98,9 +96,9 @@ impl Key { bytes.extend(self.prefix()); match self { - Self::BlockSmallData(hash) - | Self::BlockEvents(hash) - | Self::LatestEraValidatorsCommitted(hash) => bytes.extend(hash.as_ref()), + Self::BlockSmallData(hash) | Self::BlockEvents(hash) | Self::BlockAnnounces(hash) => { + bytes.extend(hash.as_ref()) + } Self::ValidatorSet(era_index) => { bytes.extend(era_index.to_le_bytes()); @@ -417,6 +415,15 @@ impl AnnounceStorageRO for RawDatabase { }) .unwrap_or_default() } + + fn block_announces(&self, block_hash: H256) -> Option>> { + self.kv + .get(&Key::BlockAnnounces(block_hash).to_bytes()) + .map(|data| { + BTreeSet::>::decode(&mut data.as_slice()) + .expect("Failed to decode data into `BTreeSet>`") + }) + } } impl AnnounceStorageRW for RawDatabase { @@ -464,6 +471,28 @@ impl AnnounceStorageRW for RawDatabase { self.kv .put(&Key::AnnounceMeta(announce_hash).to_bytes(), meta.encode()); } + + fn set_block_announces(&self, block_hash: H256, announces: BTreeSet>) { + tracing::trace!("Set block {block_hash} announces: len {}", announces.len()); + self.kv.put( + &Key::BlockAnnounces(block_hash).to_bytes(), + announces.encode(), + ); + } + + fn mutate_block_announces( + &self, + block_hash: H256, + f: impl FnOnce(&mut BTreeSet>), + ) { + tracing::trace!("For block {block_hash} mutate announces"); + let mut announces = self.block_announces(block_hash).unwrap_or_default(); + f(&mut announces); + self.kv.put( + &Key::BlockAnnounces(block_hash).to_bytes(), + announces.encode(), + ); + } } impl OnChainStorageRO for RawDatabase { @@ -504,15 +533,6 @@ impl OnChainStorageRO for RawDatabase { .expect("Failed to decode data into `ValidatorsVec`") }) } - - fn block_validators_committed_for_era(&self, block_hash: H256) -> Option { - self.kv - .get(&Key::LatestEraValidatorsCommitted(block_hash).to_bytes()) - .map(|data| { - Decode::decode(&mut data.as_slice()) - .expect("Failed to decode data into `u64` (era_index)") - }) - } } impl OnChainStorageRW for RawDatabase { @@ -547,13 +567,6 @@ impl OnChainStorageRW for RawDatabase { validator_set.encode(), ); } - - fn set_block_validators_committed_for_era(&self, block_hash: H256, era_index: u64) { - self.kv.put( - &Key::LatestEraValidatorsCommitted(block_hash).to_bytes(), - era_index.encode(), - ); - } } impl BlockMetaStorageRO for RawDatabase { @@ -797,11 +810,11 @@ impl HashStorageRO for Database { } } -#[derive(Debug, Clone, Default, Encode, Decode, PartialEq, Eq)] -struct BlockSmallData { - block_header: Option, - block_is_synced: bool, - meta: BlockMeta, +#[derive(Debug, Clone, Default, Encode, Decode, TypeInfo, PartialEq, Eq)] +pub(crate) struct BlockSmallData { + pub block_header: Option, + pub block_is_synced: bool, + pub meta: BlockMeta, } impl BlockMetaStorageRO for Database { @@ -858,7 +871,6 @@ impl OnChainStorageRO for Database { fn code_blob_info(&self, code_id: CodeId) -> Option; fn block_synced(&self, block_hash: H256) -> bool; fn validators(&self, era_index: u64) -> Option; - fn block_validators_committed_for_era(&self, block_hash: H256) -> Option; } } } @@ -871,7 +883,6 @@ impl OnChainStorageRW for Database { fn set_code_blob_info(&self, code_id: CodeId, code_info: CodeBlobInfo); fn set_block_synced(&self, block_hash: H256); fn set_validators(&self, era_index: u64, validator_set: ValidatorsVec); - fn set_block_validators_committed_for_era(&self, block_hash: H256, era_index: u64); } } } @@ -883,6 +894,7 @@ impl AnnounceStorageRO for Database { fn announce_outcome(&self, announce_hash: HashOf) -> Option>; fn announce_schedule(&self, announce_hash: HashOf) -> Option; fn announce_meta(&self, announce_hash: HashOf) -> AnnounceMeta; + fn block_announces(&self, block_hash: H256) -> Option>>; }); } @@ -901,6 +913,12 @@ impl AnnounceStorageRW for Database { announce_hash: HashOf, f: impl FnOnce(&mut AnnounceMeta), ); + fn set_block_announces(&self, block_hash: H256, announces: BTreeSet>); + fn mutate_block_announces( + &self, + block_hash: H256, + f: impl FnOnce(&mut BTreeSet>), + ); }); } diff --git a/ethexe/db/src/iterator.rs b/ethexe/db/src/iterator.rs index b77089cae8c..28653dce8d3 100644 --- a/ethexe/db/src/iterator.rs +++ b/ethexe/db/src/iterator.rs @@ -523,16 +523,10 @@ where } fn iter_block_meta(&mut self, BlockMetaNode { block, meta }: &BlockMetaNode) { - let BlockMeta { - prepared: _, - announces, - codes_queue, - last_committed_batch: _, - last_committed_announce: _, - } = meta; - - if let Some(announces) = announces { - for &announce_hash in announces { + let BlockMeta { codes_queue, .. } = meta; + + if let Some(announces) = self.storage.block_announces(*block) { + for announce_hash in announces.into_iter() { try_push_node!(with_hash: self.announce(announce_hash)); } } else { diff --git a/ethexe/db/src/migrations/mod.rs b/ethexe/db/src/migrations/mod.rs index ce9ad2a33db..db216e4d05e 100644 --- a/ethexe/db/src/migrations/mod.rs +++ b/ethexe/db/src/migrations/mod.rs @@ -31,10 +31,11 @@ mod migration; mod v0; mod v1; +mod v2; pub const OLDEST_SUPPORTED_VERSION: u32 = v0::VERSION; -pub const LATEST_VERSION: u32 = v1::VERSION; -pub const MIGRATIONS: &[&dyn Migration] = &[&v1::migration_from_v0]; +pub const LATEST_VERSION: u32 = v2::VERSION; +pub const MIGRATIONS: &[&dyn Migration] = &[&v1::migration_from_v0, &v2::migration_from_v1]; const _: () = assert!( (LATEST_VERSION - OLDEST_SUPPORTED_VERSION) as usize == MIGRATIONS.len(), diff --git a/ethexe/db/src/migrations/v0.rs b/ethexe/db/src/migrations/v0.rs index 70947abb2d2..3dcb27cdae1 100644 --- a/ethexe/db/src/migrations/v0.rs +++ b/ethexe/db/src/migrations/v0.rs @@ -16,10 +16,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use ethexe_common::{Announce, HashOf, SimpleBlockData}; -use gprimitives::H256; +use ethexe_common::{Announce, BlockHeader, HashOf, SimpleBlockData}; +use gprimitives::{CodeId, H256}; +use gsigner::Digest; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; +use std::collections::{BTreeSet, VecDeque}; pub const VERSION: u32 = 0; @@ -40,3 +42,19 @@ pub struct ProtocolTimelines { pub era: u64, pub election: u64, } + +#[derive(Encode, Decode, TypeInfo)] +pub struct BlockMeta { + pub prepared: bool, + pub announces: Option>>, + pub codes_queue: Option>, + pub last_committed_batch: Option, + pub last_committed_announce: Option>, +} + +#[derive(Encode, Decode, TypeInfo)] +pub struct BlockSmallData { + pub block_header: Option, + pub block_is_synced: bool, + pub meta: BlockMeta, +} diff --git a/ethexe/db/src/migrations/v2.rs b/ethexe/db/src/migrations/v2.rs new file mode 100644 index 00000000000..be2457853f0 --- /dev/null +++ b/ethexe/db/src/migrations/v2.rs @@ -0,0 +1,121 @@ +// This file is part of Gear. +// +// Copyright (C) 2026 Gear Technologies Inc. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::{InitConfig, RawDatabase, database::BlockSmallData, migrations::v0}; +use anyhow::{Context, Result}; +use ethexe_common::db::{BlockMeta, DBConfig}; +use gprimitives::H256; +use parity_scale_codec::{Decode, Encode}; + +pub const VERSION: u32 = 2; + +pub async fn migration_from_v1(_: &InitConfig, db: &RawDatabase) -> Result<()> { + // Changes from v1 to v2: + // - Block announces are moved from `BlockMeta` to `BlockAnnounces` key. + // - `LatestEraValidators` key is merged into `BlockMeta`. + + let block_small_data_prefix = H256::from_low_u64_be(0); + let block_announces_prefix = H256::from_low_u64_be(13); + let latest_era_prefix = H256::from_low_u64_be(16); + + for (key, value) in db.kv.iter_prefix(block_small_data_prefix.as_bytes()) { + let v0::BlockSmallData { + block_header, + block_is_synced, + meta: + v0::BlockMeta { + prepared, + announces, + codes_queue, + last_committed_batch, + last_committed_announce, + }, + } = v0::BlockSmallData::decode(&mut value.as_slice())?; + + let block_hash = &key[32..]; + + let announces_key = [block_announces_prefix.as_bytes(), block_hash].concat(); + let latest_era_key = [latest_era_prefix.as_bytes(), block_hash].concat(); + + let latest_era_validators_committed = db + .kv + .get(&latest_era_key) + .context("`LatestEraValidators` is not found for block") + .and_then(|bytes| Ok(u64::decode(&mut bytes.as_slice())?))?; + + db.kv.put(&announces_key, announces.encode()); + + db.kv.put( + &key, + BlockSmallData { + block_header, + block_is_synced, + meta: BlockMeta { + prepared, + codes_queue, + last_committed_batch, + last_committed_announce, + latest_era_validators_committed, + }, + } + .encode(), + ); + } + + let config_key = [H256::from_low_u64_be(15).0.as_slice(), &[0u8; 8]].concat(); + + let old_config = db + .kv + .get(&config_key) + .context("Database config are guaranteed for version 1, but not found") + .and_then(|bytes| Ok(DBConfig::decode(&mut bytes.as_slice())?))?; + + db.kv.put( + &config_key, + DBConfig { + version: VERSION, + ..old_config + } + .encode(), + ); + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::migrations::test::assert_migration_types_hash; + use ethexe_common::db::DBConfig; + use scale_info::meta_type; + + #[test] + fn ensure_migration_types() { + assert_migration_types_hash( + "v1->v2", + vec![ + meta_type::(), + meta_type::(), + meta_type::(), + meta_type::(), + meta_type::(), + ], + "6506461993fe4e74645148eb4af27aecfef09e5b4789b5b9936c86adab62a8ff", + ); + } +} diff --git a/ethexe/db/src/verifier.rs b/ethexe/db/src/verifier.rs index f321b459f59..89f1f6c973b 100644 --- a/ethexe/db/src/verifier.rs +++ b/ethexe/db/src/verifier.rs @@ -23,7 +23,7 @@ use crate::{ }; use ethexe_common::{ Announce, BlockHeader, HashOf, ScheduledTask, - db::{AnnounceStorageRO, BlockMeta, BlockMetaStorageRO, OnChainStorageRO}, + db::{AnnounceStorageRO, BlockMeta, OnChainStorageRO}, }; use ethexe_runtime_common::state::{MessageQueue, MessageQueueHashWithSize}; use gear_core::code::CodeMetadata; @@ -166,7 +166,7 @@ impl DatabaseVisitor for IntegrityVerifier { self.errors .push(IntegrityVerifierError::NoBlockLastCommittedAnnounce(block)); } - if let Some(announces) = meta.announces { + if let Some(announces) = self.db.block_announces(block) { if announces.is_empty() { self.errors .push(IntegrityVerifierError::BlockAnnouncesIsEmpty(block)); @@ -185,8 +185,7 @@ impl DatabaseVisitor for IntegrityVerifier { } if self .db - .block_meta(announce.block_hash) - .announces + .block_announces(announce.block_hash) .map(|announces| announces.iter().all(|a| *a != announce_hash)) .unwrap_or(true) { @@ -694,11 +693,11 @@ mod tests { db.set_block_header(block_hash, block_header); db.set_block_events(block_hash, &[]); + db.set_block_announces(block_hash, [announce_hash].into()); db.mutate_block_meta(block_hash, |meta| { meta.prepared = true; meta.last_committed_batch = Some(Digest::random()); meta.last_committed_announce = Some(announce_hash); - meta.announces = Some([announce_hash].into()); meta.codes_queue = Some(Default::default()); }); db.set_block_synced(block_hash); diff --git a/ethexe/network/src/db_sync/mod.rs b/ethexe/network/src/db_sync/mod.rs index a021344d006..20b3d92d3a7 100644 --- a/ethexe/network/src/db_sync/mod.rs +++ b/ethexe/network/src/db_sync/mod.rs @@ -1351,13 +1351,12 @@ pub(crate) mod tests { .set_programs_code_ids_at(program_ids.clone(), H256::zero(), code_ids.clone()) .await; - let mut announce_hash = HashOf::zero(); - right_db.mutate_block_meta(H256::zero(), |meta| { - assert!(meta.announces.is_none()); - let announce = Announce::base(H256::zero(), HashOf::zero()); - announce_hash = announce.to_hash(); - meta.announces = Some([announce_hash].into()); + let announce = Announce::base(H256::zero(), HashOf::zero()); + let announce_hash = announce.to_hash(); + right_db.mutate_block_announces(H256::zero(), |announces| { + announces.insert(announce_hash); }); + right_db.mutate_block_meta(H256::zero(), |_meta| {}); right_db.set_announce_program_states( announce_hash, diff --git a/ethexe/network/src/db_sync/responses.rs b/ethexe/network/src/db_sync/responses.rs index 8981d3f8017..34c4ae0a01b 100644 --- a/ethexe/network/src/db_sync/responses.rs +++ b/ethexe/network/src/db_sync/responses.rs @@ -25,7 +25,7 @@ use crate::{ }; use ethexe_common::{ Announce, HashOf, - db::{AnnounceStorageRO, BlockMetaStorageRO, ConfigStorageRO, GlobalsStorageRO}, + db::{AnnounceStorageRO, ConfigStorageRO, GlobalsStorageRO}, network::{AnnouncesRequest, AnnouncesRequestUntil}, }; use libp2p::request_response; @@ -84,8 +84,7 @@ impl OngoingResponses { ) .into(), InnerRequest::ProgramIds(request) => InnerProgramIdsResponse( - db.block_meta(request.at) - .announces + db.block_announces(request.at) .into_iter() .flatten() .find_map(|announce_hash| db.announce_program_states(announce_hash)) diff --git a/ethexe/rpc/src/apis/mod.rs b/ethexe/rpc/src/apis/mod.rs index 8ed642f4ca1..8a0d0275584 100644 --- a/ethexe/rpc/src/apis/mod.rs +++ b/ethexe/rpc/src/apis/mod.rs @@ -24,9 +24,11 @@ mod program; pub use block::{BlockApi, BlockServer}; pub use code::{CodeApi, CodeServer}; pub use injected::{InjectedApi, InjectedServer}; -pub use program::{FullProgramState, ProgramApi, ProgramServer}; +pub use program::{ProgramApi, ProgramServer}; #[cfg(feature = "client")] pub use crate::apis::{ block::BlockClient, code::CodeClient, injected::InjectedClient, program::ProgramClient, }; +#[cfg(feature = "client")] +pub use program::FullProgramState; diff --git a/ethexe/rpc/src/utils.rs b/ethexe/rpc/src/utils.rs index 9bd1cec3bd3..a96aeafbd7c 100644 --- a/ethexe/rpc/src/utils.rs +++ b/ethexe/rpc/src/utils.rs @@ -19,7 +19,7 @@ use crate::errors; use ethexe_common::{ Announce, HashOf, SimpleBlockData, - db::{AnnounceStorageRO, BlockMetaStorageRO, GlobalsStorageRO, OnChainStorageRO}, + db::{AnnounceStorageRO, GlobalsStorageRO, OnChainStorageRO}, }; use ethexe_db::Database; use jsonrpsee::core::RpcResult; @@ -54,8 +54,7 @@ pub fn announce_at_or_latest_computed( ) -> RpcResult> { if let Some(at) = at.into() { let computed_announces: Vec<_> = db - .block_meta(at) - .announces + .block_announces(at) .into_iter() .flatten() .filter(|announce_hash| db.announce_meta(*announce_hash).computed) diff --git a/ethexe/service/src/tests/mod.rs b/ethexe/service/src/tests/mod.rs index a02f55aaae4..7c225b78d68 100644 --- a/ethexe/service/src/tests/mod.rs +++ b/ethexe/service/src/tests/mod.rs @@ -1646,9 +1646,9 @@ async fn fast_sync() { bob_meta.last_committed_batch ); - let Some((alice_announces, bob_announces)) = - alice_meta.announces.zip(bob_meta.announces) - else { + let alice_announces = alice.db.block_announces(block); + let bob_announces = bob.db.block_announces(block); + let Some((alice_announces, bob_announces)) = alice_announces.zip(bob_announces) else { panic!("alice or bob has no announces"); }; @@ -2983,8 +2983,7 @@ async fn announces_conflicts() { let timelines = env.db.config().timelines; let era_index = timelines.era_from_ts(block.header.timestamp); let parent = validator1_db - .block_meta(block.header.parent_hash) - .announces + .block_announces(block.header.parent_hash) .into_iter() .flatten() .find(|&announce_hash| validator1_db.announce(announce_hash).unwrap().is_base()) diff --git a/utils/gear-workspace-hack/Cargo.toml b/utils/gear-workspace-hack/Cargo.toml index 147d61f8e92..6d7413ed7f8 100644 --- a/utils/gear-workspace-hack/Cargo.toml +++ b/utils/gear-workspace-hack/Cargo.toml @@ -262,6 +262,7 @@ concurrent-queue = { version = "2" } const-hex = { version = "1", features = ["core-error", "serde"] } constant_time_eq = { version = "0.4", default-features = false, features = ["std"] } crc32fast = { version = "1" } +crossbeam-channel = { version = "0.5" } crossbeam-utils = { version = "0.8" } crunchy = { version = "0.2", features = ["std"] } crypto-common = { version = "0.1", default-features = false, features = ["getrandom", "std"] } @@ -403,7 +404,6 @@ sha3 = { version = "0.10", features = ["asm"] } signature = { version = "2", default-features = false, features = ["digest", "rand_core", "std"] } slice-group-by = { version = "0.3" } smallvec = { version = "1", default-features = false, features = ["const_new", "serde", "union"] } -socket2 = { version = "0.4", default-features = false, features = ["all"] } soketto = { version = "0.8", features = ["http"] } sp-allocator = { git = "https://github.com/gear-tech/polkadot-sdk.git", branch = "gear-polkadot-stable2409-wasm32v1-none" } sp-api = { git = "https://github.com/gear-tech/polkadot-sdk.git", branch = "gear-polkadot-stable2409-wasm32v1-none", features = ["frame-metadata"] } @@ -539,6 +539,7 @@ concurrent-queue = { version = "2" } const-hex = { version = "1", features = ["core-error", "serde"] } constant_time_eq = { version = "0.4", default-features = false, features = ["std"] } crc32fast = { version = "1" } +crossbeam-channel = { version = "0.5" } crossbeam-utils = { version = "0.8" } crunchy = { version = "0.2", features = ["std"] } crypto-common = { version = "0.1", default-features = false, features = ["getrandom", "std"] } @@ -688,7 +689,6 @@ sha3 = { version = "0.10", features = ["asm"] } signature = { version = "2", default-features = false, features = ["digest", "rand_core", "std"] } slice-group-by = { version = "0.3" } smallvec = { version = "1", default-features = false, features = ["const_new", "serde", "union"] } -socket2 = { version = "0.4", default-features = false, features = ["all"] } soketto = { version = "0.8", features = ["http"] } sp-allocator = { git = "https://github.com/gear-tech/polkadot-sdk.git", branch = "gear-polkadot-stable2409-wasm32v1-none" } sp-api = { git = "https://github.com/gear-tech/polkadot-sdk.git", branch = "gear-polkadot-stable2409-wasm32v1-none", features = ["frame-metadata"] } @@ -781,7 +781,7 @@ errno = { version = "0.3" } gimli = { version = "0.28" } hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "ring", "tls12", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } -itertools-a6292c17cd707f01 = { package = "itertools", version = "0.11" } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13", default-features = false, features = ["use_std"] } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } mio = { version = "1", features = ["net", "os-ext"] } @@ -806,7 +806,7 @@ errno = { version = "0.3" } gimli = { version = "0.28" } hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "ring", "tls12", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } -itertools-a6292c17cd707f01 = { package = "itertools", version = "0.11" } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13", default-features = false, features = ["use_std"] } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } mio = { version = "1", features = ["net", "os-ext"] } @@ -832,7 +832,7 @@ errno = { version = "0.3" } gimli = { version = "0.28" } hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "ring", "tls12", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } -itertools-a6292c17cd707f01 = { package = "itertools", version = "0.11" } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13", default-features = false, features = ["use_std"] } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } mio = { version = "1", features = ["net", "os-ext"] } @@ -856,7 +856,7 @@ errno = { version = "0.3" } gimli = { version = "0.28" } hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "ring", "tls12", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } -itertools-a6292c17cd707f01 = { package = "itertools", version = "0.11" } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13", default-features = false, features = ["use_std"] } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } mio = { version = "1", features = ["net", "os-ext"] } @@ -881,7 +881,7 @@ errno = { version = "0.3" } gimli = { version = "0.28" } hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "ring", "tls12", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } -itertools-a6292c17cd707f01 = { package = "itertools", version = "0.11" } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13", default-features = false, features = ["use_std"] } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } nom = { version = "7" } @@ -903,7 +903,7 @@ errno = { version = "0.3" } gimli = { version = "0.28" } hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "ring", "tls12", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } -itertools-a6292c17cd707f01 = { package = "itertools", version = "0.11" } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13", default-features = false, features = ["use_std"] } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } nom = { version = "7" }