Skip to content

Commit e8d1fcd

Browse files
author
David Himmelstrup
authored
feat: Replace Chain Muxer with a simpler state-machine (#5322)
1 parent 6708366 commit e8d1fcd

File tree

28 files changed

+1323
-2446
lines changed

28 files changed

+1323
-2446
lines changed

src/blocks/block.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,19 @@ pub const BLOCK_MESSAGE_LIMIT: usize = 10000;
1414

1515
/// A complete Filecoin block. This contains the block header as well as all BLS
1616
/// and SECP messages.
17-
#[derive(Clone, Debug, PartialEq)]
17+
#[derive(Clone, Debug, PartialEq, Eq)]
1818
pub struct Block {
1919
pub header: CachingBlockHeader,
2020
pub bls_messages: Vec<Message>,
2121
pub secp_messages: Vec<SignedMessage>,
2222
}
2323

24+
impl std::hash::Hash for Block {
25+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
26+
std::hash::Hash::hash(self.cid(), state)
27+
}
28+
}
29+
2430
impl Block {
2531
pub fn header(&self) -> &CachingBlockHeader {
2632
&self.header

src/blocks/chain4u.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,24 @@ impl Chain4UInner {
289289
});
290290
header.state_root.close_with(Cid::default);
291291

292+
// Message root
293+
///////////////
294+
header.messages.close_with(|| {
295+
use crate::utils::db::CborStoreExt as _;
296+
use fil_actors_shared::fvm_ipld_amt::Amtv0 as Amt;
297+
298+
let blockstore = MemoryDB::default();
299+
let bls_message_root = Amt::<Cid, _>::new(&blockstore).flush().unwrap();
300+
let secp_message_root = Amt::<Cid, _>::new(&blockstore).flush().unwrap();
301+
let meta = TxMeta {
302+
bls_message_root,
303+
secp_message_root,
304+
};
305+
306+
// Store message roots and receive meta_root CID
307+
blockstore.put_cbor_default(&meta).unwrap()
308+
});
309+
292310
// Miner
293311
////////
294312
let sibling_miner_addresses = siblings

src/blocks/header.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ impl PartialEq for CachingBlockHeader {
233233
}
234234
}
235235

