Skip to content

Commit

Permalink
fix(circom): Light client fix next sync committee bug
Browse files Browse the repository at this point in the history
  • Loading branch information
Dimo99 authored and zah committed Mar 9, 2023
1 parent 06ccdb8 commit 99e7b0e
Show file tree
Hide file tree
Showing 21 changed files with 771 additions and 376 deletions.
68 changes: 44 additions & 24 deletions beacon-light-client/circom/circuits/light_client.circom
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ template LightClient(N) {
signal input prevHeaderHash[256];
signal input nextHeaderHash[256];

signal input prevHeaderStateRoot[256];
signal input prevHeaderStateRootBranch[3][256];
signal input prevFinalizedHeaderRoot[256];
signal input prevFinalizedHeaderRootBranch[9][256];

signal input prevHeaderFinalizedStateRoot[256];
signal input prevHeaderFinalizedStateRootBranch[3][256];

signal input prevHeaderFinalizedSlot;
signal input prevHeaderFinalizedSlotBranch[9][256];
signal input prevHeaderFinalizedSlotBranch[3][256];

signal input nextHeaderSlot;
signal input nextHeaderSlotBranch[3][256];
Expand Down Expand Up @@ -52,22 +55,6 @@ template LightClient(N) {

signal output output_commitment[2];

component isValidMerkleBranchPrevHeaderStateRoot = IsValidMerkleBranch(3);

for(var i = 0; i < 256; i++) {
isValidMerkleBranchPrevHeaderStateRoot.leaf[i] <== prevHeaderStateRoot[i];
isValidMerkleBranchPrevHeaderStateRoot.root[i] <== prevHeaderHash[i];
}

for(var i = 0; i < 3; i++) {
for(var j = 0; j < 256; j++) {
isValidMerkleBranchPrevHeaderStateRoot.branch[i][j] <== prevHeaderStateRootBranch[i][j];
}
}

isValidMerkleBranchPrevHeaderStateRoot.index <== 11;
isValidMerkleBranchPrevHeaderStateRoot.out === 1;

component signatureSlotGreaterThanNext = GreaterThan(64);
signatureSlotGreaterThanNext.in[0] <== signatureSlot;
signatureSlotGreaterThanNext.in[1] <== nextHeaderSlot;
Expand Down Expand Up @@ -104,22 +91,38 @@ template LightClient(N) {
component nextHeaderSlotSSZ = SSZNum(64);
nextHeaderSlotSSZ.in <== nextHeaderSlot;

component isValidMerkleBranchPrevHeaderSlot = IsValidMerkleBranch(9);
component isValidMerkleBranchPrevHeaderSlot = IsValidMerkleBranch(3);

for(var i = 0; i < 256; i++) {
isValidMerkleBranchPrevHeaderSlot.leaf[i] <== prevHeaderFinalizedSlotSSZ.out[i];
isValidMerkleBranchPrevHeaderSlot.root[i] <== prevHeaderStateRoot[i];
isValidMerkleBranchPrevHeaderSlot.root[i] <== prevFinalizedHeaderRoot[i];
}

for(var i = 0; i < 9; i++) {
for(var i = 0; i < 3; i++) {
for(var j = 0; j < 256; j++) {
isValidMerkleBranchPrevHeaderSlot.branch[i][j] <== prevHeaderFinalizedSlotBranch[i][j];
}
}

isValidMerkleBranchPrevHeaderSlot.index <== 840;
isValidMerkleBranchPrevHeaderSlot.index <== 8;
isValidMerkleBranchPrevHeaderSlot.out === 1;

component isValidMerkleBranchPrevHeaderFinalizedStateRoot = IsValidMerkleBranch(3);

for(var i = 0; i < 256; i++) {
isValidMerkleBranchPrevHeaderFinalizedStateRoot.leaf[i] <== prevHeaderFinalizedStateRoot[i];
isValidMerkleBranchPrevHeaderFinalizedStateRoot.root[i] <== prevFinalizedHeaderRoot[i];
}

for(var i = 0; i < 3; i++) {
for(var j = 0; j < 256; j++) {
isValidMerkleBranchPrevHeaderFinalizedStateRoot.branch[i][j] <== prevHeaderFinalizedStateRootBranch[i][j];
}
}

isValidMerkleBranchPrevHeaderFinalizedStateRoot.index <== 11;
isValidMerkleBranchPrevHeaderFinalizedStateRoot.out === 1;


component isValidMerkleBranchNextHeaderSlot = IsValidMerkleBranch(3);

Expand Down Expand Up @@ -203,6 +206,23 @@ template LightClient(N) {
hasher.aggregatedKey[i] <== aggregatedKey[i];
}

component isValidMerkleBranchPrevFinality = IsValidMerkleBranch(9);

for(var i = 0; i < 9; i++) {
for(var j = 0; j < 256; j++) {
isValidMerkleBranchPrevFinality.branch[i][j] <== prevFinalizedHeaderRootBranch[i][j];
}
}

for(var i = 0; i < 256; i++) {
isValidMerkleBranchPrevFinality.leaf[i] <== prevFinalizedHeaderRoot[i];
isValidMerkleBranchPrevFinality.root[i] <== prevHeaderHash[i];
}

isValidMerkleBranchPrevFinality.index <== 745;

isValidMerkleBranchPrevFinality.out === 1;

component isValidMerkleBranchFinality = IsValidMerkleBranch(9);

for(var i = 0; i < 9; i++) {
Expand Down Expand Up @@ -250,7 +270,7 @@ template LightClient(N) {
}

for(var i = 0; i < 256; i++) {
isValidMerkleBranchSyncCommittee.root[i] <== prevHeaderStateRoot[i];
isValidMerkleBranchSyncCommittee.root[i] <== prevHeaderFinalizedStateRoot[i];
}

component arePeriodsEqual = IsEqual();
Expand Down
5 changes: 4 additions & 1 deletion beacon-light-client/circom/scripts/light_client/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@
"rapidSnarkProverPath": "../../../../../vendor/rapidsnark/build/prover",
"zkeyFilePath": "../../../build/light_client/light_client_0.zkey",
"witnessGeneratorPath": "../../../build/light_client/light_client_cpp/light_client",
"updatePolingTime": 60000
"updatePolingTime": 450000,
"lightClientAddress": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0",
"etherJsonRpcProvider": "http://127.0.0.1:8545",
"privateKey": "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export async function getProofInput(
let finalizedHeaderHash =
ssz.phase0.BeaconBlockHeader.hashTreeRoot(finalizedHeader);

let finalityBranch = update.finality_branch.map(x => hexToBits(x));
let finalityBranchBits = update.finality_branch.map(x => hexToBits(x));

let finalizedHeaderBodyRootProof = getMerkleProof(
ssz.phase0.BeaconBlockHeader,
Expand All @@ -148,12 +148,20 @@ export async function getProofInput(
let prevFinalizedHeader = ssz.phase0.BeaconBlockHeader.fromJson(
prevUpdate.finalized_header.beacon,
);

let prevFinalizedHeaderBranch = prevUpdate.finality_branch;
let prevHeaderFinalizedSlotBranch = getMerkleProof(
ssz.phase0.BeaconBlockHeader,
['slot'],
prevFinalizedHeader,
).map(x => hexToBits(x));

let prevFinalizedHeaderStateProof = getMerkleProof(
ssz.phase0.BeaconBlockHeader,
['state_root'],
prevFinalizedHeader,
);

const executionPayload = ExecutionPayload.fromJson(
update.finalized_header.execution,
);
Expand All @@ -176,16 +184,27 @@ export async function getProofInput(
return {
prevHeaderHash: hexToBits(bytesToHex(prevBlockHeaderHash)),
nextHeaderHash: hexToBits(bytesToHex(nextBlockHeaderHash)),

prevHeaderStateRoot: hexToBits(bytesToHex(prevBlockHeader.stateRoot)),
prevHeaderStateRootBranch: prevBlockHeaderStateRootProof,

prevHeaderFinalizedSlot: prevFinalizedHeader.slot,
prevHeaderFinalizedSlotBranch: [
...prevHeaderFinalizedSlotBranch,
prevFinalizedHeaderRoot: hexToBits(
bytesToHex(
ssz.phase0.BeaconBlockHeader.hashTreeRoot(prevFinalizedHeader),
),
),
prevFinalizedHeaderRootBranch: [
...prevHeaderFinalizedBranch,
...prevBlockHeaderStateRootProof,
],
prevHeaderFinalizedStateRoot: hexToBits(
prevUpdate.finalized_header.beacon.state_root,
),
prevHeaderFinalizedStateRootBranch: prevFinalizedHeaderStateProof.map(x =>
hexToBits(x),
),

// prevHeaderStateRoot: hexToBits(bytesToHex(prevBlockHeader.stateRoot)),
// prevHeaderStateRootBranch: prevBlockHeaderStateRootProof,

prevHeaderFinalizedSlot: prevFinalizedHeader.slot,
prevHeaderFinalizedSlotBranch: [...prevHeaderFinalizedSlotBranch],
nextHeaderSlot: nextBlockHeader.slot,
nextHeaderSlotBranch: nextHeaderSlotBranch,

Expand All @@ -195,16 +214,17 @@ export async function getProofInput(
Number(update.signature_slot),
),
finalizedHeaderSlotSyncCommitteePeriod: computeSyncCommitteePeriodAt(
Number(prevUpdate.finalized_header.beacon.slot),
prevFinalizedHeader.slot,
),

finalizedHeaderRoot: hexToBits(bytesToHex(finalizedHeaderHash)),
finalizedHeaderBranch: [
...finalityBranch,
...finalityBranchBits,
...nextBlockHeaderStateRootProof,
],

execution_state_root: hexToBits(bytesToHex(executionPayload.state_root)),
execution_state_root: hexToBits(
update.finalized_header.execution.state_root,
),
execution_state_root_branch: [
...executionPayloadStateProof,
...update.finalized_header.execution_branch,
Expand All @@ -225,11 +245,7 @@ export async function getProofInput(
bigint_to_array(55, 7, x.toAffine()[1].value),
]),
aggregatedKey: hexToBits(prevUpdate.sync_committee.aggregate_pubkey, 384),
syncCommitteeBranch: [
...syncCommitteeBranch,
...prevBlockHeaderStateRootProof,
],

syncCommitteeBranch: [...syncCommitteeBranch],
bitmask: bitmask.toBoolArray().map(x => (x ? '1' : '0')),
signature: [
[
Expand Down
141 changes: 141 additions & 0 deletions beacon-light-client/circom/scripts/light_client/light_client.abi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
[
{
"inputs": [
{
"internalType": "bytes32",
"name": "__optimistic_header_root",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "__finalized_header_root",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "__execution_state_root",
"type": "bytes32"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "execution_state_root",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "finalized_header_root",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "bytes32",
"name": "attested_header_root",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "finalized_header_root",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "finalized_execution_state_root",
"type": "bytes32"
},
{
"internalType": "uint256[2]",
"name": "a",
"type": "uint256[2]"
},
{
"internalType": "uint256[2][2]",
"name": "b",
"type": "uint256[2][2]"
},
{
"internalType": "uint256[2]",
"name": "c",
"type": "uint256[2]"
}
],
"internalType": "struct BeaconLightClient.LightClientUpdate",
"name": "update",
"type": "tuple"
}
],
"name": "light_client_update",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "optimistic_header_root",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256[2]",
"name": "a",
"type": "uint256[2]"
},
{
"internalType": "uint256[2][2]",
"name": "b",
"type": "uint256[2][2]"
},
{
"internalType": "uint256[2]",
"name": "c",
"type": "uint256[2]"
},
{
"internalType": "uint256[2]",
"name": "input",
"type": "uint256[2]"
}
],
"name": "verifyProof",
"outputs": [
{
"internalType": "bool",
"name": "r",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
}
]
Loading

0 comments on commit 99e7b0e

Please sign in to comment.