Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions crates/core/src/types/block.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
rlp::{encode::RLPEncode, structs::Encoder},
types::Receipt,
Address, H256, U256,
};
use bytes::Bytes;
Expand Down Expand Up @@ -104,6 +105,28 @@ impl BlockBody {
);
H256(root.into())
}

pub fn compute_receipts_root(&self, receipts: Vec<Receipt>) -> H256 {
let receipts_iter: Vec<_> = receipts
.iter()
.enumerate()
.map(|(i, receipt)| {
// Key: RLP(index)
let mut k = Vec::new();
i.encode(&mut k);

// Value: tx_type || RLP(receipt) if tx_type != 0
// RLP(receipt) else
let mut v = Vec::new();
receipt.encode_with_type(&mut v);

(k, v)
})
.collect();
let root =
PatriciaMerkleTree::<_, _, Keccak256>::compute_hash_from_sorted_iter(&receipts_iter);
H256(root.into())
}
}

impl RLPEncode for BlockBody {
Expand Down
31 changes: 31 additions & 0 deletions crates/core/src/types/receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,48 @@ use crate::rlp::{encode::RLPEncode, structs::Encoder};
use crate::types::Bloom;
use bytes::Bytes;
use ethereum_types::{Address, H256};

use super::TxType;
pub type Index = u64;

/// Result of a transaction
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Receipt {
tx_type: TxType,
succeeded: bool,
cumulative_gas_used: u64,
bloom: Bloom,
logs: Vec<Log>,
}

impl Receipt {
pub fn new(
tx_type: TxType,
succeeded: bool,
cumulative_gas_used: u64,
bloom: Bloom,
logs: Vec<Log>,
) -> Self {
Self {
tx_type,
succeeded,
cumulative_gas_used,
bloom,
logs,
}
}

pub fn encode_with_type(&self, buf: &mut dyn bytes::BufMut) {
// tx_type || RLP(receipt) if tx_type != 0
// RLP(receipt) else
match self.tx_type {
TxType::Legacy => {}
_ => buf.put_u8(self.tx_type as u8),
}
self.encode(buf);
}
}

impl RLPEncode for Receipt {
fn encode(&self, buf: &mut dyn bytes::BufMut) {
Encoder::new(buf)
Expand Down
21 changes: 19 additions & 2 deletions crates/core/src/types/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,8 @@ fn recover_address(
mod tests {
use hex_literal::hex;

use super::LegacyTransaction;
use crate::{
types::{BlockBody, Transaction, TxKind},
types::{BlockBody, LegacyTransaction, Receipt, Transaction, TxKind, TxType},
U256,
};

Expand Down Expand Up @@ -315,4 +314,22 @@ mod tests {

assert_eq!(result, expected_root.into());
}

#[test]
fn test_compute_receipts_root() {
// example taken from
// https://github.com/ethereum/go-ethereum/blob/f8aa62353666a6368fb3f1a378bd0a82d1542052/cmd/evm/testdata/1/exp.json#L18
let body = BlockBody::empty();
let tx_type = TxType::Legacy;
let succeeded = true;
let cumulative_gas_used = 0x5208;
let bloom = [0x00; 256];
let logs = vec![];
let receipt = Receipt::new(tx_type, succeeded, cumulative_gas_used, bloom, logs);

let result = body.compute_receipts_root(vec![receipt]);
let expected_root =
hex!("056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2");
assert_eq!(result, expected_root.into());
}
}