Using package @ethereumjs and having 'invalid transaction trie'

24 views Asked by At

I'm trying to create a sequence of block for a blockchain with the ethereumjs-monorepo. Those are the versions i'm using

"@ethereumjs/block": "^5.0.1",
"@ethereumjs/blockchain": "^7.0.1",
"@ethereumjs/common": "^4.1.0",
"@ethereumjs/tx": "^5.1.0",
"@ethereumjs/vm": "^7.1.0",
"@ethereumjs/util": "^9.0.1"

I'm running the following code

import { Block } from '@ethereumjs/block'
import { TransactionFactory } from '@ethereumjs/tx'
import { Blockchain } from '@ethereumjs/blockchain'
import { Common, CustomChain } from '@ethereumjs/common'
import { VM } from '@ethereumjs/vm'
import { privateToPublic, publicToAddress, Address, Account } from '@ethereumjs/util'
import { randomBytes } from 'crypto'

const createAccount = () => {
  const privateKey = randomBytes(32);
  const publicKey = privateToPublic(privateKey)
  const pubAddr = publicToAddress(publicKey)
  const address = new Address(pubAddr)
  const details = new Account(BigInt(0), BigInt(100000000))
  return { privateKey, publicKey, address, details }
}

async function createBlocks() {
  const common = Common.custom(CustomChain.PolygonMumbai)
  common.setEIPs([1559]);
  const blockchain = await Blockchain.create({ common })
  const vm = await VM.create({ common, blockchain })
  await vm.stateManager.checkpoint()
  const account = createAccount();
  vm.stateManager.putAccount(account.address, account.details)
  await vm.stateManager.commit()
  

  let timestamp = Math.floor(Date.now() / 1000)
  let lastBlock = common.genesis()
  let lastHash = blockchain.genesisBlock.hash();
  for (let i = 1; i < 10; i++) {
    const transactions: any = [];
    //if (i !== 0) {
      for (let j = 0; j < 6; j++, account.details.nonce++) {
        const txData = {
          "hash": "0xce97011d4977ad8eec16b87bedefda436357734f9e39d8c3ce2d508af99d868d",
          "accessList": [],
          from: account.address.toString(),
          "gasLimit": "0x5208",
          "gasPrice": "0x5804253a",
          "input": "0x",
          "maxFeePerGas": "0x5804253a",
          "maxPriorityFeePerGas": "0x5804252a",
          "nonce": account.details.nonce,
          "to": "0x38a50480fdd3d612c5f5f86dd0a81d4b73555391",
          "transactionIndex": j,
          "type": "0x2",
          "value": "0x1402462f6000"
        }
        const tx = TransactionFactory.fromTxData(txData, { common })
        const signedTx = tx.sign(account.privateKey);
        transactions.push(signedTx)
        console.log(signedTx.toJSON());
      }  
    //}
    const blockData = {
      header: {
        number: i,
        timestamp: timestamp++,
        gasLimit: lastBlock.gasLimit,
        parentHash: lastHash,
        baseFeePerGas: lastBlock.baseFeePerGas,
      },
      transactions,
    }
    //console.log(blockData);
    const block = Block.fromBlockData(blockData, { common })
    //await block.genTxTrie();

    console.log(i);
    await block.genTxTrie() // Generate the transaction trie
    await blockchain.putBlock(block)
    lastHash = block.hash();
    const result = await vm.runBlock({ block, generate: true })
    // Display the block, transactions, and receipts in JSON format
    console.log(JSON.stringify(block.toJSON(), null, 2))
    transactions.forEach((tx: any) => console.log(JSON.stringify(tx.toJSON(), null, 2)))
    result.receipts.forEach((receipt: any) => console.log(JSON.stringify(receipt, null, 2)))
  }
}

createBlocks().catch(console.error)

I keep getting this error

Error: invalid transaction trie (block number=1 hash=0xd837b21b15426eedcd23ceb3658edfc04563d5e9c9ad6962c7da56106fb7cbfc hf=shanghai baseFeePerGas=7 txs=6 uncles=0)
    at Block.validateData (D:\github\node_modules\@ethereumjs\block\src\block.ts:550:13)
    at async Blockchain.validateBlock (D:\github\node_modules\@ethereumjs\blockchain\src\blockchain.ts:657:5)
    at async D:\github\node_modules\@ethereumjs\blockchain\src\blockchain.ts:493:11
    at async Blockchain.runWithLock (D:\github\node_modules\@ethereumjs\blockchain\src\blockchain.ts:296:21)
    at async Blockchain._putBlockOrHeader (D:\github\node_modules\@ethereumjs\blockchain\src\blockchain.ts:454:5)
    at async Blockchain.putBlock (D:\github\node_modules\@ethereumjs\blockchain\src\blockchain.ts:385:5)
    at async createBlocks (D:\github\test.ts:80:5)

I understand that the block has to be computed when created but from the documentation i don't understand what i'm missing to let the blockchain.putBlock create a block with a correct trie, since its getting the transactions in the building block, it should be able to create the correct trie no?

1

There are 1 answers

0
Darksorrow On

well i managed to get it working so i'll post it there even tho it seems not many people are using this lately but just in case :p

const trie = await Block.genTransactionsTrieRoot(transactions, new Trie());
const blockData = {
  header: {
    number: i,
    timestamp: intToHex(timestamp),
    gasLimit: 21000 * numTx,
    parentHash: lastHash,
    baseFeePerGas: lastBlock.baseFeePerGas,
    transactionsTrie: trie,
  },
  transactions,
}

I had to create a trie using the @ethereumjs/trie, get the results from the transaction i made and pass it to the block header before the block gets created.