Skip to content

Commit 7c4c5b9

Browse files
authored
Merge pull request #1091 from ethereumjs/fix-rinkeby-block-14182-consensus-bug
Client, VM -> Rinkeby: Fix consensus error on block 14182 (invalid receipt trie)
2 parents 6822c08 + 8d0afb7 commit 7c4c5b9

File tree

5 files changed

+88
-1
lines changed

5 files changed

+88
-1
lines changed

packages/client/bin/cli.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ const args = require('yargs')
8888
describe: 'EIP-1459 ENR tree urls to query for peer discovery targets',
8989
array: true,
9090
},
91+
debugCode: {
92+
describe: 'Generate code for local debugging (internal usage mostly)',
93+
boolean: true,
94+
default: Config.DEBUGCODE_DEFAULT,
95+
},
9196
})
9297
.locale('en_EN').argv
9398

@@ -168,6 +173,7 @@ async function run() {
168173
maxPeers: args.maxPeers,
169174
dnsAddr: args.dnsAddr,
170175
dnsNetworks: args.dnsNetworks,
176+
debugCode: args.debugCode,
171177
})
172178
logger = config.logger
173179

packages/client/lib/config.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,15 @@ export interface ConfigOptions {
114114
* EIP-1459 ENR Tree urls to query via DNS for peer discovery
115115
*/
116116
dnsNetworks?: string[]
117+
118+
/**
119+
* Generate code for local debugging, currently providing a
120+
* code snippet which can be used to run blocks on the
121+
* EthereumJS VM on execution errors
122+
*
123+
* (meant to be used internally for the most part)
124+
*/
125+
debugCode?: boolean
117126
}
118127

119128
export class Config {
@@ -129,6 +138,7 @@ export class Config {
129138
public static readonly MINPEERS_DEFAULT = 1
130139
public static readonly MAXPEERS_DEFAULT = 25
131140
public static readonly DNSADDR_DEFAULT = '8.8.8.8'
141+
public static readonly DEBUGCODE_DEFAULT = false
132142

133143
public readonly logger: Logger
134144
public readonly syncmode: string
@@ -143,6 +153,7 @@ export class Config {
143153
public readonly minPeers: number
144154
public readonly maxPeers: number
145155
public readonly dnsAddr: string
156+
public readonly debugCode: boolean
146157

147158
public readonly chainCommon: Common
148159
public readonly execCommon: Common
@@ -162,6 +173,7 @@ export class Config {
162173
this.minPeers = options.minPeers ?? Config.MINPEERS_DEFAULT
163174
this.maxPeers = options.maxPeers ?? Config.MAXPEERS_DEFAULT
164175
this.dnsAddr = options.dnsAddr ?? Config.DNSADDR_DEFAULT
176+
this.debugCode = options.debugCode ?? Config.DEBUGCODE_DEFAULT
165177

166178
// TODO: map chainParams (and lib/util.parseParams) to new Common format
167179
const common =

packages/client/lib/sync/execution/vmexecution.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import VM from '@ethereumjs/vm'
44
import { DefaultStateManager } from '@ethereumjs/vm/dist/state'
55
import { SecureTrie as Trie } from '@ethereumjs/trie'
66
import { Block } from '@ethereumjs/block'
7+
import { debugCodeReplayBlock } from '../../util/debug'
78

89
export class VMExecution extends Execution {
910
public vm: VM
@@ -155,6 +156,9 @@ export class VMExecution extends Execution {
155156
this.config.logger.warn(
156157
`Execution of block number=${blockNumber} hash=${hash} hardfork=${this.hardfork} failed`
157158
)
159+
if (this.config.debugCode) {
160+
await debugCodeReplayBlock(this, block)
161+
}
158162
this.emit('error', error)
159163
errorBlock = block
160164
}

packages/client/lib/util/debug.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { Block } from '@ethereumjs/block'
2+
import { VMExecution } from '../sync/execution'
3+
4+
/**
5+
* Generates a code snippet which can be used to replay an erraneous block
6+
* locally in the VM
7+
*
8+
* @param block
9+
*/
10+
export async function debugCodeReplayBlock(execution: VMExecution, block: Block) {
11+
const code = `
12+
/**
13+
* Script for locally executing a block in the EthereumJS VM,
14+
* meant to be used from packages/vm directory within the
15+
* https://github.com/ethereumjs/ethereumjs-monorepo repository.
16+
*
17+
* Block: ${block.header.number}
18+
* Hardfork: ${execution.hardfork}
19+
*
20+
* Run with: DEBUG=vm:*:*,vm:*,-vm:ops:* ts-node [SCRIPT_NAME].ts
21+
*
22+
*/
23+
24+
const level = require('level')
25+
import Common from '@ethereumjs/common'
26+
import { Block } from '@ethereumjs/block'
27+
import VM from './lib'
28+
import { SecureTrie as Trie } from '@ethereumjs/trie'
29+
import { DefaultStateManager } from './lib/state'
30+
import Blockchain from '@ethereumjs/blockchain'
31+
32+
const main = async () => {
33+
const common = new Common({ chain: '${execution.config.execCommon.chainName()}', hardfork: '${
34+
execution.hardfork
35+
}' })
36+
const block = Block.fromRLPSerializedBlock(Buffer.from('${block
37+
.serialize()
38+
.toString('hex')}', 'hex'), { common })
39+
40+
const stateDB = level('${execution.config.getStateDataDirectory()}')
41+
const trie = new Trie(stateDB)
42+
const stateManager = new DefaultStateManager({ trie, common })
43+
// Ensure we run on the right root
44+
stateManager.setStateRoot(Buffer.from('${(
45+
await execution.vm.stateManager.getStateRoot(true)
46+
).toString('hex')}', 'hex'))
47+
48+
49+
const chainDB = level('${execution.config.getChainDataDirectory()}')
50+
const blockchain = await Blockchain.create({
51+
db: chainDB,
52+
common,
53+
validateBlocks: true,
54+
validateConsensus: false,
55+
})
56+
const vm = new VM({ stateManager, blockchain, common })
57+
58+
await vm.runBlock({ block })
59+
}
60+
61+
main()
62+
`
63+
64+
execution.config.logger.info(code)
65+
}

packages/vm/lib/runTx.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise<RunTxResult> {
176176
.hash()
177177
.toString('hex')} with caller=${caller.toString()} gasLimit=${gasLimit} to=${
178178
to ? to.toString() : ''
179-
} value=${value} data=0x${data.toString('hex')}`
179+
} value=${value} data=0x${short(data)}`
180180
)
181181
const results = (await evm.executeMessage(message)) as RunTxResult
182182
debug('-'.repeat(100))

0 commit comments

Comments
 (0)