block/
block.rs

1use rlp::{self, Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp};
2use bigint::{H256, U256};
3use trie::FixedMemoryTrieMut;
4use sha3::{Keccak256, Digest};
5use super::{Header, Transaction, Receipt};
6
7pub fn transactions_root(transactions: &[Transaction]) -> H256 {
8    let mut trie = FixedMemoryTrieMut::default();
9    for (i, transaction) in transactions.iter().enumerate() {
10        trie.insert(&U256::from(i), transaction);
11    }
12    trie.root()
13}
14
15pub fn receipts_root(receipts: &[Receipt]) -> H256 {
16    let mut trie = FixedMemoryTrieMut::default();
17    for (i, receipt) in receipts.iter().enumerate() {
18        trie.insert(&U256::from(i), receipt);
19    }
20    trie.root()
21}
22
23pub fn ommers_hash(ommers: &[Header]) -> H256 {
24    let encoded = rlp::encode_list(ommers).to_vec();
25    let hash = H256::from(Keccak256::digest(&encoded).as_slice());
26    hash
27}
28
29#[derive(Clone, Debug, PartialEq, Eq)]
30pub struct Block {
31    pub header: Header,
32    pub transactions: Vec<Transaction>,
33    pub ommers: Vec<Header>,
34}
35
36impl Block {
37    pub fn is_basic_valid(&self) -> bool {
38        if transactions_root(&self.transactions) != self.header.transactions_root {
39            return false;
40        }
41
42        if ommers_hash(&self.ommers) != self.header.ommers_hash {
43            return false;
44        }
45
46        return true;
47    }
48}
49
50impl Encodable for Block {
51    fn rlp_append(&self, s: &mut RlpStream) {
52        s.begin_list(3);
53        s.append(&self.header);
54        s.append_list(&self.transactions);
55        s.append_list(&self.ommers);
56    }
57}
58
59impl Decodable for Block {
60    fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
61        Ok(Self {
62            header: rlp.val_at(0)?,
63            transactions: rlp.list_at(1)?,
64            ommers: rlp.list_at(2)?,
65        })
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use rlp::{encode, decode};
72    use hexutil::read_hex;
73    use bigint::{U256, H256, Address, Gas};
74    use block::Block;
75    use TransactionAction;
76    use std::str::FromStr;
77
78    #[test]
79    fn block_53165_rlp() {
80        let raw = read_hex("f9050df901ffa037ecbfd908ece3c54fa5b9f8e1b4a6089139da1dc4b5013a46c5818304de47b3a05cd40176209a61f3b26f3b5b491f177b93a3c33c595d0be75c26c97bdb60e7a294a50ec0d39fa913e62f1bae7074e6f36caa71855ba0a1b07a1f98248efee3d2111fcf9dcb2c1ad9f961a192e02571c0b55e7539b427a0f739c0f6d17bcad52552bfe3a4950885222ae694750135a75f452efc033d425da0b61bbed645e5b6366521a5c3bddb98d788067dc7a0f1515bfe4bdad0fb63b188b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086016f2c8a34da82cfad8320f4018307a1208455c5e86b80a05fca8f6fce90e5f92549824d7b7d456cefafb92f223f97d60efee8e62522b9778870cee9238ebd5c31f8ecf8ea04850d9afee4208307a12094dc884e349103eaee4aef913d532cb5db2745f48b80b884de6f24bb0000000000000000000000008674c218f0351a62c3ba78c34fd2182a93da94e20000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000568656c6c6f0000000000000000000000000000000000000000000000000000001ba04f2dfebd7c0f712119678fdd5ce6abc357a91df2284edafa5dc1c7503bb2d5c6a023b85af577d777b5cc5af8a4ece80bf45ae9f0be7b8e166a91271deb938b72aff9021af90217a059c53a8471fdc848352699052890b6156753a94743cfb4dc3f921df67e16978aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f2d2aff1320476cb8c6b607199d23175cc595693a0bf6464bc0efe71b06723bf303cc661322eff513b247e714537d6593472ae76bea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086016f2c8ff18c82cfab8320f404808455c5e84b9b476574682f76312e302e312f77696e646f77732f676f312e342e32a0fc0a1197dee6cf57a6d8afeaa1d070462638d484e1f71266b114b9cc5d5a5b0e88f48a42a38b85ccf0").unwrap();
81        let block: Block = decode(&raw);
82        assert_eq!(block.header.parent_hash, H256::from_str("37ecbfd908ece3c54fa5b9f8e1b4a6089139da1dc4b5013a46c5818304de47b3").unwrap());
83        assert_eq!(block.transactions[0].action, TransactionAction::Call(Address::from_str("0xdc884e349103eaee4aef913d532cb5db2745f48b").unwrap()));
84        assert_eq!(block.transactions[0].gas_limit, Gas::from(500000u64));
85        assert_eq!(block.transactions[0].value, U256::zero());
86        assert_eq!(block.ommers[0].parent_hash, H256::from_str("59c53a8471fdc848352699052890b6156753a94743cfb4dc3f921df67e16978a").unwrap());
87        assert_eq!(block.ommers[0].beneficiary, Address::from_str("f2d2aff1320476cb8c6b607199d23175cc595693").unwrap());
88        assert_eq!(block, decode(&encode(&block).to_vec()));
89
90        let encoded = encode(&block).to_vec();
91        assert_eq!(encoded, raw);
92    }
93}