@@ -23,6 +23,7 @@ import {
23
23
intToBytes ,
24
24
setLengthLeft ,
25
25
short ,
26
+ ssz ,
26
27
unprefixedHexToBytes ,
27
28
} from '@ethereumjs/util'
28
29
import debugDefault from 'debug'
@@ -44,11 +45,14 @@ import type {
44
45
TxReceipt ,
45
46
} from './types.js'
46
47
import type { VM } from './vm.js'
48
+ import type { ValueOf } from '@chainsafe/ssz'
47
49
import type { Block } from '@ethereumjs/block'
48
50
import type { Common } from '@ethereumjs/common'
49
51
import type { EVM , EVMInterface } from '@ethereumjs/evm'
50
52
import type { CLRequest , CLRequestType , PrefixedHexString } from '@ethereumjs/util'
51
53
54
+ export type SSZReceiptType = ValueOf < typeof ssz . Receipt >
55
+
52
56
const debug = debugDefault ( 'vm:block' )
53
57
54
58
const parentBeaconBlockRootAddress = createAddressFromString (
@@ -583,11 +587,6 @@ async function applyTransactions(vm: VM, block: Block, opts: RunBlockOpts) {
583
587
// the total amount of gas used processing these transactions
584
588
let gasUsed = BIGINT_0
585
589
586
- let receiptTrie : MerklePatriciaTrie | undefined = undefined
587
- if ( block . transactions . length !== 0 ) {
588
- receiptTrie = new MerklePatriciaTrie ( { common : vm . common } )
589
- }
590
-
591
590
const receipts : TxReceipt [ ] = [ ]
592
591
const txResults : RunTxResult [ ] = [ ]
593
592
@@ -637,16 +636,30 @@ async function applyTransactions(vm: VM, block: Block, opts: RunBlockOpts) {
637
636
638
637
// Add receipt to trie to later calculate receipt root
639
638
receipts . push ( txRes . receipt )
640
- const encodedReceipt = encodeReceipt ( txRes . receipt , tx . type )
641
- await receiptTrie ! . put ( RLP . encode ( txIdx ) , encodedReceipt )
642
639
}
643
640
644
641
if ( enableProfiler ) {
645
642
// eslint-disable-next-line no-console
646
643
console . timeEnd ( processTxsLabel )
647
644
}
648
645
649
- const receiptsRoot = receiptTrie !== undefined ? receiptTrie . root ( ) : KECCAK256_RLP
646
+ let receiptsRoot
647
+ if ( vm . common . isActivatedEIP ( 6493 ) ) {
648
+ const sszReceipts : SSZReceiptType [ ] = [ ]
649
+ for ( const [ i , txReceipt ] of receipts . entries ( ) ) {
650
+ const tx = block . transactions [ i ]
651
+ sszReceipts . push ( encodeSszReceipt ( txReceipt , tx . type ) )
652
+ }
653
+ receiptsRoot = ssz . Receipts . hashTreeRoot ( sszReceipts )
654
+ } else {
655
+ const receiptTrie = new MerklePatriciaTrie ( { common : vm . common } )
656
+ for ( const [ i , txReceipt ] of receipts . entries ( ) ) {
657
+ const tx = block . transactions [ i ]
658
+ const encodedReceipt = encodeReceipt ( txReceipt , tx . type )
659
+ await receiptTrie ! . put ( RLP . encode ( i ) , encodedReceipt )
660
+ }
661
+ receiptsRoot = receiptTrie . root ( )
662
+ }
650
663
651
664
return {
652
665
bloom,
@@ -761,6 +774,28 @@ export function encodeReceipt(receipt: TxReceipt, txType: TransactionType) {
761
774
return concatBytes ( intToBytes ( txType ) , encoded )
762
775
}
763
776
777
+ export function encodeSszReceipt ( receipt : TxReceipt , _txType : TransactionType ) {
778
+ const sszRaw : SSZReceiptType = {
779
+ root : ( receipt as PreByzantiumTxReceipt ) . stateRoot ?? null ,
780
+ gasUsed : receipt . cumulativeBlockGasUsed ,
781
+ contractAddress : receipt . contractAddress ?. bytes ?? null ,
782
+ logs : receipt . logs . map ( ( log ) => ( {
783
+ address : log [ 0 ] ,
784
+ topics : log [ 1 ] ,
785
+ data : log [ 2 ] ,
786
+ } ) ) ,
787
+ status :
788
+ ( receipt as PostByzantiumTxReceipt ) . status !== undefined
789
+ ? ( receipt as PostByzantiumTxReceipt ) . status === 0
790
+ ? false
791
+ : true
792
+ : null ,
793
+ authorities : receipt . authorities ?. map ( ( auth ) => auth . bytes ) ?? null ,
794
+ }
795
+
796
+ return sszRaw
797
+ }
798
+
764
799
/**
765
800
* Apply the DAO fork changes to the VM
766
801
*/
0 commit comments