Skip to content

Commit 6ac36fd

Browse files
AIQnetLabclaude
andcommitted
Fix consensus stall class, heartbeat eligibility/emission, bound storage
- Fork-choice: unify to one deterministic round-based non-destructive reorg (round-supersede + macroblock-anchor); remove the entropy-halt crutch, chain_weight, dead resolve_fork/competing-producer and the fork-poll; observer-rejection becomes non-destructive peer-scoring. - Failover: derive the timeout-vote leader from select_microblock_producer_with_round (pure fn) instead of the evictable cache, fixing the expected=- macroblock-boundary stall. - Heartbeat TX: thread the Dilithium-only Heartbeat through gossip admission (Ed25519-batch skip, is_system_tx, Dilithium verify, skip_nonce) so it lands on-chain so heartbeat_slots/eligibility/emission work; remove the dead HBC Phase-2A scan; classify the Heartbeat type for the explorer. - Storage: EIP-4444-style microblock body-expiry on Super nodes (drop bodies older than 6 epochs; keep hashes, macroblocks, state, snapshots). - benches/full_benchmark: update to the current VRF/storage API. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent b7b46c5 commit 6ac36fd

9 files changed

Lines changed: 159 additions & 956 deletions

File tree

development/qnet-integration/benches/full_benchmark.rs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33

44
use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId, Throughput};
55
use qnet_integration::{
6-
poh::PoH,
7-
vrf::{QNetVrf, select_producer_with_vrf},
6+
vrf::QNetVrf,
7+
vrf_hybrid::select_producer_with_vrf_no_fallback,
88
storage::PersistentStorage,
9-
node::NodeType,
109
};
10+
use pqcrypto_mldsa::mldsa65 as dilithium3;
11+
use pqcrypto_traits::sign::{PublicKey as PkTrait, SecretKey as SkTrait};
1112
use sha3::{Sha3_512, Sha3_256, Digest};
1213
use std::time::Duration;
1314

@@ -48,34 +49,38 @@ fn benchmark_poh_throughput(c: &mut Criterion) {
4849
fn benchmark_vrf_operations(c: &mut Criterion) {
4950
let mut group = c.benchmark_group("vrf_performance");
5051

51-
// VRF initialization
52+
// Dilithium3 keypair, generated once for the init/evaluate/verify benches.
53+
let (pk, sk) = dilithium3::keypair();
54+
let pk_b = PkTrait::as_bytes(&pk).to_vec();
55+
let sk_b = SkTrait::as_bytes(&sk).to_vec();
56+
57+
// VRF initialization (construct + load keys)
5258
group.bench_function("vrf_init", |b| {
5359
b.iter(|| {
54-
let mut vrf = QNetVrf::new();
55-
vrf.initialize("test_node_001").unwrap();
60+
let mut vrf = QNetVrf::new("test_node_001".to_string());
61+
vrf.initialize_from_keys(&pk_b, &sk_b).unwrap();
5662
black_box(vrf)
5763
});
5864
});
59-
65+
6066
// VRF evaluation
61-
let mut vrf = QNetVrf::new();
62-
vrf.initialize("test_node_001").unwrap();
67+
let mut vrf = QNetVrf::new("test_node_001".to_string());
68+
vrf.initialize_from_keys(&pk_b, &sk_b).unwrap();
6369
let input = b"test_input_for_vrf_evaluation";
64-
70+
6571
group.bench_function("vrf_evaluate", |b| {
6672
b.iter(|| {
6773
let output = vrf.evaluate(input).unwrap();
6874
black_box(output)
6975
});
7076
});
71-
77+
7278
// VRF verification
7379
let output = vrf.evaluate(input).unwrap();
74-
let public_key = vrf.get_public_key().unwrap();
75-
80+
7681
group.bench_function("vrf_verify", |b| {
7782
b.iter(|| {
78-
let verified = QNetVrf::verify(&public_key, input, &output).unwrap();
83+
let verified = QNetVrf::verify_static(&pk_b, input, &output).unwrap();
7984
black_box(verified)
8085
});
8186
});
@@ -99,7 +104,7 @@ fn benchmark_producer_selection(c: &mut Criterion) {
99104
|b, candidates| {
100105
b.to_async(tokio::runtime::Runtime::new().unwrap()).iter(|| async {
101106
let entropy = [0x42u8; 32];
102-
let result = select_producer_with_vrf(
107+
let result = select_producer_with_vrf_no_fallback(
103108
1,
104109
candidates,
105110
"test_node",
@@ -160,14 +165,14 @@ fn benchmark_storage(c: &mut Criterion) {
160165
group.bench_function("save_block_1kb", |b| {
161166
let mut height = 0u64;
162167
b.iter(|| {
163-
storage.save_microblock(height, &test_block, "test_hash").unwrap();
168+
storage.save_microblock(height, &test_block).unwrap();
164169
height += 1;
165170
black_box(height)
166171
});
167172
});
168173

169174
// Benchmark block load
170-
storage.save_microblock(999999, &test_block, "test_hash").unwrap();
175+
storage.save_microblock(999999, &test_block).unwrap();
171176
group.bench_function("load_block", |b| {
172177
b.iter(|| {
173178
let block = storage.load_microblock(999999).unwrap();

development/qnet-integration/src/block_pipeline.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3113,9 +3113,9 @@ impl BlockPipeline {
31133113
// BlockAttestationMsg / EmptySlotAttestationMsg handlers in
31143114
// `unified_p2p.rs`). That layer is non-blocking — attestations
31153115
// travel on a separate gossip channel, do not gate block
3116-
// production, and form the basis of the cumulative-weight fork
3117-
// choice rule (`chain_weight.rs`). It supplies per-block 2f+1
3118-
// safety AND deterministic empty-slot failover, without sharing
3116+
// production, and form the basis of the per-block 2f+1 fork-choice
3117+
// keep-local rule. It supplies that 2f+1 safety AND deterministic
3118+
// empty-slot failover, without sharing
31193119
// the macroblock commit rate-limit bucket. Macroblock 2f+1
31203120
// commit/reveal at the 90-block boundary remains the canonical
31213121
// finality anchor.

0 commit comments

Comments
 (0)