forked from ethereumjs/ethereumjs-monorepo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun-blockchain.ts
97 lines (77 loc) · 3.24 KB
/
run-blockchain.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// The example does these things:
//
// 1. Instantiates a VM and a Blockchain
// 2. Creates the accounts from ../utils/blockchain-mock-data "pre" attribute
// 3. Creates a genesis block
// 4. Puts the blocks from ../utils/blockchain-mock-data "blocks" attribute into the Blockchain
// 5. Runs the Blockchain on the VM.
import { createBlock, createBlockFromRLP } from '@ethereumjs/block'
import { EthashConsensus, createBlockchain } from '@ethereumjs/blockchain'
import { Common, ConsensusAlgorithm, ConsensusType, Mainnet } from '@ethereumjs/common'
import { Ethash } from '@ethereumjs/ethash'
import {
Address,
bytesToHex,
createAccount,
hexToBytes,
setLengthLeft,
toBytes,
} from '@ethereumjs/util'
import { createVM, runBlock } from '@ethereumjs/vm'
import testData from './helpers/blockchain-mock-data.json'
import type { Block } from '@ethereumjs/block'
import type { Blockchain, ConsensusDict } from '@ethereumjs/blockchain'
import type { VM } from '@ethereumjs/vm'
async function setupPreConditions(vm: VM, data: any) {
await vm.stateManager.checkpoint()
for (const [addr, acct] of Object.entries(data.pre)) {
const { nonce, balance, storage, code } = acct as any
const address = new Address(hexToBytes(addr))
const account = createAccount({ nonce, balance })
await vm.stateManager.putAccount(address, account)
for (const [key, val] of Object.entries(storage)) {
const storageKey = setLengthLeft(hexToBytes(key), 32)
const storageVal = hexToBytes(val as string)
await vm.stateManager.putStorage(address, storageKey, storageVal)
}
const codeBuf = hexToBytes('0x' + code)
await vm.stateManager.putCode(address, codeBuf)
}
await vm.stateManager.commit()
}
async function putBlocks(blockchain: Blockchain, common: Common, data: typeof testData) {
for (const blockData of data.blocks) {
const blockRlp = toBytes(blockData.rlp)
const block = createBlockFromRLP(blockRlp, { common })
await blockchain.putBlock(block)
}
}
async function main() {
const common = new Common({ chain: Mainnet, hardfork: testData.network.toLowerCase() })
const validatePow = common.consensusType() === ConsensusType.ProofOfWork
const validateBlocks = true
const genesisBlock = createBlock({ header: testData.genesisBlockHeader }, { common })
const consensusDict: ConsensusDict = {}
consensusDict[ConsensusAlgorithm.Ethash] = new EthashConsensus(new Ethash())
const blockchain = await createBlockchain({
common,
validateBlocks,
validateConsensus: validatePow,
consensusDict,
genesisBlock,
})
const vm = await createVM({ blockchain, common })
await setupPreConditions(vm, testData)
await putBlocks(blockchain, common, testData)
await blockchain.iterator('vm', async (block: Block, _reorg: boolean) => {
const parentBlock = await blockchain!.getBlock(block.header.parentHash)
const parentState = parentBlock.header.stateRoot
// run block
await runBlock(vm, { block, root: parentState, skipHardForkValidation: true })
})
const blockchainHead = await vm.blockchain.getIteratorHead!()
console.log('--- Finished processing the Blockchain ---')
console.log('New head:', bytesToHex(blockchainHead.hash()))
console.log('Expected:', testData.lastblockhash)
}
void main()