From d47eb0bba656d613f91c0b107856c08deecabc6f Mon Sep 17 00:00:00 2001 From: Boyu Yang Date: Fri, 11 Aug 2023 15:42:02 +0800 Subject: [PATCH] fix(consensus): correct receipts root (#1270) --- core/executor/src/lib.rs | 10 +++++-- core/run/src/tests.rs | 2 +- protocol/src/types/transaction.rs | 48 ++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/core/executor/src/lib.rs b/core/executor/src/lib.rs index c599cc5a5..3edb4dbb3 100644 --- a/core/executor/src/lib.rs +++ b/core/executor/src/lib.rs @@ -158,7 +158,10 @@ impl Executor for AxonExecutor { gas += r.gas_used; fee = fee.checked_add(r.fee_cost).unwrap_or(U256::max_value()); - hashes.push(Hasher::digest(&r.ret)); + let logs_bloom = logs_bloom(r.logs.iter()); + let receipt = tx.encode_receipt(&r, logs_bloom); + + hashes.push(Hasher::digest(&receipt)); res.push(r); } @@ -354,7 +357,10 @@ impl AxonExecutor { gas += r.gas_used; fee = fee.checked_add(r.fee_cost).unwrap_or(U256::max_value()); - hashes.push(Hasher::digest(&r.ret)); + let logs_bloom = logs_bloom(r.logs.iter()); + let receipt = tx.encode_receipt(&r, logs_bloom); + + hashes.push(Hasher::digest(&receipt)); res.push(r); } diff --git a/core/run/src/tests.rs b/core/run/src/tests.rs index ce755a8ef..483238c15 100644 --- a/core/run/src/tests.rs +++ b/core/run/src/tests.rs @@ -27,7 +27,7 @@ const GENESIS_HASH: &str = "0x69eca8420bb4b072d732db96260a656f0e10201c6841b215a8 const GENESIS_STATE_ROOT: &str = "0x65f57a6a666e656de33ed68957e04b35b3fe1b35a90f6eafb6f283c907dc3d77"; const GENESIS_RECEIPTS_ROOT: &str = - "0x0abcdb8fd7acc8c71f28a16c3095fdafca0171f371076650152b1c356a1bccad"; + "0x8544b530238201f1620b139861a6841040b37f78f8bdae8736ef5cec474e979b"; #[test] fn decode_genesis() { diff --git a/protocol/src/types/transaction.rs b/protocol/src/types/transaction.rs index 260e56473..06f46864a 100644 --- a/protocol/src/types/transaction.rs +++ b/protocol/src/types/transaction.rs @@ -7,7 +7,10 @@ use serde::{Deserialize, Serialize}; use common_crypto::secp256k1_recover; -use crate::types::{Bytes, BytesMut, Hash, Hasher, Public, TypesError, H160, H256, H520, U256}; +use crate::types::{ + Bloom, Bytes, BytesMut, ExitReason, Hash, Hasher, Public, TxResp, TypesError, H160, H256, H520, + U256, +}; use crate::ProtocolResult; pub const GAS_PER_ZERO_BYTE: u64 = 4; @@ -468,6 +471,49 @@ impl SignedTransaction { pub fn get_to(&self) -> Option { self.transaction.unsigned.to() } + + /// Encode a transaction receipt into bytes. + /// + /// According to [`EIP-2718`]: + /// - `Receipt` is either `TransactionType || ReceiptPayload` or + /// `LegacyReceipt`. + /// - `LegacyReceipt` is kept to be RLP encoded bytes; it is `rlp([status, + /// cumulativeGasUsed, logsBloom, logs])`. + /// - `ReceiptPayload` is an opaque byte array whose interpretation is + /// dependent on the `TransactionType` and defined in future EIPs. + /// - As [`EIP-2930`] defined: if `TransactionType` is `1`, + /// `ReceiptPayload` is `rlp([status, cumulativeGasUsed, logsBloom, + /// logs])`. + /// - As [`EIP-1559`] defined: if `TransactionType` is `2`, + /// `ReceiptPayload` is `rlp([status, cumulative_transaction_gas_used, + /// logs_bloom, logs])`. + /// + /// [`EIP-2718`]: https://eips.ethereum.org/EIPS/eip-2718#receipts + /// [`EIP-2930`]: https://eips.ethereum.org/EIPS/eip-2930#parameters + /// [`EIP-1559`]: https://eips.ethereum.org/EIPS/eip-1559#specification + pub fn encode_receipt(&self, r: &TxResp, logs_bloom: Bloom) -> Bytes { + // Status: either 1 (success) or 0 (failure). + // Only present after activation of [EIP-658](https://eips.ethereum.org/EIPS/eip-658) + let status: u64 = if matches!(r.exit_reason, ExitReason::Succeed(_)) { + 1 + } else { + 0 + }; + let used_gas = U256::from(r.gas_used); + let legacy_receipt = { + let mut rlp = RlpStream::new(); + rlp.begin_list(4); + rlp.append(&status); + rlp.append(&used_gas); + rlp.append(&logs_bloom); + rlp.append_list(&r.logs); + rlp.out().freeze() + }; + match self.type_() { + x if x == 0x01 || x == 0x02 => [&x.to_be_bytes()[7..], &legacy_receipt].concat().into(), + _ => legacy_receipt, // legacy (0x00) or undefined type + } + } } pub fn public_to_address(public: &Public) -> H160 {