236+
impl Eq for CachingBlockHeader {}
237+
236238
impl Clone for CachingBlockHeader {
237239
fn clone(&self) -> Self {
238240
Self {

src/blocks/tipset.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,24 @@ impl TipsetKey {
6767
pub fn len(&self) -> usize {
6868
self.0.len()
6969
}
70+
71+
/// Terse representation of the tipset key.
72+
/// `bafy2bzaceaqrqoasufr7gdwrbhvlfy2xmc4e5sdzekjgyha2kldxigu73gilo`
73+
/// becomes `eaq...ilo`. The `bafy2bzac` prefix is removed.
74+
pub fn terse(&self) -> String {
75+
fn terse_cid(cid: Cid) -> String {
76+
let s = cid::multibase::encode(
77+
cid::multibase::Base::Base32Lower,
78+
cid.to_bytes().as_slice(),
79+
);
80+
format!("{}...{}", &s[9..12], &s[s.len() - 3..])
81+
}
82+
self.to_cids()
83+
.into_iter()
84+
.map(terse_cid)
85+
.collect::<Vec<_>>()
86+
.join(", ")
87+
}
7088
}
7189

7290
impl From<NonEmpty<Cid>> for TipsetKey {
@@ -412,13 +430,19 @@ impl Tipset {
412430

413431
/// `FullTipset` is an expanded version of a tipset that contains all the blocks
414432
/// and messages.
415-
#[derive(Debug, Clone)]
433+
#[derive(Debug, Clone, Eq)]
416434
pub struct FullTipset {
417435
blocks: NonEmpty<Block>,
418436
// key is lazily initialized via `fn key()`.
419437
key: OnceCell<TipsetKey>,
420438
}
421439

440+
impl std::hash::Hash for FullTipset {
441+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
442+
self.key().hash(state)
443+
}
444+
}
445+
422446
// Constructing a FullTipset from a single Block is infallible.
423447
impl From<Block> for FullTipset {
424448
fn from(block: Block) -> Self {
@@ -480,6 +504,10 @@ impl FullTipset {
480504
pub fn parent_state(&self) -> &Cid {
481505
&self.first_block().header().state_root
482506
}
507+
/// Returns the state root for the tipset parent.
508+
pub fn parents(&self) -> &TipsetKey {
509+
&self.first_block().header().parents
510+
}
483511
/// Returns epoch of the tipset.
484512
pub fn epoch(&self) -> ChainEpoch {
485513
self.first_block().header().epoch

src/chain/store/chain_store.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use super::{
66
tipset_tracker::TipsetTracker,
77
Error,
88
};
9-
use crate::db::{EthMappingsStore, EthMappingsStoreExt};
109
use crate::fil_cns;
1110
use crate::interpreter::{BlockMessages, VMEvent, VMTrace};
1211
use crate::libp2p_bitswap::{BitswapStoreRead, BitswapStoreReadWrite};
@@ -24,6 +23,10 @@ use crate::{
2423
blocks::{CachingBlockHeader, Tipset, TipsetKey, TxMeta},
2524
db::HeaviestTipsetKeyProvider,
2625
};
26+
use crate::{
27+
chain_sync::metrics,
28+
db::{EthMappingsStore, EthMappingsStoreExt},
29+
};
2730
use ahash::{HashMap, HashMapExt, HashSet};
2831
use anyhow::Context as _;
2932
use cid::Cid;
@@ -36,7 +39,7 @@ use parking_lot::{Mutex, RwLock};
3639
use serde::{de::DeserializeOwned, Serialize};
3740
use std::{num::NonZeroUsize, sync::Arc};
3841
use tokio::sync::broadcast::{self, Sender as Publisher};
39-
use tracing::{debug, info, trace, warn};
42+
use tracing::{debug, trace, warn};
4043

4144
// A cap on the size of the future_sink
4245
const SINK_CAP: usize = 200;
@@ -139,6 +142,7 @@ where
139142

140143
/// Sets heaviest tipset
141144
pub fn set_heaviest_tipset(&self, ts: Arc<Tipset>) -> Result<(), Error> {
145+
metrics::HEAD_EPOCH.set(ts.epoch());
142146
self.heaviest_tipset_key_provider
143147
.set_heaviest_tipset_key(ts.key())?;
144148
if self.publisher.send(HeadChange::Apply(ts)).is_err() {
@@ -255,7 +259,6 @@ where
255259
let curr_weight = heaviest_weight;
256260

257261
if new_weight > curr_weight {
258-
info!("New heaviest tipset! {} (EPOCH = {})", ts.key(), ts.epoch());
259262
self.set_heaviest_tipset(ts)?;
260263
}
261264
Ok(())

src/chain_sync/bad_block_cache.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use lru::LruCache;
88
use nonzero_ext::nonzero;
99
use parking_lot::Mutex;
1010

11+
use crate::blocks::TipsetKey;
12+
1113
/// Thread-safe cache for tracking bad blocks.
1214
/// This cache is checked before validating a block, to ensure no duplicate
1315
/// work.
@@ -34,15 +36,21 @@ impl BadBlockCache {
3436
self.cache.lock().put(c, reason)
3537
}
3638

37-
/// Returns `Some` with the reason if the block CID is in bad block cache.
38-
/// This also updates the key to the head of the cache.
39-
pub fn get(&self, c: &Cid) -> Option<String> {
40-
self.cache.lock().get(c).cloned()
41-
}
42-
4339
/// Returns `Some` with the reason if the block CID is in bad block cache.
4440
/// This function does not update the head position of the `Cid` key.
4541
pub fn peek(&self, c: &Cid) -> Option<String> {
4642
self.cache.lock().peek(c).cloned()
4743
}
44+
45+
/// Returns `Some` with the reason if there are any known bad blocks in the tipset.
46+
/// This function does not update the head position of the `Cid` key.
47+
pub fn peek_tipset_key(&self, tipset_key: &TipsetKey) -> Option<String> {
48+
let cache = self.cache.lock();
49+
for block in tipset_key.iter() {
50+
if let Some(reason) = cache.peek(&block) {
51+
return Some(reason.clone());
52+
}
53+
}
54+
None
55+
}
4856
}

0 commit comments

Comments
 (0)