Files
nanoreth/crates/primitives/src/proofs.rs
Bjerg 92a7818512 feat: bodies stage (#190)
* chore: clean up `.gitignore`

* fix: make RO cursors `Send + Sync`

* feat(wip): bodies stage

* driveby: improve docs

* chore: don't panic if we're the first stage

* chore: use `Vec` for ommers

* feat: error handling in bodies downloader

* chore: remove stale comment

* chore: pascal-case stage id

* refactor: remove unused new fns

* refactor: distinguish downloaders with prefix

* refactor: move downloader errs to own module

* refactor: `stream_bodies` -> `bodies_stream`

* test: fix borked imports in header stage

* test: clean up header tests

* test: add basic body stage tests

* test: add 2 more body stage test skeletons

* test: move generator test utils to own module

* refactor: move proof functions to primitives crate

* feat: add block generator test utils

* test: more body stage tests

* chore: fix typo (`Cannonical*` -> `Canonical`)

* docs: document `bodies_to_download`

* test: more body stage tests

* test: more body stage tests

* refactor: clean up body stage tests a bit

* test: fix broken tests

* refactor: clean up body stage tests

* test: more body stage tests
2022-11-15 08:49:11 +01:00

107 lines
3.2 KiB
Rust

use crate::{keccak256, Bytes, Header, Log, Receipt, TransactionSigned, H256};
use ethers_core::utils::rlp::RlpStream;
use hash_db::Hasher;
use hex_literal::hex;
use plain_hasher::PlainHasher;
use reth_rlp::Encodable;
use triehash::sec_trie_root;
/// Keccak-256 hash of the RLP of an empty list, KEC("\xc0").
pub const EMPTY_LIST_HASH: H256 =
H256(hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"));
/// Root hash of an empty trie.
pub const EMPTY_ROOT: H256 =
H256(hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"));
/// A [Hasher] that calculates a keccak256 hash of the given data.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
struct KeccakHasher;
impl Hasher for KeccakHasher {
type Out = H256;
type StdHasher = PlainHasher;
const LENGTH: usize = 32;
fn hash(x: &[u8]) -> Self::Out {
keccak256(x)
}
}
/// Calculate a transaction root.
///
/// Iterates over the given transactions and the merkle merkle trie root of
/// `(rlp(index), encoded(tx))` pairs.
pub fn calculate_transaction_root<'a>(
transactions: impl IntoIterator<Item = &'a TransactionSigned>,
) -> H256 {
sec_trie_root::<KeccakHasher, _, _, _>(
transactions
.into_iter()
.enumerate()
.map(|(index, tx)| {
// TODO replace with reth-rlp
let mut stream = RlpStream::new();
stream.append(&index);
let mut bytes = Vec::new();
tx.encode(&mut bytes);
(stream.out().freeze().into(), bytes)
})
.collect::<Vec<(Bytes, Vec<u8>)>>(),
)
}
/// Calculates the receipt root for a header.
pub fn calculate_receipt_root<'a>(receipts: impl IntoIterator<Item = &'a Receipt>) -> H256 {
sec_trie_root::<KeccakHasher, _, _, _>(
receipts
.into_iter()
.enumerate()
.map(|(index, receipt)| {
let mut stream = RlpStream::new();
stream.append(&index);
let mut bytes = Vec::new();
receipt.encode(&mut bytes);
(stream.out().freeze().into(), bytes)
})
.collect::<Vec<(Bytes, Vec<u8>)>>(),
)
}
/// Calculates the log root for a header.
pub fn calculate_log_root<'a>(logs: impl IntoIterator<Item = &'a Log>) -> H256 {
//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)
}
/// Calculates the root hash for ommer/uncle headers.
pub fn calculate_ommers_root<'a>(_ommers: impl IntoIterator<Item = &'a Header>) -> H256 {
// RLP Encode
let mut stream = RlpStream::new();
stream.begin_unbounded_list();
/* TODO
for ommer in ommers {
stream.append(ommer)
}
*/
stream.finalize_unbounded_list();
let bytes = stream.out().freeze();
keccak256(bytes)
}
// TODO state root
// TODO bloom