Skip to content

Commit 2d55aa0

Browse files
committed
Add CreateFiatShamirFinalBitfield
1 parent e3734b3 commit 2d55aa0

File tree

1 file changed

+76
-49
lines changed

1 file changed

+76
-49
lines changed

contracts/src/BeefyClient.sol

Lines changed: 76 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,82 @@ contract BeefyClient {
401401
emit NewMMRRoot(newMMRRoot, commitment.blockNumber);
402402
}
403403

404+
/**
405+
* @dev Verify that the supplied MMR leaf is included in the latest verified MMR root.
406+
* @param leafHash contains the merkle leaf to be verified
407+
* @param proof contains simplified mmr proof
408+
* @param proofOrder a bitfield describing the order of each item (left vs right)
409+
*/
410+
function verifyMMRLeafProof(bytes32 leafHash, bytes32[] calldata proof, uint256 proofOrder)
411+
external
412+
view
413+
returns (bool)
414+
{
415+
return MMRProof.verifyLeafProof(latestMMRRoot, leafHash, proof, proofOrder);
416+
}
417+
418+
/**
419+
* @dev Helper to create an initial validator bitfield.
420+
* @param bitsToSet contains indexes of all signed validators, should be deduplicated
421+
* @param length of validator set
422+
*/
423+
function createInitialBitfield(uint256[] calldata bitsToSet, uint256 length)
424+
external
425+
pure
426+
returns (uint256[] memory)
427+
{
428+
if (length < bitsToSet.length) {
429+
revert InvalidBitfieldLength();
430+
}
431+
return Bitfield.createBitfield(bitsToSet, length);
432+
}
433+
434+
/**
435+
* @dev Helper to create a final bitfield, with subsampled validator selections
436+
* @param commitmentHash contains the commitmentHash signed by the validators
437+
* @param bitfield claiming which validators have signed the commitment
438+
*/
439+
function createFinalBitfield(bytes32 commitmentHash, uint256[] calldata bitfield)
440+
external
441+
view
442+
returns (uint256[] memory)
443+
{
444+
Ticket storage ticket = tickets[createTicketID(msg.sender, commitmentHash)];
445+
if (ticket.bitfieldHash != keccak256(abi.encodePacked(bitfield))) {
446+
revert InvalidBitfield();
447+
}
448+
return Bitfield.subsample(
449+
ticket.prevRandao, bitfield, ticket.numRequiredSignatures, ticket.validatorSetLen
450+
);
451+
}
452+
453+
/**
454+
* @dev Helper to create a final bitfield with subsampled validator selections using the Fiat-Shamir approach
455+
* @param commitment contains the full commitment that was used for the commitmentHash
456+
* @param bitfield claiming which validators have signed the commitment
457+
*/
458+
function createFiatShamirFinalBitfield(
459+
Commitment calldata commitment,
460+
uint256[] calldata bitfield
461+
) external view returns (uint256[] memory) {
462+
ValidatorSetState storage vset;
463+
if (commitment.validatorSetID == nextValidatorSet.id) {
464+
vset = nextValidatorSet;
465+
} else if (commitment.validatorSetID == currentValidatorSet.id) {
466+
vset = currentValidatorSet;
467+
} else {
468+
revert InvalidCommitment();
469+
}
470+
471+
bytes32 bitFieldHash = keccak256(abi.encodePacked(bitfield));
472+
bytes32 commitmentHash = keccak256(encodeCommitment(commitment));
473+
bytes32 fiatShamirHash = keccak256(bytes.concat(commitmentHash, bitFieldHash, vset.root));
474+
475+
return Bitfield.subsample(
476+
uint256(fiatShamirHash), bitfield, fiatShamirRequiredSignatures, vset.length
477+
);
478+
}
479+
404480
/**
405481
* @dev Submit a commitment and leaf using the Fiat-Shamir approach
406482
* @param commitment contains the full commitment that was used for the commitmentHash
@@ -466,55 +542,6 @@ contract BeefyClient {
466542
emit NewMMRRoot(newMMRRoot, commitment.blockNumber);
467543
}
468544

469-
/**
470-
* @dev Verify that the supplied MMR leaf is included in the latest verified MMR root.
471-
* @param leafHash contains the merkle leaf to be verified
472-
* @param proof contains simplified mmr proof
473-
* @param proofOrder a bitfield describing the order of each item (left vs right)
474-
*/
475-
function verifyMMRLeafProof(bytes32 leafHash, bytes32[] calldata proof, uint256 proofOrder)
476-
external
477-
view
478-
returns (bool)
479-
{
480-
return MMRProof.verifyLeafProof(latestMMRRoot, leafHash, proof, proofOrder);
481-
}
482-
483-
/**
484-
* @dev Helper to create an initial validator bitfield.
485-
* @param bitsToSet contains indexes of all signed validators, should be deduplicated
486-
* @param length of validator set
487-
*/
488-
function createInitialBitfield(uint256[] calldata bitsToSet, uint256 length)
489-
external
490-
pure
491-
returns (uint256[] memory)
492-
{
493-
if (length < bitsToSet.length) {
494-
revert InvalidBitfieldLength();
495-
}
496-
return Bitfield.createBitfield(bitsToSet, length);
497-
}
498-
499-
/**
500-
* @dev Helper to create a final bitfield, with subsampled validator selections
501-
* @param commitmentHash contains the commitmentHash signed by the validators
502-
* @param bitfield claiming which validators have signed the commitment
503-
*/
504-
function createFinalBitfield(bytes32 commitmentHash, uint256[] calldata bitfield)
505-
external
506-
view
507-
returns (uint256[] memory)
508-
{
509-
Ticket storage ticket = tickets[createTicketID(msg.sender, commitmentHash)];
510-
if (ticket.bitfieldHash != keccak256(abi.encodePacked(bitfield))) {
511-
revert InvalidBitfield();
512-
}
513-
return Bitfield.subsample(
514-
ticket.prevRandao, bitfield, ticket.numRequiredSignatures, ticket.validatorSetLen
515-
);
516-
}
517-
518545
/* Internal Functions */
519546

520547
// Creates a unique ticket ID for a new interactive prover-verifier session

0 commit comments

Comments
 (0)