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
5 changes: 5 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ jobs:
sudo update-alternatives --install /usr/bin/gcov-tool gcov-tool /usr/bin/gcov-tool-11 11
gcc --version

- name: Free disk space
run: |
sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc
df -h

- name: Build dependencies
run: |
cd deps
Expand Down
29 changes: 21 additions & 8 deletions libethereum/Block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -999,8 +999,14 @@ u256 Block::enact( VerifiedBlockRef const& _block, BlockChain const& _bc ) {
throw;
}

// EIP-2718: use typed receipt encoding for non-Legacy transactions.
if ( EIP1559TransactionsPatch::isEnabledInWorkingBlock() &&
// The EIP-1559
// transaction format is accepted before Berlin, but the typed-receipt
// encoding must only change at the coordinated Berlin fork so blocks
// produced before it keep their original receiptsRoot.
// The parent block timestamp is used (not the global committed-block
// timestamp) so the encoding is deterministic per block, including when
// a block is re-enacted out of order.
if ( BerlinForkPatch::isEnabledWhen( previousInfo().timestamp() ) &&
m_receipts.back().txType() > 0 ) {
receipts.push_back( m_receipts.back().typedRlp() );
} else {
Expand Down Expand Up @@ -1420,10 +1426,15 @@ void Block::commitToSeal(
RLPStream k;
k << i;

// Since EIP-1559 API is enabled before Berlin fork,
// this part of EIP-2718 logic is activated depending on EIP1559TransactionsPatch
// EIP-2718 typed-receipt encoding is gated on BerlinForkPatch:
// the EIP-1559 transaction format is accepted
// before Berlin, but the receipt encoding must only change at the
// coordinated Berlin fork so pre-Berlin blocks keep their receiptsRoot.
// The parent block timestamp is used (not the global committed-block
// timestamp) so the encoding is deterministic per block and matches enact().
bytes receiptBytes;
if ( EIP1559TransactionsPatch::isEnabledInWorkingBlock() && receipt( i ).txType() > 0 ) {
if ( BerlinForkPatch::isEnabledWhen( previousInfo().timestamp() ) &&
receipt( i ).txType() > 0 ) {
receiptBytes = receipt( i ).typedRlp();
} else {
RLPStream receiptrlp;
Expand All @@ -1433,9 +1444,11 @@ void Block::commitToSeal(
receiptsMap.insert( std::make_pair( k.out(), receiptBytes ) );

dev::bytes txOutput = m_transactions[i].toBytes();
// Same as receiptBytes creation:
// this part of EIP-2718 logic is activated depending on EIP1559TransactionsPatch
if ( EIP1559TransactionsPatch::isEnabledInWorkingBlock() &&
// EIP-2718: typed transactions go into the transactions trie wrapped as an
// RLP byte string. Unlike the receipt encoding above, this is gated on
// EIP1559TransactionsPatch because typed transactions are accepted
// before Berlin.
if ( EIP1559TransactionsPatch::isEnabledWhen( previousInfo().timestamp() ) &&
m_transactions[i].txType() != dev::eth::TransactionType::Legacy ) {
RLPStream s;
s.append( txOutput );
Expand Down
31 changes: 16 additions & 15 deletions test/api-tests/hardfork-compat/test_hardfork_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
- a factory whose constructor runs CREATE and CREATE2
3. Launch the 5.2.0 sync node (syncNode=true, archiveMode=true)
4. Wait for the sync node to catch up to the primary head
5. Compare the per-block stateRoot of every block (the primary assertion)
6. Compare per-block hashes as a diagnostic cross-check
5. Compare the per-block stateRoot of every block
6. Compare per-block hashes (covers receiptsRoot/transactionsRoot)
Both comparisons are hard assertions: any mismatch fails the test.

Tests run in file order (sequential): the workload must complete before the
sync node is launched and the comparison runs.
Expand Down Expand Up @@ -280,20 +281,20 @@ def test_sync_catchup_and_state_root_comparison(
compare_bn = min(w3_primary.eth.block_number, w3_sync.eth.block_number)
logger.info("Comparing stateRoot for blocks 0..%d (5.1.0 vs 5.2.0)", compare_bn)

# Run both comparisons before asserting so a failure reports the full
# picture (stateRoot and hash mismatches) in one go. The block hash
# embeds receiptsRoot/transactionsRoot, so it must fail the test just
# like a stateRoot mismatch -- not be logged as a diagnostic.
root_mismatches = compare_state_roots(w3_primary, w3_sync, compare_bn)
assert len(root_mismatches) == 0, (
f"stateRoot mismatches between 5.1.0 and 5.2.0 at blocks: {root_mismatches}"
)
logger.info("All %d block stateRoots match between 5.1.0 and 5.2.0", compare_bn + 1)

hash_mismatches = compare_block_hashes(w3_primary, w3_sync, compare_bn)
if hash_mismatches:
logger.warning(
"Block hash mismatches between 5.1.0 and 5.2.0 at blocks %s; "
"stateRoot matched, so this is diagnostic only",
hash_mismatches,
)
else:
logger.info("All %d block hashes match between 5.1.0 and 5.2.0", compare_bn + 1)

assert not root_mismatches and not hash_mismatches, (
f"5.1.0 vs 5.2.0 divergence: stateRoot mismatches at blocks "
f"{root_mismatches}, block hash mismatches at blocks {hash_mismatches}"
)
logger.info(
"All %d block stateRoots and hashes match between 5.1.0 and 5.2.0",
compare_bn + 1,
)
finally:
_stop_node(proc, log_fd, "SYNC(5.2.0)")
Loading