-
Notifications
You must be signed in to change notification settings - Fork 782
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clique small fixes / follow-up work #1074
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
b0dee27
add block option: cliqueSigner
ryanio 38b28cc
exactly compare checkpointSigners list with activeSigners list
ryanio 7ff5b16
* keep signer states and votes for `CLIQUE_SIGNER_HISTORY_BLOCK_LIMIT…
ryanio 81dbd8d
ensure extraDataWithoutSeal has a minimum length of 32 bytes
ryanio c0f81de
* in trimming signer states, always keep at least one item on the stack
ryanio 52cc5fb
explicitly check for `blockchain.cliqueActiveSigners()` in `BlockHead…
ryanio 11689d0
improve BlockHeader.validate typedoc
ryanio 9db72c2
upgrade ethereumjs-util to v7.0.8 and use new Address.equals(address)…
ryanio 8f09e8a
Merge branch 'master' into clique-small-fixes
holgerd77 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,8 @@ import { | |
BN, | ||
bnToHex, | ||
ecrecover, | ||
ecsign, | ||
intToBuffer, | ||
KECCAK256_RLP_ARRAY, | ||
KECCAK256_RLP, | ||
rlp, | ||
|
@@ -238,6 +240,11 @@ export class BlockHeader { | |
this.difficulty = this.canonicalDifficulty(options.calcDifficultyFromHeader) | ||
} | ||
|
||
// If cliqueSigner is provided, seal block with provided privateKey. | ||
if (options.cliqueSigner) { | ||
this.extraData = this.cliqueSealBlock(options.cliqueSigner) | ||
} | ||
|
||
const freeze = options?.freeze ?? true | ||
if (freeze) { | ||
Object.freeze(this) | ||
|
@@ -371,21 +378,25 @@ export class BlockHeader { | |
|
||
/** | ||
* For poa, validates `difficulty` is correctly identified as INTURN or NOTURN. | ||
* Returns false if invalid. | ||
*/ | ||
validateCliqueDifficulty(blockchain: Blockchain): boolean { | ||
if (!this.difficulty.eq(CLIQUE_DIFF_INTURN) && !this.difficulty.eq(CLIQUE_DIFF_NOTURN)) { | ||
throw new Error( | ||
`difficulty for clique block must be INTURN (2) or NOTURN (1), received: ${this.difficulty.toString()}` | ||
) | ||
} | ||
const signers = blockchain.cliqueActiveSigners() | ||
if ('cliqueActiveSigners' in blockchain === false) { | ||
throw new Error( | ||
'PoA blockchain requires method blockchain.cliqueActiveSigners() to validate clique difficulty' | ||
) | ||
} | ||
const signers = (blockchain as any).cliqueActiveSigners() | ||
if (signers.length === 0) { | ||
// abort if signers are unavailable | ||
return true | ||
} | ||
const signerIndex = signers.findIndex((address: Address) => | ||
address.toBuffer().equals(this.cliqueSigner().toBuffer()) | ||
) | ||
const signerIndex = signers.findIndex((address: Address) => address.equals(this.cliqueSigner())) | ||
const inTurn = this.number.modn(signers.length) === signerIndex | ||
if ( | ||
(inTurn && this.difficulty.eq(CLIQUE_DIFF_INTURN)) || | ||
|
@@ -426,10 +437,13 @@ export class BlockHeader { | |
* - The `parentHash` is part of the blockchain (it is a valid header) | ||
* - Current block number is parent block number + 1 | ||
* - Current block has a strictly higher timestamp | ||
* - Additional PoA -> Clique check: Current block has a timestamp diff greater or equal to PERIOD | ||
* - Current block has valid difficulty (only PoW, otherwise pass) and gas limit | ||
* - In case that the header is an uncle header, it should not be too old or young in the chain. | ||
* @param blockchain - validate against a @ethereumjs/blockchain | ||
* - Additional PoW checks -> | ||
* - Current block has valid difficulty and gas limit | ||
* - In case that the header is an uncle header, it should not be too old or young in the chain. | ||
* - Additional PoA clique checks -> | ||
* - Current block has a timestamp diff greater or equal to PERIOD | ||
* - Current block has difficulty correctly marked as INTURN or NOTURN | ||
* @param blockchain - validate against an @ethereumjs/blockchain | ||
* @param height - If this is an uncle header, this is the height of the block that is including it | ||
*/ | ||
async validate(blockchain: Blockchain, height?: BN): Promise<void> { | ||
|
@@ -602,6 +616,27 @@ export class BlockHeader { | |
return this.extraData.slice(-CLIQUE_EXTRA_SEAL) | ||
} | ||
|
||
/** | ||
* Seal block with the provided signer. | ||
* Returns the final extraData field to be assigned to `this.extraData`. | ||
* @hidden | ||
*/ | ||
private cliqueSealBlock(privateKey: Buffer) { | ||
this._requireClique('cliqueSealBlock') | ||
const signature = ecsign(this.hash(), privateKey) | ||
const signatureB = Buffer.concat([signature.r, signature.s, intToBuffer(signature.v - 27)]) | ||
|
||
let extraDataWithoutSeal = this.extraData.slice(0, this.extraData.length - CLIQUE_EXTRA_SEAL) | ||
// ensure extraDataWithoutSeal is at least 32 bytes (CLIQUE_EXTRA_VANITY) | ||
if (extraDataWithoutSeal.length < CLIQUE_EXTRA_VANITY) { | ||
const remainingLength = Buffer.alloc(CLIQUE_EXTRA_VANITY - extraDataWithoutSeal.length) | ||
extraDataWithoutSeal = Buffer.concat([extraDataWithoutSeal, remainingLength]) | ||
} | ||
|
||
const extraData = Buffer.concat([extraDataWithoutSeal, signatureB]) | ||
return extraData | ||
} | ||
|
||
/** | ||
* Returns a list of signers | ||
* (only clique PoA, throws otherwise) | ||
|
@@ -636,9 +671,9 @@ export class BlockHeader { | |
*/ | ||
cliqueVerifySignature(signerList: Address[]): boolean { | ||
this._requireClique('cliqueVerifySignature') | ||
const signerAddress = this.cliqueSigner().toBuffer() | ||
const signerAddress = this.cliqueSigner() | ||
const signerFound = signerList.find((signer) => { | ||
return signer.toBuffer().equals(signerAddress) | ||
return signer.equals(signerAddress) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, yes, that's really a much nicer API! 😄 |
||
}) | ||
return !!signerFound | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, also like that the private key is not residing in the library, was a bit worried that we introduce some new potential security risks here.