Skip to content
Open

Slasher #1041

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
c1546a3
fix(consensus): duplicate stats emission
Mododo Mar 17, 2026
be55375
feat(consensus): engine starts once per TKA
Mododo Mar 19, 2026
3b09634
fix(consensus): tighten config
Mododo Mar 19, 2026
e3d9768
fix(build): remove unused feature
Mododo Mar 23, 2026
25c1673
feat(consensus): include anchor in its history
Mododo Mar 15, 2026
577e65b
chore: bump version
Rexagon Mar 24, 2026
a31514e
fix(consensus): don't read DB on overlay change
Mododo Mar 25, 2026
b11183e
feat(core)!: rework state apply
Rexagon Feb 13, 2026
805797a
fix(storage): skip quick_cache insertion on cell reads to prevent mem…
pashinov Mar 13, 2026
a655b0d
fix(collator): clean shard_blocks cache using top blocks from MC stat…
pashinov Mar 14, 2026
b29d386
feat(storage): force direct state store when new cells exceed threshold
pashinov Mar 15, 2026
db8525c
feat(storage): restore ghost allocation in raw cells cache and add ac…
pashinov Mar 16, 2026
1ca72e5
feat(storage): defer block data loading to reduce ram usage
Rexagon Mar 17, 2026
8e6066e
feat(storage): warmup RawCellsCache; bump tycho-types
pashinov Mar 31, 2026
ef5cc5d
feat(consensus): moderator core
Mododo Mar 27, 2026
92c3a48
feat(consensus): moderator events
Mododo Mar 27, 2026
175d1ef
feat(cli): bind moderator to node
Mododo Mar 27, 2026
fdf5c14
feat(consensus): bind query limits to moderator
Mododo Dec 5, 2025
165e95e
feat(consensus): bind round inspector to moderator
Mododo Mar 27, 2026
6075995
feat(control): moderator list events
Mododo Mar 27, 2026
6c2539c
feat(control): moderator (un)ban and delete
Mododo Mar 27, 2026
106a810
feat(control): moderator dump bans and events
Mododo Nov 17, 2025
d65d31a
feat(control): moderator get point
Mododo Nov 17, 2025
06c2d2f
feat(simulator): mempool control server
Mododo Dec 16, 2025
dbe5086
chore: bump version
Rexagon Apr 6, 2026
963e890
feat(slasher): add slasher crates
Rexagon Jul 17, 2025
9a5fc9f
feat(collator): propagate original vset item index
Rexagon Nov 25, 2025
754c8cf
feat(core): add boxed block/state subscribers
Rexagon Nov 28, 2025
2374245
feat(slasher): send block batches to the slasher contract
Rexagon Dec 24, 2025
bc5999c
feat(slasher): add stub contract
Rexagon Dec 25, 2025
0e30625
feat(slasher): persistent storage
Rexagon Jan 15, 2026
bb97523
feat(slasher): check blocks batch seqno range
Rexagon Feb 2, 2026
3d8b9ae
chore(core): change ValidationSessionId signature
MrWad3r Feb 24, 2026
e629dd2
chore(contracts): propagate new validation session id into contract
MrWad3r Mar 10, 2026
26ade7a
feat(slasher): add slasher analyzer to create signatures reports
MrWad3r Mar 11, 2026
7a186ad
chore(contract): bump dependencies
MrWad3r Mar 20, 2026
f142825
chore(slasher): update cc_seqno derivation from `KbNextSessionUpdate`
MrWad3r Mar 17, 2026
3d6ea72
chore(slasher): add slasher generation to zerostate
MrWad3r Mar 17, 2026
d151b80
chore(slasher): add logs with `slasher` target
MrWad3r Mar 17, 2026
1de5ae8
chore(slasher): review pt.1
MrWad3r Mar 26, 2026
8542d1f
chore(slasher): fix signature condition
MrWad3r Mar 27, 2026
0e96c8a
fix(collator): shuffle with vset_switch_round
Mododo Apr 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,655 changes: 930 additions & 725 deletions Cargo.lock

