1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
    Appellation: block <module>
    Contrib: FL03 <jo3mccain@icloud.com>
    Description: ... Summary ...
*/
use crate::{
    blocks::{generate_genesis_block, Block, BlockContent, BlockHeader},
    compute_key_hash,
    transactions::SignedTransaction,
    BlockHs, BlockNc, BlockTs,
};
use scsys::prelude::{Hashable, H256};

pub trait Resistable {
    fn pos_difficulty(&self) -> H256;
    fn pow_difficulty(&self) -> H256;
}

pub trait Verifiable {
    fn vrf_hash(&self) -> Vec<u8>;
    fn vrf_proof(&self) -> Vec<u8>;
    fn vrf_pub_key(&self) -> Vec<u8>;
}

pub trait BlockHeaderSpec: Hashable + Resistable + Verifiable {
    fn header(&self) -> &Self {
        self
    }
    fn merkle_root(&self) -> H256;
    fn nonce(&self) -> BlockNc;
    fn parent(&self) -> H256;
    // randomness for PoS leader election. TODO: update rand every epoch
    fn rand(&self) -> u128;
    fn timestamp(&self) -> BlockTs;
}

pub trait CoreBlockSpec: Hashable {
    fn content(&self) -> &BlockContent;
    fn header(&self) -> &BlockHeader;
    fn nonce(&self) -> BlockNc {
        self.header().nonce()
    }
    fn parent(&self) -> BlockHs {
        self.header().parent()
    }
    fn timestamp(&self) -> BlockTs {
        self.header().timestamp
    }
    fn transactions(&self) -> &Vec<SignedTransaction> {
        &self.content().data
    }
}

pub trait CoreBlockWrapper: CoreBlockSpec {
    fn clear_txns(&mut self) -> &Self;
    fn print_txns(&self) -> &Self {
        let txns = self.transactions().clone();
        log::info!("***** Print txns in block {:?} *****", self.hash());
        for txn in txns {
            let sender = compute_key_hash(txn.sign.pubk);
            let recv = txn.transaction.recv;
            log::info!(
                "{:?} sends {:?} value {:?}",
                sender,
                recv,
                txn.transaction.value
            );
        }
        log::info!("*************************************");
        self
    }
}

pub trait CoreBlockWrapperExt: CoreBlockWrapper {
    fn genesis(timestamp: BlockTs) -> Block
    where
        Self: Sized,
    {
        generate_genesis_block(timestamp)
    }
}