mod helpers;
use std::collections::HashMap;
use dig_coinstore::{
ApplyBlockResult, BlockData, Bytes32, CoinAddition, CoinId, CoinRecord, CoinStoreError,
CoinStoreSnapshot, PuzzleHash, RollbackResult, UnspentLineageInfo,
};
#[test]
fn vv_req_api_009_coin_id_alias_matches_bytes32() {
let raw: Bytes32 = helpers::test_hash(0x41);
let as_coin_id: CoinId = raw;
let round_trip: Bytes32 = as_coin_id;
assert_eq!(round_trip, raw);
}
#[test]
fn vv_req_api_009_puzzle_hash_alias_matches_bytes32() {
let raw: Bytes32 = helpers::test_hash(0x42);
let as_puzzle: PuzzleHash = raw;
assert_eq!(Bytes32::from(as_puzzle), raw);
}
#[test]
fn vv_req_api_009_coin_puzzle_hash_assignable_to_puzzle_hash_alias() {
let coin = helpers::test_coin(7, 8, 999);
let ph: PuzzleHash = coin.puzzle_hash;
assert_eq!(ph, coin.puzzle_hash);
}
#[test]
fn vv_req_api_009_coin_coin_id_assignable_to_coin_id_alias() {
let coin = helpers::test_coin(9, 10, 1);
let id: CoinId = coin.coin_id();
assert_eq!(id, coin.coin_id());
}
#[test]
fn vv_req_api_009_unspent_lineage_info_all_fields_accessible() {
let a = helpers::test_hash(1);
let b = helpers::test_hash(2);
let c = helpers::test_hash(3);
let info = UnspentLineageInfo {
coin_id: a,
parent_id: b,
parent_parent_id: c,
};
assert_eq!(info.coin_id, a);
assert_eq!(info.parent_id, b);
assert_eq!(info.parent_parent_id, c);
}
#[test]
fn vv_req_api_009_unspent_lineage_info_debug_clone_partial_eq() {
let info = UnspentLineageInfo {
coin_id: helpers::test_hash(0x11),
parent_id: helpers::test_hash(0x22),
parent_parent_id: helpers::test_hash(0x33),
};
let dbg = format!("{info:?}");
assert!(
dbg.contains("coin_id") && dbg.contains("parent_id"),
"Debug output should name fields for operators: {dbg}"
);
let cloned = info.clone();
assert_eq!(cloned, info);
let different = UnspentLineageInfo {
coin_id: helpers::filled_hash(0xFF),
parent_id: info.parent_id,
parent_parent_id: info.parent_parent_id,
};
assert_ne!(different, info);
}
#[test]
fn vv_req_api_009_unspent_lineage_info_genesis_sentinel_row() {
let zero = Bytes32::default();
let info = UnspentLineageInfo {
coin_id: helpers::test_hash(0x77),
parent_id: zero,
parent_parent_id: zero,
};
assert_eq!(info.parent_id, info.parent_parent_id);
}
#[test]
fn vv_req_api_009_aliases_used_on_listed_public_types() {
let coin = helpers::test_coin(5, 6, 1234);
let coin_id: CoinId = coin.coin_id();
let addition = CoinAddition::from_coin(coin, false);
let block = BlockData {
height: 2,
timestamp: 3,
block_hash: helpers::test_hash(0xB1),
parent_hash: helpers::test_hash(0xB2),
additions: vec![addition.clone()],
removals: vec![coin_id],
coinbase_coins: vec![helpers::test_coin(0xC0, 0xC1, 50)],
hints: vec![(coin_id, helpers::filled_hash(0x01))],
expected_state_root: Some(helpers::test_hash(0xB3)),
};
let apply = ApplyBlockResult {
state_root: helpers::test_hash(0xD0),
coins_created: 1,
coins_spent: 0,
height: block.height,
};
let mut modified = HashMap::new();
modified.insert(
coin_id,
CoinRecord::new(helpers::test_coin(0xE0, 0xE1, 99), 0, 1_700_000_000, false),
);
let rollback = RollbackResult {
modified_coins: modified,
coins_deleted: 0,
coins_unspent: 1,
new_height: 1,
};
let mut coins = HashMap::new();
coins.insert(
coin_id,
CoinRecord::new(helpers::test_coin(0xF0, 0xF1, 42), 0, 1_700_000_001, false),
);
let snapshot = CoinStoreSnapshot {
height: 9,
block_hash: helpers::test_hash(0xA0),
state_root: helpers::test_hash(0xA1),
timestamp: 1_700_000_002,
coins,
hints: vec![(coin_id, helpers::filled_hash(0x02))],
total_coins: 1,
total_value: 42,
};
let err = CoinStoreError::CoinNotFound(coin_id);
assert_eq!(block.removals.len(), 1);
assert_eq!(apply.coins_created, 1);
assert_eq!(rollback.coins_unspent, 1);
assert_eq!(snapshot.total_coins, 1);
assert!(matches!(err, CoinStoreError::CoinNotFound(id) if id == coin_id));
let _: &CoinId = &addition.coin_id;
let _: PuzzleHash = addition.coin.puzzle_hash;
}