Skip to content

Commit 4aa4cef

Browse files
am1r021holgerd77
andauthored
Blockchain debug additions (#3676)
* Add debug logging to core blockchain class * Add debug logging to PoW consensus validation * Remove logs where errors are thrown * Update blockchain docs with new debug namespaces * Put consensus debug namespaces in the same parent space * Fix spelling mistake * Fix lint issues * Optimize out hash recalculation * Add recomended stats to debug logs * Rename debug namespaces to be more simple * Some debug log enhancements * Fix spelling --------- Co-authored-by: Holger Drewes <[email protected]>
1 parent 9c16211 commit 4aa4cef

File tree

4 files changed

+80
-5
lines changed

4 files changed

+80
-5
lines changed

packages/blockchain/README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,11 @@ This library uses the [debug](https://github.com/visionmedia/debug) debugging ut
245245

246246
The following initial logger is currently available:
247247

248-
| Logger | Description |
249-
| ------------------- | ----------------------------------------------------------- |
250-
| `blockchain:clique` | Clique operations like updating the vote and/or signer list |
248+
| Logger | Description |
249+
| ------------------- | ------------------------------------------------------------------------ |
250+
| `blockchain` | Core blockchain operations like when a block or header is put or deleted |
251+
| `blockchain:clique` | Clique consensus operations like updating the vote and/or signer list |
252+
| `blockchain:ethash` | Ethash consensus operations like PoW block or header validation |
251253

252254
The following is an example for a logger run:
253255

packages/blockchain/src/blockchain.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import {
88
KECCAK256_RLP,
99
Lock,
1010
MapDB,
11+
bigIntToHex,
1112
bytesToHex,
1213
bytesToUnprefixedHex,
1314
concatBytes,
1415
equalsBytes,
1516
} from '@ethereumjs/util'
17+
import debugDefault from 'debug'
1618

1719
import { CasperConsensus } from './consensus/casper.js'
1820
import {
@@ -36,6 +38,7 @@ import type {
3638
import type { HeaderData } from '@ethereumjs/block'
3739
import type { CliqueConfig } from '@ethereumjs/common'
3840
import type { BigIntLike, DB, DBObject, GenesisState } from '@ethereumjs/util'
41+
import type { Debugger } from 'debug'
3942

4043
/**
4144
* Blockchain implementation to create and maintain a valid canonical chain
@@ -88,6 +91,9 @@ export class Blockchain implements BlockchainInterface {
8891
*/
8992
private _deletedBlocks: Block[] = []
9093

94+
private DEBUG: boolean // Guard for debug logs
95+
private _debug: Debugger
96+
9197
/**
9298
* Creates new Blockchain object.
9399
*
@@ -99,6 +105,10 @@ export class Blockchain implements BlockchainInterface {
99105
* {@link BlockchainOptions}.
100106
*/
101107
constructor(opts: BlockchainOptions = {}) {
108+
this.DEBUG =
109+
typeof window === 'undefined' ? (process?.env?.DEBUG?.includes('ethjs') ?? false) : false
110+
this._debug = debugDefault('blockchain')
111+
102112
if (opts.common) {
103113
this.common = opts.common
104114
} else {
@@ -262,6 +272,8 @@ export class Blockchain implements BlockchainInterface {
262272
for (let i = 0; i < blocks.length; i++) {
263273
await this.putBlock(blocks[i])
264274
}
275+
276+
this.DEBUG && this._debug(`put ${blocks.length} blocks`)
265277
}
266278

267279
/**
@@ -289,6 +301,8 @@ export class Blockchain implements BlockchainInterface {
289301
for (let i = 0; i < headers.length; i++) {
290302
await this.putHeader(headers[i])
291303
}
304+
305+
this.DEBUG && this._debug(`put ${headers.length} headers`)
292306
}
293307

294308
/**
@@ -312,8 +326,10 @@ export class Blockchain implements BlockchainInterface {
312326
*/
313327

314328
async resetCanonicalHead(canonicalHead: bigint) {
329+
let hash: Uint8Array | undefined
330+
const canonicalHeadHash = (await this.getCanonicalHeadHeader()).hash()
315331
await this.runWithLock<void>(async () => {
316-
const hash = await this.dbManager.numberToHash(canonicalHead)
332+
hash = await this.dbManager.numberToHash(canonicalHead)
317333
if (hash === undefined) {
318334
throw new Error(`no block for ${canonicalHead} found in DB`)
319335
}
@@ -328,6 +344,17 @@ export class Blockchain implements BlockchainInterface {
328344
})
329345
if (this._deletedBlocks.length > 0) {
330346
this.events.emit('deletedCanonicalBlocks', this._deletedBlocks)
347+
for (const block of this._deletedBlocks)
348+
this.DEBUG &&
349+
this._debug(
350+
`deleted block along head reset: number ${block.header.number} hash ${bytesToHex(block.hash())}`,
351+
)
352+
353+
this.DEBUG &&
354+
this._debug(
355+
`Canonical head set from ${bytesToHex(canonicalHeadHash)} to ${bytesToHex(hash!)} (number ${bigIntToHex(canonicalHead)})`,
356+
)
357+
331358
this._deletedBlocks = []
332359
}
333360
}
@@ -452,6 +479,8 @@ export class Blockchain implements BlockchainInterface {
452479
await this.dbManager.batch(ops)
453480

454481
await this.consensus?.newBlock(block, commonAncestor, ancestorHeaders)
482+
this.DEBUG &&
483+
this._debug(`put block number=${block.header.number} hash=${bytesToHex(blockHash)}`)
455484
} catch (e) {
456485
// restore head to the previously sane state
457486
this._heads = oldHeads
@@ -462,6 +491,11 @@ export class Blockchain implements BlockchainInterface {
462491
})
463492
if (this._deletedBlocks.length > 0) {
464493
this.events.emit('deletedCanonicalBlocks', this._deletedBlocks)
494+
for (const block of this._deletedBlocks)
495+
this.DEBUG &&
496+
this._debug(
497+
`delete stale canonical block number=${block.header.number} hash=${bytesToHex(block.hash())}`,
498+
)
465499
this._deletedBlocks = []
466500
}
467501
}
@@ -829,6 +863,11 @@ export class Blockchain implements BlockchainInterface {
829863

830864
if (this._deletedBlocks.length > 0) {
831865
this.events.emit('deletedCanonicalBlocks', this._deletedBlocks)
866+
for (const block of this._deletedBlocks)
867+
this.DEBUG &&
868+
this._debug(
869+
`delete stale canonical block number=${block.header.number} hash=${blockHash})}`,
870+
)
832871
this._deletedBlocks = []
833872
}
834873
}
@@ -1018,6 +1057,9 @@ export class Blockchain implements BlockchainInterface {
10181057
if (!equalsBytes(header.hash(), newHeader.hash())) {
10191058
throw new Error('Failed to find ancient header')
10201059
}
1060+
1061+
this.DEBUG && this._debug(`found common ancestor with hash=${bytesToHex(header.hash())}`)
1062+
this.DEBUG && this._debug(`total ancestor headers num=${ancestorHeaders.size}`)
10211063
return {
10221064
commonAncestor: header,
10231065
ancestorHeaders: Array.from(ancestorHeaders),
@@ -1080,6 +1122,10 @@ export class Blockchain implements BlockchainInterface {
10801122

10811123
hash = await this.safeNumberToHash(blockNumber)
10821124
}
1125+
1126+
this.DEBUG &&
1127+
this._deletedBlocks.length > 0 &&
1128+
this._debug(`deleted ${this._deletedBlocks.length} stale canonical blocks in total`)
10831129
} catch (e) {
10841130
// Ensure that if this method throws, `_deletedBlocks` is reset to the empty array
10851131
this._deletedBlocks = []
@@ -1162,6 +1208,8 @@ export class Blockchain implements BlockchainInterface {
11621208
if (staleHeadBlock) {
11631209
this._headBlockHash = currentCanonicalHash
11641210
}
1211+
1212+
this.DEBUG && this._debug(`stale heads found num=${staleHeads.length}`)
11651213
}
11661214

11671215
/* Helper functions */

packages/blockchain/src/consensus/ethash.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { ConsensusAlgorithm } from '@ethereumjs/common'
2+
import { bytesToHex } from '@ethereumjs/util'
3+
import debugDefault from 'debug'
24

35
import type { Blockchain } from '../index.js'
46
import type { Consensus, ConsensusOptions } from '../types.js'
57
import type { Block, BlockHeader } from '@ethereumjs/block'
8+
import type { Debugger } from 'debug'
69

710
type MinimalEthashInterface = {
811
cacheDB?: any
@@ -17,7 +20,14 @@ export class EthashConsensus implements Consensus {
1720
algorithm: ConsensusAlgorithm
1821
_ethash: MinimalEthashInterface
1922

23+
private DEBUG: boolean // Guard for debug logs
24+
private _debug: Debugger
25+
2026
constructor(ethash: MinimalEthashInterface) {
27+
this.DEBUG =
28+
typeof window === 'undefined' ? (process?.env?.DEBUG?.includes('ethjs') ?? false) : false
29+
this._debug = debugDefault('blockchain:ethash')
30+
2131
this.algorithm = ConsensusAlgorithm.Ethash
2232
this._ethash = ethash
2333
}
@@ -27,6 +37,10 @@ export class EthashConsensus implements Consensus {
2737
if (!valid) {
2838
throw new Error('invalid POW')
2939
}
40+
this.DEBUG &&
41+
this._debug(
42+
`valid PoW consensus block: number ${block.header.number} hash ${bytesToHex(block.hash())}`,
43+
)
3044
}
3145

3246
/**
@@ -41,6 +55,10 @@ export class EthashConsensus implements Consensus {
4155
if (header.ethashCanonicalDifficulty(parentHeader) !== header.difficulty) {
4256
throw new Error(`invalid difficulty ${header.errorStr()}`)
4357
}
58+
this.DEBUG &&
59+
this._debug(
60+
`valid difficulty header: number ${header.number} difficulty ${header.difficulty} parentHash ${bytesToHex(header.parentHash)}`,
61+
)
4462
}
4563

4664
public async genesisInit(): Promise<void> {}

packages/blockchain/src/constructors.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { createBlock } from '@ethereumjs/block'
2-
import { BIGINT_0, equalsBytes } from '@ethereumjs/util'
2+
import { BIGINT_0, bytesToHex, equalsBytes } from '@ethereumjs/util'
3+
import debugDefault from 'debug'
34

45
import {
56
Blockchain,
@@ -14,6 +15,10 @@ import type { BlockchainOptions, DBOp } from './index.js'
1415
import type { BlockData } from '@ethereumjs/block'
1516
import type { Chain } from '@ethereumjs/common'
1617

18+
const DEBUG =
19+
typeof window === 'undefined' ? (process?.env?.DEBUG?.includes('ethjs') ?? false) : false
20+
const debug = debugDefault('blockchain')
21+
1722
export async function createBlockchain(opts: BlockchainOptions = {}) {
1823
const blockchain = new Blockchain(opts)
1924

@@ -81,6 +86,8 @@ export async function createBlockchain(opts: BlockchainOptions = {}) {
8186
await blockchain.checkAndTransitionHardForkByNumber(latestHeader.number, latestHeader.timestamp)
8287
}
8388

89+
DEBUG && debug(`genesis block initialized with hash ${bytesToHex(genesisHash!)}`)
90+
8491
return blockchain
8592
}
8693

0 commit comments

Comments
 (0)