Large diffs are not rendered by default.

111 changes: 57 additions & 54 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace.package]
version = "0.3.6"
version = "0.3.8"
edition = "2024"
authors = ["Broxus Team"]
rust-version = "1.91.0"
Expand All @@ -16,15 +16,16 @@ members = [
"control",
"core",
"gen-protos",
"light-node",
"network",
"rpc",
"simulator",
"storage",
"slasher-traits",
"slasher",
"storage-traits",
"storage",
"tycho-build-info",
"util",
"util-proc",
"util",
"wu-tuner",
"rpc-subscriptions",
]
Expand All @@ -41,51 +42,51 @@ backon = "1.5.1"
base64 = "0.22.0"
bitflags = "2.6"
blake3 = "1.5.3"
bumpalo = "3.14.0"
bumpalo = "3.20.2"
bumpalo-herd = "0.1.2"
bytes = "1.9.0"
bytesize = { version = "1.3.0", features = ["serde"] }
cassadilia = { version = "0.4.7" }
castaway = "0.2"
clap = { version = "4.5.3", features = ["derive"] }
clap = { version = "4.6.0", features = ["derive"] }
clap-markdown = "0.1.4"
crc32c = "0.6"
criterion = "0.7.0"
criterion = "0.8.0"
crossbeam-deque = "0.8.6"
crossbeam-queue = "0.3.12"
dashmap = "6.1.0"
dirs = "6.0.0"
ed25519 = "2.0"
ed25519-dalek = "2.1"
ed25519 = "2.2.3"
ed25519-dalek = "2.2.0"
exponential-backoff = "1.2.1"
fdlimit = "0.3.0"
futures-executor = "0.3"
futures-util = "0.3"
governor = { version = "0.9", default-features = false, features = ["std", "quanta"] }
getip = "0.2.0"
getip = "0.2.1"
hdrhistogram = "7.5.4"
hex = "0.4"
http-body-util = "0.1.3"
humantime = "2"
indexmap = "2.2"
indexmap = "2.13"
itertools = "0.14"
libc = "0.2"
metrics = "0.24"
metrics-exporter-prometheus = "0.17"
metrics-exporter-prometheus = "0.18"
moka = { version = "0.12", features = ["sync"] }
num-bigint = "0.4.6"
num-traits = "0.2.19"
parking_lot = { version = "0.12.1" }
parking_lot_core = "0.9.9"
parking_lot = { version = "0.12.5" }
parking_lot_core = "0.9.12"
pin-project-lite = "0.2"
pkcs8 = "0.10"
proc-macro2 = "1.0"
prost = "0.14.1"
prost-build = "0.14.1"
quick_cache = "0.6.0"
prost = "0.14.3"
prost-build = "0.14.3"
quick_cache = "0.6.21"
quinn = { version = "0.11.9", default-features = false, features = ["runtime-tokio", "rustls"] }
quote = "1.0"
object_store = "0.12"
object_store = "0.13"
rand = "0.9"
rand_distr = "0.5"
rand_pcg = { version = "0.9" }
Expand All @@ -94,20 +95,20 @@ reqwest = { version = "0.12", default-features = false }
ring = "0.17.14"
rlimit = "0.10.1"
rustc_version = "0.4"
rustls = "0.23.28"
rustls-pki-types = "1.12"
rustls-webpki = "0.103.3"
rustls = "0.23.37"
rustls-pki-types = "1.14"
rustls-webpki = "0.103.10"
similar-asserts = "1.7.0" # looks better than pretty_assertions(compresses output)
scc = "2.3.3"
scc = "2.4.0"
scopeguard = "1.2"
serde = "1.0"
serde_json = "1.0.114"
serde_path_to_error = "0.1"
sha2 = "0.10.8"
smallvec = "1.13.1"
socket2 = "0.6.0"
sha2 = "0.10.9"
smallvec = "1.15.1"
socket2 = "0.6.3"
syn = "2.0.104"
sysinfo = "0.37"
sysinfo = "0.38.4"
tabled = { version = "0.20.0", default-features = false }
tarpc = { version = "0.37", features = [
"tokio1",
Expand All @@ -116,54 +117,56 @@ tarpc = { version = "0.37", features = [
"serde-transport-bincode",
"unix",
] }
tempfile = "3.10"
tempfile = "3.27"
thiserror = "2.0"
tikv-jemallocator = { version = "0.6.0", features = [
tikv-jemallocator = { version = "0.6.1", features = [
"unprefixed_malloc_on_supported_platforms",
"background_threads",
] }
tikv-jemalloc-ctl = { version = "0.6.0", features = ["stats"] }
tl-proto = "0.5.1"
tikv-jemalloc-ctl = { version = "0.6.1", features = ["stats"] }
tl-proto = "0.5.4"
tokio = { version = "1", default-features = false }
tokio-stream = "0.1.15"
tokio-util = { version = "0.7.10", default-features = false, features = ["codec"] }
tokio-stream = "0.1.18"
tokio-util = { version = "0.7.18", default-features = false, features = ["codec"] }
tower = "0.5"
tower-http = "0.6"
tracing = "0.1"
tracing-appender = "0.2.3"
tracing-appender = "0.2.4"
tracing-flame = "0.2"
tracing-stackdriver = "0.10.0"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
triomphe = "0.1.11"
triomphe = "0.1.15"
tycho-crypto = { version = "0.4", features = ["tl-proto", "serde", "rand9"] }
tycho-executor = "0.3.2"
tycho-types = { version = "0.3.2", features = ["tycho", "stats"] }
tycho-vm = "0.3.2"
uuid = "1.18.1"
tycho-executor = "0.3.5"
tycho-types = { version = "0.3.4", features = ["tycho", "stats"] }
tycho-vm = "0.3.5"
uuid = "1.22.0"
walkdir = "2.5.0"
weedb = "0.6.0"
zstd-safe = "7.2"
zstd-sys = "2.0"

# local deps
tycho-block-util = { path = "./block-util", version = "0.3.6" }
tycho-build-info = { path = "./tycho-build-info", version = "0.3.6" }
tycho-collator = { path = "./collator", version = "0.3.6" }
tycho-consensus = { path = "./consensus", version = "0.3.6" }
tycho-control = { path = "./control", version = "0.3.6" }
tycho-core = { path = "./core", version = "0.3.6" }
tycho-network = { path = "./network", version = "0.3.6" }
tycho-rpc-subscriptions = { path = "./rpc-subscriptions", version = "0.3.6" }
tycho-rpc = { path = "./rpc", version = "0.3.6" }
tycho-storage = { path = "./storage", version = "0.3.6" }
tycho-storage-traits = { path = "./storage-traits", version = "0.3.6" }
tycho-util = { path = "./util", version = "0.3.6" }
tycho-util-proc = { path = "./util-proc", version = "0.3.6" }
tycho-wu-tuner = { path = "./wu-tuner", version = "0.3.6" }
tycho-block-util = { path = "./block-util", version = "0.3.8" }
tycho-build-info = { path = "./tycho-build-info", version = "0.3.8" }
tycho-collator = { path = "./collator", version = "0.3.8" }
tycho-consensus = { path = "./consensus", version = "0.3.8" }
tycho-control = { path = "./control", version = "0.3.8" }
tycho-core = { path = "./core", version = "0.3.8" }
tycho-network = { path = "./network", version = "0.3.8" }
tycho-rpc-subscriptions = { path = "./rpc-subscriptions", version = "0.3.8" }
tycho-rpc = { path = "./rpc", version = "0.3.8" }
tycho-slasher = { path = "./slasher", version = "0.3.8" }
tycho-slasher-traits = { path = "./slasher-traits", version = "0.3.8" }
tycho-storage = { path = "./storage", version = "0.3.8" }
tycho-storage-traits = { path = "./storage-traits", version = "0.3.8" }
tycho-util = { path = "./util", version = "0.3.8" }
tycho-util-proc = { path = "./util-proc", version = "0.3.8" }
tycho-wu-tuner = { path = "./wu-tuner", version = "0.3.8" }

[patch.crates-io]
# patches here
tycho-types = { git = "https://github.com/broxus/tycho-types.git", rev = "1a7bfbf2b2cbf336e58314b4c22f0e8b9805d1b8" }
tycho-types = { git = "https://github.com/broxus/tycho-types.git", rev = "aeea4e8d007e8a64439d3d923a3752fc823b2256" }

[workspace.lints.rust]
future_incompatible = "warn"
Expand All @@ -180,7 +183,7 @@ dbg_macro = "warn"
debug_assert_with_mut_call = "warn"
disallowed_methods = "warn"
doc_markdown = "warn"
empty_enum = "warn"
empty_enums = "warn"
enum_glob_use = "warn"
exit = "warn"
expl_impl_clone_on_copy = "warn"
Expand Down
19 changes: 10 additions & 9 deletions block-util/src/block/block_proof_stuff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ impl BlockProofStuff {

let weight = match signatures
.signatures
.check_signatures(&subset.validators, &checked_data)
.check_signatures(subset.validators.iter().map(AsRef::as_ref), &checked_data)
{
Ok(weight) => weight,
Err(e) => anyhow::bail!("proof contains invalid signatures: {e:?}"),
Expand Down Expand Up @@ -388,15 +388,16 @@ impl BlockProofStuff {
validator_set: &ValidatorSet,
shuffle_validators: bool,
) -> Result<ValidatorSubsetInfo> {
let cc_seqno = self
let Some(vset_switch_round) = self
.inner
.proof
.signatures
.as_ref()
.map(|s| s.validator_info.catchain_seqno)
.unwrap_or_default();

ValidatorSubsetInfo::compute_standard(validator_set, cc_seqno, shuffle_validators)
.map(|s| s.consensus_info.vset_switch_round)
else {
anyhow::bail!("no `consensus_info` to compute subset from");
};
ValidatorSubsetInfo::compute_standard(validator_set, vset_switch_round, shuffle_validators)
}
}

Expand Down Expand Up @@ -520,18 +521,18 @@ fn pre_check_key_block_proof(virt_block: &Block) -> Result<()> {

#[derive(Clone, Debug)]
pub struct ValidatorSubsetInfo {
pub validators: Vec<ValidatorDescription>,
pub validators: Vec<IndexedValidatorDescription>,
pub short_hash: u32,
}

impl ValidatorSubsetInfo {
pub fn compute_standard(
validator_set: &ValidatorSet,
cc_seqno: u32,
vset_switch_round: u32,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: better to rename to switch_round, because the switch round applies not only to the set but also to the subset

shuffle_validators: bool,
) -> Result<Self> {
let Some((validators, short_hash)) =
validator_set.compute_mc_subset(cc_seqno, shuffle_validators)
validator_set.compute_mc_subset_indexed(vset_switch_round, shuffle_validators)
else {
anyhow::bail!("failed to compute a validator subset");
};
Expand Down
43 changes: 17 additions & 26 deletions block-util/src/state/shard_state_stuff.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
use std::mem::ManuallyDrop;
use std::sync::Arc;

use anyhow::{Context, Result};
use anyhow::Result;
use tycho_types::cell::Lazy;
use tycho_types::merkle::MerkleUpdate;
use tycho_types::merkle::{FindCell, ParMerkleUpdateApplier};
use tycho_types::models::*;
use tycho_types::prelude::*;
use tycho_util::FastHashSet;
use tycho_util::mem::Reclaimer;

use crate::dict::split_aug_dict_raw;
use crate::state::RefMcStateHandle;

/// Parsed shard state.
Expand Down Expand Up @@ -136,32 +134,25 @@ impl ShardStateStuff {
/// the `tracker` from the initial state.
///
/// NOTE: Call from inside `rayon`.
pub fn par_make_next_state(
pub fn par_make_next_state<F>(
&self,
next_block_id: &BlockId,
merkle_update: &MerkleUpdate,
split_at_depth: Option<u8>,
) -> Result<Self> {
let old_split_at = if let Some(depth) = split_at_depth {
let shard_accounts = self
.root_cell()
.reference_cloned(1)
.context("invalid shard state")?
.parse::<ShardAccounts>()
.context("failed to load shard accounts")?;

split_aug_dict_raw(shard_accounts, depth)
.context("failed to split shard accounts")?
.into_keys()
.collect::<FastHashSet<_>>()
} else {
Default::default()
partial_new_root: Cell,
applier: &ParMerkleUpdateApplier<'_, F>,
) -> Result<Self>
where
F: FindCell + Send + Sync + 'static,
{
let new_root = 'apply: {
if let Some(cell) = applier.find_cell.find_cell(partial_new_root.hash(0)) {
break 'apply cell;
}

let new =
rayon::scope(|scope| applier.run(partial_new_root.as_ref(), 0, 0, Some(scope)))?;
new.resolve(Cell::empty_context())?
};

let new_root = merkle_update
.par_apply(&self.inner.root, &old_split_at)
.context("failed to apply merkle update")?;

let shard_state = new_root.parse::<Box<ShardStateUnsplit>>()?;
anyhow::ensure!(
shard_state.shard_ident == next_block_id.shard,
Expand Down
17 changes: 9 additions & 8 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
[package]
name = "tycho-cli"
description = "Node CLI."
include = ["src/**/*.rs", "res/**/*.boc", "./LICENSE-*", "./README.md", "build.rs"]
include = [
"src/**/*.rs",
"res/**/*.boc",
"./LICENSE-*",
"./README.md",
"build.rs",
]
version.workspace = true
authors.workspace = true
edition.workspace = true
Expand Down Expand Up @@ -30,7 +36,6 @@ hex = { workspace = true }
humantime = { workspace = true }
num-bigint = { workspace = true }
num-traits = { workspace = true }
parking_lot = { workspace = true }
rand = { workspace = true }
reqwest = { workspace = true, features = ["http2", "json", "rustls-tls"] }
scopeguard = { workspace = true }
Expand All @@ -56,14 +61,15 @@ weedb = { workspace = true }
# local deps
tycho-block-util = { workspace = true }
tycho-collator = { workspace = true }
tycho-consensus = { workspace = true }
tycho-control = { workspace = true, features = ["full"] }
tycho-core = { workspace = true, features = ["cli"] }
tycho-network = { workspace = true }
tycho-rpc = { workspace = true, features = ["http2"] }
tycho-slasher = { workspace = true }
tycho-storage = { workspace = true }
tycho-util = { workspace = true, features = ["cli"] }
tycho-wu-tuner = { workspace = true }
tycho-consensus = { workspace = true }

[dev-dependencies]
tycho-collator = { workspace = true, features = ["test"] }
Expand All @@ -76,14 +82,9 @@ tycho-build-info = { workspace = true }
[features]
default = ["jemalloc"]
jemalloc = ["dep:tikv-jemallocator", "dep:tikv-jemalloc-ctl"]
deadlock-detection = ["parking_lot/deadlock_detection"]
debug = ["tycho-consensus/test", "tycho-consensus/mock-feedback"]
lto = ["weedb/lto"]
s3 = ["tycho-core/s3"]

[lints]
workspace = true

[package.metadata.cargo-shear]
# required for `deadlock-detection` feature
ignored = ["parking_lot"]
Binary file added cli/res/slasher_code.boc
Binary file not shown.
Loading