Skip to content

Commit bf27f31

Browse files
consensus: log compensation_entries summary per apply (diagnostic only)
Follow-up to the waiting-pool reward instrumentation (c0a6d88), which just proved that path is a permanent no-op in the current worker configuration (all 3 registered workers are always the 3 rotating producers, so the waiting pool is always empty and its balance-mutation loop never runs, on any node, identically). That rules it out as the source of the 2026-07-26 bal-category divergence and leaves lsu.compensation_entries -- simple, deterministic, part of the hashed LSU -- as the only other thing that mutates bal: on an empty-tx-batch cycle. log_compensation_entries_summary() logs entry count, applied (nonzero) count, total amount credited, and a short fingerprint of the entries themselves, from both apply_lsu_to_storage_locked and apply_lsu_to_storage_without_root_check. If this logs identically across nodes for a cycle but balances still diverge afterward, that proves the starting balance already differed (deficit from an earlier cycle); if the logged values themselves differ, that's the bug. No behavior change, full test suite passes (96/96).
1 parent c0a6d88 commit bf27f31

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

crates/catalyst-cli/src/node.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1816,6 +1816,7 @@ async fn apply_lsu_to_storage_without_root_check(
18161816
let cur = get_balance_i64(store, &c.public_key).await;
18171817
let _ = set_balance_i64(store, &c.public_key, cur.saturating_add(c.amount as i64)).await;
18181818
}
1819+
log_compensation_entries_summary(lsu.cycle_number, &lsu.compensation_entries);
18191820

18201821
// Nonce increments.
18211822
use std::collections::BTreeMap;
@@ -2518,6 +2519,42 @@ fn pubkey_list_fingerprint(pks: &[[u8; 32]]) -> String {
25182519
hex_encode(&full[..4])
25192520
}
25202521

2522+
/// Diagnostic (2026-07-26/27 `bal`-category divergence investigation): logs whether the
2523+
/// compensation-entries loop actually ran and what it credited, on every apply. The waiting-pool
2524+
/// reward path was just proven to be a no-op in the current worker configuration (always
2525+
/// `n_eligible=0`), which leaves `compensation_entries` -- simple, deterministic, and part of the
2526+
/// hashed LSU (so byte-identical across nodes for the same `applied_lsu_hash`) -- as the only
2527+
/// remaining thing that mutates `bal:` on an empty-tx-batch cycle. If this logs the same
2528+
/// `entries_hash`/`applied_count`/`total_amount` on every node for a cycle yet balances still end
2529+
/// up different afterward, that proves the *starting* balance already differed (the deficit is
2530+
/// from an earlier cycle, not this one). If the logged values themselves differ, that is the bug.
2531+
fn log_compensation_entries_summary(
2532+
cycle: u64,
2533+
entries: &[catalyst_consensus::types::CompensationEntry],
2534+
) {
2535+
use sha2::{Digest, Sha256};
2536+
let mut h = Sha256::new();
2537+
let mut applied_count = 0u64;
2538+
let mut total_amount: u64 = 0;
2539+
for e in entries {
2540+
h.update(&e.public_key);
2541+
h.update(e.amount.to_le_bytes());
2542+
if e.amount != 0 {
2543+
applied_count += 1;
2544+
total_amount = total_amount.saturating_add(e.amount);
2545+
}
2546+
}
2547+
let full: [u8; 32] = h.finalize().into();
2548+
info!(
2549+
"Cycle {} compensation_entries: count={} applied_count={} total_amount={} entries_hash={}",
2550+
cycle,
2551+
entries.len(),
2552+
applied_count,
2553+
total_amount,
2554+
hex_encode(&full[..4])
2555+
);
2556+
}
2557+
25212558
async fn distribute_waiting_pool_rewards_and_fee_credits(
25222559
store: &StorageManager,
25232560
lsu: &catalyst_consensus::types::LedgerStateUpdate,
@@ -3559,6 +3596,7 @@ async fn apply_lsu_to_storage_locked(
35593596
let cur = get_balance_i64(store, &c.public_key).await;
35603597
let _ = set_balance_i64(store, &c.public_key, cur.saturating_add(c.amount as i64)).await;
35613598
}
3599+
log_compensation_entries_summary(lsu.cycle_number, &lsu.compensation_entries);
35623600

35633601
// Update nonces: group by signature bytes (our current "tx boundary" marker).
35643602
use std::collections::BTreeMap;

0 commit comments

Comments
 (0)