-
Notifications
You must be signed in to change notification settings - Fork 648
/
Copy pathmerkle_trie.rs
69 lines (61 loc) · 2.03 KB
/
merkle_trie.rs
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
use bytes::Bytes;
use hash_db::Hasher;
use plain_hasher::PlainHasher;
use primitive_types::{H160, H256};
use revm::{db::DbAccount, Log ,U256,B160,B256,common::keccak256,};
use rlp::RlpStream;
use sha3::{Digest, Keccak256};
use triehash::sec_trie_root;
pub fn log_rlp_hash(logs: Vec<Log>) -> B256 {
//https://github.com/ethereum/go-ethereum/blob/356bbe343a30789e77bb38f25983c8f2f2bfbb47/cmd/evm/internal/t8ntool/execution.go#L255
let mut stream = RlpStream::new();
stream.begin_unbounded_list();
for log in logs {
stream.begin_list(3);
stream.append(&log.address);
stream.append_list(&log.topics);
stream.append(&log.data);
}
stream.finalize_unbounded_list();
let out = stream.out().freeze();
keccak256(&out)
}
pub fn state_merkle_trie_root(accounts: impl Iterator<Item = (B160, DbAccount)>) -> B256 {
let vec = accounts
.map(|(address, info)| {
let acc_root = trie_account_rlp(&info);
(H160::from(address), acc_root)
})
.collect();
trie_root(vec)
}
/// Returns the RLP for this account.
pub fn trie_account_rlp(acc: &DbAccount) -> Bytes {
let mut stream = RlpStream::new_list(4);
stream.append(&acc.info.nonce);
stream.append(&acc.info.balance);
stream.append(&{
sec_trie_root::<KeccakHasher, _, _, _>(
acc.storage
.iter()
.filter(|(_k, &v)| v != U256::ZERO)
.map(|(&k, v)| (H256::from(B256::from(k)), rlp::encode(v))),
)
});
stream.append(&acc.info.code_hash.to_be_bytes_vec());
stream.out().freeze()
}
pub fn trie_root(acc_data: Vec<(H160, Bytes)>) -> B256 {
sec_trie_root::<KeccakHasher, _, _, _>(acc_data.into_iter()).into()
}
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct KeccakHasher;
impl Hasher for KeccakHasher {
type Out = H256;
type StdHasher = PlainHasher;
const LENGTH: usize = 32;
fn hash(x: &[u8]) -> Self::Out {
let out = Keccak256::digest(x);
H256::from_slice(out.as_slice())
}
}