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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use candid::CandidType;
use ex3_serde::bincode;
use serde::{Deserialize, Serialize};
use serde_bytes::ByteBuf;

use crate::{BlockHash, BlockHeight, CandidBlockHeight, CandidPackageId, MerkleRoot, PackageId};

/// Block head
#[derive(Serialize, Deserialize, Clone, Debug, Ord, PartialOrd, PartialEq, Eq)]
pub struct BlockHead {
    /// Block version
    pub version: u8,

    /// Height of the block
    pub height: BlockHeight,

    /// Package id of the block
    pub p_id: PackageId,

    /// Previous block hash
    pub pre_block_hash: BlockHash,

    /// Transaction merkle root of the block accepted transactions
    pub tx_root: MerkleRoot,

    /// Balance changed merkle root of the block
    pub balance_changed_root: MerkleRoot,

    /// Data integrity merkle root of the block
    pub data_integrity_root: MerkleRoot,

    /// Rejected transaction merkle root of the block rejected transactions
    pub rejected_tx_root: MerkleRoot,
}

#[derive(CandidType, Deserialize, Clone, Debug, Ord, PartialOrd, PartialEq, Eq)]
pub struct CandidBlockHead {
    pub version: u8,
    pub height: CandidBlockHeight,
    pub p_id: CandidPackageId,
    pub pre_block_hash: BlockHash,
    pub tx_root: MerkleRoot,
    pub balance_changed_root: MerkleRoot,
    pub data_integrity_root: MerkleRoot,
    pub rejected_tx_root: MerkleRoot,
}

impl From<CandidBlockHead> for BlockHead {
    fn from(candid_block_head: CandidBlockHead) -> Self {
        BlockHead {
            version: candid_block_head.version,
            height: candid_block_head.height.0,
            p_id: candid_block_head.p_id.0,
            pre_block_hash: candid_block_head.pre_block_hash,
            tx_root: candid_block_head.tx_root,
            balance_changed_root: candid_block_head.balance_changed_root,
            data_integrity_root: candid_block_head.data_integrity_root,
            rejected_tx_root: candid_block_head.rejected_tx_root,
        }
    }
}

impl From<BlockHead> for CandidBlockHead {
    fn from(block_head: BlockHead) -> Self {
        CandidBlockHead {
            version: block_head.version,
            height: block_head.height.into(),
            p_id: block_head.p_id.into(),
            pre_block_hash: block_head.pre_block_hash,
            tx_root: block_head.tx_root,
            balance_changed_root: block_head.balance_changed_root,
            data_integrity_root: block_head.data_integrity_root,
            rejected_tx_root: block_head.rejected_tx_root,
        }
    }
}

impl BlockHead {
    pub fn hash(&self) -> BlockHash {
        let block_head_bytes = bincode::serialize(&self).unwrap();
        ex3_crypto::sha256(block_head_bytes.as_slice())
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct EncodedBlockHead(pub ByteBuf);

impl From<BlockHead> for EncodedBlockHead {
    fn from(head: BlockHead) -> Self {
        let bytes = bincode::serialize(&head).unwrap();
        EncodedBlockHead(ByteBuf::from(bytes))
    }
}

impl From<EncodedBlockHead> for BlockHead {
    fn from(encoded_head: EncodedBlockHead) -> Self {
        bincode::deserialize(encoded_head.0.as_slice()).expect("Decode block head should success")
    }
}

impl std::ops::Deref for EncodedBlockHead {
    type Target = ByteBuf;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct BlockHeadExt {
    pub height: BlockHeight,
    pub validate_on_chain: bool,
    pub sharding_reported: bool,
    pub has_local_body: bool,
}