@@ -46,6 +46,7 @@ export class BlockHeader {
46
46
public readonly nonce : Buffer
47
47
48
48
public readonly _common : Common
49
+ public _errorPostfix = ''
49
50
50
51
public static fromHeaderData ( headerData : HeaderData = { } , opts ?: BlockOptions ) {
51
52
const {
@@ -172,7 +173,10 @@ export class BlockHeader {
172
173
options : BlockOptions = { }
173
174
) {
174
175
if ( options . common ) {
175
- this . _common = options . common
176
+ this . _common = Object . assign (
177
+ Object . create ( Object . getPrototypeOf ( options . common ) ) ,
178
+ options . common
179
+ )
176
180
} else {
177
181
const chain = 'mainnet' // default
178
182
if ( options . initWithGenesisHeader ) {
@@ -245,6 +249,10 @@ export class BlockHeader {
245
249
this . extraData = this . cliqueSealBlock ( options . cliqueSigner )
246
250
}
247
251
252
+ this . _errorPostfix = `block number=${ this . number . toNumber ( ) } hash=${ this . hash ( ) . toString (
253
+ 'hex'
254
+ ) } `
255
+
248
256
const freeze = options ?. freeze ?? true
249
257
if ( freeze ) {
250
258
Object . freeze ( this )
@@ -455,37 +463,37 @@ export class BlockHeader {
455
463
if (
456
464
this . extraData . length > this . _common . paramByHardfork ( 'vm' , 'maxExtraDataSize' , hardfork )
457
465
) {
458
- throw new Error ( 'invalid amount of extra data' )
466
+ const msg = 'invalid amount of extra data'
467
+ throw this . _error ( msg )
459
468
}
460
469
} else {
461
470
const minLength = CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL
462
471
if ( ! this . cliqueIsEpochTransition ( ) ) {
463
472
// ExtraData length on epoch transition
464
473
if ( this . extraData . length !== minLength ) {
465
- throw new Error (
466
- `extraData must be ${ minLength } bytes on non-epoch transition blocks, received ${ this . extraData . length } bytes`
467
- )
474
+ const msg = `extraData must be ${ minLength } bytes on non-epoch transition blocks, received ${ this . extraData . length } bytes`
475
+ throw this . _error ( msg )
468
476
}
469
477
} else {
470
478
const signerLength = this . extraData . length - minLength
471
479
if ( signerLength % 20 !== 0 ) {
472
- throw new Error (
473
- `invalid signer list length in extraData, received signer length of ${ signerLength } (not divisible by 20)`
474
- )
480
+ const msg = `invalid signer list length in extraData, received signer length of ${ signerLength } (not divisible by 20)`
481
+ throw this . _error ( msg )
475
482
}
476
483
// coinbase (beneficiary) on epoch transition
477
484
if ( ! this . coinbase . isZero ( ) ) {
478
- throw new Error (
479
- `coinbase must be filled with zeros on epoch transition blocks, received ${ this . coinbase . toString ( ) } `
480
- )
485
+ const msg = `coinbase must be filled with zeros on epoch transition blocks, received ${ this . coinbase . toString ( ) } `
486
+ throw this . _error ( msg )
481
487
}
482
488
}
483
489
// MixHash format
484
490
if ( ! this . mixHash . equals ( Buffer . alloc ( 32 ) ) ) {
485
- throw new Error ( `mixHash must be filled with zeros, received ${ this . mixHash } ` )
491
+ const msg = `mixHash must be filled with zeros, received ${ this . mixHash } `
492
+ throw this . _error ( msg )
486
493
}
487
494
if ( ! this . validateCliqueDifficulty ( blockchain ) ) {
488
- throw new Error ( 'invalid clique difficulty' )
495
+ const msg = `invalid clique difficulty`
496
+ throw this . _error ( msg )
489
497
}
490
498
}
491
499
@@ -557,9 +565,6 @@ export class BlockHeader {
557
565
* Returns the hash of the block header.
558
566
*/
559
567
hash ( ) : Buffer {
560
- if ( this . _common . consensusAlgorithm ( ) === 'clique' && ! this . isGenesis ( ) ) {
561
- return this . cliqueHash ( )
562
- }
563
568
return rlphash ( this . raw ( ) )
564
569
}
565
570
@@ -577,10 +582,9 @@ export class BlockHeader {
577
582
}
578
583
579
584
/**
580
- * Hash for PoA clique blocks is created without the seal.
581
- * @hidden
585
+ * PoA clique signature hash without the seal.
582
586
*/
583
- private cliqueHash ( ) {
587
+ cliqueSigHash ( ) {
584
588
const raw = this . raw ( )
585
589
raw [ 12 ] = this . extraData . slice ( 0 , this . extraData . length - CLIQUE_EXTRA_SEAL )
586
590
return rlphash ( raw )
@@ -623,7 +627,7 @@ export class BlockHeader {
623
627
*/
624
628
private cliqueSealBlock ( privateKey : Buffer ) {
625
629
this . _requireClique ( 'cliqueSealBlock' )
626
- const signature = ecsign ( this . hash ( ) , privateKey )
630
+ const signature = ecsign ( this . cliqueSigHash ( ) , privateKey )
627
631
const signatureB = Buffer . concat ( [ signature . r , signature . s , intToBuffer ( signature . v - 27 ) ] )
628
632
629
633
let extraDataWithoutSeal = this . extraData . slice ( 0 , this . extraData . length - CLIQUE_EXTRA_SEAL )
@@ -684,10 +688,14 @@ export class BlockHeader {
684
688
cliqueSigner ( ) : Address {
685
689
this . _requireClique ( 'cliqueSigner' )
686
690
const extraSeal = this . cliqueExtraSeal ( )
691
+ // Reasonable default for default blocks
692
+ if ( extraSeal . length === 0 ) {
693
+ return Address . zero ( )
694
+ }
687
695
const r = extraSeal . slice ( 0 , 32 )
688
696
const s = extraSeal . slice ( 32 , 64 )
689
697
const v = bufferToInt ( extraSeal . slice ( 64 , 65 ) ) + 27
690
- const pubKey = ecrecover ( this . hash ( ) , v , r , s )
698
+ const pubKey = ecrecover ( this . cliqueSigHash ( ) , v , r , s )
691
699
return Address . fromPublicKey ( pubKey )
692
700
}
693
701
@@ -721,6 +729,18 @@ export class BlockHeader {
721
729
}
722
730
}
723
731
732
+ /**
733
+ * Internal helper function to create an annotated error message
734
+ *
735
+ * @param msg Base error message
736
+ * @hidden
737
+ */
738
+ _error ( msg : string ) {
739
+ msg += ` (${ this . _errorPostfix } )`
740
+ const e = new Error ( msg )
741
+ return e
742
+ }
743
+
724
744
private _getHardfork ( ) : string {
725
745
return this . _common . hardfork ( ) || this . _common . activeHardfork ( this . number . toNumber ( ) )
726
746
}
0 commit comments