#![allow(dead_code)]
use std::collections::HashMap;
use chia_bls::{sign, PublicKey, SecretKey, Signature};
use chia_protocol::{Bytes32, Coin, CoinSpend, CoinState, Program, SpendBundle};
use dig_block::traits::SignerError;
use dig_block::{BlockSigner, CoinLookup, Cost, L2Block, L2BlockHeader, EMPTY_ROOT};
pub struct MockCoinLookup {
coins: HashMap<Bytes32, CoinState>,
chain_height: u64,
chain_timestamp: u64,
}
impl MockCoinLookup {
pub fn new() -> Self {
Self {
coins: HashMap::new(),
chain_height: 0,
chain_timestamp: 0,
}
}
pub fn add_coin_state(&mut self, coin_id: Bytes32, state: CoinState) {
self.coins.insert(coin_id, state);
}
pub fn set_chain_height(&mut self, height: u64) {
self.chain_height = height;
}
pub fn set_chain_timestamp(&mut self, timestamp: u64) {
self.chain_timestamp = timestamp;
}
}
impl CoinLookup for MockCoinLookup {
fn get_coin_state(&self, coin_id: &Bytes32) -> Option<CoinState> {
self.coins.get(coin_id).cloned()
}
fn get_chain_height(&self) -> u64 {
self.chain_height
}
fn get_chain_timestamp(&self) -> u64 {
self.chain_timestamp
}
}
pub struct MockBlockSigner {
secret_key: SecretKey,
}
impl MockBlockSigner {
pub fn new() -> Self {
let seed: [u8; 32] = [
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
0x1d, 0x1e, 0x1f, 0x20,
];
let secret_key = SecretKey::from_seed(&seed);
Self { secret_key }
}
pub fn public_key(&self) -> PublicKey {
self.secret_key.public_key()
}
}
impl BlockSigner for MockBlockSigner {
fn sign_block(&self, header_hash: &Bytes32) -> Result<Signature, SignerError> {
Ok(sign(&self.secret_key, header_hash.as_ref()))
}
}
pub fn test_header() -> L2BlockHeader {
test_header_at_height(1)
}
pub fn test_header_at_height(height: u64) -> L2BlockHeader {
L2BlockHeader::new(
height,
0,
Bytes32::new([0xee; 32]),
EMPTY_ROOT,
EMPTY_ROOT,
EMPTY_ROOT,
EMPTY_ROOT,
EMPTY_ROOT,
1,
Bytes32::new([0xdd; 32]),
0,
0,
0 as Cost,
0,
0,
0,
0,
EMPTY_ROOT,
)
}
pub fn test_block() -> L2Block {
L2Block::new(test_header(), Vec::new(), Vec::new(), Signature::default())
}
pub fn test_spend_bundle() -> SpendBundle {
let parent = Bytes32::default();
let puzzle_hash = Bytes32::default();
let amount = 1_000_000u64;
let coin = Coin::new(parent, puzzle_hash, amount);
let puzzle_reveal = Program::from(vec![0x01]);
let solution = Program::from(vec![0x80]);
let coin_spend = CoinSpend::new(coin, puzzle_reveal, solution);
SpendBundle::new(vec![coin_spend], Signature::default())
}
pub fn test_coin_state(coin: Coin, created_height: u32, spent_height: Option<u32>) -> CoinState {
CoinState {
coin,
created_height: Some(created_height),
spent_height,
}
}
pub fn sync_block_header_for_validate_structure(b: &mut L2Block) {
b.header.spend_bundle_count = u32::try_from(b.spend_bundles.len()).unwrap_or(u32::MAX);
b.header.additions_count = u32::try_from(b.all_additions().len()).unwrap_or(u32::MAX);
b.header.removals_count = b
.spend_bundles
.iter()
.map(|sb| u32::try_from(sb.coin_spends.len()).unwrap_or(u32::MAX))
.sum();
b.header.slash_proposal_count =
u32::try_from(b.slash_proposal_payloads.len()).unwrap_or(u32::MAX);
b.header.spends_root = b.compute_spends_root();
b.header.additions_root = b.compute_additions_root();
b.header.removals_root = b.compute_removals_root();
b.header.slash_proposals_root = b.compute_slash_proposals_root();
b.header.filter_hash = b.compute_filter_hash();
b.header.block_size = u32::try_from(b.compute_size()).unwrap_or(u32::MAX);
}
pub fn stv_test_proposer_keypair() -> (SecretKey, PublicKey) {
let seed: [u8; 32] = [
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
0x3f, 0x40,
];
let sk = SecretKey::from_seed(&seed);
let pk = sk.public_key();
(sk, pk)
}
pub fn stv_sign_proposer(block: &mut L2Block, sk: &SecretKey) {
let header_hash = block.header.hash();
block.proposer_signature = sign(sk, header_hash.as_ref());
}