From 377f6c654057ffc2976d6e30302172993031bf2e Mon Sep 17 00:00:00 2001 From: Dimo99 Date: Mon, 19 Jun 2023 14:19:03 +0300 Subject: [PATCH] feat(plonky2): Add circuits primitives needed for commitment mapper --- .github/workflows/ci.yml | 3 + Makefile | 4 + .../circom/circuits/validator_balances.circom | 3 + .../circom/scripts/validator_balances/test.ts | 24 +- .../plonky2/circuits/Cargo.lock | 26 + .../plonky2/circuits/Cargo.toml | 6 + .../examples/is_valid_merkle_branch.rs | 95 + .../plonky2/circuits/examples/merkle_tree.rs | 104 + .../is_valid_merkle_branch_input.json | 11099 ++++++++++++++++ .../plonky2/circuits/src/hash_tree_root.rs | 506 +- .../circuits/src/is_valid_merkle_branch.rs | 82 +- .../plonky2/circuits/src/lib.rs | 6 + .../plonky2/circuits/src/main.rs | 8 - .../plonky2/circuits/src/utils.rs | 57 +- .../circuits/src/validator_commitment.rs | 37 + .../circuits/src/validator_hash_tree_root.rs | 316 +- .../src/validator_hash_tree_root_poseidon.rs | 54 + .../src/is_valid_merkle_branch.rs | 106 +- .../is_valid_merkle_branch/src/main.rs | 33 +- relay/save_proof_inputs_from_redis.ts | 23 + 20 files changed, 12417 insertions(+), 175 deletions(-) create mode 100644 beacon-light-client/plonky2/circuits/examples/is_valid_merkle_branch.rs create mode 100644 beacon-light-client/plonky2/circuits/examples/merkle_tree.rs create mode 100644 beacon-light-client/plonky2/circuits/is_valid_merkle_branch_input.json create mode 100644 beacon-light-client/plonky2/circuits/src/lib.rs delete mode 100644 beacon-light-client/plonky2/circuits/src/main.rs create mode 100644 beacon-light-client/plonky2/circuits/src/validator_commitment.rs create mode 100644 beacon-light-client/plonky2/circuits/src/validator_hash_tree_root_poseidon.rs create mode 100644 relay/save_proof_inputs_from_redis.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 43e67335d..861a53ca2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,6 +61,9 @@ jobs: - name: Run circom tests run: nix develop -c make test-circom-circuits + - name: Run plonky2 circuit tests + run: nix develop -c make test-plonky2-circuits + - name: Run Verifier in Cosmos - Relayer test run: nix develop -c yarn test './tests/cosmosLightClient/test-verifier-in-cosmos-relay.ts' diff --git a/Makefile b/Makefile index dd36a302c..d70a2cbb2 100644 --- a/Makefile +++ b/Makefile @@ -28,3 +28,7 @@ test-solidity-beacon-light-client-verifier: test-circom-circuits: cd beacon-light-client/circom && \ ./test/run_snarkit2_tests.sh + +test-plonky2-circuits: + cd beacon-light-client/plonky2/circuits && \ + cargo test --release diff --git a/beacon-light-client/circom/circuits/validator_balances.circom b/beacon-light-client/circom/circuits/validator_balances.circom index 402e542d4..cb90dc0a0 100644 --- a/beacon-light-client/circom/circuits/validator_balances.circom +++ b/beacon-light-client/circom/circuits/validator_balances.circom @@ -117,9 +117,12 @@ template ValidatorBalances(N) { signal output commitment; signal currentEpoch <-- slot \ 32; + // signal currentEpochRemainder <-- slot % 32; + // slot === currentEpoch * 32 + currentEpochRemainder; signal epochHighestSlot <== currentEpoch * 32; + // Should be LessThanOrEqualBitsCheck(64)([slot, epochHighestSlot + 32]) signal slotLessThan <== LessThanBitsCheck(64)([slot, epochHighestSlot]); signal slotBits[256] <== SSZNum(64)(slot); diff --git a/beacon-light-client/circom/scripts/validator_balances/test.ts b/beacon-light-client/circom/scripts/validator_balances/test.ts index a75502827..4f56586d1 100644 --- a/beacon-light-client/circom/scripts/validator_balances/test.ts +++ b/beacon-light-client/circom/scripts/validator_balances/test.ts @@ -3,7 +3,11 @@ import { BeaconApi } from '../../../../relay/implementations/beacon-api'; import { Tree } from '@chainsafe/persistent-merkle-tree'; import { bytesToHex } from '../../../../libs/typescript/ts-utils/bls'; import { sha256 } from 'ethers/lib/utils'; -import { verifyMerkleProof } from '../../../../libs/typescript/ts-utils/ssz-utils'; +import { + verifyMerkleProof, + hashTreeRoot, +} from '../../../../libs/typescript/ts-utils/ssz-utils'; +import { get } from 'node:http'; (async () => { const { ssz } = await import('@lodestar/types'); @@ -24,6 +28,22 @@ import { verifyMerkleProof } from '../../../../libs/typescript/ts-utils/ssz-util const beaconState = ssz.capella.BeaconState.deserialize(beaconStateSZZ); + console.log( + BigInt( + '0x' + + bytesToHex( + ssz.phase0.Validator.fields.exitEpoch.hashTreeRoot( + beaconState.validators[0].exitEpoch, + ), + ), + ) + .toString(2) + .padStart(256, '0') + .split('') + .map(x => `"${x.toString()}"`) + .join(','), + ); + console.log( BigInt( '0x' + @@ -41,6 +61,8 @@ import { verifyMerkleProof } from '../../../../libs/typescript/ts-utils/ssz-util // const beaconStateView = ssz.capella.BeaconState.toViewDU(beaconState); // const beaconStateTree = new Tree(beaconStateView.node); + // beaconStateTree.getProof() + // console.log(beaconState.slot); // console.log(ssz.capella.BeaconState.getPathInfo(['slot']).gindex); diff --git a/beacon-light-client/plonky2/circuits/Cargo.lock b/beacon-light-client/plonky2/circuits/Cargo.lock index 975927032..da7412a1b 100644 --- a/beacon-light-client/plonky2/circuits/Cargo.lock +++ b/beacon-light-client/plonky2/circuits/Cargo.lock @@ -81,8 +81,11 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" name = "circuits" version = "0.1.0" dependencies = [ + "anyhow", "plonky2", "plonky2_sha256", + "serde", + "serde_json", "sha2 0.9.9", ] @@ -344,6 +347,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + [[package]] name = "keccak-hash" version = "0.8.0" @@ -709,6 +718,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + [[package]] name = "scopeguard" version = "1.1.0" @@ -735,6 +750,17 @@ dependencies = [ "syn 2.0.18", ] +[[package]] +name = "serde_json" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdf3bf93142acad5821c99197022e170842cdbc1c30482b98750c688c640842a" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "sha2" version = "0.9.9" diff --git a/beacon-light-client/plonky2/circuits/Cargo.toml b/beacon-light-client/plonky2/circuits/Cargo.toml index 4dcec7a8d..8403d50e7 100644 --- a/beacon-light-client/plonky2/circuits/Cargo.toml +++ b/beacon-light-client/plonky2/circuits/Cargo.toml @@ -1,3 +1,6 @@ +[net] +git-fetch-with-cli = true + [package] name = "circuits" version = "0.1.0" @@ -9,3 +12,6 @@ edition = "2021" plonky2 = { git = "https://github.com/polymerdao/plonky2", rev = "4cb0b48df1d227d5461a4c28ed025aaea64e2e62" } plonky2_sha256 = { git = "https://github.com/polymerdao/plonky2-sha256", branch = "main" } sha2 = "0.9" +serde = "1.0.164" +serde_json = "1.0.96" +anyhow = "1.0.71" diff --git a/beacon-light-client/plonky2/circuits/examples/is_valid_merkle_branch.rs b/beacon-light-client/plonky2/circuits/examples/is_valid_merkle_branch.rs new file mode 100644 index 000000000..f1a9a16eb --- /dev/null +++ b/beacon-light-client/plonky2/circuits/examples/is_valid_merkle_branch.rs @@ -0,0 +1,95 @@ +use anyhow::Result; +use circuits::is_valid_merkle_branch::is_valid_merkle_branch; +use plonky2::field::goldilocks_field::GoldilocksField; +use plonky2::field::types::Field; +use plonky2::iop::witness::{PartialWitness, WitnessWrite}; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2::plonk::circuit_data::{CircuitConfig}; +use plonky2::plonk::config::PoseidonGoldilocksConfig; +use serde::Deserialize; +use std::fs::File; +use std::io::BufReader; +use std::println; + +#[derive(Debug, Deserialize)] +struct RawMerkleProof { + root: Vec, + leaf: Vec, + branch: Vec>, + index: u64, +} + +#[derive(Debug)] +struct MerkleProof { + root: Vec, + leaf: Vec, + branch: Vec>, + index: u64, +} + +fn main() -> Result<()> { + let input_file = File::open("is_valid_merkle_branch_input.json")?; + let reader = BufReader::new(input_file); + let raw_merkle_proof: RawMerkleProof = serde_json::from_reader(reader)?; + + let merkle_proof = MerkleProof { + root: raw_merkle_proof + .root + .into_iter() + .map(|s| s == "1") + .collect(), + leaf: raw_merkle_proof + .leaf + .into_iter() + .map(|s| s == "1") + .collect(), + branch: raw_merkle_proof + .branch + .into_iter() + .map(|v| v.into_iter().map(|s| s == "1").collect()) + .collect(), + index: raw_merkle_proof.index, + }; + + create_proof(merkle_proof)?; + + Ok(()) +} + +fn create_proof(merkle_proof: MerkleProof) -> std::result::Result<(), anyhow::Error> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = GoldilocksField; + + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); + + let hasher = is_valid_merkle_branch(&mut builder, merkle_proof.branch.len()); + println!("Building circuit"); + + let data = builder.build::(); + + println!("Building proof"); + + let mut pw = PartialWitness::new(); + pw.set_target(hasher.index, F::from_canonical_u64(merkle_proof.index)); + + for i in 0..256 { + pw.set_bool_target(hasher.root[i], merkle_proof.root[i]); + pw.set_bool_target(hasher.leaf[i], merkle_proof.leaf[i]); + } + + for i in 0..merkle_proof.branch.len() { + for j in 0..256 { + pw.set_bool_target(hasher.branch[i][j], merkle_proof.branch[i][j]); + } + } + + let proof = data.prove(pw).unwrap(); + + println!("Verifying proof"); + + let res = data.verify(proof); + + res +} diff --git a/beacon-light-client/plonky2/circuits/examples/merkle_tree.rs b/beacon-light-client/plonky2/circuits/examples/merkle_tree.rs new file mode 100644 index 000000000..d91b8ac5a --- /dev/null +++ b/beacon-light-client/plonky2/circuits/examples/merkle_tree.rs @@ -0,0 +1,104 @@ +use std::{marker::PhantomData, println}; + +use plonky2::{ + field::{goldilocks_field::GoldilocksField, types::Field}, + hash::{ + hash_types::{RichField}, + hashing::{PlonkyPermutation, SPONGE_WIDTH}, + merkle_tree::MerkleTree, + }, + plonk::config::{GenericHashOut, Hasher}, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct AdditionPermutation { + phantom: PhantomData, +} + +impl PlonkyPermutation for AdditionPermutation { + fn permute(input: [F; SPONGE_WIDTH]) -> [F; SPONGE_WIDTH] { + let mut output = input; + output.rotate_left(1); + output + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default)] +#[serde(bound = "")] +pub struct AdditionHash(F); + +impl GenericHashOut for AdditionHash { + fn to_bytes(&self) -> Vec { + let bytes = self.0.0.to_le_bytes().to_vec(); + bytes + } + + fn from_bytes(bytes: &[u8]) -> Self { + let mut array = [0u8; 8]; + let bytes = &bytes[..array.len()]; // panics if not enough input + array.copy_from_slice(bytes); + let num = u64::from_le_bytes(array); + AdditionHash(GoldilocksField::from_canonical_u64(num)) + } + + fn to_vec(&self) -> Vec { + vec![self.0] + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct AdditionHasher { + phantom: PhantomData, +} + +impl Hasher for AdditionHasher { + const HASH_SIZE: usize = std::mem::size_of::(); + + type Hash = AdditionHash; + type Permutation = AdditionPermutation; + + fn hash_no_pad(input: &[GoldilocksField]) -> Self::Hash { + AdditionHash(input.iter().fold(GoldilocksField::ZERO, |acc, x| acc + *x)) + } + + fn hash_public_inputs(input: &[GoldilocksField]) -> Self::Hash { + Self::hash_no_pad(input) + } + + fn two_to_one(left: Self::Hash, right: Self::Hash) -> Self::Hash { + AdditionHash(left.0 + right.0) + } +} + +fn main() { + type F = GoldilocksField; + + let merkle_tree = MerkleTree::::new( + vec![ + vec![F::from_canonical_u32(1)], + vec![F::from_canonical_u32(2)], + vec![F::from_canonical_u32(3)], + vec![F::from_canonical_u32(4)], + vec![F::from_canonical_u32(5)], + vec![F::from_canonical_u32(6)], + vec![F::from_canonical_u32(7)], + vec![F::from_canonical_u32(8)], + vec![F::from_canonical_u32(9)], + vec![F::from_canonical_u32(10)], + vec![F::from_canonical_u32(11)], + vec![F::from_canonical_u32(12)], + vec![F::from_canonical_u32(13)], + vec![F::from_canonical_u32(14)], + vec![F::from_canonical_u32(15)], + vec![F::from_canonical_u32(16)], + ], + 0, + ); + + let proof = merkle_tree.prove(3); + + println!("{:?}", proof); + + println!("{:?}", merkle_tree.digests); +} diff --git a/beacon-light-client/plonky2/circuits/is_valid_merkle_branch_input.json b/beacon-light-client/plonky2/circuits/is_valid_merkle_branch_input.json new file mode 100644 index 000000000..8c5eba6e1 --- /dev/null +++ b/beacon-light-client/plonky2/circuits/is_valid_merkle_branch_input.json @@ -0,0 +1,11099 @@ +{ + "root": [ + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1" + ], + "leaf": [ + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1" + ], + "branch": [ + [ + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0" + ], + [ + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1" + ], + [ + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0" + ], + [ + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0" + ], + [ + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1" + ], + [ + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1" + ], + [ + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1" + ], + [ + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0" + ], + [ + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0" + ], + [ + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1" + ], + [ + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0" + ], + [ + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0" + ], + [ + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1" + ], + [ + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1" + ], + [ + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1" + ], + [ + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1" + ], + [ + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0" + ], + [ + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0" + ], + [ + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1" + ], + [ + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0" + ], + [ + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0" + ], + [ + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0" + ], + [ + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1" + ], + [ + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1" + ], + [ + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0" + ], + [ + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0" + ], + [ + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1" + ], + [ + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0" + ], + [ + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1" + ], + [ + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0" + ], + [ + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0" + ], + [ + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1" + ], + [ + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1" + ], + [ + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1" + ], + [ + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1" + ], + [ + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0" + ], + [ + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1" + ], + [ + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "0" + ], + [ + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "0" + ], + [ + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "1", + "1", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "1", + "0", + "0", + "0", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "1", + "1" + ], + [ + "1", + "0", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0" + ] + ], + "index": 2199023255552 +} diff --git a/beacon-light-client/plonky2/circuits/src/hash_tree_root.rs b/beacon-light-client/plonky2/circuits/src/hash_tree_root.rs index 3b648ba0b..f41b48172 100644 --- a/beacon-light-client/plonky2/circuits/src/hash_tree_root.rs +++ b/beacon-light-client/plonky2/circuits/src/hash_tree_root.rs @@ -1,25 +1,509 @@ use plonky2::{ - field::extension::Extendable, - hash::hash_types::RichField, - iop::witness::{PartialWitness, WitnessWrite}, + field::extension::Extendable, hash::hash_types::RichField, iop::target::BoolTarget, plonk::circuit_builder::CircuitBuilder, }; -use plonky2_sha256::circuit::make_circuits; +use plonky2_sha256::circuit::{make_circuits, Sha256Targets}; + +use crate::utils::create_bool_target_array; + +pub struct HashTreeRootTargets { + pub leaves: Vec<[BoolTarget; 256]>, + pub hash_tree_root: [BoolTarget; 256], +} pub fn hash_tree_root, const D: usize>( builder: &mut CircuitBuilder, - pw: &mut PartialWitness, - leaves: &Vec<[bool; 256]>, -) { - for i in 0..leaves.len() - 1 { - let hasher = make_circuits(builder, 512); + leaves_len: usize, +) -> HashTreeRootTargets { + let leaves: Vec<[BoolTarget; 256]> = (0..leaves_len) + .map(|_| create_bool_target_array(builder)) + .collect(); + + let mut hashers: Vec = Vec::new(); + + for i in 0..(leaves_len / 2) { + hashers.push(make_circuits(builder, 512)); for j in 0..256 { - pw.set_bool_target(hasher.message[i], leaves[i][j]); + builder.connect(hashers[i].message[j].target, leaves[i * 2][j].target); + builder.connect( + hashers[i].message[j + 256].target, + leaves[i * 2 + 1][j].target, + ); } + } + + let mut k = 0; + for i in leaves_len / 2..leaves_len - 1 { + hashers.push(make_circuits(builder, 512)); for j in 0..256 { - pw.set_bool_target(hasher.message[i + 256], leaves[i + 1][j]); + builder.connect( + hashers[i].message[j].target, + hashers[k * 2].digest[j].target, + ); + builder.connect( + hashers[i].message[j + 256].target, + hashers[k * 2 + 1].digest[j].target, + ); + } + + k += 1; + } + + HashTreeRootTargets { + leaves: leaves, + hash_tree_root: hashers[leaves_len - 2].digest.clone().try_into().unwrap(), + } +} + +#[cfg(test)] +mod tests { + use anyhow::Result; + use plonky2::{ + field::goldilocks_field::GoldilocksField, + iop::witness::{PartialWitness, WitnessWrite}, + plonk::{ + circuit_builder::CircuitBuilder, circuit_data::CircuitConfig, + config::PoseidonGoldilocksConfig, + }, + }; + + use crate::{hash_tree_root::hash_tree_root, utils::hash_bit_array}; + + #[test] + fn test_hash_tree_root() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = GoldilocksField; + + let mut builder = CircuitBuilder::::new(CircuitConfig::standard_recursion_config()); + + let targets = hash_tree_root(&mut builder, 4); + + let mut pw: PartialWitness = PartialWitness::new(); + + let first = vec![ + "0", "1", "1", "0", "0", "1", "1", "1", "0", "0", "1", "1", "0", "1", "0", "1", "0", + "0", "0", "0", "1", "1", "1", "1", "1", "0", "0", "0", "0", "1", "0", "1", "1", "1", + "0", "0", "0", "1", "1", "0", "1", "0", "0", "0", "0", "0", "1", "1", "0", "1", "1", + "1", "0", "1", "1", "1", "0", "1", "1", "1", "1", "1", "1", "0", "0", "1", "0", "1", + "1", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "1", "0", "0", "1", "1", "0", + "1", "1", "1", "1", "1", "0", "0", "1", "1", "0", "0", "1", "1", "1", "0", "0", "0", + "0", "1", "1", "1", "1", "1", "0", "1", "1", "0", "0", "1", "1", "0", "0", "1", "0", + "1", "0", "0", "1", "0", "0", "0", "1", "1", "0", "0", "0", "0", "0", "0", "1", "0", + "0", "1", "1", "1", "0", "1", "1", "0", "1", "0", "0", "0", "1", "1", "0", "0", "0", + "0", "1", "0", "0", "1", "1", "0", "0", "0", "1", "1", "0", "1", "1", "0", "1", "0", + "1", "1", "1", "0", "0", "0", "0", "1", "0", "1", "1", "1", "0", "0", "0", "1", "1", + "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "1", "1", "0", "0", "0", "1", + "1", "1", "0", "0", "0", "1", "0", "0", "0", "1", "0", "0", "1", "0", "1", "1", "0", + "1", "1", "0", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "0", "1", "1", "0", + "0", "0", "0", "0", "0", "1", "1", "1", "0", "1", "0", "0", "1", "0", "1", "1", "0", + "1", + ]; + + let second = vec![ + "0", "0", "1", "1", "0", "1", "0", "1", "1", "1", "0", "0", "1", "1", "0", "1", "1", + "0", "0", "1", "0", "1", "0", "1", "1", "0", "0", "1", "0", "1", "1", "1", "0", "1", + "1", "0", "1", "0", "1", "1", "0", "1", "1", "0", "1", "0", "0", "0", "1", "1", "1", + "1", "1", "0", "1", "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "1", "0", "1", + "0", "0", "1", "0", "0", "1", "1", "1", "0", "0", "0", "0", "1", "0", "1", "0", "1", + "0", "0", "0", "0", "0", "1", "1", "1", "0", "1", "0", "0", "1", "1", "1", "1", "0", + "1", "0", "1", "0", "0", "0", "0", "0", "0", "0", "1", "0", "0", "1", "0", "0", "1", + "0", "1", "0", "1", "1", "1", "0", "1", "1", "0", "0", "1", "1", "1", "1", "1", "1", + "0", "1", "0", "1", "1", "0", "1", "0", "0", "1", "1", "0", "0", "0", "1", "0", "0", + "0", "1", "0", "0", "1", "0", "1", "0", "0", "0", "0", "1", "0", "0", "0", "1", "0", + "1", "1", "0", "0", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", "1", "1", "1", + "1", "1", "0", "0", "1", "0", "1", "1", "1", "1", "0", "1", "1", "1", "1", "1", "0", + "1", "0", "0", "0", "1", "1", "1", "0", "1", "1", "0", "1", "1", "1", "1", "0", "1", + "0", "0", "1", "1", "1", "1", "0", "1", "0", "1", "1", "0", "0", "0", "0", "0", "0", + "1", "1", "1", "1", "0", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", "0", "1", + "0", + ]; + + let third = vec![ + "1", "0", "0", "1", "1", "1", "0", "1", "1", "1", "0", "0", "1", "1", "0", "0", "0", + "0", "0", "0", "0", "0", "1", "0", "0", "1", "0", "1", "1", "1", "0", "1", "0", "1", + "1", "1", "0", "0", "0", "0", "0", "1", "0", "1", "1", "0", "0", "1", "0", "1", "1", + "0", "1", "0", "1", "0", "1", "1", "1", "1", "1", "1", "0", "0", "1", "0", "0", "1", + "1", "0", "0", "0", "1", "1", "0", "1", "1", "0", "0", "1", "0", "0", "0", "0", "1", + "1", "1", "0", "0", "0", "1", "0", "1", "0", "1", "0", "1", "1", "1", "0", "1", "0", + "1", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "1", "1", "0", "0", "1", "0", + "0", "1", "1", "1", "1", "1", "0", "1", "1", "0", "0", "1", "0", "1", "1", "1", "1", + "1", "0", "0", "0", "1", "1", "0", "0", "1", "1", "0", "1", "1", "1", "0", "0", "1", + "0", "0", "0", "1", "1", "0", "0", "1", "0", "1", "1", "1", "0", "1", "0", "0", "1", + "1", "0", "0", "1", "1", "1", "1", "1", "0", "0", "0", "1", "1", "1", "0", "1", "0", + "0", "0", "0", "1", "1", "0", "0", "0", "1", "0", "1", "0", "0", "0", "0", "1", "1", + "1", "0", "1", "0", "0", "1", "1", "1", "1", "0", "0", "0", "0", "0", "1", "1", "0", + "1", "1", "0", "0", "0", "1", "0", "0", "1", "1", "1", "0", "1", "0", "0", "0", "0", + "0", "0", "0", "1", "0", "0", "0", "1", "1", "1", "0", "0", "1", "1", "0", "1", "0", + "0", + ]; + + let fourth = vec![ + "1", "1", "0", "0", "0", "0", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", "0", + "1", "0", "1", "1", "0", "0", "1", "0", "1", "0", "0", "1", "0", "1", "1", "0", "0", + "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "0", "1", "1", "0", "1", "0", + "0", "0", "0", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", "1", "0", "0", "1", + "1", "0", "1", "1", "1", "1", "0", "0", "1", "0", "0", "1", "0", "1", "0", "1", "1", + "0", "1", "0", "0", "1", "1", "0", "1", "0", "0", "1", "0", "0", "0", "1", "1", "0", + "0", "1", "0", "0", "0", "0", "1", "0", "1", "1", "1", "0", "0", "0", "0", "1", "0", + "1", "1", "1", "0", "1", "1", "0", "1", "0", "1", "1", "0", "1", "1", "1", "1", "1", + "0", "1", "1", "1", "0", "1", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "0", + "0", "0", "0", "0", "1", "0", "1", "1", "0", "0", "1", "0", "0", "1", "0", "0", "0", + "0", "1", "1", "0", "1", "1", "1", "1", "1", "0", "1", "0", "0", "0", "1", "0", "1", + "0", "0", "0", "0", "1", "1", "1", "1", "1", "0", "0", "1", "1", "1", "0", "1", "0", + "1", "1", "0", "1", "1", "0", "1", "1", "1", "1", "0", "1", "0", "0", "1", "1", "1", + "0", "0", "1", "1", "1", "0", "0", "1", "1", "0", "0", "1", "0", "0", "1", "0", "0", + "0", "0", "0", "1", "1", "0", "1", "1", "1", "1", "0", "1", "0", "0", "0", "0", "0", + "1", + ]; + + let hash_tree_root = vec![ + "1", "0", "0", "1", "0", "1", "0", "0", "0", "0", "1", "1", "1", "1", "0", "0", "1", + "1", "1", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "1", + "1", "1", "1", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "0", "1", "0", "1", + "1", "1", "0", "0", "1", "1", "0", "1", "0", "1", "0", "1", "0", "1", "0", "1", "0", + "1", "0", "1", "1", "1", "1", "0", "1", "0", "0", "1", "0", "1", "0", "1", "1", "1", + "0", "1", "1", "0", "1", "0", "1", "1", "0", "1", "0", "0", "0", "1", "0", "0", "1", + "1", "0", "0", "1", "0", "1", "0", "0", "1", "0", "1", "1", "0", "1", "1", "1", "1", + "1", "0", "0", "1", "0", "0", "1", "0", "1", "1", "1", "0", "0", "0", "0", "1", "0", + "0", "1", "1", "0", "1", "1", "1", "0", "0", "0", "0", "0", "1", "1", "0", "1", "0", + "1", "0", "1", "1", "0", "1", "1", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", + "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "1", "1", "1", "0", "1", "1", "1", + "0", "0", "1", "0", "0", "0", "1", "1", "1", "0", "1", "1", "1", "1", "1", "1", "1", + "0", "1", "0", "1", "1", "1", "1", "0", "1", "1", "0", "1", "1", "1", "1", "1", "1", + "1", "0", "1", "1", "1", "1", "0", "0", "1", "1", "0", "0", "1", "0", "1", "0", "1", + "1", "1", "0", "0", "0", "0", "0", "1", "0", "1", "1", "0", "1", "0", "0", "0", "1", + "0", + ]; + + for i in 0..256 { + pw.set_bool_target(targets.leaves[0][i], first[i] == "1"); + pw.set_bool_target(targets.leaves[1][i], second[i] == "1"); + pw.set_bool_target(targets.leaves[2][i], third[i] == "1"); + pw.set_bool_target(targets.leaves[3][i], fourth[i] == "1"); + } + + for i in 0..256 { + if hash_tree_root[i] == "1" { + builder.assert_one(targets.hash_tree_root[i].target); + } else { + builder.assert_zero(targets.hash_tree_root[i].target); + } + } + + let data = builder.build::(); + let proof = data.prove(pw).unwrap(); + + data.verify(proof) + } + + #[test] + fn validators_hash_tree_root() -> Result<()> { + let validator_pubkey = [ + "1", "0", "0", "1", "0", "0", "1", "1", "0", "0", "1", "1", "1", "0", "1", "0", "1", + "1", "0", "1", "1", "0", "0", "1", "0", "1", "0", "0", "1", "0", "0", "1", "0", "0", + "0", "1", "1", "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "0", "0", "0", + "0", "0", "1", "0", "1", "1", "0", "0", "1", "1", "1", "0", "1", "1", "1", "0", "1", + "0", "0", "0", "0", "0", "1", "1", "0", "0", "1", "0", "1", "1", "0", "1", "1", "0", + "1", "0", "1", "0", "1", "1", "0", "0", "0", "0", "0", "1", "1", "0", "1", "0", "0", + "1", "0", "0", "1", "0", "1", "0", "1", "1", "0", "1", "1", "0", "1", "1", "0", "0", + "0", "1", "0", "0", "1", "0", "1", "0", "1", "0", "1", "1", "1", "1", "0", "1", "0", + "1", "0", "0", "0", "1", "1", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", + "0", "1", "0", "1", "1", "0", "0", "1", "1", "0", "0", "0", "1", "1", "0", "1", "1", + "1", "0", "1", "0", "0", "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "1", "1", + "0", "1", "1", "1", "0", "0", "1", "1", "1", "0", "0", "1", "0", "1", "0", "0", "1", + "0", "0", "0", "0", "1", "0", "1", "0", "1", "1", "1", "0", "0", "0", "0", "1", "0", + "0", "0", "1", "1", "1", "1", "0", "1", "0", "0", "0", "1", "1", "1", "1", "0", "1", + "1", "1", "0", "0", "1", "1", "0", "0", "1", "0", "1", "0", "0", "1", "0", "0", "1", + "0", "0", "1", "1", "0", "0", "1", "1", "1", "1", "0", "1", "0", "1", "0", "0", "0", + "1", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "1", "1", "1", "0", "0", "0", + "0", "1", "1", "1", "0", "0", "1", "0", "1", "1", "1", "0", "1", "0", "1", "0", "0", + "1", "0", "1", "0", "0", "1", "1", "1", "0", "1", "1", "0", "1", "0", "1", "1", "0", + "0", "0", "1", "0", "1", "0", "0", "1", "0", "1", "0", "1", "0", "1", "1", "1", "0", + "0", "0", "0", "1", "0", "0", "1", "1", "0", "1", "0", "0", "0", "0", "1", "0", "1", + "0", "1", "1", "1", "0", "1", "0", "0", "1", "0", "1", "1", "0", "0", "0", "1", "1", + "0", "0", "1", "0", "0", "1", "0", "1", "0", "1", + ]; + + let withdraw_credentials = [ + "0", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "1", "1", + "0", "1", "0", "0", "1", "1", "0", "1", "1", "0", "1", "0", "0", "1", "1", "0", "1", + "1", "1", "0", "1", "1", "0", "1", "0", "0", "1", "0", "0", "1", "1", "1", "1", "0", + "1", "1", "1", "1", "1", "0", "1", "0", "0", "1", "0", "1", "0", "0", "0", "1", "0", + "0", "0", "0", "0", "0", "0", "0", "1", "1", "1", "1", "1", "1", "0", "1", "0", "0", + "1", "1", "1", "0", "1", "1", "1", "0", "0", "0", "0", "1", "1", "0", "1", "0", "1", + "0", "1", "0", "0", "1", "1", "1", "1", "1", "1", "0", "0", "0", "0", "0", "1", "0", + "1", "0", "0", "0", "1", "1", "0", "0", "0", "1", "0", "1", "0", "1", "0", "1", "1", + "1", "0", "1", "1", "0", "1", "0", "0", "0", "0", "0", "0", "1", "0", "0", "1", "1", + "0", "1", "0", "0", "1", "0", "1", "1", "0", "1", "0", "1", "0", "1", "0", "0", "0", + "0", + ]; + + let effective_balance = [ + "0", "0", "0", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", + "1", "0", "1", "1", "0", "0", "1", "0", "1", "1", "1", "0", "0", "1", "1", "0", "0", + "0", "0", "0", "1", "1", "1", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", + ]; + + let slashed = [ + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", + ]; + + let activation_eligibility_epoch = [ + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", + ]; + + let withdrawable_epoch = [ + "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", + "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", + "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", + "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", + ]; + + let validator_hash_tree_root = [ + "0", "0", "1", "0", "1", "0", "1", "1", "1", "0", "1", "0", "1", "1", "1", "1", "0", + "1", "0", "0", "0", "0", "0", "0", "0", "1", "1", "0", "0", "1", "0", "1", "1", "0", + "1", "1", "0", "1", "0", "1", "1", "1", "0", "1", "0", "1", "1", "0", "0", "0", "1", + "0", "0", "1", "0", "0", "0", "1", "1", "0", "0", "1", "0", "0", "0", "0", "0", "1", + "0", "0", "0", "0", "0", "1", "0", "1", "0", "0", "0", "1", "1", "0", "0", "0", "1", + "1", "0", "0", "0", "1", "1", "1", "1", "0", "0", "1", "1", "0", "0", "0", "0", "0", + "0", "1", "1", "1", "1", "0", "0", "1", "0", "1", "0", "1", "0", "1", "0", "0", "0", + "0", "0", "1", "1", "1", "1", "1", "0", "0", "1", "1", "1", "0", "1", "0", "0", "0", + "0", "0", "1", "0", "1", "1", "0", "1", "0", "1", "0", "0", "0", "1", "1", "0", "1", + "1", "0", "1", "1", "0", "0", "0", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", + "0", "0", "0", "0", "0", "0", "1", "0", "0", "1", "1", "0", "0", "1", "1", "1", "0", + "1", "1", "1", "1", "1", "0", "1", "0", "1", "0", "0", "1", "0", "1", "1", "0", "0", + "0", "0", "1", "1", "1", "0", "0", "1", "0", "1", "1", "0", "1", "1", "0", "0", "0", + "0", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "1", "0", + "1", "1", "0", "0", "0", "0", "1", "1", "1", "1", "1", "1", "0", "1", "0", "1", "0", + "1", + ]; + + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = GoldilocksField; + + let pubkey_binary_result = hash_bit_array(validator_pubkey.to_vec()); + + let mut builder = CircuitBuilder::::new(CircuitConfig::standard_recursion_config()); + + let targets = hash_tree_root(&mut builder, 8); + + let mut pw: PartialWitness = PartialWitness::new(); + + for i in 0..256 { + pw.set_bool_target(targets.leaves[0][i], pubkey_binary_result[i] == "1"); + pw.set_bool_target(targets.leaves[1][i], withdraw_credentials[i] == "1"); + pw.set_bool_target(targets.leaves[2][i], effective_balance[i] == "1"); + pw.set_bool_target(targets.leaves[3][i], slashed[i] == "1"); + pw.set_bool_target(targets.leaves[4][i], activation_eligibility_epoch[i] == "1"); + pw.set_bool_target(targets.leaves[5][i], false); + pw.set_bool_target(targets.leaves[6][i], if i < 64 { true } else { false }); + pw.set_bool_target(targets.leaves[7][i], withdrawable_epoch[i] == "1"); + } + + for i in 0..256 { + if validator_hash_tree_root[i] == "1" { + builder.assert_one(targets.hash_tree_root[i].target); + } else { + builder.assert_zero(targets.hash_tree_root[i].target); + } + } + + let data = builder.build::(); + let proof = data.prove(pw).unwrap(); + + data.verify(proof) + } + + #[test] + #[should_panic] + fn test_hash_tree_root_failure() { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = GoldilocksField; + + let mut builder = CircuitBuilder::::new(CircuitConfig::standard_recursion_config()); + + let targets = hash_tree_root(&mut builder, 4); + + let mut pw: PartialWitness = PartialWitness::new(); + + let first = vec![ + "0", "1", "1", "0", "0", "1", "1", "1", "0", "0", "1", "1", "0", "1", "0", "1", "0", + "0", "0", "0", "1", "1", "1", "1", "1", "0", "0", "0", "0", "1", "0", "1", "1", "1", + "0", "0", "0", "1", "1", "0", "1", "0", "0", "0", "0", "0", "1", "1", "0", "1", "1", + "1", "0", "1", "1", "1", "0", "1", "1", "1", "1", "1", "1", "0", "0", "1", "0", "1", + "1", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "1", "0", "0", "1", "1", "0", + "1", "1", "1", "1", "1", "0", "0", "1", "1", "0", "0", "1", "1", "1", "0", "0", "0", + "0", "1", "1", "1", "1", "1", "0", "1", "1", "0", "0", "1", "1", "0", "0", "1", "0", + "1", "0", "0", "1", "0", "0", "0", "1", "1", "0", "0", "0", "0", "0", "0", "1", "0", + "0", "1", "1", "1", "0", "1", "1", "0", "1", "0", "0", "0", "1", "1", "0", "0", "0", + "0", "1", "0", "0", "1", "1", "0", "0", "0", "1", "1", "0", "1", "1", "0", "1", "0", + "1", "1", "1", "0", "0", "0", "0", "1", "0", "1", "1", "1", "0", "0", "0", "1", "1", + "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "1", "1", "0", "0", "0", "1", + "1", "1", "0", "0", "0", "1", "0", "0", "0", "1", "0", "0", "1", "0", "1", "1", "0", + "1", "1", "0", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "0", "1", "1", "0", + "0", "0", "0", "0", "0", "1", "1", "1", "0", "1", "0", "0", "1", "0", "1", "1", "0", + "1", + ]; + + let second = vec![ + "0", "0", "1", "1", "0", "1", "0", "1", "1", "1", "0", "0", "1", "1", "0", "1", "1", + "0", "0", "1", "0", "1", "0", "1", "1", "0", "0", "1", "0", "1", "1", "1", "0", "1", + "1", "0", "1", "0", "1", "1", "0", "1", "1", "0", "1", "0", "0", "0", "1", "1", "1", + "1", "1", "0", "1", "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "1", "0", "1", + "0", "0", "1", "0", "0", "1", "1", "1", "0", "0", "0", "0", "1", "0", "1", "0", "1", + "0", "0", "0", "0", "0", "1", "1", "1", "0", "1", "0", "0", "1", "1", "1", "1", "0", + "1", "0", "1", "0", "0", "0", "0", "0", "0", "0", "1", "0", "0", "1", "0", "0", "1", + "0", "1", "0", "1", "1", "1", "0", "1", "1", "0", "0", "1", "1", "1", "1", "1", "1", + "0", "1", "0", "1", "1", "0", "1", "0", "0", "1", "1", "0", "0", "0", "1", "0", "0", + "0", "1", "0", "0", "1", "0", "1", "0", "0", "0", "0", "1", "0", "0", "0", "1", "0", + "1", "1", "0", "0", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", "1", "1", "1", + "1", "1", "0", "0", "1", "0", "1", "1", "1", "1", "0", "1", "1", "1", "1", "1", "0", + "1", "0", "0", "0", "1", "1", "1", "0", "1", "1", "0", "1", "1", "1", "1", "0", "1", + "0", "0", "1", "1", "1", "1", "0", "1", "0", "1", "1", "0", "0", "0", "0", "0", "0", + "1", "1", "1", "1", "0", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", "0", "1", + "0", + ]; + + let third = vec![ + "1", "0", "0", "1", "1", "1", "0", "1", "1", "1", "0", "0", "1", "1", "0", "0", "0", + "0", "0", "0", "0", "0", "1", "0", "0", "1", "0", "1", "1", "1", "0", "1", "0", "1", + "1", "1", "0", "0", "0", "0", "0", "1", "0", "1", "1", "0", "0", "1", "0", "1", "1", + "0", "1", "0", "1", "0", "1", "1", "1", "1", "1", "1", "0", "0", "1", "0", "0", "1", + "1", "0", "0", "0", "1", "1", "0", "1", "1", "0", "0", "1", "0", "0", "0", "0", "1", + "1", "1", "0", "0", "0", "1", "0", "1", "0", "1", "0", "1", "1", "1", "0", "1", "0", + "1", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "1", "1", "0", "0", "1", "0", + "0", "1", "1", "1", "1", "1", "0", "1", "1", "0", "0", "1", "0", "1", "1", "1", "1", + "1", "0", "0", "0", "1", "1", "0", "0", "1", "1", "0", "1", "1", "1", "0", "0", "1", + "0", "0", "0", "1", "1", "0", "0", "1", "0", "1", "1", "1", "0", "1", "0", "0", "1", + "1", "0", "0", "1", "1", "1", "1", "1", "0", "0", "0", "1", "1", "1", "0", "1", "0", + "0", "0", "0", "1", "1", "0", "0", "0", "1", "0", "1", "0", "0", "0", "0", "1", "1", + "1", "0", "1", "0", "0", "1", "1", "1", "1", "0", "0", "0", "0", "0", "1", "1", "0", + "1", "1", "0", "0", "0", "1", "0", "0", "1", "1", "1", "0", "1", "0", "0", "0", "0", + "0", "0", "0", "1", "0", "0", "0", "1", "1", "1", "0", "0", "1", "1", "0", "1", "0", + "0", + ]; + + let fourth = vec![ + "1", "1", "0", "0", "0", "0", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", "0", + "1", "0", "1", "1", "0", "0", "1", "0", "1", "0", "0", "1", "0", "1", "1", "0", "0", + "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "0", "1", "1", "0", "1", "0", + "0", "0", "0", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", "1", "0", "0", "1", + "1", "0", "1", "1", "1", "1", "0", "0", "1", "0", "0", "1", "0", "1", "0", "1", "1", + "0", "1", "0", "0", "1", "1", "0", "1", "0", "0", "1", "0", "0", "0", "1", "1", "0", + "0", "1", "0", "0", "0", "0", "1", "0", "1", "1", "1", "0", "0", "0", "0", "1", "0", + "1", "1", "1", "0", "1", "1", "0", "1", "0", "1", "1", "0", "1", "1", "1", "1", "1", + "0", "1", "1", "1", "0", "1", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "0", + "0", "0", "0", "0", "1", "0", "1", "1", "0", "0", "1", "0", "0", "1", "0", "0", "0", + "0", "1", "1", "0", "1", "1", "1", "1", "1", "0", "1", "0", "0", "0", "1", "0", "1", + "0", "0", "0", "0", "1", "1", "1", "1", "1", "0", "0", "1", "1", "1", "0", "1", "0", + "1", "1", "0", "1", "1", "0", "1", "1", "1", "1", "0", "1", "0", "0", "1", "1", "1", + "0", "0", "1", "1", "1", "0", "0", "1", "1", "0", "0", "1", "0", "0", "1", "0", "0", + "0", "0", "0", "1", "1", "0", "1", "1", "1", "1", "0", "1", "0", "0", "0", "0", "0", + "1", + ]; + + let hash_tree_root = vec![ + "1", "0", "0", "1", "0", "1", "0", "0", "0", "0", "1", "1", "1", "1", "0", "0", "1", + "1", "1", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "1", + "1", "1", "1", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "0", "1", "0", "1", + "1", "1", "0", "0", "1", "1", "0", "1", "0", "1", "0", "1", "0", "1", "0", "1", "0", + "1", "0", "1", "1", "1", "1", "0", "1", "0", "0", "1", "0", "1", "0", "1", "1", "1", + "0", "1", "1", "0", "1", "0", "1", "1", "0", "1", "0", "0", "0", "1", "0", "0", "1", + "1", "0", "0", "1", "0", "1", "0", "0", "1", "0", "1", "1", "0", "1", "1", "1", "1", + "1", "0", "0", "1", "0", "0", "1", "0", "1", "1", "1", "0", "0", "0", "0", "1", "0", + "0", "1", "1", "0", "1", "1", "1", "0", "0", "0", "0", "0", "1", "1", "0", "1", "0", + "1", "0", "1", "1", "0", "1", "1", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", + "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "1", "1", "1", "0", "1", "1", "1", + "0", "0", "1", "0", "0", "0", "1", "1", "1", "0", "1", "1", "1", "1", "1", "1", "1", + "0", "1", "0", "1", "1", "1", "1", "0", "1", "1", "0", "1", "1", "1", "1", "1", "1", + "1", "0", "1", "1", "1", "1", "0", "0", "1", "1", "0", "0", "1", "0", "1", "0", "1", + "1", "1", "0", "0", "0", "0", "0", "1", "0", "1", "1", "0", "1", "0", "0", "0", "1", + "1", + ]; + + for i in 0..256 { + pw.set_bool_target(targets.leaves[0][i], first[i] == "1"); + pw.set_bool_target(targets.leaves[1][i], second[i] == "1"); + pw.set_bool_target(targets.leaves[2][i], third[i] == "1"); + pw.set_bool_target(targets.leaves[3][i], fourth[i] == "1"); } + + for i in 0..256 { + if hash_tree_root[i] == "1" { + builder.assert_one(targets.hash_tree_root[i].target); + } else { + builder.assert_zero(targets.hash_tree_root[i].target); + } + } + + let data = builder.build::(); + let proof = data.prove(pw).unwrap(); + + data.verify(proof).expect("") } } diff --git a/beacon-light-client/plonky2/circuits/src/is_valid_merkle_branch.rs b/beacon-light-client/plonky2/circuits/src/is_valid_merkle_branch.rs index ddb9ecd28..f3e3df7da 100644 --- a/beacon-light-client/plonky2/circuits/src/is_valid_merkle_branch.rs +++ b/beacon-light-client/plonky2/circuits/src/is_valid_merkle_branch.rs @@ -1,68 +1,64 @@ use plonky2::{ field::extension::Extendable, hash::hash_types::RichField, - iop::witness::{PartialWitness, WitnessWrite}, + iop::target::{BoolTarget, Target}, plonk::circuit_builder::CircuitBuilder, }; -use plonky2_sha256::circuit::{array_to_bits, make_circuits, Sha256Targets}; +use plonky2_sha256::circuit::make_circuits; -use sha2::{Digest, Sha256}; +use crate::utils::create_bool_target_array; -use crate::utils::hash_values; +pub struct IsValidMerkleBranchTargets { + pub leaf: [BoolTarget; 256], + pub branch: Vec<[BoolTarget; 256]>, + pub index: Target, + pub root: [BoolTarget; 256], +} pub fn is_valid_merkle_branch, const D: usize>( builder: &mut CircuitBuilder, - pw: &mut PartialWitness, - root: &[bool; 256], - leaf: &[bool; 256], - branch: &[[bool; 256]], - index: &u64, -) { - let mut leaf = leaf.clone(); + depth: usize, +) -> IsValidMerkleBranchTargets { + let index = builder.add_virtual_target(); - let mut index = index.clone(); + let leaf: [BoolTarget; 256] = create_bool_target_array(builder); - for (i, sibling) in branch.iter().enumerate() { - let is_right = index % 2 == 1; - let mut lhs = leaf.clone(); - let mut rhs = sibling.clone(); + let branch: Vec<[BoolTarget; 256]> = (0..depth) + .map(|_| create_bool_target_array(builder)) + .collect(); - if is_right { - std::mem::swap(&mut lhs, &mut rhs); - } + let root: [BoolTarget; 256] = create_bool_target_array(builder); - let hasher = make_circuits(builder, 512); + let indexes = builder.split_le(index, depth + 1); - for i in 0..256 { - pw.set_bool_target(hasher.message[i], lhs[i]); - } + let mut hashers = Vec::new(); - for i in 0..256 { - pw.set_bool_target(hasher.message[i + 256], rhs[i]); - } + for i in 0..depth { + hashers.push(make_circuits(builder, 512)); + let current: [BoolTarget; 256] = if i == 0 { + leaf + } else { + hashers[i - 1].digest.clone().try_into().unwrap() + }; - leaf = hash_values(lhs, rhs); + for j in 0..256 { + let el1 = builder._if(indexes[i], branch[i][j].target, current[j].target); + builder.connect(hashers[i].message[j].target, el1); - // constraint the root - if i == branch.len() - 1 { - assert_hasher(root, builder, hasher) + let el2 = builder._if(indexes[i], current[j].target, branch[i][j].target); + builder.connect(hashers[i].message[j + 256].target, el2); } - - index /= 2; } -} -fn assert_hasher, const D: usize>( - result: &[bool; 256], - builder: &mut CircuitBuilder, - hasher: Sha256Targets, -) { for i in 0..256 { - if result[i] { - builder.assert_one(hasher.digest[i].target); - } else { - builder.assert_zero(hasher.digest[i].target); - } + builder.connect(hashers[depth - 1].digest[i].target, root[i].target) + } + + IsValidMerkleBranchTargets { + leaf: leaf, + branch: branch, + index: index, + root: root, } } diff --git a/beacon-light-client/plonky2/circuits/src/lib.rs b/beacon-light-client/plonky2/circuits/src/lib.rs new file mode 100644 index 000000000..f3f3ce1e2 --- /dev/null +++ b/beacon-light-client/plonky2/circuits/src/lib.rs @@ -0,0 +1,6 @@ +pub mod hash_tree_root; +pub mod is_valid_merkle_branch; +pub mod utils; +pub mod validator_hash_tree_root; +pub mod validator_hash_tree_root_poseidon; +pub mod validator_commitment; diff --git a/beacon-light-client/plonky2/circuits/src/main.rs b/beacon-light-client/plonky2/circuits/src/main.rs deleted file mode 100644 index 62df128e5..000000000 --- a/beacon-light-client/plonky2/circuits/src/main.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod hash_tree_root; -mod is_valid_merkle_branch; -mod utils; -mod validator_hash_tree_root; - -fn main() { - println!("Hello, world!"); -} diff --git a/beacon-light-client/plonky2/circuits/src/utils.rs b/beacon-light-client/plonky2/circuits/src/utils.rs index 8f89a73c9..a9e618a62 100644 --- a/beacon-light-client/plonky2/circuits/src/utils.rs +++ b/beacon-light-client/plonky2/circuits/src/utils.rs @@ -1,25 +1,50 @@ -use plonky2_sha256::circuit::array_to_bits; -use sha2::{Sha256, Digest}; +use plonky2::{ + field::extension::Extendable, hash::hash_types::RichField, iop::target::BoolTarget, + plonk::circuit_builder::CircuitBuilder, +}; +use sha2::{Digest, Sha256}; -pub fn hash_values(lhs: [bool; 256], rhs: [bool; 256]) -> [bool; 256] { - let bytes: Vec = [lhs, rhs] - .concat() +pub fn hash_bit_array(validator_pubkey: Vec<&str>) -> Vec { + // Concatenate the array into a single binary string + let binary_string: String = validator_pubkey.join(""); + + // Convert binary string to bytes + let mut byte_string: Vec = binary_string + .as_str() + .chars() + .collect::>() .chunks(8) .map(|chunk| { - let mut byte = 0u8; - for (i, &bit) in chunk.iter().enumerate() { - if bit { - byte |= 1u8 << (7 - i); - } - } - byte + let byte_str: String = chunk.into_iter().collect(); + u8::from_str_radix(&byte_str, 2).unwrap() }) .collect(); - let mut hasher = Sha256::default(); - hasher.update(&bytes); + byte_string.resize(64, 0); + + let mut hasher = Sha256::new(); + hasher.update(byte_string); + let result = hasher.finalize(); - let finalized = hasher.finalize(); + let pubkey_binary_result: Vec = result + .iter() + .map(|byte| { + format!("{:08b}", byte) + .chars() + .map(|ch| ch.to_string()) + .collect::>() + }) + .flatten() + .collect(); + pubkey_binary_result +} - array_to_bits(finalized.as_slice()).try_into()?; +pub fn create_bool_target_array, const D: usize>( + builder: &mut CircuitBuilder, +) -> [BoolTarget; 256] { + (0..256) + .map(|_| builder.add_virtual_bool_target_safe()) + .collect::>() + .try_into() + .unwrap() } diff --git a/beacon-light-client/plonky2/circuits/src/validator_commitment.rs b/beacon-light-client/plonky2/circuits/src/validator_commitment.rs new file mode 100644 index 000000000..2c6bea951 --- /dev/null +++ b/beacon-light-client/plonky2/circuits/src/validator_commitment.rs @@ -0,0 +1,37 @@ +use plonky2::{ + field::extension::Extendable, + gadgets::hash, + hash::{ + hash_types::{HashOutTarget, RichField}, + poseidon::PoseidonHash, + }, + iop::target::{BoolTarget, Target}, + plonk::circuit_builder::CircuitBuilder, +}; + +use crate::{ + utils::create_bool_target_array, + validator_hash_tree_root::{hash_tree_root_validator_sha256, Validator}, + validator_hash_tree_root_poseidon::hash_tree_root_validator_poseidon, +}; +pub struct ValidatorCommitment { + pub validator: Validator, + pub sha256_hash_tree_root: [BoolTarget; 256], + pub poseidon_hash_tree_root: HashOutTarget, +} + +pub fn validator_commitment, const D: usize>( + builder: &mut CircuitBuilder, +) -> ValidatorCommitment { + let hash_tree_root_sha256 = hash_tree_root_validator_sha256(builder); + + let validator_poseidon = hash_tree_root_validator_poseidon(builder); + + // TODO: Map from Validator to ValidatorPoseidon and connect the mapping and the result + + ValidatorCommitment { + validator: hash_tree_root_sha256.validator, + sha256_hash_tree_root: hash_tree_root_sha256.hash_tree_root, + poseidon_hash_tree_root: validator_poseidon.hash_tree_root, + } +} diff --git a/beacon-light-client/plonky2/circuits/src/validator_hash_tree_root.rs b/beacon-light-client/plonky2/circuits/src/validator_hash_tree_root.rs index 03cabfbda..9e377bca1 100644 --- a/beacon-light-client/plonky2/circuits/src/validator_hash_tree_root.rs +++ b/beacon-light-client/plonky2/circuits/src/validator_hash_tree_root.rs @@ -1,37 +1,317 @@ use plonky2::{ - field::extension::Extendable, - hash::hash_types::RichField, - iop::witness::{PartialWitness, WitnessWrite}, + field::extension::Extendable, hash::hash_types::RichField, iop::target::BoolTarget, plonk::circuit_builder::CircuitBuilder, }; -use plonky2_sha256::circuit::{array_to_bits, make_circuits, Sha256Targets}; +use plonky2_sha256::circuit::make_circuits; + +use crate::{hash_tree_root::hash_tree_root, utils::create_bool_target_array}; pub struct Validator { - pubkey: [bool; 256], - withdrawal_credentials: [bool; 256], - effective_balance: [bool; 256], - slashed: [bool; 256], - activation_eligibility_epoch: [bool; 256], - activation_epoch: [bool; 256], - exit_epoch: [bool; 256], - withdrawable_epoch: [bool; 256], + pub pubkey: [BoolTarget; 384], + pub withdrawal_credentials: [BoolTarget; 256], + pub effective_balance: [BoolTarget; 256], + pub slashed: [BoolTarget; 256], + pub activation_eligibility_epoch: [BoolTarget; 256], + pub activation_epoch: [BoolTarget; 256], + pub exit_epoch: [BoolTarget; 256], + pub withdrawable_epoch: [BoolTarget; 256], } +pub struct ValidatorHashTreeRootTargets { + pub validator: Validator, + pub hash_tree_root: [BoolTarget; 256], +} pub fn hash_tree_root_validator_sha256, const D: usize>( builder: &mut CircuitBuilder, - pw: &mut PartialWitness, - validator: &Validator, -) { +) -> ValidatorHashTreeRootTargets { + let hash_tree_root = hash_tree_root(builder, 8); + + let pubkey: [BoolTarget; 384] = (0..384) + .map(|_| builder.add_virtual_bool_target_safe()) + .collect::>() + .try_into() + .unwrap(); + let hasher = make_circuits(builder, 512); - for i in 0..256 { - pw.set_bool_target(hasher.message[i], validator.pubkey[i]); + for i in 0..384 { + builder.connect(hasher.message[i].target, pubkey[i].target); } + for i in 384..512 { + let zero = builder._false(); + builder.connect(hasher.message[i].target, zero.target); + } + + let withdrawal_credentials = create_bool_target_array(builder); + let effective_balance = create_bool_target_array(builder); + let slashed = create_bool_target_array(builder); + let activation_eligibility_epoch = create_bool_target_array(builder); + let activation_epoch = create_bool_target_array(builder); + let exit_epoch = create_bool_target_array(builder); + let withdrawable_epoch = create_bool_target_array(builder); + for i in 0..256 { - pw.set_bool_target(hasher.message[i + 256], validator.withdrawal_credentials[i]); + builder.connect(hash_tree_root.leaves[0][i].target, hasher.digest[i].target); + + builder.connect( + hash_tree_root.leaves[1][i].target, + withdrawal_credentials[i].target, + ); + + builder.connect( + hash_tree_root.leaves[2][i].target, + effective_balance[i].target, + ); + + builder.connect(hash_tree_root.leaves[3][i].target, slashed[i].target); + + builder.connect( + hash_tree_root.leaves[4][i].target, + activation_eligibility_epoch[i].target, + ); + + builder.connect( + hash_tree_root.leaves[5][i].target, + activation_epoch[i].target, + ); + + builder.connect(hash_tree_root.leaves[6][i].target, exit_epoch[i].target); + + builder.connect( + hash_tree_root.leaves[7][i].target, + withdrawable_epoch[i].target, + ); + } + + ValidatorHashTreeRootTargets { + validator: Validator { + pubkey, + withdrawal_credentials, + effective_balance, + slashed, + activation_eligibility_epoch, + activation_epoch, + exit_epoch, + withdrawable_epoch, + }, + hash_tree_root: hash_tree_root.hash_tree_root, } +} + +#[cfg(test)] +mod test { + use anyhow::Result; + use plonky2::{ + field::goldilocks_field::GoldilocksField, + iop::witness::{PartialWitness, WitnessWrite}, + plonk::{ + circuit_builder::CircuitBuilder, circuit_data::CircuitConfig, + config::PoseidonGoldilocksConfig, + }, + }; + + use crate::validator_hash_tree_root::hash_tree_root_validator_sha256; + + #[test] + fn test_validator_hash_tree_root() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = GoldilocksField; + let mut builder = CircuitBuilder::::new(CircuitConfig::standard_recursion_config()); + let targets = hash_tree_root_validator_sha256(&mut builder); + + let mut pw = PartialWitness::new(); + + let validator_pubkey = [ + "1", "0", "0", "1", "0", "0", "1", "1", "0", "0", "1", "1", "1", "0", "1", "0", "1", + "1", "0", "1", "1", "0", "0", "1", "0", "1", "0", "0", "1", "0", "0", "1", "0", "0", + "0", "1", "1", "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "0", "0", "0", + "0", "0", "1", "0", "1", "1", "0", "0", "1", "1", "1", "0", "1", "1", "1", "0", "1", + "0", "0", "0", "0", "0", "1", "1", "0", "0", "1", "0", "1", "1", "0", "1", "1", "0", + "1", "0", "1", "0", "1", "1", "0", "0", "0", "0", "0", "1", "1", "0", "1", "0", "0", + "1", "0", "0", "1", "0", "1", "0", "1", "1", "0", "1", "1", "0", "1", "1", "0", "0", + "0", "1", "0", "0", "1", "0", "1", "0", "1", "0", "1", "1", "1", "1", "0", "1", "0", + "1", "0", "0", "0", "1", "1", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", + "0", "1", "0", "1", "1", "0", "0", "1", "1", "0", "0", "0", "1", "1", "0", "1", "1", + "1", "0", "1", "0", "0", "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "1", "1", + "0", "1", "1", "1", "0", "0", "1", "1", "1", "0", "0", "1", "0", "1", "0", "0", "1", + "0", "0", "0", "0", "1", "0", "1", "0", "1", "1", "1", "0", "0", "0", "0", "1", "0", + "0", "0", "1", "1", "1", "1", "0", "1", "0", "0", "0", "1", "1", "1", "1", "0", "1", + "1", "1", "0", "0", "1", "1", "0", "0", "1", "0", "1", "0", "0", "1", "0", "0", "1", + "0", "0", "1", "1", "0", "0", "1", "1", "1", "1", "0", "1", "0", "1", "0", "0", "0", + "1", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "1", "1", "1", "0", "0", "0", + "0", "1", "1", "1", "0", "0", "1", "0", "1", "1", "1", "0", "1", "0", "1", "0", "0", + "1", "0", "1", "0", "0", "1", "1", "1", "0", "1", "1", "0", "1", "0", "1", "1", "0", + "0", "0", "1", "0", "1", "0", "0", "1", "0", "1", "0", "1", "0", "1", "1", "1", "0", + "0", "0", "0", "1", "0", "0", "1", "1", "0", "1", "0", "0", "0", "0", "1", "0", "1", + "0", "1", "1", "1", "0", "1", "0", "0", "1", "0", "1", "1", "0", "0", "0", "1", "1", + "0", "0", "1", "0", "0", "1", "0", "1", "0", "1", + ]; + + let withdraw_credentials = [ + "0", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "1", "1", + "0", "1", "0", "0", "1", "1", "0", "1", "1", "0", "1", "0", "0", "1", "1", "0", "1", + "1", "1", "0", "1", "1", "0", "1", "0", "0", "1", "0", "0", "1", "1", "1", "1", "0", + "1", "1", "1", "1", "1", "0", "1", "0", "0", "1", "0", "1", "0", "0", "0", "1", "0", + "0", "0", "0", "0", "0", "0", "0", "1", "1", "1", "1", "1", "1", "0", "1", "0", "0", + "1", "1", "1", "0", "1", "1", "1", "0", "0", "0", "0", "1", "1", "0", "1", "0", "1", + "0", "1", "0", "0", "1", "1", "1", "1", "1", "1", "0", "0", "0", "0", "0", "1", "0", + "1", "0", "0", "0", "1", "1", "0", "0", "0", "1", "0", "1", "0", "1", "0", "1", "1", + "1", "0", "1", "1", "0", "1", "0", "0", "0", "0", "0", "0", "1", "0", "0", "1", "1", + "0", "1", "0", "0", "1", "0", "1", "1", "0", "1", "0", "1", "0", "1", "0", "0", "0", + "0", + ]; + + let effective_balance = [ + "0", "0", "0", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", + "1", "0", "1", "1", "0", "0", "1", "0", "1", "1", "1", "0", "0", "1", "1", "0", "0", + "0", "0", "0", "1", "1", "1", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", + ]; + + let slashed = [ + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", + ]; + + let activation_eligibility_epoch = [ + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", + ]; + + let withdrawable_epoch = [ + "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", + "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", + "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", + "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", + "0", + ]; + + let validator_hash_tree_root = [ + "0", "0", "1", "0", "1", "0", "1", "1", "1", "0", "1", "0", "1", "1", "1", "1", "0", + "1", "0", "0", "0", "0", "0", "0", "0", "1", "1", "0", "0", "1", "0", "1", "1", "0", + "1", "1", "0", "1", "0", "1", "1", "1", "0", "1", "0", "1", "1", "0", "0", "0", "1", + "0", "0", "1", "0", "0", "0", "1", "1", "0", "0", "1", "0", "0", "0", "0", "0", "1", + "0", "0", "0", "0", "0", "1", "0", "1", "0", "0", "0", "1", "1", "0", "0", "0", "1", + "1", "0", "0", "0", "1", "1", "1", "1", "0", "0", "1", "1", "0", "0", "0", "0", "0", + "0", "1", "1", "1", "1", "0", "0", "1", "0", "1", "0", "1", "0", "1", "0", "0", "0", + "0", "0", "1", "1", "1", "1", "1", "0", "0", "1", "1", "1", "0", "1", "0", "0", "0", + "0", "0", "1", "0", "1", "1", "0", "1", "0", "1", "0", "0", "0", "1", "1", "0", "1", + "1", "0", "1", "1", "0", "0", "0", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", + "0", "0", "0", "0", "0", "0", "1", "0", "0", "1", "1", "0", "0", "1", "1", "1", "0", + "1", "1", "1", "1", "1", "0", "1", "0", "1", "0", "0", "1", "0", "1", "1", "0", "0", + "0", "0", "1", "1", "1", "0", "0", "1", "0", "1", "1", "0", "1", "1", "0", "0", "0", + "0", "1", "1", "1", "0", "1", "1", "0", "1", "1", "0", "0", "0", "1", "0", "1", "0", + "1", "1", "0", "0", "0", "0", "1", "1", "1", "1", "1", "1", "0", "1", "0", "1", "0", + "1", + ]; + + for i in 0..384 { + pw.set_bool_target(targets.validator.pubkey[i], validator_pubkey[i] == "1"); + } + + for i in 0..256 { + pw.set_bool_target( + targets.validator.withdrawal_credentials[i], + withdraw_credentials[i] == "1", + ); + + pw.set_bool_target( + targets.validator.effective_balance[i], + effective_balance[i] == "1", + ); + + pw.set_bool_target(targets.validator.slashed[i], slashed[i] == "1"); + + pw.set_bool_target( + targets.validator.activation_eligibility_epoch[i], + activation_eligibility_epoch[i] == "1", + ); + + pw.set_bool_target(targets.validator.activation_epoch[i], false); + + pw.set_bool_target( + targets.validator.exit_epoch[i], + if i < 64 { true } else { false }, + ); + + pw.set_bool_target( + targets.validator.withdrawable_epoch[i], + withdrawable_epoch[i] == "1", + ); + } + + for i in 0..256 { + if validator_hash_tree_root[i] == "1" { + builder.assert_one(targets.hash_tree_root[i].target); + } else { + builder.assert_zero(targets.hash_tree_root[i].target); + } + } + + let data = builder.build::(); + let proof = data.prove(pw).unwrap(); + + data.verify(proof) + } } diff --git a/beacon-light-client/plonky2/circuits/src/validator_hash_tree_root_poseidon.rs b/beacon-light-client/plonky2/circuits/src/validator_hash_tree_root_poseidon.rs new file mode 100644 index 000000000..b791665d4 --- /dev/null +++ b/beacon-light-client/plonky2/circuits/src/validator_hash_tree_root_poseidon.rs @@ -0,0 +1,54 @@ +use plonky2::{ + field::extension::Extendable, + hash::{hash_types::{HashOutTarget, RichField}, poseidon::PoseidonHash}, + iop::target::Target, + plonk::circuit_builder::CircuitBuilder, +}; + +pub struct ValidatorPoseidon { + pub pubkey: [Target; 7], + pub activation_epoch: [Target; 2], + pub exit_epoch: [Target; 2], +} + +pub struct ValidatorPoseidonHashTreeRootTargets { + pub validator: ValidatorPoseidon, + pub hash_tree_root: HashOutTarget, +} + +pub fn hash_tree_root_validator_poseidon, const D: usize>( + builder: &mut CircuitBuilder, +) -> ValidatorPoseidonHashTreeRootTargets { + let validator = ValidatorPoseidon { + pubkey: [ + builder.add_virtual_target(), + builder.add_virtual_target(), + builder.add_virtual_target(), + builder.add_virtual_target(), + builder.add_virtual_target(), + builder.add_virtual_target(), + builder.add_virtual_target(), + ], + activation_epoch: [builder.add_virtual_target(), builder.add_virtual_target()], + exit_epoch: [builder.add_virtual_target(), builder.add_virtual_target()], + }; + + let hash_tree_root = builder.hash_n_to_hash_no_pad::(vec![ + validator.pubkey[0], + validator.pubkey[1], + validator.pubkey[2], + validator.pubkey[3], + validator.pubkey[4], + validator.pubkey[5], + validator.pubkey[6], + validator.activation_epoch[0], + validator.activation_epoch[1], + validator.exit_epoch[0], + validator.exit_epoch[1], + ]); + + ValidatorPoseidonHashTreeRootTargets { + validator, + hash_tree_root, + } +} diff --git a/beacon-light-client/plonky2/is_valid_merkle_branch/src/is_valid_merkle_branch.rs b/beacon-light-client/plonky2/is_valid_merkle_branch/src/is_valid_merkle_branch.rs index ed6cf04a9..b51912ba5 100644 --- a/beacon-light-client/plonky2/is_valid_merkle_branch/src/is_valid_merkle_branch.rs +++ b/beacon-light-client/plonky2/is_valid_merkle_branch/src/is_valid_merkle_branch.rs @@ -1,89 +1,65 @@ use plonky2::{ field::extension::Extendable, hash::hash_types::RichField, - iop::witness::{PartialWitness, WitnessWrite}, + iop::target::{BoolTarget, Target}, plonk::circuit_builder::CircuitBuilder, }; -use plonky2_sha256::circuit::{array_to_bits, make_circuits, Sha256Targets}; +use plonky2_sha256::circuit::make_circuits; -use sha2::{Digest, Sha256}; +pub struct IsValidMerkleBranchTargets { + pub leaf: [BoolTarget; 256], + pub branch: Vec<[BoolTarget; 256]>, + pub index: Target, + pub root: [BoolTarget; 256], +} pub fn is_valid_merkle_branch, const D: usize>( builder: &mut CircuitBuilder, - pw: &mut PartialWitness, - root: &Vec, - leaf: &Vec, - branch: &[Vec], - index: &u64, -) { - let mut leaf = leaf.clone(); + depth: usize, +) -> IsValidMerkleBranchTargets { + let index = builder.add_virtual_target(); - let mut index = index.clone(); + let leaf: [BoolTarget; 256] = [builder.add_virtual_bool_target_safe(); 256]; + let mut branch: Vec<[BoolTarget; 256]> = Vec::new(); - for (i, sibling) in branch.iter().enumerate() { - let is_right = index % 2 == 1; - let mut lhs = leaf.clone(); - let mut rhs = sibling.clone(); + for _i in 0..depth { + branch.push([builder.add_virtual_bool_target_safe(); 256]); + } - if is_right { - std::mem::swap(&mut lhs, &mut rhs); - } + let root: [BoolTarget; 256] = [builder.add_virtual_bool_target_safe(); 256]; - let hasher = make_circuits(builder, 512); + let indexes = builder.split_le(index, depth); - for i in 0..256 { - pw.set_bool_target(hasher.message[i], lhs[i]); - } + let mut hashers = Vec::new(); + hashers.push(make_circuits(builder, 512)); - for i in 0..256 { - pw.set_bool_target(hasher.message[i + 256], rhs[i]); - } + for i in 0..depth { + hashers.push(make_circuits(builder, 512)); - leaf = hash_values(lhs, rhs); + let current: [BoolTarget; 256] = if i == 0 { + leaf + } else { + hashers[i - 1].digest.clone().try_into().unwrap() + }; - // constraint the root - if i == branch.len() - 1 { - assert_hasher(root, builder, hasher) - } + for j in 0..256 { + let el1 = builder._if(indexes[i], branch[i][j].target, current[j].target); + builder.connect(hashers[i].message[i].target, el1); - index /= 2; + let el2 = builder._if(indexes[i], current[j].target, branch[i][j].target); + builder.connect(hashers[i].message[i + 256].target, el2); + } } -} - -fn hash_values(lhs: Vec, rhs: Vec) -> Vec { - let bytes: Vec = [lhs, rhs] - .concat() - .chunks(8) - .map(|chunk| { - let mut byte = 0u8; - for (i, &bit) in chunk.iter().enumerate() { - if bit { - byte |= 1u8 << (7 - i); - } - } - byte - }) - .collect(); - let mut hasher = Sha256::default(); - hasher.update(&bytes); - - let finalized = hasher.finalize(); - - return array_to_bits(finalized.as_slice()); -} - -fn assert_hasher, const D: usize>( - result: &Vec, - builder: &mut CircuitBuilder, - hasher: Sha256Targets, -) { for i in 0..256 { - if result[i] { - builder.assert_one(hasher.digest[i].target); - } else { - builder.assert_zero(hasher.digest[i].target); - } + builder.connect(hashers[depth - 1].digest[i].target, root[i].target) + } + + IsValidMerkleBranchTargets { + leaf: leaf, + branch: branch, + index: index, + root: root, } } diff --git a/beacon-light-client/plonky2/is_valid_merkle_branch/src/main.rs b/beacon-light-client/plonky2/is_valid_merkle_branch/src/main.rs index 77b1e7ac0..a683ae543 100644 --- a/beacon-light-client/plonky2/is_valid_merkle_branch/src/main.rs +++ b/beacon-light-client/plonky2/is_valid_merkle_branch/src/main.rs @@ -1,14 +1,15 @@ -use std::fs::File; -use std::io::BufReader; use anyhow::Result; use plonky2::field::goldilocks_field::GoldilocksField; -use plonky2::iop::witness::PartialWitness; +use plonky2::field::types::Field; +use plonky2::iop::witness::{PartialWitness, WitnessWrite}; use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::CircuitConfig; -use plonky2::plonk::config::{PoseidonGoldilocksConfig}; +use plonky2::plonk::config::PoseidonGoldilocksConfig; +use std::fs::File; +use std::io::BufReader; mod is_valid_merkle_branch; use is_valid_merkle_branch::is_valid_merkle_branch; -use serde::{Deserialize}; +use serde::Deserialize; #[derive(Debug, Deserialize)] struct RawMerkleProof { @@ -64,14 +65,20 @@ fn create_proof(merkle_proof: MerkleProof) -> std::result::Result<(), anyhow::Er let mut builder = CircuitBuilder::::new(config); let mut pw = PartialWitness::new(); - is_valid_merkle_branch( - &mut builder, - &mut pw, - &merkle_proof.root, - &merkle_proof.leaf, - &merkle_proof.branch, - &merkle_proof.index, - ); + let hasher = is_valid_merkle_branch(&mut builder, merkle_proof.branch.len()); + + pw.set_target(hasher.index, F::from_canonical_u64(merkle_proof.index)); + + for i in 0..256 { + pw.set_bool_target(hasher.leaf[i], merkle_proof.leaf[i]); + pw.set_bool_target(hasher.root[i], merkle_proof.root[i]); + } + + for i in 0..merkle_proof.branch.len() { + for j in 0..256 { + pw.set_bool_target(hasher.branch[i][j], merkle_proof.branch[i][j]); + } + } let data = builder.build::(); let proof = data.prove(pw).unwrap(); diff --git a/relay/save_proof_inputs_from_redis.ts b/relay/save_proof_inputs_from_redis.ts new file mode 100644 index 000000000..75aeefe74 --- /dev/null +++ b/relay/save_proof_inputs_from_redis.ts @@ -0,0 +1,23 @@ +import { writeFile, writeFileSync } from 'fs'; +import { Redis } from './implementations/redis'; + +(async () => { + const redis = new Redis('localhost', 6379); + + let proof = await redis.getNextProof(5644385); + + while (proof != null) { + const proofInput = proof.proofInput; + + writeFileSync( + `../vendor/eth2-light-client-updates/prater/capella-94-proof-inputs/public_output_${proof.prevUpdateSlot}_${proof.updateSlot}.json`, + JSON.stringify(proof.proof.public, null, 2), + ); + + console.log('Saved proof input for slot', proof.updateSlot); + + proof = await redis.getNextProof(proof.updateSlot); + } + + console.log('Finished.'); +})();