Skip to content

feat: compute receipts root #111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jul 3, 2024
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());
}
}
Loading