Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
22 changes: 22 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 @@ -106,6 +107,27 @@ impl BlockBody {
}
}

pub fn compute_receipts_root(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 {
fn encode(&self, buf: &mut dyn bytes::BufMut) {
Encoder::new(buf)
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
23 changes: 21 additions & 2 deletions crates/core/src/types/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,11 @@ fn recover_address(
mod tests {
use hex_literal::hex;

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

Expand Down Expand Up @@ -315,4 +317,21 @@ 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 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 = compute_receipts_root(vec![receipt]);
let expected_root =
hex!("056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2");
assert_eq!(result, expected_root.into());
}
}