Skip to content

Commit d20cca8

Browse files
committed
impl ssz receipts and dev modify the receipts rooting work
1 parent 2d51f62 commit d20cca8

File tree

7 files changed

+108
-19
lines changed

7 files changed

+108
-19
lines changed

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/util/src/ssz.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Tree, hasher } from '@chainsafe/persistent-merkle-tree'
22
import {
33
BitArray,
4+
BooleanType,
45
ByteListType,
56
ByteVectorType,
67
ContainerType,
@@ -24,6 +25,8 @@ export const MAX_TRANSACTION_PAYLOAD_FIELDS = 32
2425
export const MAX_TRANSACTION_SIGNATURE_FIELDS = 16
2526
export const MAX_BLOB_COMMITMENTS_PER_BLOCK = 4096
2627

28+
export const Boolean = new BooleanType()
29+
2730
export const Uint8 = new UintBigintType(1)
2831
export const Uint64 = new UintBigintType(8)
2932
export const Uint256 = new UintBigintType(32)
@@ -393,6 +396,37 @@ export type TransactionV1 = {
393396
signature: ExecutionSignatureV1
394397
}
395398

399+
const MAX_TOPICS_PER_LOG = 4
400+
const MAX_LOG_DATA_SIZE = 16_777_216
401+
const MAX_RECEIPT_FIELDS = 32
402+
const MAX_LOGS_PER_RECEIPT = 2_097_152
403+
404+
export const LogTopics = new ListCompositeType(Bytes32, MAX_TOPICS_PER_LOG)
405+
export const Log = new ContainerType(
406+
{
407+
address: ExecutionAddress,
408+
topics: LogTopics,
409+
data: new ByteListType(MAX_LOG_DATA_SIZE),
410+
},
411+
{ typeName: 'Log', jsonCase: 'eth2' },
412+
)
413+
export const LogList = new ListCompositeType(Log, MAX_LOGS_PER_RECEIPT)
414+
export const AuthoritiesList = new ListCompositeType(ExecutionAddress, MAX_AUTHORIZATION_LIST_SIZE)
415+
416+
export const Receipt = new StableContainerType(
417+
{
418+
root: new OptionalType(Bytes32),
419+
gasUsed: new OptionalType(Uint64),
420+
contractAddress: new OptionalType(ExecutionAddress),
421+
logs: new OptionalType(LogList),
422+
status: new OptionalType(Boolean),
423+
authorities: new OptionalType(AuthoritiesList),
424+
},
425+
MAX_RECEIPT_FIELDS,
426+
{ typeName: 'Receipt', jsonCase: 'eth2' },
427+
)
428+
export const Receipts = new ListCompositeType(Receipt, MAX_TRANSACTIONS_PER_PAYLOAD)
429+
396430
export const MAX_BLOCKHEADER_FIELDS = 64
397431
const MAX_EXTRA_DATA_BYTES = 32
398432

packages/vm/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"tsc": "../../config/cli/ts-compile.sh"
6565
},
6666
"dependencies": {
67+
"@chainsafe/ssz": "https://github.com/ChainSafe/ssz/raw/cayman/stable-container/packages/ssz/package.tgz",
6768
"@ethereumjs/block": "^5.3.0",
6869
"@ethereumjs/common": "^4.4.0",
6970
"@ethereumjs/evm": "^3.1.0",

packages/vm/src/buildBlock.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ import {
1717
BIGINT_1,
1818
BIGINT_2,
1919
GWEI_TO_WEI,
20-
KECCAK256_RLP,
2120
TypeOutput,
2221
createWithdrawal,
2322
createZeroAddress,
23+
ssz,
2424
toBytes,
2525
toType,
2626
} from '@ethereumjs/util'
@@ -32,11 +32,13 @@ import {
3232
accumulateParentBlockHash,
3333
calculateMinerReward,
3434
encodeReceipt,
35+
encodeSszReceipt,
3536
rewardAccount,
3637
} from './runBlock.js'
3738

3839
import { runTx } from './index.js'
3940

41+
import type { SSZReceiptType } from './runBlock.js'
4042
import type { BuildBlockOpts, BuilderOpts, RunTxResult, SealBlockOpts } from './types.js'
4143
import type { VM } from './vm.js'
4244
import type { Block, HeaderData } from '@ethereumjs/block'
@@ -147,7 +149,10 @@ export class BlockBuilder {
147149
public async transactionsTrie() {
148150
return this.vm.common.isActivatedEIP(6493)
149151
? genTransactionsSszRoot(this.transactions)
150-
: genTransactionsTrieRoot(this.transactions, new MerklePatriciaTrie({ common: this.vm.common }))
152+
: genTransactionsTrieRoot(
153+
this.transactions,
154+
new MerklePatriciaTrie({ common: this.vm.common }),
155+
)
151156
}
152157

153158
public async withdrawalsTrie() {
@@ -176,16 +181,22 @@ export class BlockBuilder {
176181
* Calculates and returns the receiptTrie for the block.
177182
*/
178183
public async receiptTrie() {
179-
if (this.transactionResults.length === 0) {
180-
return KECCAK256_RLP
181-
}
182-
const receiptTrie = new MerklePatriciaTrie({ common: this.vm.common })
183-
for (const [i, txResult] of this.transactionResults.entries()) {
184-
const tx = this.transactions[i]
185-
const encodedReceipt = encodeReceipt(txResult.receipt, tx.type)
186-
await receiptTrie.put(RLP.encode(i), encodedReceipt)
184+
if (this.vm.common.isActivatedEIP(6493)) {
185+
const sszReceipts: SSZReceiptType[] = []
186+
for (const [i, txResult] of this.transactionResults.entries()) {
187+
const tx = this.transactions[i]
188+
sszReceipts.push(encodeSszReceipt(txResult.receipt, tx.type))
189+
}
190+
return ssz.Receipts.hashTreeRoot(sszReceipts)
191+
} else {
192+
const receiptTrie = new MerklePatriciaTrie({ common: this.vm.common })
193+
for (const [i, txResult] of this.transactionResults.entries()) {
194+
const tx = this.transactions[i]
195+
const encodedReceipt = encodeReceipt(txResult.receipt, tx.type)
196+
await receiptTrie.put(RLP.encode(i), encodedReceipt)
197+
}
198+
return receiptTrie.root()
187199
}
188-
return receiptTrie.root()
189200
}
190201

191202
/**

packages/vm/src/runBlock.ts

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
intToBytes,
2424
setLengthLeft,
2525
short,
26+
ssz,
2627
unprefixedHexToBytes,
2728
} from '@ethereumjs/util'
2829
import debugDefault from 'debug'
@@ -44,11 +45,14 @@ import type {
4445
TxReceipt,
4546
} from './types.js'
4647
import type { VM } from './vm.js'
48+
import type { ValueOf } from '@chainsafe/ssz'
4749
import type { Block } from '@ethereumjs/block'
4850
import type { Common } from '@ethereumjs/common'
4951
import type { EVM, EVMInterface } from '@ethereumjs/evm'
5052
import type { CLRequest, CLRequestType, PrefixedHexString } from '@ethereumjs/util'
5153

54+
export type SSZReceiptType = ValueOf<typeof ssz.Receipt>
55+
5256
const debug = debugDefault('vm:block')
5357

5458
const parentBeaconBlockRootAddress = createAddressFromString(
@@ -583,11 +587,6 @@ async function applyTransactions(vm: VM, block: Block, opts: RunBlockOpts) {
583587
// the total amount of gas used processing these transactions
584588
let gasUsed = BIGINT_0
585589

586-
let receiptTrie: MerklePatriciaTrie | undefined = undefined
587-
if (block.transactions.length !== 0) {
588-
receiptTrie = new MerklePatriciaTrie({ common: vm.common })
589-
}
590-
591590
const receipts: TxReceipt[] = []
592591
const txResults: RunTxResult[] = []
593592

@@ -637,16 +636,30 @@ async function applyTransactions(vm: VM, block: Block, opts: RunBlockOpts) {
637636

638637
// Add receipt to trie to later calculate receipt root
639638
receipts.push(txRes.receipt)
640-
const encodedReceipt = encodeReceipt(txRes.receipt, tx.type)
641-
await receiptTrie!.put(RLP.encode(txIdx), encodedReceipt)
642639
}
643640

644641
if (enableProfiler) {
645642
// eslint-disable-next-line no-console
646643
console.timeEnd(processTxsLabel)
647644
}
648645

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+
}
650663

651664
return {
652665
bloom,
@@ -761,6 +774,28 @@ export function encodeReceipt(receipt: TxReceipt, txType: TransactionType) {
761774
return concatBytes(intToBytes(txType), encoded)
762775
}
763776

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+
764799
/**
765800
* Apply the DAO fork changes to the VM
766801
*/

packages/vm/src/runTx.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,8 @@ export async function generateTxReceipt(
808808
cumulativeBlockGasUsed: cumulativeGasUsed,
809809
bitvector: txResult.bloom.bitvector,
810810
logs: txResult.execResult.logs ?? [],
811+
contractAddress: txResult.createdAddress,
812+
authorities: txResult.authorities,
811813
}
812814

813815
let receipt

packages/vm/src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010
} from '@ethereumjs/evm'
1111
import type { AccessList, TypedTransaction } from '@ethereumjs/tx'
1212
import type {
13+
Address,
1314
BigIntLike,
1415
CLRequest,
1516
CLRequestType,
@@ -34,6 +35,8 @@ export interface BaseTxReceipt {
3435
* Logs emitted
3536
*/
3637
logs: Log[]
38+
contractAddress?: Address
39+
authorities?: Address[]
3740
}
3841

3942
/**
@@ -488,6 +491,8 @@ export interface RunTxResult extends EVMResult {
488491
* This is the blob gas units times the fee per blob gas for 4844 transactions
489492
*/
490493
blobGasUsed?: bigint
494+
495+
authorities?: Address[]
491496
}
492497

493498
export interface AfterTxEvent extends RunTxResult {

0 commit comments

Comments
 (0)