use bincode::{deserialize, serialize};
use dig_block::{Bytes32, EMPTY_ROOT, ZERO_HASH};
use dig_block::{Cost, L2BlockHeader, VERSION_V1};
fn sample_header() -> L2BlockHeader {
let b = |tag: u8| Bytes32::new([tag; 32]);
L2BlockHeader {
version: VERSION_V1,
height: 100,
epoch: 10,
parent_hash: b(0x01),
state_root: b(0x02),
spends_root: b(0x03),
additions_root: b(0x04),
removals_root: b(0x05),
receipts_root: b(0x06),
l1_height: 9_000_001,
l1_hash: b(0x07),
timestamp: 1_700_000_000,
proposer_index: 3,
spend_bundle_count: 5,
total_cost: 42_000 as Cost,
total_fees: 1_000,
additions_count: 11,
removals_count: 7,
block_size: 4096,
filter_hash: b(0x08),
extension_data: ZERO_HASH,
l1_collateral_coin_id: Some(b(0x10)),
l1_reserve_coin_id: Some(b(0x11)),
l1_prev_epoch_finalizer_coin_id: Some(b(0x12)),
l1_curr_epoch_finalizer_coin_id: Some(b(0x13)),
l1_network_coin_id: Some(b(0x14)),
slash_proposal_count: 2,
slash_proposals_root: b(0x20),
collateral_registry_root: EMPTY_ROOT,
cid_state_root: b(0x21),
node_registry_root: b(0x22),
namespace_update_root: b(0x23),
dfsp_finalize_commitment_root: b(0x24),
}
}
#[test]
fn test_header_all_fields() {
let h = sample_header();
assert_eq!(h.version, VERSION_V1);
assert_eq!(h.height, 100);
assert_eq!(h.epoch, 10);
assert_eq!(h.parent_hash, Bytes32::new([0x01; 32]));
assert_eq!(h.state_root, Bytes32::new([0x02; 32]));
assert_eq!(h.spends_root, Bytes32::new([0x03; 32]));
assert_eq!(h.additions_root, Bytes32::new([0x04; 32]));
assert_eq!(h.removals_root, Bytes32::new([0x05; 32]));
assert_eq!(h.receipts_root, Bytes32::new([0x06; 32]));
assert_eq!(h.l1_height, 9_000_001);
assert_eq!(h.l1_hash, Bytes32::new([0x07; 32]));
assert_eq!(h.timestamp, 1_700_000_000);
assert_eq!(h.proposer_index, 3);
assert_eq!(h.spend_bundle_count, 5);
assert_eq!(h.total_cost, 42_000);
assert_eq!(h.total_fees, 1_000);
assert_eq!(h.additions_count, 11);
assert_eq!(h.removals_count, 7);
assert_eq!(h.block_size, 4096);
assert_eq!(h.filter_hash, Bytes32::new([0x08; 32]));
assert_eq!(h.extension_data, ZERO_HASH);
assert_eq!(h.l1_collateral_coin_id, Some(Bytes32::new([0x10; 32])));
assert_eq!(h.slash_proposal_count, 2);
assert_eq!(h.slash_proposals_root, Bytes32::new([0x20; 32]));
assert_eq!(h.collateral_registry_root, EMPTY_ROOT);
assert_eq!(h.dfsp_finalize_commitment_root, Bytes32::new([0x24; 32]));
}
#[test]
fn test_header_serialize_roundtrip() {
let h = sample_header();
let bytes = serialize(&h).expect("bincode serialize L2BlockHeader");
let back: L2BlockHeader = deserialize(&bytes).expect("bincode deserialize L2BlockHeader");
assert_eq!(h, back);
}
#[test]
fn test_header_clone() {
let h = sample_header();
assert_eq!(h.clone(), h);
}
#[test]
fn test_header_debug() {
let h = sample_header();
let s = format!("{h:?}");
assert!(
s.contains("L2BlockHeader") || s.contains("version") || s.contains("height"),
"Debug output should expose struct identity: {s}"
);
}
#[test]
fn test_header_optional_l1_proofs() {
let b = |tag: u8| Bytes32::new([tag; 32]);
let h = L2BlockHeader {
version: VERSION_V1,
height: 0,
epoch: 0,
parent_hash: b(0xa1),
state_root: EMPTY_ROOT,
spends_root: EMPTY_ROOT,
additions_root: EMPTY_ROOT,
removals_root: EMPTY_ROOT,
receipts_root: EMPTY_ROOT,
l1_height: 1,
l1_hash: b(0xa2),
timestamp: 0,
proposer_index: 0,
spend_bundle_count: 0,
total_cost: 0,
total_fees: 0,
additions_count: 0,
removals_count: 0,
block_size: 0,
filter_hash: EMPTY_ROOT,
extension_data: ZERO_HASH,
l1_collateral_coin_id: None,
l1_reserve_coin_id: None,
l1_prev_epoch_finalizer_coin_id: None,
l1_curr_epoch_finalizer_coin_id: None,
l1_network_coin_id: None,
slash_proposal_count: 0,
slash_proposals_root: EMPTY_ROOT,
collateral_registry_root: EMPTY_ROOT,
cid_state_root: EMPTY_ROOT,
node_registry_root: EMPTY_ROOT,
namespace_update_root: EMPTY_ROOT,
dfsp_finalize_commitment_root: EMPTY_ROOT,
};
assert!(h.l1_collateral_coin_id.is_none());
assert!(h.l1_reserve_coin_id.is_none());
assert!(h.l1_prev_epoch_finalizer_coin_id.is_none());
assert!(h.l1_curr_epoch_finalizer_coin_id.is_none());
assert!(h.l1_network_coin_id.is_none());
let bytes = serialize(&h).unwrap();
let back: L2BlockHeader = deserialize(&bytes).unwrap();
assert_eq!(back.l1_collateral_coin_id, None);
assert_eq!(back.l1_network_coin_id, None);
}