-
Notifications
You must be signed in to change notification settings - Fork 109
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
Optimize BLSSignatureChecker #76
Closed
Closed
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
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
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 |
---|---|---|
|
@@ -69,96 +69,74 @@ contract BLSSignatureChecker is IBLSSignatureChecker { | |
bytes32 | ||
) | ||
{ | ||
// verify the provided apk was the apk at referenceBlockNumber | ||
// loop through every quorumNumber and keep track of the apk | ||
QuorumStakeTotals memory quorumStakeTotals; | ||
quorumStakeTotals.totalStakeForQuorum = new uint96[](quorumNumbers.length); | ||
quorumStakeTotals.signedStakeForQuorum = new uint96[](quorumNumbers.length); | ||
BN254.G1Point memory apk = BN254.G1Point(0, 0); | ||
for (uint i = 0; i < quorumNumbers.length; i++) { | ||
require( | ||
bytes24(nonSignerStakesAndSignature.quorumApks[i].hashG1Point()) == | ||
IBLSPubkeyRegistry(blsPubkeyRegistry).getApkHashAtBlockNumberAndIndex( | ||
blsPubkeyRegistry.getApkHashAtBlockNumberAndIndex( | ||
uint8(quorumNumbers[i]), | ||
referenceBlockNumber, | ||
nonSignerStakesAndSignature.quorumApkIndices[i] | ||
), | ||
"BLSSignatureChecker.checkSignatures: quorumApk hash in storage does not match provided quorum apk" | ||
); | ||
apk = apk.plus(nonSignerStakesAndSignature.quorumApks[i]); | ||
|
||
quorumStakeTotals.totalStakeForQuorum[i] = | ||
stakeRegistry.getTotalStakeAtBlockNumberFromIndex(uint8(quorumNumbers[i]), referenceBlockNumber, nonSignerStakesAndSignature.totalStakeIndices[i]); | ||
quorumStakeTotals.signedStakeForQuorum[i] = quorumStakeTotals.totalStakeForQuorum[i]; | ||
} | ||
|
||
// initialize memory for the quorumStakeTotals | ||
QuorumStakeTotals memory quorumStakeTotals; | ||
quorumStakeTotals.totalStakeForQuorum = new uint96[](quorumNumbers.length); | ||
quorumStakeTotals.signedStakeForQuorum = new uint96[](quorumNumbers.length); | ||
// the pubkeyHashes of the nonSigners | ||
bytes32[] memory nonSignerPubkeyHashes = new bytes32[](nonSignerStakesAndSignature.nonSignerPubkeys.length); | ||
{ | ||
// the quorumBitmaps of the nonSigners | ||
uint256[] memory nonSignerQuorumBitmaps = new uint256[](nonSignerStakesAndSignature.nonSignerPubkeys.length); | ||
{ | ||
// the bitmap of the quorumNumbers | ||
uint256 signingQuorumBitmap = BitmapUtils.bytesArrayToBitmap(quorumNumbers); | ||
uint32[] memory nonSignerForQuorumIndices = new uint32[](quorumNumbers.length); | ||
uint256 signingQuorumBitmap = BitmapUtils.bytesArrayToBitmap(quorumNumbers); | ||
|
||
for (uint i = 0; i < nonSignerStakesAndSignature.nonSignerPubkeys.length; i++) { | ||
nonSignerPubkeyHashes[i] = nonSignerStakesAndSignature.nonSignerPubkeys[i].hashG1Point(); | ||
|
||
// check that the nonSignerPubkeys are sorted and free of duplicates | ||
if (i != 0) { | ||
require(uint256(nonSignerPubkeyHashes[i]) > uint256(nonSignerPubkeyHashes[i - 1]), "BLSSignatureChecker.checkSignatures: nonSignerPubkeys not sorted"); | ||
} | ||
for (uint i = 0; i < nonSignerStakesAndSignature.nonSignerPubkeys.length; i++) { | ||
nonSignerPubkeyHashes[i] = nonSignerStakesAndSignature.nonSignerPubkeys[i].hashG1Point(); | ||
|
||
if (i != 0) { | ||
require(uint256(nonSignerPubkeyHashes[i]) > uint256(nonSignerPubkeyHashes[i - 1]), "BLSSignatureChecker.checkSignatures: nonSignerPubkeys not sorted"); | ||
} | ||
|
||
nonSignerQuorumBitmaps[i] = | ||
registryCoordinator.getQuorumBitmapAtBlockNumberByIndex( | ||
nonSignerPubkeyHashes[i], | ||
referenceBlockNumber, | ||
nonSignerStakesAndSignature.nonSignerQuorumBitmapIndices[i] | ||
); | ||
|
||
// subtract the nonSignerPubkey from the running apk to get the apk of all signers | ||
apk = apk.plus( | ||
nonSignerStakesAndSignature.nonSignerPubkeys[i] | ||
.negate() | ||
.scalar_mul_tiny( | ||
BitmapUtils.countNumOnes(nonSignerQuorumBitmaps[i] & signingQuorumBitmap) | ||
) | ||
uint256 nonSignerQuorumBitmap = | ||
registryCoordinator.getQuorumBitmapAtBlockNumberByIndex( | ||
nonSignerPubkeyHashes[i], | ||
referenceBlockNumber, | ||
nonSignerStakesAndSignature.nonSignerQuorumBitmapIndices[i] | ||
); | ||
} | ||
} | ||
// loop through each quorum number | ||
for (uint8 quorumNumberIndex = 0; quorumNumberIndex < quorumNumbers.length;) { | ||
// get the quorum number | ||
uint8 quorumNumber = uint8(quorumNumbers[quorumNumberIndex]); | ||
// get the totalStake for the quorum at the referenceBlockNumber | ||
quorumStakeTotals.totalStakeForQuorum[quorumNumberIndex] = | ||
stakeRegistry.getTotalStakeAtBlockNumberFromIndex(quorumNumber, referenceBlockNumber, nonSignerStakesAndSignature.totalStakeIndices[quorumNumberIndex]); | ||
// copy total stake to signed stake | ||
quorumStakeTotals.signedStakeForQuorum[quorumNumberIndex] = quorumStakeTotals.totalStakeForQuorum[quorumNumberIndex]; | ||
// loop through all nonSigners, checking that they are a part of the quorum via their quorumBitmap | ||
// if so, load their stake at referenceBlockNumber and subtract it from running stake signed | ||
for (uint32 i = 0; i < nonSignerStakesAndSignature.nonSignerPubkeys.length; i++) { | ||
// keep track of the nonSigners index in the quorum | ||
uint32 nonSignerForQuorumIndex = 0; | ||
// if the nonSigner is a part of the quorum, subtract their stake from the running total | ||
if (BitmapUtils.numberIsInBitmap(nonSignerQuorumBitmaps[i], quorumNumber)) { | ||
|
||
apk = apk.plus( | ||
nonSignerStakesAndSignature.nonSignerPubkeys[i] | ||
.negate() | ||
.scalar_mul_tiny( | ||
BitmapUtils.countNumOnes(nonSignerQuorumBitmap & signingQuorumBitmap) | ||
) | ||
); | ||
|
||
for (uint8 quorumNumberIndex = 0; quorumNumberIndex < quorumNumbers.length;) { | ||
if (BitmapUtils.numberIsInBitmap(nonSignerQuorumBitmap, uint8(quorumNumbers[quorumNumberIndex]))) { | ||
quorumStakeTotals.signedStakeForQuorum[quorumNumberIndex] -= | ||
stakeRegistry.getStakeAtBlockNumberAndIndex( | ||
quorumNumber, | ||
uint8(quorumNumbers[quorumNumberIndex]), | ||
referenceBlockNumber, | ||
nonSignerPubkeyHashes[i], | ||
nonSignerStakesAndSignature.nonSignerStakeIndices[quorumNumberIndex][nonSignerForQuorumIndex] | ||
nonSignerStakesAndSignature.nonSignerStakeIndices[quorumNumberIndex][nonSignerForQuorumIndices[quorumNumberIndex]] | ||
); | ||
unchecked { | ||
++nonSignerForQuorumIndex; | ||
++nonSignerForQuorumIndices[quorumNumberIndex]; | ||
} | ||
} | ||
} | ||
|
||
unchecked { | ||
++quorumNumberIndex; | ||
unchecked { | ||
++quorumNumberIndex; | ||
} | ||
} | ||
} | ||
} | ||
{ | ||
// verify the signature | ||
(bool pairingSuccessful, bool signatureIsValid) = trySignatureAndApkVerification( | ||
msgHash, | ||
apk, | ||
|
@@ -168,10 +146,8 @@ contract BLSSignatureChecker is IBLSSignatureChecker { | |
require(pairingSuccessful, "BLSSignatureChecker.checkSignatures: pairing precompile call failed"); | ||
require(signatureIsValid, "BLSSignatureChecker.checkSignatures: signature is invalid"); | ||
} | ||
// set signatoryRecordHash variable used for fraudproofs | ||
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. why deleting comments |
||
bytes32 signatoryRecordHash = keccak256(abi.encodePacked(referenceBlockNumber, nonSignerPubkeyHashes)); | ||
|
||
// return the total stakes that signed for each quorum, and a hash of the information required to prove the exact signers and stake | ||
return (quorumStakeTotals, signatoryRecordHash); | ||
} | ||
|
||
|
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
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.
do we have estimates of how much gas this saves