diff --git a/Cargo.lock b/Cargo.lock index ec99a9b..5d2213e 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -4986,6 +4986,7 @@ dependencies = [ "pallet-aura", "pallet-balances", "pallet-grandpa", + "pallet-reward", "pallet-sudo", "pallet-template", "pallet-timestamp", @@ -5279,6 +5280,21 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-reward" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet_zkp_verify", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", +] + [[package]] name = "pallet-session" version = "4.0.0-dev" @@ -5410,6 +5426,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "hex", "parity-scale-codec", "rkyv", "scale-info", diff --git a/frontend/groth16.html b/frontend/groth16.html new file mode 100755 index 0000000..a19c7f5 --- /dev/null +++ b/frontend/groth16.html @@ -0,0 +1,34 @@ + + + + + Polkadot.js Integration + + + + + + + + + + +
+
+

Sustrate ZKP Pallet

+ + + + +
+
+
+
+ + + + + \ No newline at end of file diff --git a/frontend/img/bg.png b/frontend/img/bg.png old mode 100644 new mode 100755 diff --git a/frontend/index.html b/frontend/index.html old mode 100644 new mode 100755 index 99d2488..ab98cc4 --- a/frontend/index.html +++ b/frontend/index.html @@ -13,13 +13,19 @@ -
+

Sustrate ZKP Pallet

- - - - + +
+ + + + +
diff --git a/frontend/js/bundle-polkadot-api-contract.js b/frontend/js/bundle-polkadot-api-contract.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-api.js b/frontend/js/bundle-polkadot-api.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-extension-dapp.js b/frontend/js/bundle-polkadot-extension-dapp.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-hw-ledger.js b/frontend/js/bundle-polkadot-hw-ledger.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-keyring.js b/frontend/js/bundle-polkadot-keyring.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-phishing.js b/frontend/js/bundle-polkadot-phishing.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-react-identicon.js b/frontend/js/bundle-polkadot-react-identicon.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-react-qr.js b/frontend/js/bundle-polkadot-react-qr.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-types.js b/frontend/js/bundle-polkadot-types.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-ui-keyring.js b/frontend/js/bundle-polkadot-ui-keyring.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-ui-settings.js b/frontend/js/bundle-polkadot-ui-settings.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-util-crypto.js b/frontend/js/bundle-polkadot-util-crypto.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-util.js b/frontend/js/bundle-polkadot-util.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-vue-identicon.js b/frontend/js/bundle-polkadot-vue-identicon.js old mode 100644 new mode 100755 diff --git a/frontend/js/bundle-polkadot-wasm-crypto.js b/frontend/js/bundle-polkadot-wasm-crypto.js old mode 100644 new mode 100755 diff --git a/frontend/script.js b/frontend/script.js old mode 100644 new mode 100755 index b2ac876..d87acf9 --- a/frontend/script.js +++ b/frontend/script.js @@ -13,7 +13,7 @@ document.getElementById('submitBtn').addEventListener('click', async function () // Replace 'palletName.methodName' with the actual pallet method you want to call // and adjust the parameters as needed. try { - const transaction = api.tx.zkpVerifyModule.verifyProofPlonk(input1, input2, input3); + const transaction = api.tx.zkpVerifyModule.verifyPlonk(input1, input2, input3); const unsub = await transaction.signAndSend(selectedAccount, { signer: injector.signer }, ({ status, events, dispatchError }) => { if (status.isInBlock || status.isFinalized) { diff --git a/frontend/script2.js b/frontend/script2.js new file mode 100644 index 0000000..4de5fac --- /dev/null +++ b/frontend/script2.js @@ -0,0 +1,178 @@ +class Proof { + + constructor(a, b, c, inputs) { + this.a = a; + this.b = b; + this.c = c; + this.inputs = inputs; + } +} + +class VerificationKey { + + constructor(alpha, beta, gamma, delta, gammaABC) { + this.alpha = alpha; + this.beta = beta; + this.gamma = gamma; + this.delta = delta; + this.gammaABC = gammaABC; + } +} + + +function readFileAsJson(file) { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onload = function (event) { + try { + const jsonObj = JSON.parse(event.target.result); + resolve(jsonObj); + } catch (error) { + reject(error); + } + }; + + reader.onerror = function () { + reject(new Error("Error reading the file.")); + }; + + reader.readAsText(file); + }); +} + +document.getElementById('submitBtn').addEventListener('click', async function () { + document.getElementById('successIndicator').style.display = 'none'; + document.getElementById('failureIndicator').style.display = 'none'; + document.getElementById('loadingIndicator').style.display = 'block'; + // Getting values from input fields + const fileInput = document.getElementById('fileInput'); + if (fileInput.files.length === 0) { + alert("Please upload a JSON file."); + document.getElementById('loadingIndicator').style.display = 'none'; + return; + } + const file = fileInput.files[0]; + + let proof; + try { + const jsonObj = await readFileAsJson(file); + + const a = jsonObj.proof.a; + const b = jsonObj.proof.b; + const c = jsonObj.proof.c; + const inputs = jsonObj.inputs; + proof = new Proof(a, b, c, inputs); + + + } catch (error) { + console.error('Error:', error); + document.getElementById('failureIndicator').style.display = 'block'; + document.getElementById('loadingIndicator').style.display = 'none'; + } + + + const fileInput2 = document.getElementById('fileInput2'); + if (fileInput2.files.length === 0) { + alert("Please upload a JSON file."); + document.getElementById('loadingIndicator').style.display = 'none'; + return; + } + const file2 = fileInput2.files[0]; + + let vk; + try { + const jsonObj = await readFileAsJson(file2); + + + const alpha = jsonObj.alpha; + const beta = jsonObj.beta; + const gamma = jsonObj.gamma; + const delta = jsonObj.delta; + const gammaABC = jsonObj.gamma_abc; + vk = new VerificationKey(alpha, beta, gamma, delta, gammaABC); + + } catch (error) { + console.error('Error:', error); + document.getElementById('failureIndicator').style.display = 'block'; + document.getElementById('loadingIndicator').style.display = 'none'; + } + + + // Call a specific pallet function (example: transfer) + // Replace 'palletName.methodName' with the actual pallet method you want to call + // and adjust the parameters as needed. + try { + let inputs = "0x"+proof.inputs.map((input) => { return input.substring(2).toLowerCase() }).join(''); + console.log(inputs); + const transaction = api.tx.zkpVerifyModule.verifyG16(vk.alpha[0], vk.alpha[1], vk.beta[0][0], vk.beta[0][1], vk.beta[1][0], vk.beta[1][1], vk.gamma[0][0], vk.gamma[0][1], vk.gamma[1][0], vk.gamma[1][1], vk.delta[0][0], vk.delta[0][1], vk.delta[1][0], vk.delta[1][1], vk.gammaABC[0][0], vk.gammaABC[0][1], vk.gammaABC[1][0], vk.gammaABC[1][1], inputs, proof.a[0], proof.a[1], proof.b[0][0], proof.b[0][1], proof.b[1][0], proof.b[1][1], proof.c[0], proof.c[1]); + + const unsub = await transaction.signAndSend(selectedAccount, { signer: injector.signer }, ({ status, events, dispatchError }) => { + console.log("Hi"); + if (status.isInBlock || status.isFinalized) { + events.forEach(({ event: { data, method, section } }) => { + console.log(`Event: ${section}.${method}`, data.toString()); + if (method === 'ValidationSuccess') { + document.getElementById('loadingIndicator').style.display = 'none'; + document.getElementById('successIndicator').style.display = 'block'; + } + }); + + if (dispatchError) { + document.getElementById('loadingIndicator').style.display = 'none'; + document.getElementById('failureIndicator').style.display = 'block'; + if (dispatchError.isModule) { + // For module errors, we have the section indexed, lookup + const decoded = api.registry.findMetaError(dispatchError.asModule); + const { documentation, method, section } = decoded; + + console.error(`${section}.${method}: ${documentation.join(' ')}`); + } else { + // Other, CannotLookup, BadOrigin, no extra info + console.error(dispatchError.toString()); + } + } + unsub(); + } + }); + } catch (error) { + console.error('Error:', error); + } + +}); +let api; +let selectedAccount; +let injector; +// On page loaded +window.addEventListener('load', async () => { + // Initialize the Polkadot.js API + const { ApiPromise, WsProvider } = polkadotApi; + const wsProvider = new WsProvider('ws://127.0.0.1:9944'); + api = await ApiPromise.create({ provider: wsProvider }); + + // Initialize the Polkadot.js API + const { web3Accounts, web3Enable, web3FromAddress } = polkadotExtensionDapp; + + + // Request access to the user's Polkadot.js accounts + const extensions = await web3Enable('My Polkadot.js Integration App'); + if (extensions.length === 0) { + // No extension installed, or the user refused to authorize access + return; + } + + // Get the user's accounts + const allAccounts = await web3Accounts(); + if (allAccounts.length === 0) { + // No accounts available + return; + } + + // Select account to use (for simplicity, using the first account) + selectedAccount = allAccounts[0].address; + injector = await web3FromAddress(selectedAccount); + +}); + +document.getElementById('successIndicator').style.display = 'none'; +document.getElementById('failureIndicator').style.display = 'none'; \ No newline at end of file diff --git a/frontend/style.css b/frontend/style.css old mode 100644 new mode 100755 index e68d905..99304db --- a/frontend/style.css +++ b/frontend/style.css @@ -118,4 +118,65 @@ h2 { border-radius: 50%; opacity: 1; } +} + + +input[type="file"] { + margin: 10px 0; + padding: 10px; + color: #ffffff; + background-color: #221; + border: 2px solid #ff00ff; /* Neon-like border */ + border-radius: 5px; + outline: none; + text-align: center; + cursor: pointer; + transition: background-color 0.3s, transform 0.3s; +} + +input[type="file"]::file-selector-button { + background-color: #ff00ff; /* Neon button color */ + color: #000; + border: none; + padding: 10px; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s; +} + +input[type="file"]::file-selector-button:hover { + background-color: #ff00aa; /* Hover effect */ +} + +input[type="file"]:hover { + background-color: #332244; /* Hover effect on the input field */ + transform: scale(1.05); /* Slight zoom effect on hover */ +} + + +.nav-buttons { + display: flex; + justify-content: center; + margin-bottom: 20px; +} + +.nav-button { + padding: 10px 20px; + margin: 0 10px; + background-color: #221; + color: #ffffff; + text-decoration: none; + border: 2px solid #ff00ff; /* Neon-like border */ + border-radius: 5px; + transition: background-color 0.3s, transform 0.3s; + cursor: pointer; +} + +.nav-button:hover { + background-color: #332244; /* Hover effect */ + transform: scale(1.1); /* Slight zoom effect on hover */ +} + +.nav-button.active { + background-color: #ff00ff; /* Active button color */ } \ No newline at end of file diff --git a/pallets/reward/Cargo.toml b/pallets/reward/Cargo.toml new file mode 100755 index 0000000..537f009 --- /dev/null +++ b/pallets/reward/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "pallet-reward" +version = "4.0.0-dev" +description = "FRAME pallet template for defining custom runtime logic." +authors = ["Substrate DevHub "] +homepage = "https://substrate.io" +edition = "2021" +license = "MIT-0" +publish = false +repository = "https://github.com/substrate-developer-hub/substrate-node-template/" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +pallet_zkp_verify = { version = "4.0.0-dev", default-features = false, path = "../zkp_verify" } + +[dev-dependencies] +sp-core = { version = "21.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-io = { version = "23.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +sp-runtime = { version = "24.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", +] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] +try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/reward/README.md b/pallets/reward/README.md new file mode 100755 index 0000000..d0d5953 --- /dev/null +++ b/pallets/reward/README.md @@ -0,0 +1 @@ +License: MIT-0 \ No newline at end of file diff --git a/pallets/reward/src/benchmarking.rs b/pallets/reward/src/benchmarking.rs new file mode 100755 index 0000000..a8150dc --- /dev/null +++ b/pallets/reward/src/benchmarking.rs @@ -0,0 +1,35 @@ +//! Benchmarking setup for pallet-reward +#![cfg(feature = "runtime-benchmarks")] +use super::*; + +#[allow(unused)] +use crate::Pallet as Template; +use frame_benchmarking::v2::*; +use frame_system::RawOrigin; + +#[benchmarks] +mod benchmarks { + use super::*; + + #[benchmark] + fn do_something() { + let value = 100u32.into(); + let caller: T::AccountId = whitelisted_caller(); + #[extrinsic_call] + do_something(RawOrigin::Signed(caller), value); + + assert_eq!(Something::::get(), Some(value)); + } + + #[benchmark] + fn cause_error() { + Something::::put(100u32); + let caller: T::AccountId = whitelisted_caller(); + #[extrinsic_call] + cause_error(RawOrigin::Signed(caller)); + + assert_eq!(Something::::get(), Some(101u32)); + } + + impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/pallets/reward/src/lib.rs b/pallets/reward/src/lib.rs new file mode 100755 index 0000000..c2abb78 --- /dev/null +++ b/pallets/reward/src/lib.rs @@ -0,0 +1,139 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +pub use pallet::*; + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +pub mod weights; +pub use weights::*; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + use pallet_zkp_verify::ZKPVerifyInterface; + + #[pallet::pallet] + pub struct Pallet(_); + + /// Configure the pallet by specifying the parameters and types on which it depends. + #[pallet::config] + pub trait Config: frame_system::Config { + /// Because this pallet emits events, it depends on the runtime's definition of an event. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// Type representing the weight of this pallet + type WeightInfo: WeightInfo; + /// + type ZKPVerify: ZKPVerifyInterface; + } + + // The pallet's runtime storage items. + // https://docs.substrate.io/main-docs/build/runtime-storage/ + #[pallet::storage] + #[pallet::getter(fn something)] + // Learn more about declaring storage items: + // https://docs.substrate.io/main-docs/build/runtime-storage/#declaring-storage-items + pub type Something = StorageValue<_, u32>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + RewardSuccess { who: T::AccountId }, + } + + #[pallet::error] + pub enum Error { + RewardFailed, + } + + // Dispatchable functions allows users to interact with the pallet and invoke state changes. + // These functions materialize as "extrinsics", which are often compared to transactions. + // Dispatchable functions must be annotated with a weight and must return a DispatchResult. + #[pallet::call] + impl Pallet { + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::cause_error())] + pub fn verify_proof( + origin: OriginFor, + + // vk: Vec, + vk_alpha_1: Vec, + vk_alpha_2: Vec, + vk_beta_1_1: Vec, + vk_beta_1_2: Vec, + vk_beta_2_1: Vec, + vk_beta_2_2: Vec, + vk_gamma_1_1: Vec, + vk_gamma_1_2: Vec, + vk_gamma_2_1: Vec, + vk_gamma_2_2: Vec, + vk_delta_1_1: Vec, + vk_delta_1_2: Vec, + vk_delta_2_1: Vec, + vk_delta_2_2: Vec, + vk_gamma_abc_1_1: Vec, + vk_gamma_abc_1_2: Vec, + vk_gamma_abc_2_1: Vec, + vk_gamma_abc_2_2: Vec, + + inputs: Vec, + + // proof: Vec, + proof_a_1: Vec, + proof_a_2: Vec, + proof_b_1_1: Vec, + proof_b_1_2: Vec, + proof_b_2_1: Vec, + proof_b_2_2: Vec, + proof_c_1: Vec, + proof_c_2: Vec, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + let result = T::ZKPVerify::verify_proof( + origin, + vk_alpha_1, + vk_alpha_2, + vk_beta_1_1, + vk_beta_1_2, + vk_beta_2_1, + vk_beta_2_2, + vk_gamma_1_1, + vk_gamma_1_2, + vk_gamma_2_1, + vk_gamma_2_2, + vk_delta_1_1, + vk_delta_1_2, + vk_delta_2_1, + vk_delta_2_2, + vk_gamma_abc_1_1, + vk_gamma_abc_1_2, + vk_gamma_abc_2_1, + vk_gamma_abc_2_2, + inputs, + proof_a_1, + proof_a_2, + proof_b_1_1, + proof_b_1_2, + proof_b_2_1, + proof_b_2_2, + proof_c_1, + proof_c_2, + ); + + if result { + Self::deposit_event(Event::RewardSuccess { who }); + Ok(()) + } else { + Err(Error::::RewardFailed.into()) + } + } + } +} diff --git a/pallets/reward/src/mock.rs b/pallets/reward/src/mock.rs new file mode 100755 index 0000000..568ebaf --- /dev/null +++ b/pallets/reward/src/mock.rs @@ -0,0 +1,54 @@ +use crate as pallet_reward; +use frame_support::traits::{ConstU16, ConstU64}; +use sp_core::H256; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, +}; + +type Block = frame_system::mocking::MockBlock; + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test + { + System: frame_system, + TemplateModule: pallet_reward, + } +); + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Block = Block; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = ConstU16<42>; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_reward::Config for Test { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} + +// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + frame_system::GenesisConfig::::default().build_storage().unwrap().into() +} diff --git a/pallets/reward/src/tests.rs b/pallets/reward/src/tests.rs new file mode 100755 index 0000000..7c2b853 --- /dev/null +++ b/pallets/reward/src/tests.rs @@ -0,0 +1,27 @@ +use crate::{mock::*, Error, Event}; +use frame_support::{assert_noop, assert_ok}; + +#[test] +fn it_works_for_default_value() { + new_test_ext().execute_with(|| { + // Go past genesis block so events get deposited + System::set_block_number(1); + // Dispatch a signed extrinsic. + assert_ok!(TemplateModule::do_something(RuntimeOrigin::signed(1), 42)); + // Read pallet storage and assert an expected result. + assert_eq!(TemplateModule::something(), Some(42)); + // Assert that the correct event was deposited + System::assert_last_event(Event::SomethingStored { something: 42, who: 1 }.into()); + }); +} + +#[test] +fn correct_error_for_none_value() { + new_test_ext().execute_with(|| { + // Ensure the expected error is thrown when no value is present. + assert_noop!( + TemplateModule::cause_error(RuntimeOrigin::signed(1)), + Error::::NoneValue + ); + }); +} diff --git a/pallets/reward/src/weights.rs b/pallets/reward/src/weights.rs new file mode 100755 index 0000000..7c42936 --- /dev/null +++ b/pallets/reward/src/weights.rs @@ -0,0 +1,90 @@ + +//! Autogenerated weights for pallet_template +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-04-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `Alexs-MacBook-Pro-2.local`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// ../../target/release/node-template +// benchmark +// pallet +// --chain +// dev +// --pallet +// pallet_template +// --extrinsic +// * +// --steps=50 +// --repeat=20 +// --wasm-execution=compiled +// --output +// pallets/template/src/weights.rs +// --template +// ../../.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for pallet_template. +pub trait WeightInfo { + fn do_something() -> Weight; + fn cause_error() -> Weight; +} + +/// Weights for pallet_template using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: TemplateModule Something (r:0 w:1) + /// Proof: TemplateModule Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn do_something() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 8_000_000 picoseconds. + Weight::from_parts(9_000_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: TemplateModule Something (r:1 w:1) + /// Proof: TemplateModule Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn cause_error() -> Weight { + // Proof Size summary in bytes: + // Measured: `32` + // Estimated: `1489` + // Minimum execution time: 6_000_000 picoseconds. + Weight::from_parts(6_000_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + /// Storage: TemplateModule Something (r:0 w:1) + /// Proof: TemplateModule Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn do_something() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 8_000_000 picoseconds. + Weight::from_parts(9_000_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: TemplateModule Something (r:1 w:1) + /// Proof: TemplateModule Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn cause_error() -> Weight { + // Proof Size summary in bytes: + // Measured: `32` + // Estimated: `1489` + // Minimum execution time: 6_000_000 picoseconds. + Weight::from_parts(6_000_000, 1489) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } +} diff --git a/pallets/zkp_verify/Cargo.toml b/pallets/zkp_verify/Cargo.toml index 4fd1346..626be7e 100755 --- a/pallets/zkp_verify/Cargo.toml +++ b/pallets/zkp_verify/Cargo.toml @@ -34,6 +34,7 @@ dusk-jubjub = { version ="0.13.1", default-features = false} dusk-plonk = {version = "0.17.0", features = ["rkyv-impl","alloc"], default-features = false } dusk-bls12_381 = {version = "0.12.3", features = ["rkyv-impl","pairings","alloc"], default-features = false} rkyv = { version = "0.7.42", features = ["validation","size_32"], default-features = false } +hex = { version = "0.4.3" ,features = ["alloc"], default-features = false} diff --git a/pallets/zkp_verify/src/groth16.rs b/pallets/zkp_verify/src/groth16.rs new file mode 100755 index 0000000..d058b91 --- /dev/null +++ b/pallets/zkp_verify/src/groth16.rs @@ -0,0 +1,117 @@ +use core::slice::Chunks; + +use ark_bls12_381::{Bls12_381, Fr}; +use ark_groth16::{prepare_verifying_key, Groth16, Proof, VerifyingKey}; +use ark_serialize::CanonicalDeserialize; +use ark_std::vec::Vec; +use hex; + +pub struct G1AffineParts { + pub part_1: Vec, + pub part_2: Vec, +} + +pub struct G2AffineParts { + pub part_1_1: Vec, + pub part_1_2: Vec, + pub part_2_1: Vec, + pub part_2_2: Vec, +} + +pub struct VKParts { + pub alpha: G1AffineParts, + pub beta: G2AffineParts, + pub gamma: G2AffineParts, + pub delta: G2AffineParts, + pub gamma_abc_1: G1AffineParts, + pub gamma_abc_2: G1AffineParts, +} + +pub struct ProofParts { + pub a: G1AffineParts, + pub b: G2AffineParts, + pub c: G1AffineParts, +} + +fn assemble_vk(vk: &VKParts) -> VerifyingKey { + let alpha = [&vk.alpha.part_1[..], &vk.alpha.part_2[..]].concat(); + let beta = [ + &vk.beta.part_1_2[..], + &vk.beta.part_1_1[..], + &vk.beta.part_2_2[..], + &vk.beta.part_2_1, + ] + .concat(); + let gamma = [ + &vk.gamma.part_1_2[..], + &vk.gamma.part_1_1[..], + &vk.gamma.part_2_2[..], + &vk.gamma.part_2_1, + ] + .concat(); + let delta = [ + &vk.delta.part_1_2[..], + &vk.delta.part_1_1[..], + &vk.delta.part_2_2[..], + &vk.delta.part_2_1, + ] + .concat(); + let gamma_abc = [ + &hex::decode("0200000000000000").unwrap()[..], + &vk.gamma_abc_1.part_1[..], + &vk.gamma_abc_1.part_2[..], + &vk.gamma_abc_2.part_1[..], + &vk.gamma_abc_2.part_2[..], + ] + .concat(); + + let vk_bytes = [ + &alpha[..], + &beta[..], + &gamma[..], + &delta[..], + &gamma_abc[..], + ] + .concat(); + + return VerifyingKey::::deserialize_uncompressed(&*vk_bytes) + .expect("Failed to create deserialize verifying key"); +} + +fn assemble_proof(proof: &ProofParts) -> Proof { + let a = [&proof.a.part_1[..], &proof.a.part_2[..]].concat(); + let b = [ + &proof.b.part_1_2[..], + &proof.b.part_1_1[..], + &proof.b.part_2_2[..], + &proof.b.part_2_1, + ] + .concat(); + let c = [&proof.c.part_1[..], &proof.c.part_2[..]].concat(); + + let proof_bytes = [&a[..], &b[..], &c[..]].concat(); + + return Proof::::deserialize_uncompressed(&*proof_bytes) + .expect("Failed to deserialize proof"); +} + +fn assemble_inputs(public_inputs: &Vec) -> Vec { + let mut frs: Vec = Vec::new(); + let chunks: Chunks = public_inputs.chunks(32); + for c in chunks { + let c_rev: Vec = c.into_iter().rev().cloned().collect(); + let fr: Fr = Fr::deserialize_uncompressed(&*c_rev).expect("Failed to deserialize Fr"); + frs.push(fr); + } + + return frs; +} + +fn verify_(vk: &VerifyingKey, proof: &Proof, public_inputs: &[Fr]) -> bool { + return Groth16::::verify_proof(&prepare_verifying_key(&vk), &proof, &public_inputs) + .expect("Error during proof verification"); +} + +pub fn verify(vk: &VKParts, proof: &ProofParts, public_inputs: &Vec) -> bool { + return verify_(&assemble_vk(vk), &assemble_proof(proof), &assemble_inputs(public_inputs)[..]); +} \ No newline at end of file diff --git a/pallets/zkp_verify/src/lib.rs b/pallets/zkp_verify/src/lib.rs index 7df8970..52e8c98 100755 --- a/pallets/zkp_verify/src/lib.rs +++ b/pallets/zkp_verify/src/lib.rs @@ -17,6 +17,8 @@ mod tests; mod benchmarking; pub mod weights; pub use weights::*; +mod groth16; +use crate::groth16::{G1AffineParts, G2AffineParts, ProofParts, VKParts}; #[frame_support::pallet] pub mod pallet { @@ -77,62 +79,144 @@ pub mod pallet { // Dispatchable functions must be annotated with a weight and must return a DispatchResult. #[pallet::call] impl Pallet { - + #[pallet::call_index(0)] #[pallet::weight(T::WeightInfo::cause_error())] - pub fn verify_proof(origin: OriginFor, vk: Vec,inputs: Vec,proof: Vec) -> DispatchResult { + pub fn verify_g16( + origin: OriginFor, + + // vk: Vec, + vk_alpha_1: Vec, + vk_alpha_2: Vec, + vk_beta_1_1: Vec, + vk_beta_1_2: Vec, + vk_beta_2_1: Vec, + vk_beta_2_2: Vec, + vk_gamma_1_1: Vec, + vk_gamma_1_2: Vec, + vk_gamma_2_1: Vec, + vk_gamma_2_2: Vec, + vk_delta_1_1: Vec, + vk_delta_1_2: Vec, + vk_delta_2_1: Vec, + vk_delta_2_2: Vec, + vk_gamma_abc_1_1: Vec, + vk_gamma_abc_1_2: Vec, + vk_gamma_abc_2_1: Vec, + vk_gamma_abc_2_2: Vec, + + inputs: Vec, + + // proof: Vec, + proof_a_1: Vec, + proof_a_2: Vec, + proof_b_1_1: Vec, + proof_b_1_2: Vec, + proof_b_2_1: Vec, + proof_b_2_2: Vec, + proof_c_1: Vec, + proof_c_2: Vec, + ) -> DispatchResult { let who = ensure_signed(origin)?; - let cursor = Cursor::new(&vk); - let vk = as SNARK>::VerifyingKey::deserialize_with_mode( - cursor, - Compress::No, - Validate::No, - ).unwrap(); + let vk_parts = VKParts { + alpha: G1AffineParts { + part_1: vk_alpha_1, + part_2: vk_alpha_2, + }, + beta: G2AffineParts { + part_1_1: vk_beta_1_1, + part_1_2: vk_beta_1_2, + part_2_1: vk_beta_2_1, + part_2_2: vk_beta_2_2, + }, + gamma: G2AffineParts { + part_1_1: vk_gamma_1_1, + part_1_2: vk_gamma_1_2, + part_2_1: vk_gamma_2_1, + part_2_2: vk_gamma_2_2, + }, + delta: G2AffineParts { + part_1_1: vk_delta_1_1, + part_1_2: vk_delta_1_2, + part_2_1: vk_delta_2_1, + part_2_2: vk_delta_2_2, + }, + gamma_abc_1: G1AffineParts{ + part_1: vk_gamma_abc_1_1, + part_2: vk_gamma_abc_1_2, + }, + gamma_abc_2: G1AffineParts{ + part_1: vk_gamma_abc_2_1, + part_2: vk_gamma_abc_2_2, + }, + }; - let cursor = Cursor::new(&inputs); - let inputs: ark_ff::Fp, 4> = - Fp::deserialize_with_mode(cursor, Compress::No, Validate::No).unwrap(); - + let proof_parts = ProofParts { + a: G1AffineParts { + part_1: proof_a_1, + part_2: proof_a_2, + }, + b: G2AffineParts { + part_1_1: proof_b_1_1, + part_1_2: proof_b_1_2, + part_2_1: proof_b_2_1, + part_2_2: proof_b_2_2, + }, + c: G1AffineParts { + part_1: proof_c_1, + part_2: proof_c_2, + }, + }; - let cursor = Cursor::new(&proof); - let proof = - as SNARK>::Proof::deserialize_with_mode( - cursor, - Compress::No, - Validate::No, - ).unwrap(); - - - let result = Groth16::::verify(&vk, &[inputs], &proof).unwrap(); - if(result){ + // let result = Groth16::::verify(&vk, &[inputs], &proof).unwrap(); + let result: bool = groth16::verify(&vk_parts, &proof_parts, &inputs); + if result { Self::deposit_event(Event::ValidationSuccess { who }); Ok(()) - }else{ + } else { Err(Error::::ValidationFailed.into()) } } #[pallet::call_index(1)] #[pallet::weight(T::WeightInfo::cause_error())] - pub fn verify_proof_plonk(origin: OriginFor, vk: Vec, inputs: Vec,proof: Vec) -> DispatchResult { + pub fn verify_plonk(origin: OriginFor, vk: Vec, inputs: Vec,proof: Vec) -> DispatchResult { let who = ensure_signed(origin)?; + + let result_vk = Verifier::try_from_bytes(&vk[..]); - let verifier: Verifier = Verifier::try_from_bytes(&vk[..]).expect("Failed to load verifier"); + let verifier = match result_vk { + Ok(verifier) => verifier, + Err(_) => return Err(Error::::ValidationFailed.into()), + }; - let archived = rkyv::check_archived_root::(&proof[..]).unwrap(); + let archived = match rkyv::check_archived_root::(&proof[..]){ + Ok(archived) => archived, + Err(_) => return Err(Error::::ValidationFailed.into()), + }; - let proof: Proof = archived.deserialize(&mut rkyv::Infallible).unwrap(); - let archived = rkyv::check_archived_root::>(&inputs[..]).unwrap(); - let inputs: Vec = archived.deserialize(&mut rkyv::Infallible).unwrap(); + let proof: Proof = match archived.deserialize(&mut rkyv::Infallible) { + Ok(proof) => proof, + Err(_) => return Err(Error::::ValidationFailed.into()), + }; + + let archived = match rkyv::check_archived_root::>(&inputs[..]) { + Ok(archived) => archived, + Err(_) => return Err(Error::::ValidationFailed.into()), + }; + let inputs: Vec = match archived.deserialize(&mut rkyv::Infallible) { + Ok(inputs) => inputs, + Err(_) => return Err(Error::::ValidationFailed.into()), + }; let verification =verifier.verify(&proof, &inputs); let result = verification.is_ok(); - if(result){ + if result { Self::deposit_event(Event::ValidationSuccess { who }); Ok(()) }else{ @@ -174,4 +258,112 @@ pub mod pallet { } }*/ } -} + + pub trait ZKPVerifyInterface { + fn verify_g16( + origin: OriginFor, + + // vk: Vec, + vk_alpha_1: Vec, + vk_alpha_2: Vec, + vk_beta_1_1: Vec, + vk_beta_1_2: Vec, + vk_beta_2_1: Vec, + vk_beta_2_2: Vec, + vk_gamma_1_1: Vec, + vk_gamma_1_2: Vec, + vk_gamma_2_1: Vec, + vk_gamma_2_2: Vec, + vk_delta_1_1: Vec, + vk_delta_1_2: Vec, + vk_delta_2_1: Vec, + vk_delta_2_2: Vec, + vk_gamma_abc_1_1: Vec, + vk_gamma_abc_1_2: Vec, + vk_gamma_abc_2_1: Vec, + vk_gamma_abc_2_2: Vec, + + inputs: Vec, + + // proof: Vec, + proof_a_1: Vec, + proof_a_2: Vec, + proof_b_1_1: Vec, + proof_b_1_2: Vec, + proof_b_2_1: Vec, + proof_b_2_2: Vec, + proof_c_1: Vec, + proof_c_2: Vec, + ) -> DispatchResult; + } + + impl ZKPVerifyInterface for Pallet { + fn verify_g16( + origin: OriginFor, + + // vk: Vec, + vk_alpha_1: Vec, + vk_alpha_2: Vec, + vk_beta_1_1: Vec, + vk_beta_1_2: Vec, + vk_beta_2_1: Vec, + vk_beta_2_2: Vec, + vk_gamma_1_1: Vec, + vk_gamma_1_2: Vec, + vk_gamma_2_1: Vec, + vk_gamma_2_2: Vec, + vk_delta_1_1: Vec, + vk_delta_1_2: Vec, + vk_delta_2_1: Vec, + vk_delta_2_2: Vec, + vk_gamma_abc_1_1: Vec, + vk_gamma_abc_1_2: Vec, + vk_gamma_abc_2_1: Vec, + vk_gamma_abc_2_2: Vec, + + inputs: Vec, + + // proof: Vec, + proof_a_1: Vec, + proof_a_2: Vec, + proof_b_1_1: Vec, + proof_b_1_2: Vec, + proof_b_2_1: Vec, + proof_b_2_2: Vec, + proof_c_1: Vec, + proof_c_2: Vec, + ) -> DistpacthResult { + //) -> Result { + return Self::verify_g16( + origin, + vk_alpha_1, + vk_alpha_2, + vk_beta_1_1, + vk_beta_1_2, + vk_beta_2_1, + vk_beta_2_2, + vk_gamma_1_1, + vk_gamma_1_2, + vk_gamma_2_1, + vk_gamma_2_2, + vk_delta_1_1, + vk_delta_1_2, + vk_delta_2_1, + vk_delta_2_2, + vk_gamma_abc_1_1, + vk_gamma_abc_1_2, + vk_gamma_abc_2_1, + vk_gamma_abc_2_2, + inputs, + proof_a_1, + proof_a_2, + proof_b_1_1, + proof_b_1_2, + proof_b_2_1, + proof_b_2_2, + proof_c_1, + proof_c_2, + ); + } + } +} \ No newline at end of file diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 3bb4141..0f65562 100755 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -50,6 +50,7 @@ frame-system-benchmarking = { version = "4.0.0-dev", default-features = false, g # Local Dependencies pallet-template = { version = "4.0.0-dev", default-features = false, path = "../pallets/template" } pallet_zkp_verify = { version = "4.0.0-dev", default-features = false, path = "../pallets/zkp_verify" } +pallet-reward = { version = "4.0.0-dev", default-features = false, path = "../pallets/reward" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", git = "https://github.com/paritytech/substrate.git", optional = true , branch = "polkadot-v1.0.0" } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 01208c5..aebcae8 100755 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -52,6 +52,9 @@ pub use pallet_template; /// Import the ZKP verifier pallet. pub use pallet_zkp_verify; +/// Import the reward pallet. +pub use pallet_reward; + /// An index to a block. pub type BlockNumber = u32; @@ -283,6 +286,12 @@ impl pallet_zkp_verify::Config for Runtime { type WeightInfo = pallet_zkp_verify::weights::SubstrateWeight; } +/// Configure the pallet-reward in pallets/reward.. +impl pallet_reward::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_reward::weights::SubstrateWeight; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub struct Runtime { @@ -296,6 +305,7 @@ construct_runtime!( // Include the custom logic from the pallet-template in the runtime. TemplateModule: pallet_template, ZKPVerifyModule: pallet_zkp_verify, + RewardModule: pallet_reward, } ); @@ -345,6 +355,7 @@ mod benches { [pallet_sudo, Sudo] [pallet_template, TemplateModule] [pallet_zkp_verify, ZKPVerifyModule] + [pallet_reward, RewardModule] ); } diff --git a/zokrates_prover/.gitignore b/zokrates_prover/.gitignore new file mode 100644 index 0000000..c426c32 --- /dev/null +++ b/zokrates_prover/.gitignore @@ -0,0 +1,36 @@ +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/ecc/babyjubjubParams.zok b/zokrates_prover/.zokrates/stdlib/ecc/babyjubjubParams.zok new file mode 100644 index 0000000..6718b83 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/ecc/babyjubjubParams.zok @@ -0,0 +1,37 @@ +#pragma curve bn128 + +// Parameters are based on: https://github.com/HarryR/ethsnarks/tree/9cdf0117c2e42c691e75b98979cb29b099eca998/src/jubjub +// Note: parameters will be updated soon to be more compatible with zCash's implementation + +struct BabyJubJubParams { + field JUBJUB_C; + field JUBJUB_A; + field JUBJUB_D; + field MONT_A; + field MONT_B; + field[2] INFINITY; + field Gu; + field Gv; +} + +const BabyJubJubParams BABYJUBJUB_PARAMS = BabyJubJubParams { + // Order of the curve for reference: 21888242871839275222246405745257275088614511777268538073601725287587578984328 + JUBJUB_C: 8, // Cofactor + JUBJUB_A: 168700, // Coefficient A + JUBJUB_D: 168696, // Coefficient D + + // Montgomery parameters + MONT_A: 168698, + MONT_B: 1, + + // Point at infinity + INFINITY: [0, 1], + + // Generator + Gu: 16540640123574156134436876038791482806971768689494387082833631921987005038935, + Gv: 20819045374670962167435360035096875258406992893633759881276124905556507972311 +}; + +def main() -> BabyJubJubParams { + return BABYJUBJUB_PARAMS; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/ecc/edwardsAdd.zok b/zokrates_prover/.zokrates/stdlib/ecc/edwardsAdd.zok new file mode 100644 index 0000000..843f6f9 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/ecc/edwardsAdd.zok @@ -0,0 +1,20 @@ +from "ecc/babyjubjubParams" import BabyJubJubParams; + +// Add two points on a twisted Edwards curve +// Curve parameters are defined with the last argument +// https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Addition_on_twisted_Edwards_curves +def main(field[2] pt1, field[2] pt2, BabyJubJubParams context) -> field[2] { + + field a = context.JUBJUB_A; + field d = context.JUBJUB_D; + + field u1 = pt1[0]; + field v1 = pt1[1]; + field u2 = pt2[0]; + field v2 = pt2[1]; + + field uOut = (u1*v2 + v1*u2) / (1 + d*u1*u2*v1*v2); + field vOut = (v1*v2 - a*u1*u2) / (1 - d*u1*u2*v1*v2); + + return [uOut, vOut]; +} diff --git a/zokrates_prover/.zokrates/stdlib/ecc/edwardsCompress.zok b/zokrates_prover/.zokrates/stdlib/ecc/edwardsCompress.zok new file mode 100644 index 0000000..1959f57 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/ecc/edwardsCompress.zok @@ -0,0 +1,21 @@ +import "utils/pack/bool/nonStrictUnpack256" as unpack256; + +// Compress JubJub Curve Point to 256bit array using big endianness bit order +// Python reference code from pycrypto: +// def compress(self): +// x = self.x.n +// y = self.y.n +// return int.to_bytes(y | ((x & 1) << 255), 32, "big") + +def main(field[2] pt) -> bool[256] { + field x = pt[0]; + field y = pt[1]; + + bool[256] xBits = unpack256(x); + bool[256] mut yBits = unpack256(y); + + bool sign = xBits[255]; + yBits[0] = sign; + + return yBits; +} diff --git a/zokrates_prover/.zokrates/stdlib/ecc/edwardsNegate.zok b/zokrates_prover/.zokrates/stdlib/ecc/edwardsNegate.zok new file mode 100644 index 0000000..62fcd1e --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/ecc/edwardsNegate.zok @@ -0,0 +1,9 @@ +// Negate a point on an Edwards curve +// Curve parameters are defined with the last argument +// Twisted Edwards Curves, BBJLP-2008, section 2 pg 2 +def main(field[2] pt) -> field[2] { + field u = pt[0]; + field v = pt[1]; + + return [-u, v]; +} diff --git a/zokrates_prover/.zokrates/stdlib/ecc/edwardsOnCurve.zok b/zokrates_prover/.zokrates/stdlib/ecc/edwardsOnCurve.zok new file mode 100644 index 0000000..d2d8240 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/ecc/edwardsOnCurve.zok @@ -0,0 +1,17 @@ +from "ecc/babyjubjubParams" import BabyJubJubParams; + +// Check if a point is on a twisted Edwards curve +// Curve parameters are defined with the last argument +// See appendix 3.3.1 of Zcash protocol specification: +// https://github.com/zcash/zips/blob/master/protocol/protocol.pdf +def main(field[2] pt, BabyJubJubParams context) -> bool { + field a = context.JUBJUB_A; + field d = context.JUBJUB_D; + + field uu = pt[0] * pt[0]; + field vv = pt[1] * pt[1]; + field uuvv = uu * vv; + + assert(a * uu + vv == 1 + d * uuvv); + return true; +} diff --git a/zokrates_prover/.zokrates/stdlib/ecc/edwardsOrderCheck.zok b/zokrates_prover/.zokrates/stdlib/ecc/edwardsOrderCheck.zok new file mode 100644 index 0000000..c691312 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/ecc/edwardsOrderCheck.zok @@ -0,0 +1,26 @@ +import "ecc/edwardsAdd" as add; +import "ecc/edwardsScalarMult" as multiply; +import "utils/pack/bool/nonStrictUnpack256" as unpack256; +from "ecc/babyjubjubParams" import BabyJubJubParams; + +// Verifies that the point is not one of the low-order points. +// If any of the points is multiplied by the cofactor, the resulting point +// will be infinity. +// Returns true if the point is not one of the low-order points, false otherwise. +// Curve parameters are defined with the last argument +// https://github.com/zcash-hackworks/sapling-crypto/blob/master/src/jubjub/edwards.rs#L166 +def main(field[2] pt, BabyJubJubParams context) -> bool { + field cofactor = context.JUBJUB_C; + assert(cofactor == 8); + + // Co-factor currently hard-coded to 8 for efficiency reasons + // See discussion here: https://github.com/Zokrates/ZoKrates/pull/301#discussion_r267203391 + // Generic code: + // bool[256] cofactorExponent = unpack256(cofactor); + // field[2] ptExp = multiply(cofactorExponent, pt, context); + field[2] mut ptExp = add(pt, pt, context); // 2*pt + ptExp = add(ptExp, ptExp, context); // 4*pt + ptExp = add(ptExp, ptExp, context); // 8*pt + + return !(ptExp[0] == 0 && ptExp[1] == 1); +} diff --git a/zokrates_prover/.zokrates/stdlib/ecc/edwardsScalarMult.zok b/zokrates_prover/.zokrates/stdlib/ecc/edwardsScalarMult.zok new file mode 100644 index 0000000..1d7dec6 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/ecc/edwardsScalarMult.zok @@ -0,0 +1,26 @@ +import "ecc/edwardsAdd" as add; +import "ecc/edwardsOnCurve" as onCurve; +from "ecc/babyjubjubParams" import BabyJubJubParams; + +// Function that implements scalar multiplication for a fixed base point +// Curve parameters are defined with the last argument +// The exponent is hard-coded to a 256bit scalar, hence we allow wrapping around the group for certain +// curve parameters. +// Note that the exponent array is not check to be boolean in this gadget +// Reference: https://github.com/zcash-hackworks/sapling-crypto/blob/master/src/jubjub/fs.rs#L555 +def main(bool[256] exponent, field[2] pt, BabyJubJubParams context) -> field[2] { + field[2] infinity = context.INFINITY; + + field[2] mut doubledP = pt; + field[2] mut accumulatedP = infinity; + + for u32 i in 0..256 { + u32 j = 255 - i; + field[2] candidateP = add(accumulatedP, doubledP, context); + accumulatedP = exponent[j] ? candidateP : accumulatedP; + doubledP = add(doubledP, doubledP, context); + } + + assert(onCurve(accumulatedP, context)); + return accumulatedP; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/ecc/proofOfOwnership.zok b/zokrates_prover/.zokrates/stdlib/ecc/proofOfOwnership.zok new file mode 100644 index 0000000..8404573 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/ecc/proofOfOwnership.zok @@ -0,0 +1,28 @@ +import "ecc/edwardsAdd" as add; +import "ecc/edwardsScalarMult" as multiply; +import "utils/pack/bool/nonStrictUnpack256" as unpack256; +from "ecc/babyjubjubParams" import BabyJubJubParams; + +/// Verifies match of a given public/private keypair. +/// +/// Checks if the following equation holds for the provided keypair: +/// pk = sk*G +/// where G is the chosen base point of the subgroup +/// and * denotes scalar multiplication in the subgroup +/// +/// Arguments: +/// pk: Curve point. Public key. +/// sk: Field element. Private key. +/// context: Curve parameters (including generator G) used to create keypair. +/// +/// Returns: +/// Return true for pk/sk being a valid keypair, false otherwise. +def main(field[2] pk, field sk, BabyJubJubParams context) -> bool { + field[2] G = [context.Gu, context.Gv]; + + bool[256] skBits = unpack256(sk); + field[2] ptExp = multiply(skBits, G, context); + + bool out = ptExp[0] == pk[0] && ptExp[1] == pk[1]; + return out; +} diff --git a/zokrates_prover/.zokrates/stdlib/field.zok b/zokrates_prover/.zokrates/stdlib/field.zok new file mode 100644 index 0000000..6a33cce --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/field.zok @@ -0,0 +1,4 @@ +from "EMBED" import FIELD_SIZE_IN_BITS; + +const field FIELD_MIN = 0; +const field FIELD_MAX = -1; \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/blake2/blake2s.zok b/zokrates_prover/.zokrates/stdlib/hashes/blake2/blake2s.zok new file mode 100644 index 0000000..f0b301a --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/blake2/blake2s.zok @@ -0,0 +1,5 @@ +import "hashes/blake2/blake2s_p" as blake2s_p; + +def main(u32[K][16] input) -> u32[8] { + return blake2s_p(input, [0; 2]); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/blake2/blake2s_p.zok b/zokrates_prover/.zokrates/stdlib/hashes/blake2/blake2s_p.zok new file mode 100644 index 0000000..628566a --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/blake2/blake2s_p.zok @@ -0,0 +1,117 @@ +// https://tools.ietf.org/html/rfc7693 + +import "utils/casts/u32_to_bits"; +import "utils/casts/u32_from_bits"; + +// Initialization Vector, section 2.6. +const u32[8] IV = [ + 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, + 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 +]; + +// Message Schedule SIGMA, section 2.7. +const u32[10][16] SIGMA = [ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], + [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], + [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], + [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], + [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], + [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], + [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], + [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], + [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], + [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0] +]; + +// right rotation +def rotr32(u32 x) -> u32 { + return (x >> N) | (x << (32 - N)); +} + +// change endianness +def swap_u32(u32 val) -> u32 { + return (val << 24) | \ + ((val << 8) & 0x00ff0000) | \ + ((val >> 8) & 0x0000ff00) | \ + ((val >> 24) & 0x000000ff); +} + + +def mixing_g(u32[16] mut v, u32 a, u32 b, u32 c, u32 d, u32 x, u32 y) -> u32[16] { + v[a] = (v[a] + v[b] + x); + v[d] = rotr32::<16>(v[d] ^ v[a]); + v[c] = (v[c] + v[d]); + v[b] = rotr32::<12>(v[b] ^ v[c]); + v[a] = (v[a] + v[b] + y); + v[d] = rotr32::<8>(v[d] ^ v[a]); + v[c] = (v[c] + v[d]); + v[b] = rotr32::<7>(v[b] ^ v[c]); + return v; +} + +def blake2s_compression(u32[8] mut h, u32[16] m, u32[2] t, bool last) -> u32[8] { + u32[16] mut v = [...h, ...IV]; + + v[12] = v[12] ^ t[0]; + v[13] = v[13] ^ t[1]; + v[14] = last ? v[14] ^ 0xFFFFFFFF : v[14]; + + for u32 i in 0..10 { + u32[16] s = SIGMA[i]; + v = mixing_g(v, 0, 4, 8, 12, m[s[0]], m[s[1]]); + v = mixing_g(v, 1, 5, 9, 13, m[s[2]], m[s[3]]); + v = mixing_g(v, 2, 6, 10, 14, m[s[4]], m[s[5]]); + v = mixing_g(v, 3, 7, 11, 15, m[s[6]], m[s[7]]); + v = mixing_g(v, 0, 5, 10, 15, m[s[8]], m[s[9]]); + v = mixing_g(v, 1, 6, 11, 12, m[s[10]], m[s[11]]); + v = mixing_g(v, 2, 7, 8, 13, m[s[12]], m[s[13]]); + v = mixing_g(v, 3, 4, 9, 14, m[s[14]], m[s[15]]); + } + + for u32 i in 0..8 { + h[i] = h[i] ^ v[i] ^ v[i + 8]; + } + + return h; +} + +def main(u32[K][16] mut input, u32[2] p) -> u32[8] { + u32[8] mut h = [ + IV[0] ^ 0x01010000 ^ 0x00000020, + IV[1], + IV[2], + IV[3], + IV[4], + IV[5], + IV[6] ^ swap_u32(p[0]), + IV[7] ^ swap_u32(p[1]) + ]; + + u32 mut t0 = 0; + u32 mut t1 = 0; + + // change endianness of inputs from big endian to little endian + for u32 i in 0..K { + for u32 j in 0..16 { + input[i][j] = swap_u32(input[i][j]); + } + } + + for u32 i in 0..K-1 { + t0 = (i + 1) * 64; + t1 = t0 == 0 ? t1 + 1 : t1; + h = blake2s_compression(h, input[i], [t0, t1], false); + } + + t0 = t0 + 64; + t1 = t0 == 0 ? t1 + 1 : t1; + + h = blake2s_compression(h, input[K - 1], [t0, t1], true); + + // change endianness of output from little endian to big endian + for u32 i in 0..8 { + h[i] = swap_u32(h[i]); + } + + return h; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/keccak/224bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/keccak/224bit.zok new file mode 100644 index 0000000..0b0df96 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/keccak/224bit.zok @@ -0,0 +1,5 @@ +from "hashes/keccak/keccak" import main as keccak; + +def main(u8[N] input) -> u8[28] { + return keccak::<_, 28>(input, 0x01); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/keccak/256bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/keccak/256bit.zok new file mode 100644 index 0000000..9e8dfc4 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/keccak/256bit.zok @@ -0,0 +1,5 @@ +from "hashes/keccak/keccak" import main as keccak; + +def main(u8[N] input) -> u8[32] { + return keccak::<_, 32>(input, 0x01); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/keccak/384bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/keccak/384bit.zok new file mode 100644 index 0000000..0f67677 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/keccak/384bit.zok @@ -0,0 +1,5 @@ +from "hashes/keccak/keccak" import main as keccak; + +def main(u8[N] input) -> u8[48] { + return keccak::<_, 48>(input, 0x01); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/keccak/512bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/keccak/512bit.zok new file mode 100644 index 0000000..1d47563 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/keccak/512bit.zok @@ -0,0 +1,5 @@ +from "hashes/keccak/keccak" import main as keccak; + +def main(u8[N] input) -> u8[64] { + return keccak::<_, 64>(input, 0x01); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/keccak/keccak.zok b/zokrates_prover/.zokrates/stdlib/hashes/keccak/keccak.zok new file mode 100644 index 0000000..08dca6c --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/keccak/keccak.zok @@ -0,0 +1,161 @@ +// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf +// based on keccak-f[1600] permutation + +import "utils/casts/u8_to_bits"; +import "utils/casts/u8_from_bits"; +import "utils/casts/u64_to_bits"; +import "utils/casts/u64_from_bits"; + +const u32[24] RHO = [ + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 +]; + +const u32[24] PI = [ + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 +]; + +const u64[24] RC = [ + 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, + 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, + 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, + 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, + 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, + 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, + 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, + 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 +]; + +// left rotation +def rotl64(u64 x, u32 n) -> u64 { + return ((x << n) | (x >> (64 - n))); +} + +// change endianness +def swap_u64(u64 mut val) -> u64 { + val = ((val << 8) & 0xFF00FF00FF00FF00) | ((val >> 8) & 0x00FF00FF00FF00FF); + val = ((val << 16) & 0xFFFF0000FFFF0000) | ((val >> 16) & 0x0000FFFF0000FFFF); + return (val << 32) | (val >> 32); +} + +// compression function +def keccakf(u64[25] mut st) -> u64[25] { + u64[5] mut bc = [0; 5]; + u64 mut t = 0; + + for u32 i in 0..25 { + st[i] = swap_u64(st[i]); + } + + for u32 r in 0..24 { + // theta + for u32 i in 0..5 { + bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]; + } + + for u32 i in 0..5 { + t = bc[(i + 4) % 5] ^ rotl64(bc[(i + 1) % 5], 1); + for u32 j in 0..5 { + st[(j * 5) + i] = st[(j * 5) + i] ^ t; + } + } + + t = st[1]; + + // rho pi + for u32 i in 0..24 { + u32 j = PI[i]; + bc[0] = st[j]; + st[j] = rotl64(t, RHO[i]); + t = bc[0]; + } + + // chi + for u32 i in 0..5 { + for u32 j in 0..5 { + bc[j] = st[(i * 5) + j]; + } + for u32 j in 0..5 { + u32 p = (i * 5) + j; + st[p] = st[p] ^ (!bc[(j + 1) % 5] & bc[(j + 2) % 5]); + } + } + + // iota + st[0] = st[0] ^ RC[r]; + } + + for u32 i in 0..25 { + st[i] = swap_u64(st[i]); + } + + return st; +} + +def u64_from_u8_array(u8[8] input) -> u64 { + bool[64] bits = [ + ...u8_to_bits(input[0]), + ...u8_to_bits(input[1]), + ...u8_to_bits(input[2]), + ...u8_to_bits(input[3]), + ...u8_to_bits(input[4]), + ...u8_to_bits(input[5]), + ...u8_to_bits(input[6]), + ...u8_to_bits(input[7]) + ]; + return u64_from_bits(bits); +} + +def u64_to_u8_array(u64 input) -> u8[8] { + bool[64] bits = u64_to_bits(input); + return [ + u8_from_bits(bits[0..8]), + u8_from_bits(bits[8..16]), + u8_from_bits(bits[16..24]), + u8_from_bits(bits[24..32]), + u8_from_bits(bits[32..40]), + u8_from_bits(bits[40..48]), + u8_from_bits(bits[48..56]), + u8_from_bits(bits[56..64]) + ]; +} + +def to_bytes(u64[25] input) -> u8[200] { + u8[200] mut output = [0; 200]; + for u32 i in 0..25 { + u8[8] t = u64_to_u8_array(input[i]); + for u32 j in 0..8 { + output[i * 8 + j] = t[j]; + } + } + return output; +} + +def from_bytes(u8[200] input) -> u64[25] { + u64[25] mut output = [0; 25]; + for u32 i in 0..25 { + output[i] = u64_from_u8_array(input[i*8..i*8+8]); + } + return output; +} + +def main(u8[N] mut input, u8 delim) -> u8[W] { + u8[200] mut b = [0; 200]; + u32 rate = 200 - (2 * W); + u32 mut pt = 0; + + // update + for u32 i in 0..N { + b[pt] = b[pt] ^ input[i]; + pt = (pt + 1) % rate; + b = pt == 0 ? to_bytes(keccakf(from_bytes(b))) : b; + } + + // finalize + b[pt] = b[pt] ^ delim; + b[rate - 1] = b[rate - 1] ^ 0x80; + b = to_bytes(keccakf(from_bytes(b))); + + return b[..W]; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/mimc7/mimc7.zok b/zokrates_prover/.zokrates/stdlib/hashes/mimc7/mimc7.zok new file mode 100644 index 0000000..f9ea589 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/mimc7/mimc7.zok @@ -0,0 +1,112 @@ +const field[91] C = [ + 0, + 20888961410941983456478427210666206549300505294776164667214940546594746570981, + 15265126113435022738560151911929040668591755459209400716467504685752745317193, + 8334177627492981984476504167502758309043212251641796197711684499645635709656, + 1374324219480165500871639364801692115397519265181803854177629327624133579404, + 11442588683664344394633565859260176446561886575962616332903193988751292992472, + 2558901189096558760448896669327086721003508630712968559048179091037845349145, + 11189978595292752354820141775598510151189959177917284797737745690127318076389, + 3262966573163560839685415914157855077211340576201936620532175028036746741754, + 17029914891543225301403832095880481731551830725367286980611178737703889171730, + 4614037031668406927330683909387957156531244689520944789503628527855167665518, + 19647356996769918391113967168615123299113119185942498194367262335168397100658, + 5040699236106090655289931820723926657076483236860546282406111821875672148900, + 2632385916954580941368956176626336146806721642583847728103570779270161510514, + 17691411851977575435597871505860208507285462834710151833948561098560743654671, + 11482807709115676646560379017491661435505951727793345550942389701970904563183, + 8360838254132998143349158726141014535383109403565779450210746881879715734773, + 12663821244032248511491386323242575231591777785787269938928497649288048289525, + 3067001377342968891237590775929219083706800062321980129409398033259904188058, + 8536471869378957766675292398190944925664113548202769136103887479787957959589, + 19825444354178182240559170937204690272111734703605805530888940813160705385792, + 16703465144013840124940690347975638755097486902749048533167980887413919317592, + 13061236261277650370863439564453267964462486225679643020432589226741411380501, + 10864774797625152707517901967943775867717907803542223029967000416969007792571, + 10035653564014594269791753415727486340557376923045841607746250017541686319774, + 3446968588058668564420958894889124905706353937375068998436129414772610003289, + 4653317306466493184743870159523234588955994456998076243468148492375236846006, + 8486711143589723036499933521576871883500223198263343024003617825616410932026, + 250710584458582618659378487568129931785810765264752039738223488321597070280, + 2104159799604932521291371026105311735948154964200596636974609406977292675173, + 16313562605837709339799839901240652934758303521543693857533755376563489378839, + 6032365105133504724925793806318578936233045029919447519826248813478479197288, + 14025118133847866722315446277964222215118620050302054655768867040006542798474, + 7400123822125662712777833064081316757896757785777291653271747396958201309118, + 1744432620323851751204287974553233986555641872755053103823939564833813704825, + 8316378125659383262515151597439205374263247719876250938893842106722210729522, + 6739722627047123650704294650168547689199576889424317598327664349670094847386, + 21211457866117465531949733809706514799713333930924902519246949506964470524162, + 13718112532745211817410303291774369209520657938741992779396229864894885156527, + 5264534817993325015357427094323255342713527811596856940387954546330728068658, + 18884137497114307927425084003812022333609937761793387700010402412840002189451, + 5148596049900083984813839872929010525572543381981952060869301611018636120248, + 19799686398774806587970184652860783461860993790013219899147141137827718662674, + 19240878651604412704364448729659032944342952609050243268894572835672205984837, + 10546185249390392695582524554167530669949955276893453512788278945742408153192, + 5507959600969845538113649209272736011390582494851145043668969080335346810411, + 18177751737739153338153217698774510185696788019377850245260475034576050820091, + 19603444733183990109492724100282114612026332366576932662794133334264283907557, + 10548274686824425401349248282213580046351514091431715597441736281987273193140, + 1823201861560942974198127384034483127920205835821334101215923769688644479957, + 11867589662193422187545516240823411225342068709600734253659804646934346124945, + 18718569356736340558616379408444812528964066420519677106145092918482774343613, + 10530777752259630125564678480897857853807637120039176813174150229243735996839, + 20486583726592018813337145844457018474256372770211860618687961310422228379031, + 12690713110714036569415168795200156516217175005650145422920562694422306200486, + 17386427286863519095301372413760745749282643730629659997153085139065756667205, + 2216432659854733047132347621569505613620980842043977268828076165669557467682, + 6309765381643925252238633914530877025934201680691496500372265330505506717193, + 20806323192073945401862788605803131761175139076694468214027227878952047793390, + 4037040458505567977365391535756875199663510397600316887746139396052445718861, + 19948974083684238245321361840704327952464170097132407924861169241740046562673, + 845322671528508199439318170916419179535949348988022948153107378280175750024, + 16222384601744433420585982239113457177459602187868460608565289920306145389382, + 10232118865851112229330353999139005145127746617219324244541194256766741433339, + 6699067738555349409504843460654299019000594109597429103342076743347235369120, + 6220784880752427143725783746407285094967584864656399181815603544365010379208, + 6129250029437675212264306655559561251995722990149771051304736001195288083309, + 10773245783118750721454994239248013870822765715268323522295722350908043393604, + 4490242021765793917495398271905043433053432245571325177153467194570741607167, + 19596995117319480189066041930051006586888908165330319666010398892494684778526, + 837850695495734270707668553360118467905109360511302468085569220634750561083, + 11803922811376367215191737026157445294481406304781326649717082177394185903907, + 10201298324909697255105265958780781450978049256931478989759448189112393506592, + 13564695482314888817576351063608519127702411536552857463682060761575100923924, + 9262808208636973454201420823766139682381973240743541030659775288508921362724, + 173271062536305557219323722062711383294158572562695717740068656098441040230, + 18120430890549410286417591505529104700901943324772175772035648111937818237369, + 20484495168135072493552514219686101965206843697794133766912991150184337935627, + 19155651295705203459475805213866664350848604323501251939850063308319753686505, + 11971299749478202793661982361798418342615500543489781306376058267926437157297, + 18285310723116790056148596536349375622245669010373674803854111592441823052978, + 7069216248902547653615508023941692395371990416048967468982099270925308100727, + 6465151453746412132599596984628739550147379072443683076388208843341824127379, + 16143532858389170960690347742477978826830511669766530042104134302796355145785, + 19362583304414853660976404410208489566967618125972377176980367224623492419647, + 1702213613534733786921602839210290505213503664731919006932367875629005980493, + 10781825404476535814285389902565833897646945212027592373510689209734812292327, + 4212716923652881254737947578600828255798948993302968210248673545442808456151, + 7594017890037021425366623750593200398174488805473151513558919864633711506220, + 18979889247746272055963929241596362599320706910852082477600815822482192194401, + 13602139229813231349386885113156901793661719180900395818909719758150455500533 +]; + +def main(field x_in, field k) -> field { + field mut t = 0; + field[R] mut t2 = [0; R]; + field[R] mut t4 = [0; R]; + field[R] mut t6 = [0; R]; + field[R] mut t7 = [0; R]; // we define t7 length +1 to avoid conditional branching + + for u32 i in 0..R { + u32 i2 = i == 0 ? 0 : i - 1; + t = i == 0 ? k + x_in : k + t7[i2] + C[i]; + t2[i] = t * t; + t4[i] = t2[i] * t2[i]; + t6[i] = t4[i] * t2[i]; + t7[i] = t6[i] * t; + } + + return t6[R - 1] * t + k; +} diff --git a/zokrates_prover/.zokrates/stdlib/hashes/mimcSponge/mimcFeistel.zok b/zokrates_prover/.zokrates/stdlib/hashes/mimcSponge/mimcFeistel.zok new file mode 100644 index 0000000..f887ce7 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/mimcSponge/mimcFeistel.zok @@ -0,0 +1,250 @@ +// MiMCFeistel configured with 220 rounds + +const u32 R = 220; +const field[R] IV = [ + 0, + 7120861356467848435263064379192047478074060781135320967663101236819528304084, + 5024705281721889198577876690145313457398658950011302225525409148828000436681, + 17980351014018068290387269214713820287804403312720763401943303895585469787384, + 19886576439381707240399940949310933992335779767309383709787331470398675714258, + 1213715278223786725806155661738676903520350859678319590331207960381534602599, + 18162138253399958831050545255414688239130588254891200470934232514682584734511, + 7667462281466170157858259197976388676420847047604921256361474169980037581876, + 7207551498477838452286210989212982851118089401128156132319807392460388436957, + 9864183311657946807255900203841777810810224615118629957816193727554621093838, + 4798196928559910300796064665904583125427459076060519468052008159779219347957, + 17387238494588145257484818061490088963673275521250153686214197573695921400950, + 10005334761930299057035055370088813230849810566234116771751925093634136574742, + 11897542014760736209670863723231849628230383119798486487899539017466261308762, + 16771780563523793011283273687253985566177232886900511371656074413362142152543, + 749264854018824809464168489785113337925400687349357088413132714480582918506, + 3683645737503705042628598550438395339383572464204988015434959428676652575331, + 7556750851783822914673316211129907782679509728346361368978891584375551186255, + 20391289379084797414557439284689954098721219201171527383291525676334308303023, + 18146517657445423462330854383025300323335289319277199154920964274562014376193, + 8080173465267536232534446836148661251987053305394647905212781979099916615292, + 10796443006899450245502071131975731672911747129805343722228413358507805531141, + 5404287610364961067658660283245291234008692303120470305032076412056764726509, + 4623894483395123520243967718315330178025957095502546813929290333264120223168, + 16845753148201777192406958674202574751725237939980634861948953189320362207797, + 4622170486584704769521001011395820886029808520586507873417553166762370293671, + 16688277490485052681847773549197928630624828392248424077804829676011512392564, + 11878652861183667748838188993669912629573713271883125458838494308957689090959, + 2436445725746972287496138382764643208791713986676129260589667864467010129482, + 1888098689545151571063267806606510032698677328923740058080630641742325067877, + 148924106504065664829055598316821983869409581623245780505601526786791681102, + 18875020877782404439294079398043479420415331640996249745272087358069018086569, + 15189693413320228845990326214136820307649565437237093707846682797649429515840, + 19669450123472657781282985229369348220906547335081730205028099210442632534079, + 5521922218264623411380547905210139511350706092570900075727555783240701821773, + 4144769320246558352780591737261172907511489963810975650573703217887429086546, + 10097732913112662248360143041019433907849917041759137293018029019134392559350, + 1720059427972723034107765345743336447947522473310069975142483982753181038321, + 6302388219880227251325608388535181451187131054211388356563634768253301290116, + 6745410632962119604799318394592010194450845483518862700079921360015766217097, + 10858157235265583624235850660462324469799552996870780238992046963007491306222, + 20241898894740093733047052816576694435372877719072347814065227797906130857593, + 10165780782761211520836029617746977303303335603838343292431760011576528327409, + 2832093654883670345969792724123161241696170611611744759675180839473215203706, + 153011722355526826233082383360057587249818749719433916258246100068258954737, + 20196970640587451358539129330170636295243141659030208529338914906436009086943, + 3180973917010545328313139835982464870638521890385603025657430208141494469656, + 17198004293191777441573635123110935015228014028618868252989374962722329283022, + 7642160509228669138628515458941659189680509753651629476399516332224325757132, + 19346204940546791021518535594447257347218878114049998691060016493806845179755, + 11501810868606870391127866188394535330696206817602260610801897042898616817272, + 3113973447392053821824427670386252797811804954746053461397972968381571297505, + 6545064306297957002139416752334741502722251869537551068239642131448768236585, + 5203908808704813498389265425172875593837960384349653691918590736979872578408, + 2246692432011290582160062129070762007374502637007107318105405626910313810224, + 11760570435432189127645691249600821064883781677693087773459065574359292849137, + 5543749482491340532547407723464609328207990784853381797689466144924198391839, + 8837549193990558762776520822018694066937602576881497343584903902880277769302, + 12855514863299373699594410385788943772765811961581749194183533625311486462501, + 5363660674689121676875069134269386492382220935599781121306637800261912519729, + 13162342403579303950549728848130828093497701266240457479693991108217307949435, + 916941639326869583414469202910306428966657806899788970948781207501251816730, + 15618589556584434434009868216186115416835494805174158488636000580759692174228, + 8959562060028569701043973060670353733575345393653685776974948916988033453971, + 16390754464333401712265575949874369157699293840516802426621216808905079127650, + 168282396747788514908709091757591226095443902501365500003618183905496160435, + 8327443473179334761744301768309008451162322941906921742120510244986704677004, + 17213012626801210615058753489149961717422101711567228037597150941152495100640, + 10394369641533736715250242399198097296122982486516256408681925424076248952280, + 17784386835392322654196171115293700800825771210400152504776806618892170162248, + 16533189939837087893364000390641148516479148564190420358849587959161226782982, + 18725396114211370207078434315900726338547621160475533496863298091023511945076, + 7132325028834551397904855671244375895110341505383911719294705267624034122405, + 148317947440800089795933930720822493695520852448386394775371401743494965187, + 19001050671757720352890779127693793630251266879994702723636759889378387053056, + 18824274411769830274877839365728651108434404855803844568234862945613766611460, + 12771414330193951156383998390424063470766226667986423961689712557338777174205, + 11332046574800279729678603488745295198038913503395629790213378101166488244657, + 9607550223176946388146938069307456967842408600269548190739947540821716354749, + 8756385288462344550200229174435953103162307705310807828651304665320046782583, + 176061952957067086877570020242717222844908281373122372938833890096257042779, + 12200212977482648306758992405065921724409841940671166017620928947866825250857, + 10868453624107875516866146499877130701929063632959660262366632833504750028858, + 2016095394399807253596787752134573207202567875457560571095586743878953450738, + 21815578223768330433802113452339488275704145896544481092014911825656390567514, + 4923772847693564777744725640710197015181591950368494148029046443433103381621, + 1813584943682214789802230765734821149202472893379265320098816901270224589984, + 10810123816265612772922113403831964815724109728287572256602010709288980656498, + 1153669123397255702524721206511185557982017410156956216465120456256288427021, + 5007518659266430200134478928344522649876467369278722765097865662497773767152, + 2511432546938591792036639990606464315121646668029252285288323664350666551637, + 32883284540320451295484135704808083452381176816565850047310272290579727564, + 10484856914279112612610993418405543310546746652738541161791501150994088679557, + 2026733759645519472558796412979210009170379159866522399881566309631434814953, + 14731806221235869882801331463708736361296174006732553130708107037190460654379, + 14740327483193277147065845135561988641238516852487657117813536909482068950652, + 18787428285295558781869865751953016580493190547148386433580291216673009884554, + 3804047064713122820157099453648459188816376755739202017447862327783289895072, + 16709604795697901641948603019242067672006293290826991671766611326262532802914, + 11061717085931490100602849654034280576915102867237101935487893025907907250695, + 2821730726367472966906149684046356272806484545281639696873240305052362149654, + 17467794879902895769410571945152708684493991588672014763135370927880883292655, + 1571520786233540988201616650622796363168031165456869481368085474420849243232, + 10041051776251223165849354194892664881051125330236567356945669006147134614302, + 3981753758468103976812813304477670033098707002886030847251581853700311567551, + 4365864398105436789177703571412645548020537580493599380018290523813331678900, + 2391801327305361293476178683853802679507598622000359948432171562543560193350, + 214219368547551689972421167733597094823289857206402800635962137077096090722, + 18192064100315141084242006659317257023098826945893371479835220462302399655674, + 15487549757142039139328911515400805508248576685795694919457041092150651939253, + 10142447197759703415402259672441315777933858467700579946665223821199077641122, + 11246573086260753259993971254725613211193686683988426513880826148090811891866, + 6574066859860991369704567902211886840188702386542112593710271426704432301235, + 11311085442652291634822798307831431035776248927202286895207125867542470350078, + 20977948360215259915441258687649465618185769343138135384346964466965010873779, + 792781492853909872425531014397300057232399608769451037135936617996830018501, + 5027602491523497423798779154966735896562099398367163998686335127580757861872, + 14595204575654316237672764823862241845410365278802914304953002937313300553572, + 13973538843621261113924259058427434053808430378163734641175100160836376897004, + 16395063164993626722686882727042150241125309409717445381854913964674649318585, + 8465768840047024550750516678171433288207841931251654898809033371655109266663, + 21345603324471810861925019445720576814602636473739003852898308205213912255830, + 21171984405852590343970239018692870799717057961108910523876770029017785940991, + 10761027113757988230637066281488532903174559953630210849190212601991063767647, + 6678298831065390834922566306988418588227382406175769592902974103663687992230, + 4993662582188632374202316265508850988596880036291765531885657575099537176757, + 18364168158495573675698600238443218434246806358811328083953887470513967121206, + 3506345610354615013737144848471391553141006285964325596214723571988011984829, + 248732676202643792226973868626360612151424823368345645514532870586234380100, + 10090204501612803176317709245679152331057882187411777688746797044706063410969, + 21297149835078365363970699581821844234354988617890041296044775371855432973500, + 16729368143229828574342820060716366330476985824952922184463387490091156065099, + 4467191506765339364971058668792642195242197133011672559453028147641428433293, + 8677548159358013363291014307402600830078662555833653517843708051504582990832, + 1022951765127126818581466247360193856197472064872288389992480993218645055345, + 1888195070251580606973417065636430294417895423429240431595054184472931224452, + 4221265384902749246920810956363310125115516771964522748896154428740238579824, + 2825393571154632139467378429077438870179957021959813965940638905853993971879, + 19171031072692942278056619599721228021635671304612437350119663236604712493093, + 10780807212297131186617505517708903709488273075252405602261683478333331220733, + 18230936781133176044598070768084230333433368654744509969087239465125979720995, + 16901065971871379877929280081392692752968612240624985552337779093292740763381, + 146494141603558321291767829522948454429758543710648402457451799015963102253, + 2492729278659146790410698334997955258248120870028541691998279257260289595548, + 2204224910006646535594933495262085193210692406133533679934843341237521233504, + 16062117410185840274616925297332331018523844434907012275592638570193234893570, + 5894928453677122829055071981254202951712129328678534592916926069506935491729, + 4947482739415078212217504789923078546034438919537985740403824517728200332286, + 16143265650645676880461646123844627780378251900510645261875867423498913438066, + 397690828254561723549349897112473766901585444153303054845160673059519614409, + 11272653598912269895509621181205395118899451234151664604248382803490621227687, + 15566927854306879444693061574322104423426072650522411176731130806720753591030, + 14222898219492484180162096141564251903058269177856173968147960855133048449557, + 16690275395485630428127725067513114066329712673106153451801968992299636791385, + 3667030990325966886479548860429670833692690972701471494757671819017808678584, + 21280039024501430842616328642522421302481259067470872421086939673482530783142, + 15895485136902450169492923978042129726601461603404514670348703312850236146328, + 7733050956302327984762132317027414325566202380840692458138724610131603812560, + 438123800976401478772659663183448617575635636575786782566035096946820525816, + 814913922521637742587885320797606426167962526342166512693085292151314976633, + 12368712287081330853637674140264759478736012797026621876924395982504369598764, + 2494806857395134874309386694756263421445039103814920780777601708371037591569, + 16101132301514338989512946061786320637179843435886825102406248183507106312877, + 6252650284989960032925831409804233477770646333900692286731621844532438095656, + 9277135875276787021836189566799935097400042171346561246305113339462708861695, + 10493603554686607050979497281838644324893776154179810893893660722522945589063, + 8673089750662709235894359384294076697329948991010184356091130382437645649279, + 9558393272910366944245875920138649617479779893610128634419086981339060613250, + 19012287860122586147374214541764572282814469237161122489573881644994964647218, + 9783723818270121678386992630754842961728702994964214799008457449989291229500, + 15550788416669474113213749561488122552422887538676036667630838378023479382689, + 15016165746156232864069722572047169071786333815661109750860165034341572904221, + 6506225705710197163670556961299945987488979904603689017479840649664564978574, + 10796631184889302076168355684722130903785890709107732067446714470783437829037, + 19871836214837460419845806980869387567383718044439891735114283113359312279540, + 20871081766843466343749609089986071784031203517506781251203251608363835140622, + 5100105771517691442278432864090229416166996183792075307747582375962855820797, + 8777887112076272395250620301071581171386440850451972412060638225741125310886, + 5300440870136391278944213332144327695659161151625757537632832724102670898756, + 1205448543652932944633962232545707633928124666868453915721030884663332604536, + 5542499997310181530432302492142574333860449305424174466698068685590909336771, + 11028094245762332275225364962905938096659249161369092798505554939952525894293, + 19187314764836593118404597958543112407224947638377479622725713735224279297009, + 17047263688548829001253658727764731047114098556534482052135734487985276987385, + 19914849528178967155534624144358541535306360577227460456855821557421213606310, + 2929658084700714257515872921366736697080475676508114973627124569375444665664, + 15092262360719700162343163278648422751610766427236295023221516498310468956361, + 21578580340755653236050830649990190843552802306886938815497471545814130084980, + 1258781501221760320019859066036073675029057285507345332959539295621677296991, + 3819598418157732134449049289585680301176983019643974929528867686268702720163, + 8653175945487997845203439345797943132543211416447757110963967501177317426221, + 6614652990340435611114076169697104582524566019034036680161902142028967568142, + 19212515502973904821995111796203064175854996071497099383090983975618035391558, + 18664315914479294273286016871365663486061896605232511201418576829062292269769, + 11498264615058604317482574216318586415670903094838791165247179252175768794889, + 10814026414212439999107945133852431304483604215416531759535467355316227331774, + 17566185590731088197064706533119299946752127014428399631467913813769853431107, + 14016139747289624978792446847000951708158212463304817001882956166752906714332, + 8242601581342441750402731523736202888792436665415852106196418942315563860366, + 9244680976345080074252591214216060854998619670381671198295645618515047080988, + 12216779172735125538689875667307129262237123728082657485828359100719208190116, + 10702811721859145441471328511968332847175733707711670171718794132331147396634, + 6479667912792222539919362076122453947926362746906450079329453150607427372979, + 15117544653571553820496948522381772148324367479772362833334593000535648316185, + 6842203153996907264167856337497139692895299874139131328642472698663046726780, + 12732823292801537626009139514048596316076834307941224506504666470961250728055, + 6936272626871035740815028148058841877090860312517423346335878088297448888663, + 17297554111853491139852678417579991271009602631577069694853813331124433680030, + 16641596134749940573104316021365063031319260205559553673368334842484345864859, + 7400481189785154329569470986896455371037813715804007747228648863919991399081, + 2273205422216987330510475127669563545720586464429614439716564154166712854048, + 15162538063742142685306302282127534305212832649282186184583465569986719234456, + 5628039096440332922248578319648483863204530861778160259559031331287721255522, + 16085392195894691829567913404182676871326863890140775376809129785155092531260, + 14227467863135365427954093998621993651369686288941275436795622973781503444257, + 18224457394066545825553407391290108485121649197258948320896164404518684305122, + 274945154732293792784580363548970818611304339008964723447672490026510689427, + 11050822248291117548220126630860474473945266276626263036056336623671308219529, + 2119542016932434047340813757208803962484943912710204325088879681995922344971, + 0 +]; + +def main(field xL_in, field xR_in, field k) -> field[2] { + field[R] mut t2 = [0; R]; + field[R] mut t4 = [0; R]; + field[R] mut xL = [0; R]; + field[R] mut xR = [0; R]; + + field mut t = 0; + field mut c = 0; + + for u32 i in 0..R { + u32 j = i == 0 ? 0 : i - 1; + + c = IV[i]; + t = i == 0 ? k + xL_in : k + xL[j] + c; + + t2[i] = t * t; + t4[i] = t2[i] * t2[i]; + + xL[i] = i < R - 1 ? (i == 0 ? xR_in + t4[i] * t : xR[j] + t4[i] * t) : xL[j]; + xR[i] = i < R - 1 ? (i == 0 ? xL_in : xL[j]) : xR[j] + t4[i] * t; + } + + return [xL[R - 1], xR[R - 1]]; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/mimcSponge/mimcSponge.zok b/zokrates_prover/.zokrates/stdlib/hashes/mimcSponge/mimcSponge.zok new file mode 100644 index 0000000..c78b0d0 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/mimcSponge/mimcSponge.zok @@ -0,0 +1,20 @@ +import "./mimcFeistel" as MiMCFeistel; + +def main(field[nInputs] ins, field k) -> field[nOutputs] { + field[nInputs + nOutputs - 1][2] mut S = [[0; 2]; nInputs + nOutputs - 1]; + field[nOutputs] mut outs = [0; nOutputs]; + + for u32 i in 0..nInputs { + u32 j = i == 0 ? 0 : i - 1; + S[i] = i == 0 ? MiMCFeistel(ins[0], 0, k) : MiMCFeistel(S[j][0] + ins[i], S[j][1], k); + } + + outs[0] = S[nInputs - 1][0]; + + for u32 i in 0..(nOutputs - 1) { + S[nInputs + i] = MiMCFeistel(S[nInputs + i - 1][0], S[nInputs + i - 1][1], k); + outs[i + 1] = S[nInputs + i][0]; + } + + return outs; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/pedersen/512bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/pedersen/512bit.zok new file mode 100644 index 0000000..b3024f1 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/pedersen/512bit.zok @@ -0,0 +1,36 @@ +import "./512bitBool.zok" as pedersen; +import "utils/casts/u32_to_bits" as to_bits; +import "utils/casts/u32_from_bits" as from_bits; + +def main(u32[16] inputs) -> u32[8] { + bool[512] e = [ + ...to_bits(inputs[0]), + ...to_bits(inputs[1]), + ...to_bits(inputs[2]), + ...to_bits(inputs[3]), + ...to_bits(inputs[4]), + ...to_bits(inputs[5]), + ...to_bits(inputs[6]), + ...to_bits(inputs[7]), + ...to_bits(inputs[8]), + ...to_bits(inputs[9]), + ...to_bits(inputs[10]), + ...to_bits(inputs[11]), + ...to_bits(inputs[12]), + ...to_bits(inputs[13]), + ...to_bits(inputs[14]), + ...to_bits(inputs[15]) + ]; + + bool[256] aC = pedersen(e); + return [ + from_bits(aC[0..32]), + from_bits(aC[32..64]), + from_bits(aC[64..96]), + from_bits(aC[96..128]), + from_bits(aC[128..160]), + from_bits(aC[160..192]), + from_bits(aC[192..224]), + from_bits(aC[224..256]) + ]; +} diff --git a/zokrates_prover/.zokrates/stdlib/hashes/pedersen/512bitBool.zok b/zokrates_prover/.zokrates/stdlib/hashes/pedersen/512bitBool.zok new file mode 100644 index 0000000..0e5873e --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/pedersen/512bitBool.zok @@ -0,0 +1,714 @@ +import "utils/multiplexer/lookup3bitSigned" as sel3s; +import "utils/multiplexer/lookup2bit" as sel2; +import "ecc/edwardsAdd" as add; +import "ecc/edwardsCompress" as edwardsCompress; +from "ecc/babyjubjubParams" import BABYJUBJUB_PARAMS; + +// Code to export generators used in this example: +// import bitstring +// from zokrates_pycrypto.gadgets.pedersenHasher import PedersenHasher +// import numpy as np + +// #%% +// entropy = np.random.bytes(64) +// hasher = PedersenHasher("test") +// hasher.hash_bytes(entropy) +// print(hasher.dsl_code) + +def main(bool[512] inputs) -> bool[256] { + bool[513] e = [ + ...inputs, + false + ]; + + field[2] mut a = BABYJUBJUB_PARAMS.INFINITY; // Infinity + field mut cx = 0; + field mut cy = 0; + + // Round 0 + cx = sel3s([e[0], e[1], e[2]], [13418723823902222986275588345615650707197303761863176429873001977640541977977, 8366451672790208592553809639953117385619257483837439526516290319251622927412, 1785026334726838136757054176272745265857971873904476677125553010508875025629, 15763987975760561753692294837740043971877392788040801334205375164715487005236]); + cy = sel2([e[0], e[1]], [15255921313433251341520743036334816584226787412845488772781699434149539664639, 10916775373885716961512013142444429405184550001421868906213743991404593770484, 18533662942827602783563125901366807026309605479742251601915445402562880550265, 12754584346112149619040942896930712185968371085994381911052593922432846916845]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 1 + cx = sel3s([e[3], e[4], e[5]], [10096735692467598736728394557736034054031417419721869067082824451240861468728, 6979151010236415881632946866847657030447196774231162748523315765559549846746, 12137947022495312670974525048647679757468392619153927921382150023166867027471, 10624360821702266736197468438435445939719745367234393212061381062942588576905]); + cy = sel2([e[3], e[4]], [16704592219657141368520262522286248296157931669321735564513068002743507745908, 11518684165372839249156788740134693928233608013641661856685773776747280808438, 21502372109496595498116676984635248026663470429940273577484250291841812814697, 17522620677401472201433112250371604936150385414760411280739362011041111141253]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 2 + cx = sel3s([e[6], e[7], e[8]], [13312232735691933658355691628172862856002099081831058080743469900077389848112, 19327977014594608605244544461851908604127577374373936700152837514516831827340, 5965720943494263185596399776343244990255258211404706922145440547143467603204, 11103963817151340664968920805661885925719434417460707046799768750046118166436]); + cy = sel2([e[6], e[7]], [13997829888819279202328839701908695991998552542771378089573544166678617234314, 13691878221338656794058835175667599549759724338245021721239544263931121101102, 706995887987748628352958611569702130644716818339521451078302067359882016752, 15519367213943391783104357888987456282196269996908068205680088855765566529720]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 3 + cx = sel3s([e[9], e[10], e[11]], [3514614172108804338031132171140068954832144631243755202685348634084887116595, 21412073555057635706619028382831866089835908408883521913045888015461883281372, 471607086653490738521346129178778785664646799897580486044670851346383461743, 10847495464297569158944970563387929708762967645792327184202073895773051681481]); + cy = sel2([e[9], e[10]], [15464894923367337880246198022819299804461472054752016232660084768002214822896, 12567819427817222147810760128898363854788230435988968217407844445582977743495, 12262870457786134457367539925912446664295463121045105711733382320777142547504, 18045012503832343228779780686530560760323693867512598336456499973983304678718]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 4 + cx = sel3s([e[12], e[13], e[14]], [15118628380960917951049569119912548662747322287644759811263888312919249703276, 16598886614963769408191675395388471256601718506085533073063821434952573740600, 18985834203956331009360396769407075613873303527461874103999130837255502328872, 4433382535573345454766736182894234755024333432764634149565968221321851794725]); + cy = sel2([e[12], e[13]], [20910093482714196883913434341954530700836700132902516503233669201436063149009, 1519565901492557479831267649363202289903292383838537677400586534724780525304, 10041416515147137792479948105907931790389702515927709045015890740481960188846, 14765380703378616132649352585549040264662795611639979047816682374423451525367]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 5 + cx = sel3s([e[15], e[16], e[17]], [12047448614322625640496087488290723061283996543855169192549742347740217312911, 4511402808301687111378591744698422835937202088514472343139677982999770140261, 12163443309105839408816984443621255269615222157093914420088948521258519452383, 3481629181674207202258216324378273648482838926623855453371874690866818821960]); + cy = sel2([e[15], e[16]], [16179347143471683729835238045770641754106645772730542840306059882771262928390, 1330606780692172668576026668607748751348574609524694619904517828208139587545, 21047796364446011793075955655871569603152857270194799075248022968227548164989, 19676582441619193608410544431560207171545714550092005317667230665261246116642]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 6 + cx = sel3s([e[18], e[19], e[20]], [12701245173613054114260668542643518710151543759808175831262148773821226772548, 18376560769194320940844431278184909327980744436343482850507604422674089850707, 2108750731998522594975480214785919514173920126687735114472940765769183959289, 8345688345972355310911106597696772464487464098975129504776508629148304380440]); + cy = sel2([e[18], e[19]], [6893882093554801220855651573375911275440312424798351852776449414399981870319, 10206179889544308860397247082680802082921236707029342452958684549094240474070, 20690576727949006946449925807058663187909753260538825130322359335830578756980, 934097825986417774187883244964416516816295235495828890679674782707274540176]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 7 + cx = sel3s([e[21], e[22], e[23]], [2944698428855471170284815781705687753367479016293091716206788980482046638948, 13677149007138113141214051970478824544363893133343069459792025336510743485579, 8778584537362078914166751980528033062427878768812683022653464796527206882567, 14187573305341020255138644844606451353103636392771375201751096173736574567883]); + cy = sel2([e[21], e[22]], [17360101552805013843890050881314712134389035043192466182420273655548320239406, 15585069751456986750767880753875189652981026069625633386060310449606941883984, 14103016602951516262329001181468262879087099584460171406752641724802127444882, 20246884593862204796710227582734862797721958090111806492549002716706329529389]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 8 + cx = sel3s([e[24], e[25], e[26]], [14561966822440683665541629338358038450751192033904756806839710397580365916408, 9033289676904424897161301113716021195450524279682799709206671901182123388512, 3130553029765252517071677341132737863162584406047933071036994763690628383497, 478748220028687672909774713203680223481010996519205842697362525656305870550]); + cy = sel2([e[24], e[25]], [2103279357051120614300268561700949519576521616178686690761693996681299230890, 20408096719725376095564479959189425244640061563902110565713028117867143533071, 10602190247054189080928144476332888853804880952034975460420247853133904008108, 8904086690633759655814572723164827369823592560037992353159979088242240507753]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 9 + cx = sel3s([e[27], e[28], e[29]], [6226499033652114521979121779728984801913588832404495199289210905837818402723, 8038917508002636084872059181598756897599119789741848736002584943229165162988, 2277325821476302201179031013369476744187798789480148846137091219460796268467, 967514222774662330369300003456258491278184516505205753272628639669418183698]); + cy = sel2([e[27], e[28]], [7443974969385276473096219793909172323973358085935860096061435962537700448286, 16080381380787087259419052592465179031841607813350912826860291224363330298665, 7197183980134554514649915487783920553359271769991651108349414168397349372685, 15259375744392791676426881929656094304768076565231411137199656518314416373020]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 10 + cx = sel3s([e[30], e[31], e[32]], [7079401365241105225661961622760419818013463250349580158302569256283647306129, 14357098412862251375028337875874646262567035230486208703024315026944432279497, 12132744267560027693690759266151433597852816079588628241106105645480008053825, 16149669420758195925157542983134397690644755714433681232247094526660232442631]); + cy = sel2([e[30], e[31]], [11050535702333135359874644130653446287886435768224627066379760227644857448025, 2102777351898195104147031754958199443749204333224032175429214522075012926330, 4445288497276728579279429434033072747592184765171167503126978668105350002482, 2895400734738526057690008272958539309751728639263619269043890651038357187575]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 11 + cx = sel3s([e[33], e[34], e[35]], [20192636532359225751119979205906307972955330178954709766736232115035084682472, 804195338747219623697418198937917828717652612397835452095971237574002648345, 6394431494852440399081028203192653448308162012036135765292083934292810191518, 11939476767684237945975176292664687849983867031644620074465117021204214089848]); + cy = sel2([e[33], e[34]], [17748517956264309916268005941322895780280007418421226047127160997826331847601, 19497513174101598882802026674952900838989414265369078336475842766531805130216, 5620469644231252504463650386222007834239202862082473485080174711171599148975, 5516661986429427386078472422851029350005420782971768428739820651749444868271]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 12 + cx = sel3s([e[36], e[37], e[38]], [1324920405111324350836746707883938204858273081019435873511569172015916187999, 15384225309297147198449617653578330654472159141743407174794062987091000857662, 9920404264935487368096005007182799973436766546149561065368669780566156587060, 15254057056535397961799214335179813200885132815863068943475012547021698517077]); + cy = sel2([e[36], e[37]], [16984705452766649815073644511059333480190120433850502120324063182300137456908, 18046160220855048074367913256918233739227589113215101142291000275961918974523, 13094718066881673586455686749880972268909309391825129019088029831712146780775, 17556146601257932451584708078305104848786797650062537873707738860847250565143]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 13 + cx = sel3s([e[39], e[40], e[41]], [10184781845128697471817965179509651550812478664395958690225791623061609959495, 5456125639262884825452992858423500073570690895733609235845616173174729575569, 2442835875584110487966438996784695688123609547017380844898154175948468234967, 1507509649954376860384651590722437356078107662975164713418836301939281575419]); + cy = sel2([e[39], e[40]], [12481681651435870984379558646813686612408709833154117210578901875084149402369, 11152008367598826226940260746556525580820232821082556208512958435351250898503, 7567915483885326926315083960846242855523572023844618551872662303018722806760, 20394803059296859730298132333424950360853695629226621934657959417500478188961]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 14 + cx = sel3s([e[42], e[43], e[44]], [10680962982327504072121608021689834159178144997131600234373184928312768469752, 2399077467035346531560164705357209055497431901223015425246039711757880798964, 3423125451159866822107483111524543716819043967842944968651561023348340629866, 9942880027482137313328709914157120920632734642771778240985776643385937071731]); + cy = sel2([e[42], e[43]], [4698845013673361363032641974440465619959991809676353365742268606915462346702, 16130578759626193985851427947711894136403468334125608062505774040115700327331, 15972516792261738383725187984065495328469263202118598475958253769706945995080, 7601042727654430423755752301100987459144576573414967660631298823059519301944]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 15 + cx = sel3s([e[45], e[46], e[47]], [559099661340368706731458173062937049444139592208939239637572972395409815235, 1445905511768661496314996877214005625534188630127375321650145036638654136508, 12558069540132067621925302006222579198925455408763618011362743955646129467625, 19809789628385980249290251944250230372682953514057413790020001670501854917090]); + cy = sel2([e[45], e[46]], [10744092763718531253355077100374662669098109929848484460119044326894952631009, 3973362040829593578154878010051739631231888449967620092704468180671355813892, 1362015208311760378785201188340495520529554642363760051915563618841646945115, 11588368620504227678083366267185871581602064602621931713732756924598104334083]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 16 + cx = sel3s([e[48], e[49], e[50]], [1678013963086824122518234712588270403106471527976328603364788331772512526348, 19217446816753374280163957047166499363370322773252755452762764797217084855190, 18251775792701212313037978569776264038974809413837373677702565241405411946778, 7791054681559787609111187809686247485256130898718509173169053332755413410611]); + cy = sel2([e[48], e[49]], [2187428842929094383038114367392650175780437811274194322303902357941058607339, 8626132368431980635626323475901790012728207722636477570331410763937692048466, 113795593186630447648084123083495614901087109757474270136294009546464903517, 3911253907085777766524239918145094862050185692851156691146764655435644911738]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 17 + cx = sel3s([e[51], e[52], e[53]], [12873968423948310899392467568104977730716801401622261861937368089215309803500, 12347009456329688755313379291270351313162786795095345538842244121034639964166, 1453033777281838070082852447488517173632198407446735454517038916605079634444, 11282290315868048695472900994602235661536258445850718305682561140328404797725]); + cy = sel2([e[51], e[52]], [8139007031385157566567411468459940290231498857090568363629902873306461631248, 9142412231629797319569179103935970351107774720462787670615972830568683805984, 12672100925996181868477785977558380430714799944709260345359951721012123501095, 16494953398584179618210238266126209360371451946684386111530845235540890038134]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 18 + cx = sel3s([e[54], e[55], e[56]], [7778254495039611795685039895928787457435875136389165268120013630439201169232, 18978376692784498976711790251498129273567483356717340918869164950830208175147, 6786343960634025784864145941287160961224170404722122001422161703472545445301, 963142484718869013546386102939529863406065949253846087785240390647819147126]); + cy = sel2([e[54], e[55]], [7284679595773642123118330714484999203099307921555787993734753019057231440983, 11863181578147413903879545253723831525079414688349285572164796614141056912840, 14506820856835670503131551890617399661938603609062325089041733284980790009293, 4347670008275218338032617206784753933320201662996772040726919225863771514568]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 19 + cx = sel3s([e[57], e[58], e[59]], [3630756302007400417952089805331380555952289748859891438940570770932527475452, 4733072488758626584177720052077496914661792393101658203493985364120366268281, 4526910185101338883574479225992287789853409001566403159278561225375682298543, 4955992755917650287600423903671744997417781344631255784951922382765227784141]); + cy = sel2([e[57], e[58]], [16596280733402230599955345374089507399680037832193751466748596443674569931646, 6390381659733151443695336725554471564240651107616043093647301732553182081233, 17125093365984505488419430885232358010204128822674623886572872558984812477756, 7907776458440631594337279500574606181494889317898652109149850067084027888619]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 20 + cx = sel3s([e[60], e[61], e[62]], [13428507160783248146944378848829437095621758280249270905793449036777555016842, 10292076501843933688687976934900220205880058108224904881677407523508189156342, 766857404192368568735095124452313950539381046754211726072981073742394879383, 19929977262929097751573344897093024390473135465066154321364399543253519251540]); + cy = sel2([e[60], e[61]], [16698341695430068847582701171147088836738454320587148532489385958997389524692, 15892936434362954902510964691481568586089663041057258511149661842770672240332, 7940515703899915602011570921990242082041971424425808524102519499134803569591, 6891504197906111172381550323513759741804319972496414093225387272302697012664]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 21 + cx = sel3s([e[63], e[64], e[65]], [9001788585918405588944162583417858847457169702891113291878897002187678929577, 6471893763677472946002018028525448192731896031469219164732421705849786414080, 6872696243264239672878286181725922526028148800020555100207514569826971690256, 6457059076269833003010871598305386357557482703463879737255688784535353986402]); + cy = sel2([e[63], e[64]], [2208441895306047741608356002988212098270630744976300198681224594148576837458, 18524825154497781981405149991295652940946623352876024366965123296382603920630, 4474085805150211658090190066955902897001661633303260299025041221776891523378, 7848328793479881488968680696062292137496770320699466501151951135248413225123]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 22 + cx = sel3s([e[66], e[67], e[68]], [9370960127159127445266474449258070389736162441470427007490084241211557822341, 14965609177224099035387154934147530900281499783229343066828915253839198476726, 10228455969106022490302521106014422994204231909208186519000062372321621002715, 329501376630941941063220737355314017862421104304435198239389326959464907258]); + cy = sel2([e[66], e[67]], [10405035931558887078762806053185283924863039263200495982754625705264574757491, 15502133231749593338314160389347860966662224717441686478526316588882854824409, 16159781620881884595657183508560936205420303661972673108699575582908291222745, 11627201183429653135859532750162240837549070563304757137644487859075461689878]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 23 + cx = sel3s([e[69], e[70], e[71]], [9435538689621391149659891449161022313817917158768482063316123517911261629051, 20034929826130067090642639519998781717754864739607562909796887703087596572733, 2387945787036487514595261230908460627602020385539203589000341684029816345462, 14287010417915184144199881651073103018750205011354171060170509879133644433324]); + cy = sel2([e[69], e[70]], [3766822724536031967241092846229703633913210151222385593884505545907921188272, 15647190524611689022349999926088308537492889236313676989549224633916679679521, 12082040904926878889054967598271733538467180307938292871588544645957948546982, 18694076414086475523793644660947803814318698157437774233969783951279622080580]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 24 + cx = sel3s([e[72], e[73], e[74]], [5859172856191457066677368896012140820864205253768332100482413148381377691822, 4109040705512320821322629424016219907769924434419769556997996401827477205364, 20898133598840700569835017147086534068242670333567622549169818027799138688520, 2562111968303466794360830608662119102867266861457203102917042145665851057610]); + cy = sel2([e[72], e[73]], [4836009713585714465496581912154882382453931120914721557804515434755336832208, 15143499611233432306382398214139440479742818510304232326049564749513747791130, 19356118393311375462052662305789820240618686111711161337705029468367145040988, 5688481852857742015073912476996667522213010914545901826896160233670889226775]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 25 + cx = sel3s([e[75], e[76], e[77]], [4623242138639627730014370601705308411725596532862597538813607327046410321312, 20015154717710755506154819006635497782515667453025611627915382742560093423171, 3514612823502534944140986983282927838609295377065173960376131742886885892219, 20191997625806343264590099369325683216271615998169853765554784065039674586670]); + cy = sel2([e[75], e[76]], [6538526769564699401600543915225940144078494544354769810309083421131300518775, 9118555176257537603156148628736012723504563452923782011591078402032233615522, 12815558970989336318868652718709831589595442899079588636818966291960853991023, 7703616604462929360855592091876031952747180200478430464323567906544600168109]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 26 + cx = sel3s([e[78], e[79], e[80]], [7426207409769264985012540642921370782277366662985635838803842004294008785185, 5999778250617485918891782298009709493035045140093544961901833503446031905913, 14130927440165985043471103750344848991689715792245153118451423398655300689873, 3796482870456559450471870663226834834712024906775762338643689176551263991246]); + cy = sel2([e[78], e[79]], [16458635168452867431186476181702908205218256620571557119181621733008943007186, 2408736441388526903801723805189252326923776373802231905332653169285504488507, 4539189593448662319023898529532785456602052593687554864880479361284144700884, 6490484418842862735983085938727562049587933870197049726191839108647357897041]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 27 + cx = sel3s([e[81], e[82], e[83]], [9274793422641213328277630692090429447322754602554792362167389139799628719939, 18213562677024477140777501284013103092531757860081519011108723177266099803615, 5928914343334640962747136863911294731157726634392529232872962806197144988571, 17364692793332784962323580622297080260599290963212510860189969183095513710617]); + cy = sel2([e[81], e[82]], [2125001664000799929029867649528637137680130729147235858348667725168119291610, 15787194912569598784093233335743719308944830093009287397433562464152875584662, 17778173794489364127449950674919162836220066518510591114146982109869842663244, 18328553264273479562530008673792097214292102347103296244385349755449098608225]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 28 + cx = sel3s([e[84], e[85], e[86]], [13710259114758767844337497139752382122951774216678047790125818858626546865590, 3343610505090632166881693615831990684789904804852523835888323130512752436557, 11550335352408668215051239093872906070657140182660747433535878335227749182418, 21793892863650948729507322696305982607072336532791041097212359516991274087980]); + cy = sel2([e[84], e[85]], [11846136982947366289908137269088548542970460276305965388699657623060915691485, 14439612735106182034303100596819001121085745615069593580210956482903072588413, 11243378354558219750264654469308879862376787156599458648274627817471028307109, 1416613801077957126034351583571856403044235139983509507026555602579721659100]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 29 + cx = sel3s([e[87], e[88], e[89]], [16898533007964698268976570330413504736326631860509774315700399063143612293661, 19762411747110048388233897239023416141949331694011759548598869652948167421240, 11749964437081939283728905999710450041654325285452589389081577137553602604162, 16314155164640857713960417655857498051596153632474886680423284957133775223285]); + cy = sel2([e[87], e[88]], [19301014021919583977567348438857464752913991729661145830439339193394619822674, 4081042960569737826610743202667127127506276066439423960421657857551695871422, 14520831020919654323745478654766278220911435521609622705053803095115677276928, 10347543397607839527923790122253286529883327940351684415635401368115385858121]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 30 + cx = sel3s([e[90], e[91], e[92]], [184222443282411811008485293978090987184574946550463281113036487016967683795, 4323925196392247451702039714921386345420807454721539995370304513020371659426, 2346825777983317939724845287942565740027799801885272779028341294742495881964, 3497425097320782814346947506403058330145264032565372769682636446824270312453]); + cy = sel2([e[90], e[91]], [13850322095814274715426304026104710047724256505475254494587134658322670671529, 11511819464672461161880080290029237185728360968222698390620899743097045452336, 8068296678016129536739401811575622149523917897086227154769231758295218255268, 10263809994502353117991909442849926729413925087877766198113026233378613424956]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 31 + cx = sel3s([e[93], e[94], e[95]], [8995760760295995916308082490351740974639094331313720900267671545759667549796, 11019493928623991376174717464416885911906134873939034428175124701672655752839, 14017581177532816290320938368540191606560126820406006677979240977503063555845, 5992767544073504039822155308781253229334004182511050716159238341577147193720]); + cy = sel2([e[93], e[94]], [19514976680591593876219573359164805119998241765130948583982557052811782267484, 16839145730766072636625126513480100227916490562760284965681235183731245254947, 1021292692554672699619028273609664837317397089685876358558294458673381089032, 19705834660126914988160966717581159186486910721909298688364547098333399879621]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 32 + cx = sel3s([e[96], e[97], e[98]], [2527638437523893015660301196665088766965588386392795314680197258969354623363, 1138471124880305373267488994599338604626881130398552196301155187554578496993, 18796280357765998280755689911684961342287093510307513491082157499389652187596, 17845424627755166990290252831103404879406229534320972756944316138691932923261]); + cy = sel2([e[96], e[97]], [19210721144465266426749734142673856566947869352583355496554030705736452071361, 14313930380744847001650971451811594041740544882894516063775993860263195402168, 21025107892840987725102949502655791789935181032924916608477285415225533245973, 3555509537083802658278452964512402851284368794121767087246797342866139363946]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 33 + cx = sel3s([e[99], e[100], e[101]], [15846792621646742652974245065938230651829248095884295067743275618391603947137, 252268672903219503110064676037004166486655891926695090023400798499584132445, 19530459807361347014390846162868811023755147873522489974990781147946076957319, 6779173153401014221878658847395058091689669042378445736327791547741105926579]); + cy = sel2([e[99], e[100]], [13124560942345768357314581178595700674622208923899518932907915338485045148127, 19427900801187548763760894641856199686412861734645157290016060446141874396762, 10578265528433465376709803300626505953445780532420709942597293441366167803051, 2814357683688249343045032287308948679662030207205739212100871663137250686972]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 34 + cx = sel3s([e[102], e[103], e[104]], [9161164860624082016500689976633279187120278305601384250238486553068325633742, 3594465641083658357640727503005755820863340547313408576898849399984296404007, 19745546026637204577602881915206827000693868119693662890799396502208696901732, 18116250696909523241042661347132525872828324429923244627289119813508105665938]); + cy = sel2([e[102], e[103]], [13685063021736046635507535227140671955502404587270095297507854657927533098685, 21481850865118949667886934355577641333398731968912180643307092533138863580900, 4539145198976864585367021826448478029652078179409326031693175016758410731544, 17461973876416788164599136875394849349337761082750935487057356278682772411162]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 35 + cx = sel3s([e[105], e[106], e[107]], [13763732875937305178862849318112327966371606623409616602363024527079535241003, 7146728911382113235576196126361394323865045988036623175328726379662117800087, 13957018179677684863250069220406779871369347949049594304698838627334319400324, 2983130106134530061974606593769911479536904265326576922594002168086009867582]); + cy = sel2([e[105], e[106]], [15902927258231569893737955890837667742457214947649307818302524420399149241212, 5394027336566373776896911094388660738090625577337970061356832815458464701108, 5175259754491075858870829756483758144360263281431531384832593797283930411109, 14151565798137996208654994826049340981954317623288904943712618832232605861595]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 36 + cx = sel3s([e[108], e[109], e[110]], [3511208839914156996602850728297722115315702089624058744395068873552707949103, 17785314838779826411805999953134869098297432649970533754606824062794244465005, 19568380235187862245567915799143793188430865272594403468605211965296271194922, 8968217637384711708369798047935037549991275897411766158377778716106218907618]); + cy = sel2([e[108], e[109]], [9113093883676083424918242033136578270322417571556449454840754893578163802387, 15195400406105586498427391734410887774383134313041084245786188708846588107061, 10391623490262978616498794103188417653962360594423044385370483010810406454393, 262198447430650388196958319338915798147458757989176286529479967365139093614]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 37 + cx = sel3s([e[111], e[112], e[113]], [11522295231047132260758343744179190547608150890072723735296048871441325064339, 6417300850099046536319790332124930285535196168151466782463281196540309297983, 19137291956859275825926699344301804549568562573423342909926469403211747707345, 2774443339156228722046927543564067034026765236710736809480294993459012359549]); + cy = sel2([e[111], e[112]], [10997633658189180813501132314065688584832302881630691645920837501861598079973, 11230602434226993956802641296087754248529927465162671110571036062223097035285, 62131588140380451567557177282839666875193860544849125919004473298285110712, 10450442472445392653150568721579575112681026302736591474982185692600259786523]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 38 + cx = sel3s([e[114], e[115], e[116]], [13408931465122001423751414891302829165042502658140645208130973182525808774770, 12919550455861565687920656314018840423444710872112059576718885637461594199393, 8902156077182438987081535936092318477847851529427670854791439040325983142815, 10551142139308027026174282362670932774470751296642556552082094389923387853839]); + cy = sel2([e[114], e[115]], [9267742985382681478817853200119409918969418222977519894367804134923874406267, 19027179442258820884726400809066833518658247567670360715860243154343698445860, 18038603127894002689531978859178109088479567097675385814346786297731217235404, 14150146649091182389991766732798336665028567292472735778013325601175132243538]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 39 + cx = sel3s([e[117], e[118], e[119]], [6540890698262697218677202035403667770177820101154223149908034301445959517274, 435497241504544923461214042595209510655313029058197261483355541334388444061, 12972419969438465538309509757262343703702203355603454637962110103300326018994, 6669959829681253734882192282716498450739929798663147573799606668374867628160]); + cy = sel2([e[117], e[118]], [2642034845320222085946302229307945658183260378358994660373441270519802248925, 14736341083198246245608013213787697485596965707560872888430876049025049794937, 4329454540840640926293454385395213780440355759242417354895666807552226740059, 13390807756542084619965526671660454489274096296730210772303889980314835989796]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 40 + cx = sel3s([e[120], e[121], e[122]], [3375661072576892623715175468380800047905893262660913295358697027074087217513, 5069202507845220698620539676049456933089654255996130713693017872693588276345, 307360032529211257870367390878851528397463530836715039216723323169226021440, 98081915276387897864111573201930613825497393423677224354881280134376446888]); + cy = sel2([e[120], e[121]], [8987539541637688797931012030256009083390767313291834963652110291129797020941, 17901947618091300697708370389296420066544823878914604900411880276648078042269, 10639219577401234864823685175468874052621402569992677814844863434253512890795, 13240331547980137691596357784155019878384406802888737259354896076218619627328]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 41 + cx = sel3s([e[123], e[124], e[125]], [9662184175454991631880218147488300829920024817382740712599708905755708816803, 17771020629416708231961523003444615645037663660747267683766850455503462282265, 14494133870721701214401742677540032810309496543890589653927595534007509078658, 16561168866198605810694591274909829276030780262733890202994760647724957996711]); + cy = sel2([e[123], e[124]], [16632142917625566129622048663670437511136716491293457317746859226945397089536, 18400270017828347077622860778898029123047396355399577145984944065126581795849, 8353334605287102455944569500604056116678191817084945684486328539838325378046, 12147075225903504606648888869906750158496142784038841529413244301117587609138]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 42 + cx = sel3s([e[126], e[127], e[128]], [20252038718269174556829574777069549258100538764143309785207012647062643184902, 19438750079062162172414919070069193686275943617816957878302458952613247286975, 2739523700389893370248547110285910821118647890992955640060929464309561828074, 18986163209792052202203221314221453057559857704913672555327882100075093616752]); + cy = sel2([e[126], e[127]], [1949203652074521007058676904301415827566224382778317340432698169556879788463, 4017921177690528677848183821427142247358574441895228503258380087834359360501, 10532220115833479369586881444322308530349489476356817032718755221032796227335, 20767633640647488765234831415684490207979213320475813611233243261000228414020]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 43 + cx = sel3s([e[129], e[130], e[131]], [13929197264592281054662634434397205757522163835293158725199610804948038924930, 18983630674546465400919161958500748450652609469567091049588112148279229509416, 21298720061922244441608259922072286340766498728629540286898859613690667559954, 1255771444824172694387038994365972934222854858110644765629654650968093841237]); + cy = sel2([e[129], e[130]], [20928589942441069163400310179733448745002695258624629275677130484867901611592, 20945151313192869288039616217247173168964585800167278953053768079971885757820, 13394130995265898710013904122336137332320804034657805114241934415456940879520, 8345380486550648681305351465341710151021284756322349929795845243989999089313]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 44 + cx = sel3s([e[132], e[133], e[134]], [20820962511183569148336349677594457306122370638840390080208640481304634109972, 21271204223521868772910817161761075423625575552213963956907846089587689594662, 10733658208915381791180435538254458430504966830986768682084274021501716755708, 3213872100717631866873070659546947812880485326599459130685149408092349854866]); + cy = sel2([e[132], e[133]], [18802948623154501291575097526503171935564067914914679326677986205652424463305, 18671196065143385675890877955428696189287618414074487330442057564568301653630, 17500512499632911097527623128158674292347613137609268450560746154383855656852, 10140717739675826292242942694935483711727546989965783109636404988746901047250]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 45 + cx = sel3s([e[135], e[136], e[137]], [14908874845345243542374913242177817956756346686642792660468745914078612972964, 6494892024924675012540500602558430897039227451488331729419886431227425262471, 19660118982815103063271284609401904064050204952733042875484811495633642263876, 10404140614423982473417062438060653585074743419249328530274575800693260655367]); + cy = sel2([e[135], e[136]], [5109688569541183345813508363367270401129385455666732942384933494548859595681, 6488452587861781859966899732568514074249818909310744177483425914897141192195, 19759144330570995637436877834773866770106917696169828968224667729682932948543, 19372158643071160860924236286390794017939077735118276297478085704446653404487]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 46 + cx = sel3s([e[138], e[139], e[140]], [1154476465911192808082307928347900064111325728833428891094393674593800812900, 6647319020085089760145868568636007917712315513936955502164154733998378717177, 12584569464684026880899751873241162942166450853083376779447501714905643756083, 14243280142991602029691394563175478833697759877979687578140951697024930901167]); + cy = sel2([e[138], e[139]], [6461899930945412323497751736369894620103555271239754245787726192367462376648, 11218209351589240489615573530963044202098579836550413344228327749253510456169, 20533060824796367399322624999408451192171574545415433951669661225068106752784, 11799997625790604641690313275280372066913716290701708574743226300595877165728]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 47 + cx = sel3s([e[141], e[142], e[143]], [3106120971963814637086817095821216892657807437909030172048489357608690908664, 19983788499223635315597700897580134177379185544458724791602486120287361195709, 20011311503290782295958825256275853340402122848359336349363185226433870439371, 17061518479999755720537296647402074631690029621158571296727706119729187756044]); + cy = sel2([e[141], e[142]], [11655780578227604806047758025034240629153798954712964172707380870816316797993, 622054523287271568164593718522127794491026889292924398674394690726823527200, 16135285950085594062254918487673085571627312978983012587993350339361155816604, 16823182833153464340537049615227906529068252572342151311965980898836651237386]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 48 + cx = sel3s([e[144], e[145], e[146]], [20374356410965803131887119977813187747682102078262988894186807366145009893312, 16140790886679277390055909624981354111468382311692868339667095804914180995816, 5269708933005858910719244518715051229221686961187992215177561544872857207052, 17003669964193566226265890987693478032205879390270724431641892912757008513023]); + cy = sel2([e[144], e[145]], [15298182760377768633156209223343487909782393543670382286190369588693664098885, 15694313374278606393252570906724471325000910752891934797182427274800382725179, 20211423855194801900153066955584657931131527051780164510917465106404910099513, 15455288363376670716062020330944532534047008363514636685826622499678373390425]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 49 + cx = sel3s([e[147], e[148], e[149]], [14165004713755765453589527153323887724160944086658242248604905215519807263185, 301131970962481505862420187551701457358785403147894839379498410579773149817, 20703780629190814394908582715811669803434202446164042946560257906844612159868, 12367443634404793487462362639029662097550355799821945744713867599113535990920]); + cy = sel2([e[147], e[148]], [20401715072789557220769413113920881979690352159560582443280493351937640089943, 9512744351810164617160144481900582699060463555523641782334998030336637339295, 19997026788203221539856525472799656962300551306251956395441891331721763269878, 4420107516401930587358239495168429945976230331917756712920657983670672632753]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 50 + cx = sel3s([e[150], e[151], e[152]], [8103748105126096403620617531109165346111017883414253359146860083465308290054, 14803748343013980101691104453457628404765420707022107332787520877316491921572, 6553189032217952509828188229822974795796651131494012230703062173727191718256, 14488140647832162063035434131927730449663617866962750748399561354722976225897]); + cy = sel2([e[150], e[151]], [6900602880532330473224374524196761198151861405485326291615150754345009304151, 1513115647408875522957756488493462370777248725072062752756727843920832160085, 14896301840535712091808125164986771300932651268478608922083726618785610993431, 18048817115801653510192862998462822947761670069362294686696577131702147477504]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 51 + cx = sel3s([e[153], e[154], e[155]], [382543238316875203894587902417533689378617036331411163099475938996384971274, 9619454944964330535387495829359535093743583319913348616872361595592109685167, 6081261874729821958303230238004699407225832699063899155741932401034312247576, 3156137884201329913786702605630625537320273632812696416791152392474314037759]); + cy = sel2([e[153], e[154]], [4793004393185972052681267640894832507973895495734257655931836941627180322533, 12524126851245821931846984936446041288760976334671736634358685272033969216980, 6277340058786227516467028124755004985063566609742747175031180490042372405740, 6981569030046806591634476164525159834865090256544287529201527685109358245562]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 52 + cx = sel3s([e[156], e[157], e[158]], [7242980429824960501440666232145028986161691674990466362832703971174936796830, 8045674190780012690331364750465564303458553754280502177743436741257674712579, 11260599103741407968666669605286104777635431193927929500939820855376897097946, 18466264932289657017935069178634633780361979903681010210726608765753592098197]); + cy = sel2([e[156], e[157]], [2313823382391584526084833833122921512331314230217820828722208559851046887792, 10089801374498501989652677350203014944991951797848003015280234323125565001040, 17328843896403558624774477961071623822106890748911687259696765820336743222251, 9096128104648798569037169791537313868030583174665566146242611146033775655076]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 53 + cx = sel3s([e[159], e[160], e[161]], [14129501557712467097681133312480956681237794589418881140932742431414452181802, 14215253979300894109266393937905007744674886266134853669970409340633353105422, 5101954416353969027375336730301151965881345391948426977373049227857281866232, 14576353231486654843487902119173617652532372118230138091256904812874365465828]); + cy = sel2([e[159], e[160]], [8967890713970048745032869372462848543847652746940083058618452105243173038725, 6265601060440963621915827684472693851147234848878380918293598569151688236174, 640827344679117882936589383352750227742240703205324868948399729377934123492, 9724475542168570127797711494687143027178927970205326782155651202256929792882]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 54 + cx = sel3s([e[162], e[163], e[164]], [5456157947126010471455582105823966618048439614862840203794276433144936442303, 21043218890179638595653930578748044093798652379401035786184926212259053133276, 1927155268257451951778867733460386031395807546286255979317875653435797662494, 2742904689169248143495331827109449907113748836918731412006506067439664106654]); + cy = sel2([e[162], e[163]], [9440520397717291873292501513394144011971438675685104804031688857727475979708, 4417998885632129975756353073742958617120204855631898102096412742879398656621, 21718244289007192530526626848367390261419399428442075984244560471039861817138, 8877177915758141474927139565405950662745390581859900899551672907102924557478]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 55 + cx = sel3s([e[165], e[166], e[167]], [14850732473677774396477975866215714018387310838284937771253941847508860390570, 15346251439912975799100173523179670100616030950715800206631108275859894555954, 9806744113621004413976521475016417033548532640900224199389230684453784278689, 21096603979133316753091339975348990230540836494614368335651248862844085270520]); + cy = sel2([e[165], e[166]], [11812452402407343928752680921354215607515699690942611270817873638995622443255, 6279013985783386608484242724725362666241553499782119548714289191679033556648, 19001277736410456807324578202368992701796359861619482537978016830870842626762, 14081519926521914451511625869848591232696520686473918498999632052868953710854]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 56 + cx = sel3s([e[168], e[169], e[170]], [13157890071808158704354468737847471048810392369152727364639634059504126884874, 8008722424616547903294828680672771630855086822683412918399539174241338981774, 18594694810411494426945160098830123105355833500416479749049639533195702072502, 3003039638546974941710738006242011804553647552380262745534233703293489168909]); + cy = sel2([e[168], e[169]], [893279927671356626449601197530638356692800493991878277093322197544680454846, 13710236865890222581902901564951693313216932700203676104342205227571583021557, 11991140728188265308988894689292592177761583244141205754043533415013439187396, 7408159576060936012801497750876509797959683640624248586584358220473720101773]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 57 + cx = sel3s([e[171], e[172], e[173]], [20379496501734200220097501155104742700678033944324898621914782326376426827694, 5628902661740155176800052287728775683561775403751721906542502141173662773805, 6649334930850298644282280075473454376493217119135753313843458230202317946465, 13953386616146853105384995231337773651826685901371822028427880819484312577968]); + cy = sel2([e[171], e[172]], [6312536910770269621417292581781438152243262819530627194840110225345012746549, 6128625960467547051042766267966540761259574034224991328868848127157477007514, 2178504154437332931470309748598630309367590073987406533802402874933913898875, 10049120191768569519993419401578117655266529530568527176008678950298967775522]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 58 + cx = sel3s([e[174], e[175], e[176]], [14193197030749382932133736734505537242924559995077781886176225169837220402133, 2565010016572214675455233006763278152319972391059007175692722972374012019501, 20022269140157840221511080273245661956116845958170472382643581298431129105222, 15951592620529204477279907750991493798200861674998832536410750610279414881478]); + cy = sel2([e[174], e[175]], [10015961841973388881391587018151977950817576225746650865142918877894543270446, 10962609190943341745700082387389939598903593214578149618076217369020441344245, 10875728650787073188338824979727792178460025858689164586811311106195554874546, 8704250736813220528338393230481759654328677814076110220308209376595986509914]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 59 + cx = sel3s([e[177], e[178], e[179]], [21185904177969045625821216347084191287459806531017721293624058180265336503811, 1250611256248923800378335492392268625608584743125298517147184362502718557754, 4732901842829850758626640836087921620095030893254064254821493648172485065995, 4686012912505407137434711885457531064310116778761775095814150050521297721079]); + cy = sel2([e[177], e[178]], [21681922300753515822840018285496181872470481450737464910861242457369823926925, 8250546098596619229605270054781796306579374634169772718113961166155976799791, 19064654253935902908485961089200674782438523882800790190859631804189001729500, 7893084863238812828005589178028293328994403260619345443806395973318698162130]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 60 + cx = sel3s([e[180], e[181], e[182]], [14071560871369419892033259843192185467358801846474749773427241883409830032328, 9559459046618636497241065316366978002044190960713451216793292122894012900863, 13031319565545666906249801044337083380860313201803429372439840529717343742035, 20069400641162643493898109922008601219601618686364720341639616051841829074334]); + cy = sel2([e[180], e[181]], [8710777380190521326883551341251426052007249230093350101154473409247609882825, 10439377650670164179707163339178975058403688089785136107598148495986084488509, 20130072726000251358667317961033491205160472226244307309389477611437739154303, 17216059825244204015919013637129845877195519789582013765405196142334767977705]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 61 + cx = sel3s([e[183], e[184], e[185]], [20777314589605673759170070653370407645867665889025835324139659856710113131826, 17380793433135473426803899659206730936771330488910864786997506181753180852018, 9135535394443552083655851762956576299400389583070951313661035134759057889658, 19259342468126216922767538099314197508403261200862162612026099962268769453780]); + cy = sel2([e[183], e[184]], [2644721599238941245572401477946144870669550581359063534170381908963477379532, 12369176861935895868206428376006904712013007036288222495431735574326142454609, 17367574625533031619575225680253098966157776114681359698904430545328078639283, 21794479452176520273231597892096817659539111123775968164861961429589103329517]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 62 + cx = sel3s([e[186], e[187], e[188]], [11749872627669176692285695179399857264465143297451429569602068921530882657945, 31939593233430950996158270398727464286178387866161404769182205304632811436, 6016890150518491477122345305716423891405612103278736006824977752295838970965, 10857254852618093631105790010825256882158099527623146563961929227148379359444]); + cy = sel2([e[186], e[187]], [2495745987765795949478491016197984302943511277003077751830848242972604164102, 6997914616631605853238336322733192620418492595988404136191499921296408710465, 6173428954671571373132804754825927617043378457799815000168451967196664752847, 9007836187082518685036356739793187792845982511088020304887245789556567564055]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 63 + cx = sel3s([e[189], e[190], e[191]], [5139361255050232661773452561726452928115803730344567411456642256556217045338, 18849283619433745348738480276785423370734769795033289874458118507070173353564, 8448578350964247311518616492977206693278225803594287158372550008714482924618, 9689086950770336907190180706142608582993499523814136266854852845122214734392]); + cy = sel2([e[189], e[190]], [14036051510959474100046039284978060652197630794277473374328558492372137493500, 16611708132761924749528167866816090876717761056993928787802780141779996313373, 830643686092782069152588625317289527987176650776268015346372712951408738404, 7124577892782407025863252010240336830171667706358033009166413008136074540762]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 64 + cx = sel3s([e[192], e[193], e[194]], [7037199118537155369331275916815326054696699996573020862644806346516390510132, 15801832773874273151484928140234822912161499004629735400320792200594998558674, 20529919447890597649764739102616587236240564012012882223198985848792346137419, 15587579342628673804059001440002406839596944474602936992474297171186661645909]); + cy = sel2([e[192], e[193]], [13107688056462500445700480209995877016295689081542565992250464593152667593220, 2950999836230463387014662253708191376901146777669866592618407913815214817829, 4910645882425237270468350930391794068554002250789220952036477599584216368730, 3842197005807929553563656299566067039385580918555124491435963737335985608367]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 65 + cx = sel3s([e[195], e[196], e[197]], [5946112335249256697077095359378565725733629742750694340878812663903909175901, 19030634249222736450152769682445487635301904450722490014396919999971262563725, 20272077332559936653726679368964023857291782018546895109417787179027229259529, 4325773325239231432990045180370600024086140077952119719002873860984820794777]); + cy = sel2([e[195], e[196]], [7559787099338642680034184654424868894988928943730034769673486129058256478240, 14955054800505659097184643689663447282484820948805633199847088945313706647256, 20527315092050743721874398127103128550881291654522271023332206474058940158292, 9254615232744118309709861811378827051213745889996697483998530345751148041402]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 66 + cx = sel3s([e[198], e[199], e[200]], [41373522534463253583709483090344938032869463670116114182911184041610044395, 123058269904779894306385100149700584700988943576532400555257363214064615908, 2188259327903131136942811179577591848088244960706164332041753317001971084806, 5677272600001855408525885379297081872841669910685379249005421935936405438326]); + cy = sel2([e[198], e[199]], [1812970364913777725848745565574644898635129603904027984751613694625700239455, 6325479481133126048154398075474627535983053143312386360869927669212098083218, 13018920334214076613442336156617958094802950850259563883918734414290288034687, 11007863126994999194753256186448493793850907406765917922947224071691321773988]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 67 + cx = sel3s([e[201], e[202], e[203]], [19366353265983664793480214800587120487923062015491759603977854723148315579274, 13009712389497066149642205706505053720391552889715847781477674095579012684216, 7540090586243428109828867879678893096981460680323209865296583411528024312326, 16312880719251887899651071843693753472207446322138586240016038563189666076704]); + cy = sel2([e[201], e[202]], [10425762558101863677692090103799691698591185440858290129753641015260969124568, 19889759528114345474077603906066211135049113446169104039752988610769598108616, 10189577411425365730046714422122931951193107064366232919940491025624263274830, 19402847860324611226251435664012558569374211845205502575728141649693622181131]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 68 + cx = sel3s([e[204], e[205], e[206]], [15647575844595805283124278572298605369081553302159286302039104118434564547757, 11119588224460846619648329471078205852940427394545403397495758589586019867123, 11531502595396972280500527673404404955773795456604503116176223280757803701142, 8880302652736630728773712083983401143315564427649676162399333300472018402820]); + cy = sel2([e[204], e[205]], [18121989769429113110431033241130632527148185431169035091659247063715924437727, 20873727571773157361636727287434618496229040659202161464546752313173048350714, 20691117161323169072636575178583071560333787206766658873639451682743014282486, 8341316767034979343476640425183870254531797329971610276320314018660072501097]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 69 + cx = sel3s([e[207], e[208], e[209]], [15099126396506559307312697471585164108461593918632286769972271267945539855806, 19719992822745709208744805037389314455441129806628318848823336999297717461102, 2498623947360180463813005839687911187525292314091943320262937967401409761873, 6773513521666107580427042608663114222160509705880285715315137855519926605076]); + cy = sel2([e[207], e[208]], [11185464183896587792324099270269738719144599552792757002841466742562118002961, 17962378754832909648632213279341274522205662106198070463591287770511029247082, 9572883626752796327156744085207279145562604122052196885537416403686418306743, 849739335033117039567862203783008236118271414428303942526044722712316390134]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 70 + cx = sel3s([e[210], e[211], e[212]], [5586425841805464495367763159434170408121119147683098906675715851224959199555, 2275887592294698256371035540589451793263643729528648494997423042939590025265, 21623018362589173579186020601617142922337607155324626054728009524185014872882, 6470935377837087985284657580709150204914393986124872780110914178120147824883]); + cy = sel2([e[210], e[211]], [18977748529759410811480134751116373952642146764796083016667926272252310801539, 15415054474257926323577643558627142211566179025425425674112343915385225979379, 10178696720359974033063364767044087765079200964723755314869211737985682962880, 2751262919149939488788372835165540688204591943865442185170575019042791606144]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 71 + cx = sel3s([e[213], e[214], e[215]], [8067396068830332270789178613335432253659758303711969642714931687060160381303, 8639011650360344590794984878540401640139910601923862912593792315052343319076, 11233915498048422123675368878285943174009257862418242010192825609765986035356, 14474288438243449444797392475230229280689019808482654245523987676777400402951]); + cy = sel2([e[213], e[214]], [1109389204114118726338211511183391561882818362713716952828416479757048480713, 20658495580821728113676289889282525822016081521980495256710356417074439523320, 5734616557338566574377893898300784804059511397655030429323489999855673254133, 7694030151585859685333610687574701561418848021817379115721565206849330185976]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 72 + cx = sel3s([e[216], e[217], e[218]], [14694205333290671963708923368506587408024223912051732033761240288927263651380, 16846840700984603406007084554481852964137248522784508429412010549513323188912, 13176399412773372610094105377631574988462669519590170596472033646615482615262, 2687848140625094867763341291336975245615611233615607599401834736964978577349]); + cy = sel2([e[216], e[217]], [9656049051507081163863869851380474393220762381365090138663873299937439711626, 16257833452680722743254377629669121273261457821544261762335781528496650481193, 6465537052899418297534883094198381748729828452125250541158965933076691478294, 709697610986733714785106299677092114124154955937070541190663241187641683175]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 73 + cx = sel3s([e[219], e[220], e[221]], [12368397247649882906953915991250714931614715588424094368585746160811998953306, 18782888042679815293214947449937714827609414183597755427793821090364126288476, 14980906670860851104998617553690749074165805207013703141953243482569349981523, 6579728809126224271038924161669519472291072114357057900231021883849035745958]); + cy = sel2([e[219], e[220]], [813793955589589118694666569995091571992486583635127942664119751723536369919, 7944299604444967298799338830762202580774561040186193713045849824532426689590, 10002642178009570948907228870686621440930898426698423035982221525801621370935, 8479337223317874954343670583381865510386888037444628897905418707487375421325]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 74 + cx = sel3s([e[222], e[223], e[224]], [7187732531650016705045248947412886871494880941757180032721434029527647591174, 21429737681997573327768382790700665701419541321736653106996131182050077581533, 11836369351087123833634897021408898134248512107687639835461193259880629295891, 19132784475506243814038464623366364810380933540097619300595341694560215897043]); + cy = sel2([e[222], e[223]], [7505964932526905326140236282846132917485872002527800757209057356562826370965, 7446191000078603169082551991705097881255381261806164450828019975914186121730, 20501368217451607884813098738754813918145802982055856468691458112065708320700, 12111360534733555932929570216465933882611889545473508372687771008732927246750]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 75 + cx = sel3s([e[225], e[226], e[227]], [11880592453253678945312808709337779570677968939895786745513483795196121148239, 15885465855717299709344092447684246292163545547216436459368792952573638150871, 15785265541005027154032372858808930773051366971093462129449868653918773012805, 18569197812514885943202170611076608358219751234067371040250790526837986392838]); + cy = sel2([e[225], e[226]], [19319714983097503154896952315362236888483358620825042533226116711980128027594, 16203396727641772481371087324762669694595077074099718953937599120235089562441, 8069072007055358551280258194912706575285364270109077890462380604843344248137, 14879918508369225877688675007526587407926006842700210091106836056129459129297]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 76 + cx = sel3s([e[228], e[229], e[230]], [4665897628623235203637312232323957679483103295583092141578808282040205079719, 13624944208440724520944284383225072602905876122550187793344788447894380752405, 13240065107073736104958720757918020581159288509346627802839384665867212601652, 5404872141819776433203748684385984691445987755176034496638153799038857512389]); + cy = sel2([e[228], e[229]], [20713846021060085908071105513304556412817630308151607438714049866357354550752, 12308156363070414998141304956459569678321247441462175945058420898750569812289, 7869135919638822130359819523186642202243136255410646018113662355856102696554, 18106721900555088660857020092432838491684499647468676099930405315728768226404]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 77 + cx = sel3s([e[231], e[232], e[233]], [18212889377782903846034117170355855193339291343619773736161614903123505780500, 5724371935927035469891307360583032289870105083635885948626519084327837492412, 15018564556029978781532805643572668082137657619876811702006326742091833640503, 1980690392504623526106436839420486135508948878537486163191798777558809427629]); + cy = sel2([e[231], e[232]], [14150007145691261709583376556777715716099818143565185837820917588114159379297, 20022624235079706615759218203483775626475427851084411515081825296526003331089, 3653600812499303949236693031235500821149221426419723829534939359247593779698, 17687818220966506140783793822520601258809092691114698078370817997514472088683]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 78 + cx = sel3s([e[234], e[235], e[236]], [20014362392122060372382978901186124374461219393111624832280409989286374019151, 7678149165067745993890478281145655203076154350573466295728882151032664933813, 3225698435546178867794794576435022149554488042976954865856749306115721077662, 11309031064526492555710928277445241789558140050876975815061803061421298770441]); + cy = sel2([e[234], e[235]], [3781524301363795687584984812832316590367643113392401377547409393858835211208, 14954378542264966404669454369751236758988379152056658083888298000396867621936, 1762346050163239223923110798598502612894079706374187891044283390513959164382, 4511820337785812086858556857918524260240820667203320876468844848816354037596]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 79 + cx = sel3s([e[237], e[238], e[239]], [9734499467834650890192498500298459962067559704398257089549121433441674087115, 5215135617552133686060655322881340267001697536486897440412599806944209294580, 4188240743485809003397687109987123955188618656835900004447532212211334022150, 10646753846009034357734238656245532993332944314059322522045789305478499710981]); + cy = sel2([e[237], e[238]], [4354361275489184569727883669567924050940590772506719250562939951242102459556, 11812679101253609883065116716426172392592451529279171373836703114919477018303, 15938685241828674681356945591247179905945286496762161102822537588243702016335, 2396399767043799129388585002615296373717040489521252489057941017313192676808]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 80 + cx = sel3s([e[240], e[241], e[242]], [9547054830379311239093093214427099367592481292385809745992166194109928893132, 15809211758984123203744250589992081971737344928666499432318524828207451637502, 2317605133926452505125489082200124096354438531853199813212363802981648616781, 11720218057191867199121604823871387192503455956722025424220873115151171617846]); + cy = sel2([e[240], e[241]], [13627319622459471863286677434492810110443625239619395014230589374758547978269, 1429116229161069264517866355097922507661063351137334983223517731193665190730, 8760550298269703331457356635709373772631633074463698514870757469189354319951, 1695059580774200437965405056230849147697820569205516838038543601601027611172]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 81 + cx = sel3s([e[243], e[244], e[245]], [5462734684060346793723051717116621327144354637585189012464556861789633254735, 1574368603481037100592052661337337694471748163849816976465511323905498090898, 21017620690824743015216528248522045704369427405753453300912995325024062710748, 335774257251677761852834523904277348100779994383726453798657085528043830396]); + cy = sel2([e[243], e[244]], [19956048369873968081515874523485925798105246605761695905870795560621002747577, 9838187823381646970305000918713399614038197140004128824046441620722100628627, 9761598443789947780667845618272433395258577614354457312915153694570906468084, 5678382193061301565104967410106463714669588791192144419019555111526838349597]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 82 + cx = sel3s([e[246], e[247], e[248]], [14120934246971429747829618071104732571014495017644755746350410437296386191831, 6321525285327330824512104449106606616844709114576208465479970358050873874349, 9828948304711234867338016094087396323909457869737239406325931677882463208355, 18078003119304519959309175940845224181126936983821549690560235900824217790962]); + cy = sel2([e[246], e[247]], [20946993100078048703890437478651577253995893117657499778417778292965813281806, 14356404021232332461217625395600664517715960389258731685389867303545696108853, 2810577432005044954032138045179699447584646279814848461184496089430514835598, 8767040452903340993130881597424027588451974218686780194782289690479045090015]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 83 + cx = sel3s([e[249], e[250], e[251]], [10074124480658003038181060843544012751655263682971006047574974839001332519369, 12077899488247602319223956898393373607365192976733626340271805296106145121355, 16135938726601100366620437452815649119119591825429317780601932003124015669028, 8179818941824323394614877573129531443686047058703515433852568295536575458823]); + cy = sel2([e[249], e[250]], [6742523042997173838799423244280133352249230789995302906545025471831316165384, 20571270140927253125417728386763981919687051926731085366043566448009069227191, 923263495309221023264076470401516657594260797987069910555955234338720881738, 10846387476002903807347429282866412191160400241233297902208546470305682775632]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 84 + cx = sel3s([e[252], e[253], e[254]], [9734317150772506967195863825775613184177780587009303743393397724706924797808, 11208201130011695436334652728584169313726840614571295516236997046457697153324, 1222680486642983364052833343811429934453835860106899436901212790725638894713, 12019238493894483056724448289009076436822742112482573063847552596048227585627]); + cy = sel2([e[252], e[253]], [21086552119896541186107689532205383551960199801453516689016972250104900583432, 3056767815025727154134820681013380076250249612276183869180162238277626532027, 8232281317297626211055636489579107493658454229617058760791605403582002142140, 14549672514437654184453326941604694948116368249587796119338038904533837120165]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 85 + cx = sel3s([e[255], e[256], e[257]], [19897146034704593618377175099239959996606643851373776355482440566659528393713, 13567220274372260527197800746127305934893509881083589343644604005840555405371, 19175080795372179131749429828665039169211560827471558543841205575231867635965, 6917449549804522032498038894724900459329834531091410689621076525743611296938]); + cy = sel2([e[255], e[256]], [12223657826278264815494051932052421695129917274617530304443478482578919678308, 8295548603728936503708692859047908287111164162226375098145740427985958712611, 6607229719664137890140258196376647042900642854569636028419328459816951119658, 14110421155257010376968111292134385106023449978845823063864491477811661996253]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 86 + cx = sel3s([e[258], e[259], e[260]], [8185677100333640041421355126903921619342273914070568426300075868606141405021, 1670466886055998857358105826250955310011203741639197041742892893805477021056, 671638389102335040808130453738616724135371178235871000115155863725237535561, 15155007602444057841308084879571465766457754342497255444459746080732112337898]); + cy = sel2([e[258], e[259]], [5730721122742653576294802609542803235749403433458024692842251665338778112357, 14898703166129675283863893661050084311561656604196737234704191900969087474133, 2459074141813559460216507737311533957327810551114696579502401763839835381335, 15516107503085209346875467061340145906150528515154791297494671889511125291207]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 87 + cx = sel3s([e[261], e[262], e[263]], [13654034957145907815962106285631017905892861670471883127206658577251723739165, 8633158844589460452837721754446206625865140330878411953122575379370751622485, 10232722293127899126024059808155635562748968165573438955077544464410325913567, 15328263964181874734867171882863588382257876665732200627067485961683406281267]); + cy = sel2([e[261], e[262]], [14648234277430895067547661111448501238234630914838612427562971477472564218927, 12394752068682518494797840832073763890437175762631359486643184011399642941695, 19427382571659868487644833684469199967640111942906298364811415181281091481616, 182598521940883711045871251162735110551301299145061787687905605212153955957]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 88 + cx = sel3s([e[264], e[265], e[266]], [10625366736090949097208784405733508126867531010210504034282606844498242195460, 5745457912443473561064508106222759378152708028067817946740487826967842596074, 19720099885004155494384241598041924024056522066497340576395346816817691557959, 4411557748754390593675263772383003703921572549170163035845149756207936580167]); + cy = sel2([e[264], e[265]], [14732913015624058203205922728424826465278063568996784510238321594483738024116, 8539999814473505400128567752428776172019356440581684960088711125461388816752, 8671134805346361443739204337860301475415660510460401138135319415884938499794, 12889649495366374604591900250806268552879620119403975808021738180701264567775]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 89 + cx = sel3s([e[267], e[268], e[269]], [8424620995080153959855099087384460880708718787657472234234125992142104413784, 1213413054380708818479960383614577938132447492306231448400493113424770669073, 17993616645286674150803280096391639271887381916203322164869533675674274690369, 153030618728554031479557843767027262505356544554897273649773418701874030937]); + cy = sel2([e[267], e[268]], [8774350273413061850499929377371854983526435316805379820854063460345613579740, 160874859222003480689240665151063301233791348742268400199413950144629148606, 3864981636983763871420661536128329698816776138190284810024785475130342429509, 8927799801878514388025533121285392339945739901708290822291826043102309328947]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 90 + cx = sel3s([e[270], e[271], e[272]], [8559837035180670877234803295116293964077309001575836599087921933374799946149, 18335809791652365585369283816437201104065890639760635850904865621132150615442, 20223042693949477624057496950714682763488956308852238106089638364544757819336, 956531986282862630457073126978994765430652506058410664783115436243377137130]); + cy = sel2([e[270], e[271]], [839500690449928047855071514156387100713350925422279056462945330783580827563, 16644736196961833445797352798716804869773621626799896168771841453493474463773, 604545836161644183235683876796430911898168138926947606928620724963455977159, 13372011982201734306725124438714782615028067496534473713140957917136368058903]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 91 + cx = sel3s([e[273], e[274], e[275]], [2094128027031828157560092686172909842260483168819281235210539106189673022187, 14831470033363035728579660771199958641838096197597230010879786959469055433282, 14580113677826055589909107333827815551732916495147612562237413782243389891044, 21457439024195964947733246659608329461028391228550531897929776149059108022400]); + cy = sel2([e[273], e[274]], [11349460624897126395359735030876451695289908168621129531254166231469594999395, 19428708736392770387243553726555356520800900418277262898221664159221843559913, 4432119977004888069457445133143529511285856348699582219607694824086497898807, 9160542608356323143471297830883618199584611885676024272763585312451903134897]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 92 + cx = sel3s([e[276], e[277], e[278]], [4354759259287077683606602421630609654573093874872166313972356669642414450557, 13648951383939395268518611670175324834705441295145081802011558222046663990635, 14109063296906889436525684297777423342039664400074253643711178181120772454442, 7920829805332901764517739207944367186855755092397343817260945923718690867274]); + cy = sel2([e[276], e[277]], [215179997319049227050677351252505122489806707992988193421803248841509506088, 15514289571504865101354424086151224801481680739860239328031576438563705370521, 5904618612526890474103927634405504783798865056645457180704237978103781216311, 5748211772814574948909294216861178264766343013494657271260147929020820008781]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 93 + cx = sel3s([e[279], e[280], e[281]], [8507753630181199902479216321724505843375506218865451254864654248120523505482, 9450124212352501425016224885075456626937137054710829941179274211424392402188, 14617760695968479875555170000896560124384001439628509056518085157675385430999, 11259792651191057957240332532512267993084988584437199185342993378682410436972]); + cy = sel2([e[279], e[280]], [10815868200773974736475276546832667321164179489094422703987813447328543028788, 270750089909256057588643640569447562301277634245971255743235422454022028456, 12525264811662854133497240150104162834870195408235601736200987821770575683753, 21492322023082787855062324449039977497952909569982074113097211015628539637105]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 94 + cx = sel3s([e[282], e[283], e[284]], [13109291774440010508838814834344208104350382843329321595606001193219335478061, 18178081082215000330236621415683992037792438414607902561151998975591610672159, 1825689425393769600328701494994687539687903068590739461592021486333291661266, 7793684058500310840246186772109776829776364159558184911962167538064855177290]); + cy = sel2([e[282], e[283]], [12538966751785809241486764416198217361134417700423840996157483469862141526006, 18918692038570377322252840249784989027502652471358614978414943590808682898821, 10739840318098234656669579810873413661071494114926975536918927404574756289141, 19177195314890990393062332918745346394029203576215723513167013054282705104509]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 95 + cx = sel3s([e[285], e[286], e[287]], [10225920463059329189289679689043403756461771898061631555012236633674500607894, 19821058226025589223575559712382894896410588163797548720897159700660021786692, 4342530929634070742874132949165242936564090903607131574088848141363806195244, 5402483411262228419126012059406829285695506472234034454332016959299908934815]); + cy = sel2([e[285], e[286]], [14845268720181506270843668435047795143673881800644972711347963164805203292028, 13672974733920510644893233723674603797496603310630434825704649796138313401676, 6411707949262855152252009198588056473458716851460397006471717726058983234993, 18779680229580121519443328584313676056219616039194596697158403462222387132381]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 96 + cx = sel3s([e[288], e[289], e[290]], [4836760236524137019788853323648085337078365119204570171912328851849081302469, 17868028324749251162769441309905628927317218753130618155651317995445082462075, 1772933343466453031175704703581215603932939906355841484695391914536709138761, 3546600638749568273439745161679319484611182076185127936908592367054940973889]); + cy = sel2([e[288], e[289]], [15727462261854339392836033936665994570356817309630572739663218192786419709049, 1337461376408438722980356088847283448049292537148264126525086899131501823829, 12238707625348281750296588592788256417660177170554983893114345282873428793086, 15525437884516977515442248737754366741726151193578138245479811700230576818338]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 97 + cx = sel3s([e[291], e[292], e[293]], [20126221763126240993614454578144859888701958472483256034667342833856637405284, 19699064573618103786080175406330154847584332570598813466503995653274429215656, 5989506922601319310850294681562133253116809072854033597983216925515271522735, 1000911579713616921402553874631906432389325985380989857769833587362794312630]); + cy = sel2([e[291], e[292]], [20063374408209966489810045113711694748195105838875731221209079272072900704065, 9194215440981146522641296536570335847038564333573070389731736048602585014353, 9856108459841119062384164372572927792749846793172495377480072007040372623532, 16456996545907573633695460898581306270452076960241899452978065386508672788709]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 98 + cx = sel3s([e[294], e[295], e[296]], [335301756618437339439144029360964383534478515390448989496515998200065120560, 8900295787747118853873347685755889791679080209434225159052383890249026687118, 7128354610803275364524320321498051406687079176221803083268519268078181474486, 10587524605383993790235166395264599817111999691721750015186077104713345396025]); + cy = sel2([e[294], e[295]], [5048381480643837407413881593434054866090196361251156389103862466064034755870, 5633507321470690754598569732643608340435754341640194463936636395149026354734, 14155759183302230320588700447409830028824433982845500795956824041195173925296, 8029144329154622500871732803176023714578210937344495829905950083327660868243]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 99 + cx = sel3s([e[297], e[298], e[299]], [4778598962832696072676642978625204359871247189399816084941520023705687820799, 1041656446764385248839445285580789894072064765593570151992974139621577464190, 16604772736533716135897718386428759521995904068172209060160905451073360508438, 5434449975739162120230503825057718004673241312353068784008427484008820677975]); + cy = sel2([e[297], e[298]], [6056883361340614567315212379835078890341975776819628834401238537031161511515, 12948572080347797369632667255105735306309789288527345335385584655912071062991, 2047203431451992701474247296709372094572802843600017662927813418631212656090, 4132565694324682855622172238297326586214736771195057409015171400249163749388]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 100 + cx = sel3s([e[300], e[301], e[302]], [6916961985409927380628327393774423923434707859806165446564471158322143896430, 5992074540412063352415311056228455935293166060283849428112990098777744329018, 15928943908823412922424046027263578805013830577468518797177611363337136608209, 9165805262654590321870254579036281540959358923531526687992873621654142568029]); + cy = sel2([e[300], e[301]], [19113997592137471372275504986229466743101683336744251847362311356790431849943, 14004712182695079610522706143578502649621084194457654873685315715331271860709, 19337382334092833222650792928980596008310896977712987991984497026496963328127, 19598147310295874176650103171586127283815601834965516057565002042355878900904]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 101 + cx = sel3s([e[303], e[304], e[305]], [10948634109523663410073892096301229908363974454242026292710198013874268733721, 15429431087099938206375989354827088309373134102432374989679474148007045226404, 15424933350139202912640857850279200342934439164947473620816895024212952340734, 7249326591094430300092421476233168005480477057146500206388167575638063334006]); + cy = sel2([e[303], e[304]], [13978844239437491612582517692269818179489578402023377256168376965218369369939, 2030861900932117628118671150363276958527364035939087076359289004302891739342, 15817916211331592751911789779171300716227893840209480318007078572691072662437, 11627409307299027242340485688430280907603952564355973323102745520536413654480]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 102 + cx = sel3s([e[306], e[307], e[308]], [18995578047969205917336954191535061050094635635378379108624715348396977983189, 4225372875497776800681698864198574622710499387413704002947025943614195612470, 17351437921298308953512714184518159189123423974926314714485788395814969849744, 8648037604000808882689040136601171409077000943524268908332163815927078223586]); + cy = sel2([e[306], e[307]], [13847262887662907650775044616657488013627923118617883909535158774246706595453, 16327475809001511779800793713087994795688106377254965385366798254360171531485, 9662682437808722890180813130657795806130406684446667889065062080930078837985, 2502962306844881519115529360019706751646009100590601561262014681428188719652]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 103 + cx = sel3s([e[309], e[310], e[311]], [15920090333582846150341817050024564335649064112537068561935372152494077145209, 5605643430930274732542971456995927736808851585930096579266761796229766916419, 16417626123069839752924241752177228747744623168825833393208640134299321885615, 10047503027147056454952493773282171263110464519924564641292405110762258997532]); + cy = sel2([e[309], e[310]], [17200096279975283058225939790642290750952306062383335630123644381672038262866, 9789126042032908977600199303915152601153926597218655498907321898754260478045, 8000890408406693601499028261723138327296400099255905955307073434675924377491, 4588804177243916206243160261751431868697632792491002746485364561078105548339]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 104 + cx = sel3s([e[312], e[313], e[314]], [17405833224461846119127359023602459766899246377474167154738658246656617261320, 17497966949182265924717994126031328897613192226672854325764486326873236644838, 18112601253331073769860162727184645241197911130662557597456857637926799952771, 18917984642138666446882277898695258545411024830699319452174655151221791211048]); + cy = sel2([e[312], e[313]], [2379006936139604897517171125029127132096844925377650383092744055973319489305, 12749848257678287712950295235536433677019860991481258729313170570275169590140, 19636804280533422414605179875456610832289030857729756765481423873607782896032, 1918232436869295272222782754406246415048195875894409329377075908962690232744]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 105 + cx = sel3s([e[315], e[316], e[317]], [12917351824629483440622737030529674983967542988637720886395195031194160632079, 8841322465723154205678020011172362816775587975165151786897606627457187155545, 14002729598867581256643018976730132585331390790166577050573493502425421127182, 15268061642248917754819598857052007481406516866069427006418085798086854466171]); + cy = sel2([e[315], e[316]], [16674117998706559220643814233136742237729068875288271911312504301619597199572, 15156988565931490695937923747057400310765196912391035444903438612244254494193, 10444568487973458741284119360757120950097746658650645740311119491238200646302, 385547467860345680569692008987772843718726855128251196487129380665836896693]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 106 + cx = sel3s([e[318], e[319], e[320]], [11485514708661668839797104792911993330100465395538998907154500209956717209980, 2378564891356297882391172511058064121371341057541144541265151112602629407486, 15431113736930357829525054375951018432490410667610553241393471463868088483568, 15128200972190674116782495538728842150282218770763850888538540847691112710086]); + cy = sel2([e[318], e[319]], [9353349283824572334689034791316525426505799181965760097150790472211583538470, 2565250682258865603262212838934596650511603775929760392607203509225620090349, 19046693709474252308020355261538860605259941620276924614654553264840108783324, 15978910116968143273641610096037639009526883121076925418594134134597880991636]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 107 + cx = sel3s([e[321], e[322], e[323]], [12732753810746517185428320079630798046136898905138090354428070504022561261129, 14570979590504848605419638850092710612576634760731998010991154705829891960303, 7081876654999237785822068068775175823259789900038464857602167050792131983158, 11911397750859796885754857056361505572472692036239385315518934824432070976827]); + cy = sel2([e[321], e[322]], [18703753174721947326863540292822225800192529767109903887849391280378615950879, 19613778040124100165889220227898498533129133505873538625549588791740345005884, 15039820717144729975607443780109118368904218216499993640810787891283371396202, 7893305471806697580362861198809218871446498187812275173987543199956558198521]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 108 + cx = sel3s([e[324], e[325], e[326]], [4396441250850868966014141809834014631796411613521413364533261157108807304791, 16836648497150572549121598580118959226192434996387135129991940567405870268725, 19465159793724690099931261171165210166819967882352842855510624454147581274670, 18758053793437253746142721581116755417112792746753684636213054094477781477382]); + cy = sel2([e[324], e[325]], [2981405188098805378415778407831807030725264692497108694734382487084076855210, 20469108288868835484927940943356623938045830438424196869633899618683134613519, 933161936100801959708943470285929527457537321589386575156679532348625637985, 269411351035529607018992916380602655161076148137839318392666564540836404599]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 109 + cx = sel3s([e[327], e[328], e[329]], [18448980711993048271679830178954781281796619509660919482566515137849326949705, 19744948717433186245821639271216553763028577858032707139265783707853921912155, 19819689638742986969009459074952228930363474994050981268236002838584672060867, 16852310388498099768769862489306840010510354704163417110628769300551675410617]); + cy = sel2([e[327], e[328]], [13538295481673593444396948705042001770075594914797407330259513771278632533788, 14779507856773747214980057665178562325159137267699293184545672938786460137545, 18422483889209125213732972603904783756680200857795267276573963126785961918198, 4225410028652447730956912638069668360808266049871102249949930413024208501463]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 110 + cx = sel3s([e[330], e[331], e[332]], [8789386218557174287787274081526754120821582438440596481230009033085305168336, 19604730670978725971286378588091820043225493993475360080974783305559899794334, 5754400819903612415922678283536801620301085919072204701407326554289862247, 8133367062275595631112870441047385208403330263311352404563334748971640119238]); + cy = sel2([e[330], e[331]], [14711352054903619189890311113670897561016852508413508359380114647296690234759, 15505081148609421707654891794900819606599284654426944331953154100271365747946, 10498745521808868190882616751430118808278388180031887838543438537592782154020, 14283723444930116423678497723705206282538086486601870839003576853131844860728]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 111 + cx = sel3s([e[333], e[334], e[335]], [16410879947793378178852309134034691965068173351773904636443113803287073468165, 2459742793248426443467557681746013841012911230130900204552944771295773437965, 14148653292536659971692314351826075143664660164844520450779907656237062521024, 3823568337665129538914482600317854425115614575078537531810182911935066246893]); + cy = sel2([e[333], e[334]], [13525280335627612179489028500357999227382280656020782481971742893960563718069, 13906986326008385599879221793305773429690045797230325194617940541283670975066, 17928827609489859058711914379940226888033289004797111427100202351646756410052, 7751873896780721346657011057490735623065509677587909473561532470621436328656]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 112 + cx = sel3s([e[336], e[337], e[338]], [6360670162449266467030644276184864100593477111108480032796373772347480922189, 6238026479435781753480651584008291445457129357178771800497280501659229824509, 14372912505742790548866622516086728314858808340582492719789600777407852624706, 2504355035079143757819920622529907675398702401030398889002491033376003993290]); + cy = sel2([e[336], e[337]], [14257529111287275777165336596087530152135443364949890695933859730727871380736, 362630247512640601958597579829458123399369864147591061426591055098065517091, 17799973102921706872164223253101644481160962872432375782799635148100439645882, 16292554915278539427322523921562887226516459098783274424269678044297404132797]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 113 + cx = sel3s([e[339], e[340], e[341]], [10885915218940734071225780147170174316285574070557833147925199753671864395970, 16952199638513201931184233985077369412021694081253114169931799009969944845190, 6579022618957621849920927439620464464347948481098737101648586523931683396941, 8954730328909621308689740172956171586217761959578457105814991014419829084276]); + cy = sel2([e[339], e[340]], [11029057981581926429073650712620964484769971154264787930046960173769123662678, 14057756519867963926667557918235357382317971790756175535573262066939972782226, 14508105580605381633693926053140229084417508695027158358695356916669309852365, 8985315555716651207654399675191261186115135312348808559060054412234307291987]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 114 + cx = sel3s([e[342], e[343], e[344]], [9591625063099557813317657356201310094684652614430671855551305338577894715651, 21710627476302748728292369634413673464477226906421695181551559967392730749884, 10189696652015358480306279349674126142601586910844054141319090928400967920492, 14575448555178809619615329760249104735737622500547600222673171666044253032327]); + cy = sel2([e[342], e[343]], [13661097518448111362501604180288489621905168345464166181035334250815558586292, 6541927678640542532346030316589325212935454830056081625698359290342280209696, 19655534040611331062875671654696954076416928174908705322979343601347718766841, 18893407984789248251370377180059349323487262100431967496838185583910928677618]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 115 + cx = sel3s([e[345], e[346], e[347]], [18886312892727437565309004732784060353326028914324367568840970250261109059822, 4969806713830542782459289156960092729650598975239889678453184524343618399703, 16622981471374298426508813360547940582831388597832992696194782397307736766285, 17207217606628134149600916884515052475396230199786007830822049511835023327746]); + cy = sel2([e[345], e[346]], [20097067895510901824034782908594630518461908899922907976633298936904395310483, 7549705567086856493177008201999701185795474113091244286639270279144087122600, 6359914741562734059777896085058461481450840152242223222499923214787802554266, 4523686415566243191697029234004097207393002925819292838991423859908963592134]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 116 + cx = sel3s([e[348], e[349], e[350]], [9611980085915454916721710377398516249069657290776790665729578385653465657608, 2808629496317279665377941162907583528406102092075003683612652910715356989065, 5146801454146059628396374424703327885864890381251241815068083494646287896482, 9712822633793199870569132733680515369277288793857035023884821044404624931246]); + cy = sel2([e[348], e[349]], [12531050708955702438977554896456788618229483698488185884652134859969233228127, 7759740123661798513430229604959580258805004199555419745903987161601748379417, 12676630374277918228347114736241248443643025357735194824989982902529942631987, 7957263793605029493947914798589160413665834659013858298537818906355583201202]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 117 + cx = sel3s([e[351], e[352], e[353]], [1741783015222897367309800534949631760951606605798891132137371646304340462458, 15753951377666759323512681415584732767525844411650049393938120048851867306800, 11318371057965241278094291737048639440256637452901941620275041654781038395027, 9043834682180335510097190442699980857932890158044577184782692529141130240824]); + cy = sel2([e[351], e[352]], [163811524362553669200342941603136686901966525127089114473510248213711571683, 20253563341205755839890642239029020576032044419644567576263861445077574198624, 1129293390247992239629138633531986375671761935795719290973869330578475352706, 12864200497534810115296604114235985076138506691530959360993894765742849428715]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 118 + cx = sel3s([e[354], e[355], e[356]], [19845239752872171546325855177077796460784181475810291663797620022786920823647, 13524819092286579506826904337550390593582530067994137276480823345309729489925, 6812066149319989921217367650719188106577252681936159930531352608504453614106, 7222950523682776178187164591717978364824407709855563372464941677077475909161]); + cy = sel2([e[354], e[355]], [10413380090476979012716640518612591288231919255093118763710930970879877622297, 13124406349881024599134718908760433545313158896610258373843772982921905937617, 10544285464977662192736078007137407440374594005235468167522962555324745898878, 4262511480267656654185538760448950673777806215660569720854482040852407424457]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 119 + cx = sel3s([e[357], e[358], e[359]], [21840644145325684882015312401601386817913954005861480185552664536266852358123, 17245795366378478445622830709744244736981686761608208515847580487483274745119, 13807005991933596253278252430914713127227144098393113439031517565273756047729, 7508257045596568083350722191515656587852775770850324460219207057837744147846]); + cy = sel2([e[357], e[358]], [8473655227220833354585864220301666825011510607427101884196854510787991763100, 12360766780968617496459580910362246207458173665456601955392871687431450155437, 16167977026195109940196928407142099851728373085986722415539043108707307260209, 198020065443013508235269047245522994471757343128188653900779810305583184096]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 120 + cx = sel3s([e[360], e[361], e[362]], [408538855946993109150255210001390137328762855947155164309686603040268044308, 9956106896094805762100856187967638241058986877712947272175178827260922476691, 10413057148806203104120616811444687722773209463542545789320471445420824622479, 11902530720628689665925185225980720963660904880464037650526790156354563593259]); + cy = sel2([e[360], e[361]], [1479997830732538227417547327573357263920837878818360220214252494202287418999, 14987839414386761194654231515173353164503075512219993482548242568337943854755, 21713504951370328462347781999791817908891510961297311340202728964936620298516, 20863127910126532592439656993995677084099363872120709138917554483343369113988]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 121 + cx = sel3s([e[363], e[364], e[365]], [16909060815089078676939420644976457427406147473547024017569298235433420995548, 13780618743481311116310648367060473410410597997822855004264478650194424563904, 2732495529118703111995546569867225395498452112166729675036576016860030980932, 13122008905793271330592610678764878579485569855365858119720314545298458579129]); + cy = sel2([e[363], e[364]], [9691045028169014905240668289132134803037917344396639164551352440947925851528, 3058069811496358922966440231506430818794592620746845318344939704361344313857, 5622098116652966523875299529800829301718212684029447361840034988407307855810, 7183269074283900923163991117263230892311528827769843151316519486217947924186]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 122 + cx = sel3s([e[366], e[367], e[368]], [20571623498624005071141088211057092924213194074152586837454876463843418144025, 14097761035973961045955839030064191145683851652701331413184120292691554339371, 4700343263415821617058086844751479864993855871131720446111591033305616384725, 15018715227933376511503870740434993985805930984246159457731592079602230709953]); + cy = sel2([e[366], e[367]], [16001479421972757821409642160488722706981473283972847385882762682377724905156, 16084059586346766494553050527349239192146155351545756557596881128274718933483, 15099192410657454417038148697642033151361229914558920712490911402249873000238, 6321931552493003117300598295325862984882362303961074819842172524617810976022]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 123 + cx = sel3s([e[369], e[370], e[371]], [9888014007610840933022906589732806947017424423907994528302713554488676542739, 8913934326838155827928873892003131738033383847534784434581587200177151201442, 11175569252941365912268295578620074710236065357166442341964835896122343271089, 14897216243038767404517178131890350534529367853478353360851740975433826101343]); + cy = sel2([e[369], e[370]], [15251452715683470293001422999667336542311051361914428663773647008481320118023, 13776813195393840721224885537714951191622587841642219673672717728440679190719, 109393055477786022036855578884727112792551641118563108378161158873180208830, 4672879465153093973501790898266208077997221906104002063988725461236876037213]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 124 + cx = sel3s([e[372], e[373], e[374]], [11201877561392804928547433284377926158320532448010089457664943460838007583898, 14898313039936563609742185951856291683792301837166735453885728355621976660447, 271087861779394868518887048853047396941902217944929345703753181641065491942, 4441061173173027475223782298768839441149677456214218957851727123779445089634]); + cy = sel2([e[372], e[373]], [17554707027223374526818340909253875671094356182527312776837442099008513816809, 20394478950504145529480516245504739970884923781915405632423034600555134724554, 16722605284146576015540826794584204150250626411625717127438407440061496436970, 18186321490023557384895834600063402151493085858585827781091438725428737294598]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 125 + cx = sel3s([e[375], e[376], e[377]], [8041169655049264647027531522783115313651111026520000925526843693578880103225, 14515227610041424277087375692958559713914998916629738058046674629183188354305, 19607007966889476958718540412171510858381328905787578252786377727252482454742, 2784733087979918000560628875496578392394872735862389774966301201852627273440]); + cy = sel2([e[375], e[376]], [16996116430274827689271070440218340032465717731948638724397047789367189212654, 1334527779675942376452476259926180292226498546209192760351592699867703388666, 2040984273885096997446285553479523685705477968103260410171803510149440153201, 1362381113387759937979242007199225976741286448134891397298462226220340605980]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 126 + cx = sel3s([e[378], e[379], e[380]], [19334565048001467439446889504730002771044189757270166846813098304840682799995, 12950908278008251424596267965839781465537497199604011584300739900170800951940, 21595247577936157693500985718654956851081515776736906827009279412148715287229, 15215490137474227465600889880755209339274086672218612829479984354294020155457]); + cy = sel2([e[378], e[379]], [11177666514768283886285136134046021748603781779508224469021361511080086667157, 19019917071840025176852012694579443932947880720292648245869222295962307004975, 4637723565271538497699679545822400204099231070875646671160251633445655525972, 17666228617432733285346663026898759021573050617000716798909504211448351974426]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 127 + cx = sel3s([e[381], e[382], e[383]], [10764100134342681938975151936530775454161936697333679961141539476099641645903, 16887585392329741143712714812495679688982136908448490321095843300899468374984, 17732836192725467148065242235309558107289861496038148884513643994394428900356, 1445275363508375975763521380916891145219085429516411016928665376398954093593]); + cy = sel2([e[381], e[382]], [19850691100864531393976360616243718992492409320965998539447518686463634627384, 11041690436464044133197365654525664032353519287590211059695239069687237542566, 12282683178748394297470306056106686277334235538468988533692942720363799093795, 21342615132598490749588725326967212830166119543678585183102318245731915882892]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 128 + cx = sel3s([e[384], e[385], e[386]], [7984775939876417845202037337929702281039643807160799398396389954446436630245, 11385355274910748832054888360458973063107383418973550712148639893241354902280, 1459026779105998101465829026524789739182470402517704469029876736898952870477, 13412666792048974377925483462948441322790663427949756029941851541794367956141]); + cy = sel2([e[384], e[385]], [11644088529951120466123058306783377782553679447618569394424538939634266570688, 3423766185322892807020818425845766412060736093511436910964946420904954554780, 4248997486365074893462023447486954255437098681775520477410894095041115503490, 13508520946233121439054409300327739993661203591041357972218149016790406863855]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 129 + cx = sel3s([e[387], e[388], e[389]], [5565157198993964726485879908963280627890845525340341493437203971709365228330, 7321058630137598328136197614874359518495943608220094707772133348409941566403, 7424926497991627209495812948930411917848701932818206777924739403931504666904, 2952280234707044917845773867363672510563637804197143708410321227590096039398]); + cy = sel2([e[387], e[388]], [16047978233091600592523116252839158499254716982332498268149527514947495047441, 3013461674923738179146278200182113922630443185951298626004001204030842783133, 21733406038088991240575501132398939052212396619770619197864537159847335678397, 9758173327391957613571828756022551933369392423107899686458119829785341358149]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 130 + cx = sel3s([e[390], e[391], e[392]], [724617195994552100441707186007100945318061137735042194166321801565168264994, 21457482305994995060621698878673403410439584990848189791210666985898821778689, 12733018351677357535096192491479720026355634001914123270202692797811692793469, 17876157828650849091584102879830086520321631185862731111337702980715729860154]); + cy = sel2([e[390], e[391]], [1941243639179655563586549731833523575056282199989602716546318426577162114198, 7186671745389328078718719957510862463188189283547797342924706384031236512232, 181655793349501388675021326982297619804658251127556562657041847324134931318, 17955220324559325573119985254939537965603633897040077737890918084344489169000]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 131 + cx = sel3s([e[393], e[394], e[395]], [20917363825188238552045899784153496987535745925685770873105753565860443082365, 4540090524117153259059229343653410962125958868702729157110889632173091362337, 19931748170703315405614719529478161068009956569206884593254142678501117968416, 2400060542928241404744010463507020801241694851019173560965950546401444426082]); + cy = sel2([e[393], e[394]], [1745736425002501661522536470728945366618822522645696668197436988525466413140, 3366347972505547411030140128225789817592493957844838153202867496815084725868, 13538672659394937012305631615026094764214309199641714104321427476435723762022, 5730310969197975636538358956003546448924042719236605822193245706535947879790]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 132 + cx = sel3s([e[396], e[397], e[398]], [12673489410414637838905637938820402546181123854591818062100393889121109718668, 2399760455052989852989301770450241617652861646522026007293921167342274767344, 20212599267512455026947565441242728025855774594658042161574807775907652589242, 8096283485634551421043683037450718803162713602325821677928898619562706870069]); + cy = sel2([e[396], e[397]], [2273218791680662828916671149332560291571458847138066661294611637128783792792, 8189321225342615133315741008578315746871762722980986965249683543300354337817, 15342161105292713352374449802912175534449400959133109035836260415735518836755, 18075013689729624974967362235212984989450911765049481574404064991547015443791]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 133 + cx = sel3s([e[399], e[400], e[401]], [1596291013949010721288060595532569432608538778619836480784785471074053165112, 6808491683819461025655595089437806112418825101974851283793281398274802390485, 364241503925827187366795904611796342209607893955620582589568264631586955422, 16490550871285168246186419126591524969189857825357227166657318003550977024941]); + cy = sel2([e[399], e[400]], [7862378404177401992071889396713852447802454946236648304807328682371781930090, 507291250759269099980701396020232970806066743976022636589996988193601483784, 10744127551738752560827414410584235701822856001225517338822143012287884858602, 18241779151498711099077315181629505156252250432591841498036131464452558240559]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 134 + cx = sel3s([e[402], e[403], e[404]], [13383782376835328120051264492485947246229335501182593669024066132006083860995, 6829659109797487915393241205795046921708391483622784165963215585089039907693, 9316519590383340417002353253254231934003449806173856616162378794199227402893, 13002922510988749141229072125743986091046064285797312111247897533544865920246]); + cy = sel2([e[402], e[403]], [1452388014885069534714863742557414467294079407912495717272255602231974271039, 5900502409092025397559171952410984687860230521181044855453255892660864354438, 10043095963739821148582141213281494171132379314509020019652213752752234376602, 9999295030621233000765070897582529515356078631699063530749343953422947829219]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 135 + cx = sel3s([e[405], e[406], e[407]], [13165533527694513928104129943149460933916076941607396715443729707678633985673, 20294369464168299590806576821399517301857816000499415634107985306452722815938, 6067645363539607688922626118164207320418666861212948609146588413602170467017, 119932367132867885429975847232185792475931817114142487620518936723703313296]); + cy = sel2([e[405], e[406]], [17238425515895072477563840544058923640858290538130746390995636765338905591675, 20628042696308823655110673878535950075986980894297665479048269813590306242580, 11749486899455580256560135562925052584441889327031335669536847121302580177052, 16957619631025354458723169845456497220362554006891490260455748609237426050971]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 136 + cx = sel3s([e[408], e[409], e[410]], [7326992374695153334569399469397596928696501586886381702972942656080738560504, 4198555626333615585226486302590784054103224208504401294485393840072962221472, 18288510281806332963207620050180295922486954421289661405933207406160563376204, 19378648346334975363564386629109544268031565617795572270340255835354171953065]); + cy = sel2([e[408], e[409]], [3441991977044037545935620478935168226411039028254665140927991316702138513190, 7980022316348851053079344973315144435710609854183180078433220232446348072790, 10703403289781310156812833248447222548151317595810496437901793212311982317063, 16301246072292511450557090225826608132244132307038997545230147196603338285964]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 137 + cx = sel3s([e[411], e[412], e[413]], [4380971751033847027929691061398944531722909263311553031455521197665070771642, 1958998764514462202561805635784673640011091472752464180193064104296547581169, 16607632498550062722823535936950763735998138401664871177932105851574722673362, 18107842395238833528194122400147411460295339366691168281515267029707554163796]); + cy = sel2([e[411], e[412]], [16794605741797752486161164743285493892529567663448780177764044251817860406839, 627364605348057780240790756195705309805910423716172983190978634837740895756, 15938340690702031578469687601244712133164105954943969813204470601233395408177, 1337728022058609756453976167140964506743665540101352471912041874198880786028]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 138 + cx = sel3s([e[414], e[415], e[416]], [4325450975911066881724043517797022496124195434220888316197251865366294339361, 16239262892194658073042878979066943080253388067983326658313518038231343725333, 3224923392579231188607529005374853676842589239602348970956358059045513499844, 18711810040957806004127569353264972856236116117792057333129328498567653245337]); + cy = sel2([e[414], e[415]], [18556589125306655880844231674670238467511897504977535323905816448582480367724, 14450907030938846250134541582271892920169763336845349109491176054829079021938, 5489164165718004081061600001298776199757130654902992957321875892970948684039, 3404126456231281994449938636645452663538090331489692208486381139765931389947]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 139 + cx = sel3s([e[417], e[418], e[419]], [3049906494165633773067493912990013841965806179225048735919293547905816967010, 2425405604681482172566807394598240014734338608183001729881716084701331638207, 21560391195338031738549905898033672840916947395960523186297949490337780382461, 10640880946275949996544592530048605056441276931537882586193904453232482475238]); + cy = sel2([e[417], e[418]], [1139270967545262231620743596254789040950691396231510347534297369410226811042, 20852287956575668107697863776884710196273757688539515338600627283890571581133, 17188605966302742252765339963794720668370341043552053263753117294010969693650, 19246586050423626713095252320183688353765457408019346352862271422811659317777]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 140 + cx = sel3s([e[420], e[421], e[422]], [19942746034266536069392101170115851306620344112551007974939114086497358930858, 15726708481134151732276229872451366695420040201434018827381159241014716358033, 3452250047812572894016965388138239348795538732265416477858038566576272340399, 732825901760241932909222883465959257672029209130800755766287912812473135470]); + cy = sel2([e[420], e[421]], [5234335526367392822375043936890479400588416815383747301372644960641216357795, 16682782393317738699538698600037172468451638588454521003611347304172554322239, 4800939729460682232720559307513657730880675292200605768084865538547688695396, 13002618796997179002671199181852958465089986403190513123030050511152310206971]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 141 + cx = sel3s([e[423], e[424], e[425]], [4345203866646269633300579468877411954334981515932585752657225898484243906660, 18369957391582635573293322493321958485207102003892958136897534329158731684885, 20673831086732472000273127370905823039882723856850376643114084876980363716192, 2498213507326390169362081908041456736901489034606083564552630396661416090091]); + cy = sel2([e[423], e[424]], [19711785928362785984568609948298550809737208754846854010480265206080190724688, 11436630733281926268922633177556600595162960771369546050376297927685306050908, 7773194831659524501769470153758921383337560398544153003929463015874290745463, 8133306555008250199402612262687855812899186562206213570420163947809045175265]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 142 + cx = sel3s([e[426], e[427], e[428]], [13604959715661441436052939762464429298226713418171390314110026091418525209941, 771054573202666486644315008474869467749501529120937703475279735897998473318, 10650739155896636131407567213077995361727149157766675911133814003745320974607, 21082274336612203666519840927907859383019309974047946161440422017817660726149]); + cy = sel2([e[426], e[427]], [9106634253925907822997376723908848470389744101982447244238790923479221740587, 7324910184007890101804849358851153077116609835592182327277588695666568522132, 9210749700131521931808418873690269098719063379384664590576822932928021903283, 12373345790154524492998539937744274645461345882077071841080883186883404184026]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 143 + cx = sel3s([e[429], e[430], e[431]], [12272981972646946567553896730199881959247853499104488943992635249117595393209, 17484113948306348142106921779441669789323552473173221235726133380929727014173, 15117556748390824311921483809280404911428464810641842112990732230853500342878, 18738665459003240153367275566837691463796036422817751002779294781153509048410]); + cy = sel2([e[429], e[430]], [12840198036955871442566173317906222816787870441489199428401326600711994709214, 13447048657087191261352674553209997835888060694120420289379298057286058954919, 11085124394828809185369563175800089294678889500629428639251047427113804175136, 20040932616180013985013159566209210337758333701488325181237556234029685365086]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 144 + cx = sel3s([e[432], e[433], e[434]], [3005593847772820450050205074163314509976806377772621088836578637506564062913, 2910567614812792758847544159495544141576095133298651646543717734234356651464, 8630893570634023334653627900758492588201195084156991103796478188432785900122, 20068438612873289533893462991408376904784837411837844241529573433855826118434]); + cy = sel2([e[432], e[433]], [17258587025904856892544250820556722922327972240440200527118380921147955645556, 9839944666562674042904466515196204595921896101136113309540898758440523509232, 382264312380680546118029507176039576064064377468124376294215202312670233326, 16859633470889096937094854459393230196320754799783499045789361347337904723211]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 145 + cx = sel3s([e[435], e[436], e[437]], [21553262056684585969628674122764109775958361035991194009613252605155913211334, 15282636750399879299317591027894754559134990135454294656134105963760417995544, 4066930541781809252860144352581968840798983673586834922803928000950012716773, 17266825085778436273993504052249489036678132768169211810048007631121526004292]); + cy = sel2([e[435], e[436]], [14469270633466381305852216281125837079646617198515099740000541993840798471084, 16980111987593030332881454298183054033228595894840772569146266548134494583283, 15118688184376333116924615779850360769477969453186921964192734694461085893102, 4748807943449256265621737370336238625547081211863390407052811770007138872316]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 146 + cx = sel3s([e[438], e[439], e[440]], [11763347508086007810977359866267798246514404258245360557926263268200652076963, 8663905006927572311188991703236656874376542152827973004022578290253373528008, 2952845374549988741320721621283121797914244173004620545437372716814928986849, 17071883097921153691621062529879599274949735278299892231358334236565401545899]); + cy = sel2([e[438], e[439]], [14706162498378202954074913829047629685039231677186626739445882650545999503202, 1719746349330736449674857345290037499267579249273019799523377364214790913723, 21616731410397798448193163892890526448374926979106286339849727909287686706845, 11446919769449393256780992769707214683226878212422736672766658759052425409242]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 147 + cx = sel3s([e[441], e[442], e[443]], [4356994949172878276640972387865792898708144237321291982532719592191935134502, 9058912028451204788275313382642068418310841490274106696805181452416351257146, 15190160120915818686650557755704440198069036613617930484645880424887234233075, 9960154561010441532105561845082645172957096392270554555453954413006726871798]); + cy = sel2([e[441], e[442]], [14574692378125259586817945291111936727424704391123959334117252195469092200764, 9224728228539828897416026999778106548490158473228676095012930511474594231477, 1760463507739730034367125481096536174852992494939001755761219582349351757169, 17340078450196530212205314520279311841731993777309479440929707007860057490354]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 148 + cx = sel3s([e[444], e[445], e[446]], [21880820504467716634106664909402072165472960350877194774465177915127008092893, 11747606579643600398471099307152208653405848363842457205852065247815894902054, 19027263041564841350573847395951723454691080012198506245692747602145336686229, 5632682422077314837831565983660289273448221389165648008167925020530588300924]); + cy = sel2([e[444], e[445]], [5182168744456816656485869911241149693404052223082761825064601932558781730740, 2685937932147288674316610675212322222716444961674715249218650895750571659552, 1912852125196207140975649985472776011293820313776376659814516409955251806791, 18263958114524880676274451483937610105571465623681831140376587635788141241088]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 149 + cx = sel3s([e[447], e[448], e[449]], [8936781701927368370215210870827508937678765478808217533286287559934624784681, 5108431664028439851662340341125863641795570652264053957564019035084276122804, 12999653496005517730722186355139904948504508219343877303366358022761375044402, 19179622495081980573635923134343351242929014436693872859625873727501193848932]); + cy = sel2([e[447], e[448]], [4623029543859886044767307470074323247069187031547412019261660683452990785239, 9857015684855568488276378660083416741199186578332924215590492662945432272825, 5242391447932956625671668911434466570194372869876929059550830464880164528131, 14646928672286452058469223988095085156895208600523868135204725017248298504143]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 150 + cx = sel3s([e[450], e[451], e[452]], [7946459614521142644206204774850419894186577869297360917934350740375926112382, 11530085592691934773947896113217121596676226719554558175458752626759168307130, 12291215261278045612022495371137973264064622535432110273152233125306665396787, 4442266885858584741818610179233325487185053295954810407262511211378152048331]); + cy = sel2([e[450], e[451]], [20393528966549387266343193152712146799161036298032725317477228673291507957942, 1831259860608244620805838343666664146008857962101286629882205237950513972028, 2581270768505724914793947599867596421087089340177029937008824731251155270286, 1824038414762784797700995677077189626495506231241155951144255369814082278582]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 151 + cx = sel3s([e[453], e[454], e[455]], [16996326686259093178712301719114535464147004200933701699216923172711169217776, 10135668620867881915901635109225909232593721615476228193005378643989870282190, 12684696285143358527008494835928613367424428569071148860201922633463847362163, 19520340433574445384932755965450431313046400213079154403779893187900476007389]); + cy = sel2([e[453], e[454]], [10879703765081907416589976314120373073533854885503210038919805342729980088501, 3042952377945780941440480619239495862925076770257741464841490662991367990723, 20568201167449878452522309826171296534890589395210499691162182782776592901489, 2515435614825363087293388949409937340469196878839891206929432371588941120828]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 152 + cx = sel3s([e[456], e[457], e[458]], [5948355082391370971277814822201259570199411254972015395356071689733858457870, 14435295688288574008552320445654835668230448171821339773392204385711009673498, 4555707692840173328761632986080641237899354311390885658902712711385985152474, 21377793559898523325502642621273525075966615158530502938404139072744665720725]); + cy = sel2([e[456], e[457]], [18781938632634665629392534748457372928296731257744451684662925940692495070899, 20870582266287640319635222130472633641883455183531701982867810507045631654099, 6255001622610081365809867580322152519018111820804890853975941295493185079617, 11444903546950465193484459453464362458126976218066241321940461471249831055834]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 153 + cx = sel3s([e[459], e[460], e[461]], [4801783634053958699406131208260321653724147389806778300442394152288266622390, 13657947007455887667569605985083889328718870615545221619668723775205747840135, 177598511756923881728697053947837521554079408931967588956714727282062478754, 1374290142752108446259268973165307183295759382785138144661109763848127727476]); + cy = sel2([e[459], e[460]], [10503832530625380631086165586158401732075983866290617431349835924922749109699, 8383317413774803586670187834721088561764237477263859389570115631886656905028, 2834233504802602126712103599378293010472650755759227696185340490923006971103, 17330582798076118742935459828744886802843487551551606246519220146369990307779]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 154 + cx = sel3s([e[462], e[463], e[464]], [5093610893249308867168031458336741939196884648123926997975341654608609426830, 12248279767532955250746877738475030196514076889129781370472666862024900770669, 5043009492124624507652527263244758360087085758651362799261288863076362039187, 16591909200159417412409462652077399999824413751859530227695887196356321679228]); + cy = sel2([e[462], e[463]], [10952612598118313917631759693602817846928839860096429550603703046117049639522, 2884939241145303979172401496138136665819626424676215132904685536232137032921, 21092145374321584925227081195844245213760374840107123770724422721835988876958, 5499840197627421265036310285493143039360364243394878011782966367266344217732]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 155 + cx = sel3s([e[465], e[466], e[467]], [3794104339739491010449122661216407115137782001618163380131794160705537757426, 7514419529276933284458458535371966876401883528785013067210805765651582633130, 2534189532451386749189970776179117832798970009395742348348119108287813471216, 5610243014937776775874159841646817951854662385825951664842167532212856045068]); + cy = sel2([e[465], e[466]], [12842968623255283384772731210441087433561383555541999360200972373794310794093, 10823437952973686303915120116380996262045441725571077692704581218749963605907, 21253964658659775229061107104903539871763760188604842330476347939642955209002, 1745535366815989039402026181267179197840739481539734000808670009580269211142]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 156 + cx = sel3s([e[468], e[469], e[470]], [3459245219635302288341483992140272707638915493010622274381776793623419230591, 9849021255480129732487752167924340739614806540698786580158805033907788030853, 3255308487469886623287718398314898379309460957968181729113829918571419337145, 15359614079733122216507425018253600855203543497608695539122606260839625565617]); + cy = sel2([e[468], e[469]], [17415928452277952995861857592997544802223350915817518744596816398543561612106, 9999856236606156376100952785476675300524456948913069129769906530665355058037, 17734497746752242925262857913765409819203458581088950917188119245918082092030, 6881580842463060802624074515204787264906621652045323766233447264566499944530]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 157 + cx = sel3s([e[471], e[472], e[473]], [634964597278986129282215293208138156361395902716873910540311662219517773576, 310253852479958835592393232442887907344502522183801152945448588489452412569, 384881480274621505303330466062621612997526527075542749162723700081976881288, 11767445114097831765826464678890553621483551558949563523534328471079851963281]); + cy = sel2([e[471], e[472]], [17203635141310737823252743409317633065422478971915442288649227045499339781109, 2545094457118912372548408336893899649182443951551613850781196845141738637170, 8609139198776064973664903858401535131314034007074283879284230416121615542308, 20092107484372320312567981037155807130829118997137612522175958096520972507336]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 158 + cx = sel3s([e[474], e[475], e[476]], [20098437969178934435495041700635313630962028038875583770224318127835756299529, 311104306589906971684844795811359683864786473908061989245919427082915904714, 5007249687217418940511624233021226494914521342148545152148356064906320432035, 9785851145981523672688289938894315309424412779439726667571213830109657407900]); + cy = sel2([e[474], e[475]], [877613904095171787446316454384924363436490179245069691113043218080238972652, 15255392602742007855606168874483544819258797919038984937824266131810915403967, 3482868076428758563707184390706074120455579821747810434457575250407348632455, 5737555899585712614112644175034540180519345050397396205967955592318835422324]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 159 + cx = sel3s([e[477], e[478], e[479]], [17889638686175315317941901427709143202478522471798280927986774735210637820526, 4586587171981050785204495209615167868746399227792813638212786811256473778221, 1864752565757236746122736751796835904389046064841800598816325031089096557478, 13943403942544820674673437343502779310324858400636923221774342029216604251440]); + cy = sel2([e[477], e[478]], [17728898667133884634264046347611298588924985692465583707491826367590591819161, 18365428070394378833051912713200271982753415548931989923757430748929339745094, 13355801165885814561827651110098104649674895992244923613944279081535896494292, 12718254346735593182641856097514926990330253814732909832265502852628068735026]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 160 + cx = sel3s([e[480], e[481], e[482]], [17159516188699622404527134263356371503443962451842558111890221401200764258125, 19697000438877661546696672369476849653861527230741461549059757921200307256689, 8082602544025295110701438493605046299287009032703969632384937719700791606339, 5936552380580117855548116310401989958728171511356588061450350806482980900531]); + cy = sel2([e[480], e[481]], [288697205606498046198642124865852628925547477970007319079115715396675917499, 11438994931015502912944770174743669059446783563412696311667974558402876489825, 2713576975757110627428489368530113978475830565467996635364633792472336700891, 20023822454992925006561366839036620580908513505208980493011483098957399405656]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 161 + cx = sel3s([e[483], e[484], e[485]], [11476903323853344813827041345787850966667514952865946400953029235796901464022, 15662688482882450089332164944545567115920791913333567306810233998084574572841, 16165244090421658682362860955446523155721204004465368156540492359518946703685, 13233236504179066734589049314166320998745790229936719431495551951291164368688]); + cy = sel2([e[483], e[484]], [21544495907681885621399294493301860022991247894450553860102494438499516461036, 15070356063300726246376329439697612629246560015487953180041607494107482212328, 10932308314438454016363769449242767120417784090441698745502660483728820506459, 15142440904746497443767345573381088273730091577283493618193631903901402378371]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 162 + cx = sel3s([e[486], e[487], e[488]], [6740469135284996394159167279126920754449900660887428959259136317440159292867, 1951789672920637712186229138057234008172951294439716801691622239946406362446, 10614706090196653889949286489862565736131644495539213256761186995450585212820, 20219336380099606710973890974478494924791931389585459347005405927908068729651]); + cy = sel2([e[486], e[487]], [12559437556228574824459283742977065667884462966124147526010574650373707978536, 11353250997656326728675199688614508617263787972463605193791786351817731868528, 9955679877407075213882986027032271351625902587325271136145291798547578901197, 7587664180577472344145946155058239620135123893989614056504418351234639990359]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 163 + cx = sel3s([e[489], e[490], e[491]], [11683193590608313373089435698057644614965227085254736967478627707109364481009, 5373593679075319624506848608700634791297845735799356231319125589754901432010, 14330496678432059141319543266495924665988744049796260830269932610430618839231, 16147138941500612947680025577703299264094926996519490683694344514795650552030]); + cy = sel2([e[489], e[490]], [14089407095672561058133609212857713657125336981293206062798215054918146117895, 5921405729554308485753035966317904019193857886291312338471036342984958996974, 14219166018565381341875979253176613205499868708487414627746489465729919459602, 9173206043848059861761039827886516664018988512989876666692360758637877840001]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 164 + cx = sel3s([e[492], e[493], e[494]], [12391241461796318677666973225906912103063953603374991439355987755433936571792, 11342324255021537810533271600486943249554637261483201032733188357979300928906, 6762143596567875242093282841823575455167081327592834568853990326935018728741, 1729094316763263611553329689516612131095524285732807879509329720064037980971]); + cy = sel2([e[492], e[493]], [6256323253756510425990684148198273229283967340029341825763386143854418092931, 608479563301898577121898469798459144789668559311173727644698121661161535370, 16118965412641868779259712849902459712114606105053804845952965420804403776265, 5207196556914412218334602277590189653542873808697180315162104560234636073976]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 165 + cx = sel3s([e[495], e[496], e[497]], [12090834415198821488072985841187199896460619427268475889346428879276625683876, 20435352555053416469114817994605784220258558984767053371686545934216871498097, 7919766463107746640570694574991853522177141706128568812747727580994437010928, 18791819403195060520893758220974368558662433382958799315116210085990602330263]); + cy = sel2([e[495], e[496]], [11186634643432676423242372187246648742599522445001126220151236883458565017089, 730264789631663387855933585769199256797088038637783970560657523730947722943, 9789319816975923274967045544277604801648452652703289939384714401867885689451, 20390569650377326057430918388837541684089995685084097630788684319064176189296]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 166 + cx = sel3s([e[498], e[499], e[500]], [9073477014345643942359994649331122800736234440180113066690071117218958686221, 17848891043122277658033397684650904021333601784635518417727821688552518594475, 8394455238188958480130266174842497177830879983439478526032000789572056999540, 3969215253795918818810265899749520158876595254756141389552909935321879395990]); + cy = sel2([e[498], e[499]], [15421230006761899572959376594938017439120427450367920423701622807634638005218, 691759570775251457416249989322179808019152722619656278259527490301863241777, 19687896560656750069557210923004770524699515901561346847457425701096560281307, 13013403796046695153969709190889488389508063704805702465177729278466953096077]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 167 + cx = sel3s([e[501], e[502], e[503]], [17605212659450062681090282709904508607567301109002577655966314961623397498778, 20706453518066591671344075213608634140534260809172831962434708646209603184096, 20530641835252913976176823270868884490574732596806683216254892843407024651486, 19512520336574558609801187648395617364107060095538444150298099264798316486399]); + cy = sel2([e[501], e[502]], [18088283300102077232647028354145534410326244238430555546504288886091850910025, 19624767204537830958950503358240075916787006780432673880401115874844576604739, 13389739174441700308398229420122777340874705736681526274430502297758537243393, 2768660518118504029156154123602101814256009402463064802144883490594220059578]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 168 + cx = sel3s([e[504], e[505], e[506]], [3898901470837850662399020072718316987511815396623761376502150466549773974269, 20681259404330431411774484706350104535474957110888110413896201115382255532278, 12146860081497614316907871444885755439616687087776665508013517962132514932126, 10103366418676857183019670163194546750004223272088526675082633522057697832251]); + cy = sel2([e[504], e[505]], [18552945270636575492780160887690665046683842994616480518496617903497833044944, 16280318807141467057522946128901953503954886894473765482004622686048871784896, 16511259671446150110679883995503700110523460228865394020432354340848786592304, 11820015885519382016829607197866756084707670961286078960070207041832708513141]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 169 + cx = sel3s([e[507], e[508], e[509]], [6124403322044682705571649214069113177521499060664580284884665715951975035077, 3806547960677312456106393355578152447583324120952390972170284549005371006887, 12796416634735923176681417392847285391386920336707070519873332365264500996292, 18113312677912280033934533469627761267183403533244965210112870702471687667512]); + cy = sel2([e[507], e[508]], [18191174947339798787646910619446409943766046946921136035021645191602921923040, 16559060177998758852323304784771936179434931576336411584121379336820727372618, 13858115732979799183025726471151602712224733686530960054365665740611187232029, 9933192519609817862698304326029579651414877338671776883175639003837130283966]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + // Round 170 + cx = sel3s([e[510], e[511], e[512]], [3342564788366736273905106071612128667477972061160313630133110787799686301495, 13766193863701503939885263345152684798552605679140222504700163745347162493183, 18523279471468319520962369406962457727155204375043681943707151819380964978377, 8094164074569624021939357073285075790695279643883973800173037824312344195506]); + cy = sel2([e[510], e[511]], [2329094643034533408459502544740928833981119919633412709248656884170940780093, 3216329736050668550647765981020076413548845117352735257893224753954595290363, 18710403072495673647060422294369054840513840567808020912157404388689648711093, 9785201456176703812798077455183487364035650707229293534561747881523562553649]); + a = add(a, [cx, cy], BABYJUBJUB_PARAMS); + + return edwardsCompress(a); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/poseidon/constants.zok b/zokrates_prover/.zokrates/stdlib/hashes/poseidon/constants.zok new file mode 100644 index 0000000..5800127 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/poseidon/constants.zok @@ -0,0 +1,2076 @@ +const field[6][497] POSEIDON_C = [ + [ + 4417881134626180770308697923359573201005643519861877412381846989312604493735, + 5433650512959517612316327474713065966758808864213826738576266661723522780033, + 13641176377184356099764086973022553863760045607496549923679278773208775739952, + 17949713444224994136330421782109149544629237834775211751417461773584374506783, + 13765628375339178273710281891027109699578766420463125835325926111705201856003, + 19179513468172002314585757290678967643352171735526887944518845346318719730387, + 5157412437176756884543472904098424903141745259452875378101256928559722612176, + 535160875740282236955320458485730000677124519901643397458212725410971557409, + 1050793453380762984940163090920066886770841063557081906093018330633089036729, + 10665495010329663932664894101216428400933984666065399374198502106997623173873, + 19965634623406616956648724894636666805991993496469370618546874926025059150737, + 13007250030070838431593222885902415182312449212965120303174723305710127422213, + 16877538715074991604507979123743768693428157847423939051086744213162455276374, + 18211747749504876135588847560312685184956239426147543810126553367063157141465, + 18151553319826126919739798892854572062191241985315767086020821632812331245635, + 19957033149976712666746140949846950406660099037474791840946955175819555930825, + 3469514863538261843186854830917934449567467100548474599735384052339577040841, + 989698510043911779243192466312362856042600749099921773896924315611668507708, + 12568377015646290945235387813564567111330046038050864455358059568128000172201, + 20856104135605479600325529349246932565148587186338606236677138505306779314172, + 8206918720503535523121349917159924938835810381723474192155637697065780938424, + 1309058477013932989380617265069188723120054926187607548493110334522527703566, + 14076116939332667074621703729512195584105250395163383769419390236426287710606, + 10153498892749751942204288991871286290442690932856658983589258153608012428674, + 18202499207234128286137597834010475797175973146805180988367589376893530181575, + 12739388830157083522877690211447248168864006284243907142044329113461613743052, + 15123358710467780770838026754240340042441262572309759635224051333176022613949, + 19925004701844594370904593774447343836015483888496504201331110250494635362184, + 10352416606816998476681131583320899030072315953910679608943150613208329645891, + 10567371822366244361703342347428230537114808440249611395507235283708966113221, + 5635498582763880627392290206431559361272660937399944184533035305989295959602, + 11866432933224219174041051738704352719163271639958083608224676028593315904909, + 5795020705294401441272215064554385591292330721703923167136157291459784140431, + 9482202378699252817564375087302794636287866584767523335624368774856230692758, + 4245237636894546151746468406560945873445548423466753843402086544922216329298, + 12000500941313982757584712677991730019124834399479314697467598397927435905133, + 7596790274058425558167520209857956363736666939016807569082239187494363541787, + 2484867918246116343205467273440098378820186751202461278013576281097918148877, + 18312645949449997391810445935615409295369169383463185688973803378104013950190, + 15320686572748723004980855263301182130424010735782762814513954166519592552733, + 12618438900597948888520621062416758747872180395546164387827245287017031303859, + 17438141672027706116733201008397064011774368832458707512367404736905021019585, + 6374197807230665998865688675365359100400438034755781666913068586172586548950, + 2189398913433273865510950346186699930188746169476472274335177556702504595264, + 6268495580028970231803791523870131137294646402347399003576649137450213034606, + 17896250365994900261202920044129628104272791547990619503076839618914047059275, + 13692156312448722528008862371944543449350293305158722920787736248435893008873, + 15234446864368744483209945022439268713300180233589581910497691316744177619376, + 1572426502623310766593681563281600503979671244997798691029595521622402217227, + 80103447810215150918585162168214870083573048458555897999822831203653996617, + 8228820324013669567851850635126713973797711779951230446503353812192849106342, + 5375851433746509614045812476958526065449377558695752132494533666370449415873, + 12115998939203497346386774317892338270561208357481805380546938146796257365018, + 9764067909645821279940531410531154041386008396840887338272986634350423466622, + 8538708244538850542384936174629541085495830544298260335345008245230827876882, + 7140127896620013355910287215441004676619168261422440177712039790284719613114, + 14297402962228458726038826185823085337698917275385741292940049024977027409762, + 6667115556431351074165934212337261254608231545257434281887966406956835140819, + 20226761165244293291042617464655196752671169026542832236139342122602741090001, + 12038289506489256655759141386763477208196694421666339040483042079632134429119, + 19027757334170818571203982241812412991528769934917288000224335655934473717551, + 16272152964456553579565580463468069884359929612321610357528838696790370074720, + 2500392889689246014710135696485946334448570271481948765283016105301740284071, + 8595254970528530312401637448610398388203855633951264114100575485022581946023, + 11635945688914011450976408058407206367914559009113158286982919675551688078198, + 614739068603482619581328040478536306925147663946742687395148680260956671871, + 18692271780377861570175282183255720350972693125537599213951106550953176268753, + 4987059230784976306647166378298632695585915319042844495357753339378260807164, + 21851403978498723616722415377430107676258664746210815234490134600998983955497, + 9830635451186415300891533983087800047564037813328875992115573428596207326204, + 4842706106434537116860242620706030229206345167233200482994958847436425185478, + 6422235064906823218421386871122109085799298052314922856340127798647926126490, + 4564364104986856861943331689105797031330091877115997069096365671501473357846, + 1944043894089780613038197112872830569538541856657037469098448708685350671343, + 21179865974855950600518216085229498748425990426231530451599322283119880194955, + 14296697761894107574369608843560006996183955751502547883167824879840894933162, + 12274619649702218570450581712439138337725246879938860735460378251639845671898, + 16371396450276899401411886674029075408418848209575273031725505038938314070356, + 3702561221750983937578095019779188631407216522704543451228773892695044653565, + 19721616877735564664624984774636557499099875603996426215495516594530838681980, + 6383350109027696789969911008057747025018308755462287526819231672217685282429, + 20860583956177367265984596617324237471765572961978977333122281041544719622905, + 5766390934595026947545001478457407504285452477687752470140790011329357286275, + 4043175758319898049344746138515323336207420888499903387536875603879441092484, + 15579382179133608217098622223834161692266188678101563820988612253342538956534, + 1864640783252634743892105383926602930909039567065240010338908865509831749824, + 15943719865023133586707144161652035291705809358178262514871056013754142625673, + 2326415993032390211558498780803238091925402878871059708106213703504162832999, + 19995326402773833553207196590622808505547443523750970375738981396588337910289, + 5143583711361588952673350526320181330406047695593201009385718506918735286622, + 15436006486881920976813738625999473183944244531070780793506388892313517319583, + 16660446760173633166698660166238066533278664023818938868110282615200613695857, + 4966065365695755376133119391352131079892396024584848298231004326013366253934, + 20683781957411705574951987677641476019618457561419278856689645563561076926702, + 17280836839165902792086432296371645107551519324565649849400948918605456875699, + 17045635513701208892073056357048619435743564064921155892004135325530808465371, + 17055032967194400710390142791334572297458033582458169295920670679093585707295, + 15727174639569115300068198908071514334002742825679221638729902577962862163505, + 1001755657610446661315902885492677747789366510875120894840818704741370398633, + 18638547332826171619311285502376343504539399518545103511265465604926625041234, + 6751954224763196429755298529194402870632445298969935050224267844020826420799, + 3526747115904224771452549517614107688674036840088422555827581348280834879405, + 15705897908180497062880001271426561999724005008972544196300715293701537574122, + 574386695213920937259007343820417029802510752426579750428758189312416867750, + 15973040855000600860816974646787367136127946402908768408978806375685439868553, + 20934130413948796333037139460875996342810005558806621330680156931816867321122, + 6918585327145564636398173845411579411526758237572034236476079610890705810764, + 14158163500813182062258176233162498241310167509137716527054939926126453647182, + 4164602626597695668474100217150111342272610479949122406544277384862187287433, + 12146526846507496913615390662823936206892812880963914267275606265272996025304, + 10153527926900017763244212043512822363696541810586522108597162891799345289938, + 13564663485965299104296214940873270349072051793008946663855767889066202733588, + 5612449256997576125867742696783020582952387615430650198777254717398552960096, + 12151885480032032868507892738683067544172874895736290365318623681886999930120, + 380452237704664384810613424095477896605414037288009963200982915188629772177, + 9067557551252570188533509616805287919563636482030947363841198066124642069518, + 21280306817619711661335268484199763923870315733198162896599997188206277056900, + 5567165819557297006750252582140767993422097822227408837378089569369734876257, + 10411936321072105429908396649383171465939606386380071222095155850987201580137, + 21338390051413922944780864872652000187403217966653363270851298678606449622266, + 12156296560457833712186127325312904760045212412680904475497938949653569234473, + 4271647814574748734312113971565139132510281260328947438246615707172526380757, + 9061738206062369647211128232833114177054715885442782773131292534862178874950, + 10134551893627587797380445583959894183158393780166496661696555422178052339133, + 8932270237664043612366044102088319242789325050842783721780970129656616386103, + 3339412934966886386194449782756711637636784424032779155216609410591712750636, + 9704903972004596791086522314847373103670545861209569267884026709445485704400, + 17467570179597572575614276429760169990940929887711661192333523245667228809456, + ...[0; 369] + ], + [ + 6745197990210204598374042828761989596302876299545964402857411729872131034734, + 426281677759936592021316809065178817848084678679510574715894138690250139748, + 4014188762916583598888942667424965430287497824629657219807941460227372577781, + 21328925083209914769191926116470334003273872494252651254811226518870906634704, + 19525217621804205041825319248827370085205895195618474548469181956339322154226, + 1402547928439424661186498190603111095981986484908825517071607587179649375482, + 18320863691943690091503704046057443633081959680694199244583676572077409194605, + 17709820605501892134371743295301255810542620360751268064484461849423726103416, + 15970119011175710804034336110979394557344217932580634635707518729185096681010, + 9818625905832534778628436765635714771300533913823445439412501514317783880744, + 6235167673500273618358172865171408902079591030551453531218774338170981503478, + 12575685815457815780909564540589853169226710664203625668068862277336357031324, + 7381963244739421891665696965695211188125933529845348367882277882370864309593, + 14214782117460029685087903971105962785460806586237411939435376993762368956406, + 13382692957873425730537487257409819532582973556007555550953772737680185788165, + 2203881792421502412097043743980777162333765109810562102330023625047867378813, + 2916799379096386059941979057020673941967403377243798575982519638429287573544, + 4341714036313630002881786446132415875360643644216758539961571543427269293497, + 2340590164268886572738332390117165591168622939528604352383836760095320678310, + 5222233506067684445011741833180208249846813936652202885155168684515636170204, + 7963328565263035669460582454204125526132426321764384712313576357234706922961, + 1394121618978136816716817287892553782094854454366447781505650417569234586889, + 20251767894547536128245030306810919879363877532719496013176573522769484883301, + 141695147295366035069589946372747683366709960920818122842195372849143476473, + 15919677773886738212551540894030218900525794162097204800782557234189587084981, + 2616624285043480955310772600732442182691089413248613225596630696960447611520, + 4740655602437503003625476760295930165628853341577914460831224100471301981787, + 19201590924623513311141753466125212569043677014481753075022686585593991810752, + 12116486795864712158501385780203500958268173542001460756053597574143933465696, + 8481222075475748672358154589993007112877289817336436741649507712124418867136, + 5181207870440376967537721398591028675236553829547043817076573656878024336014, + 1576305643467537308202593927724028147293702201461402534316403041563704263752, + 2555752030748925341265856133642532487884589978209403118872788051695546807407, + 18840924862590752659304250828416640310422888056457367520753407434927494649454, + 14593453114436356872569019099482380600010961031449147888385564231161572479535, + 20826991704411880672028799007667199259549645488279985687894219600551387252871, + 9159011389589751902277217485643457078922343616356921337993871236707687166408, + 5605846325255071220412087261490782205304876403716989785167758520729893194481, + 1148784255964739709393622058074925404369763692117037208398835319441214134867, + 20945896491956417459309978192328611958993484165135279604807006821513499894540, + 229312996389666104692157009189660162223783309871515463857687414818018508814, + 21184391300727296923488439338697060571987191396173649012875080956309403646776, + 21853424399738097885762888601689700621597911601971608617330124755808946442758, + 12776298811140222029408960445729157525018582422120161448937390282915768616621, + 7556638921712565671493830639474905252516049452878366640087648712509680826732, + 19042212131548710076857572964084011858520620377048961573689299061399932349935, + 12871359356889933725034558434803294882039795794349132643274844130484166679697, + 3313271555224009399457959221795880655466141771467177849716499564904543504032, + 15080780006046305940429266707255063673138269243146576829483541808378091931472, + 21300668809180077730195066774916591829321297484129506780637389508430384679582, + 20480395468049323836126447690964858840772494303543046543729776750771407319822, + 10034492246236387932307199011778078115444704411143703430822959320969550003883, + 19584962776865783763416938001503258436032522042569001300175637333222729790225, + 20155726818439649091211122042505326538030503429443841583127932647435472711802, + 13313554736139368941495919643765094930693458639277286513236143495391474916777, + 14606609055603079181113315307204024259649959674048912770003912154260692161833, + 5563317320536360357019805881367133322562055054443943486481491020841431450882, + 10535419877021741166931390532371024954143141727751832596925779759801808223060, + 12025323200952647772051708095132262602424463606315130667435888188024371598063, + 2906495834492762782415522961458044920178260121151056598901462871824771097354, + 19131970618309428864375891649512521128588657129006772405220584460225143887876, + 8896386073442729425831367074375892129571226824899294414632856215758860965449, + 7748212315898910829925509969895667732958278025359537472413515465768989125274, + 422974903473869924285294686399247660575841594104291551918957116218939002865, + 6398251826151191010634405259351528880538837895394722626439957170031528482771, + 18978082967849498068717608127246258727629855559346799025101476822814831852169, + 19150742296744826773994641927898928595714611370355487304294875666791554590142, + 12896891575271590393203506752066427004153880610948642373943666975402674068209, + 9546270356416926575977159110423162512143435321217584886616658624852959369669, + 2159256158967802519099187112783460402410585039950369442740637803310736339200, + 8911064487437952102278704807713767893452045491852457406400757953039127292263, + 745203718271072817124702263707270113474103371777640557877379939715613501668, + 19313999467876585876087962875809436559985619524211587308123441305315685710594, + 13254105126478921521101199309550428567648131468564858698707378705299481802310, + 1842081783060652110083740461228060164332599013503094142244413855982571335453, + 9630707582521938235113899367442877106957117302212260601089037887382200262598, + 5066637850921463603001689152130702510691309665971848984551789224031532240292, + 4222575506342961001052323857466868245596202202118237252286417317084494678062, + 2919565560395273474653456663643621058897649501626354982855207508310069954086, + 6828792324689892364977311977277548750189770865063718432946006481461319858171, + 2245543836264212411244499299744964607957732316191654500700776604707526766099, + 19602444885919216544870739287153239096493385668743835386720501338355679311704, + 8239538512351936341605373169291864076963368674911219628966947078336484944367, + 15053013456316196458870481299866861595818749671771356646798978105863499965417, + 7173615418515925804810790963571435428017065786053377450925733428353831789901, + 8239211677777829016346247446855147819062679124993100113886842075069166957042, + 15330855478780269194281285878526984092296288422420009233557393252489043181621, + 10014883178425964324400942419088813432808659204697623248101862794157084619079, + 14014440630268834826103915635277409547403899966106389064645466381170788813506, + 3580284508947993352601712737893796312152276667249521401778537893620670305946, + 2559754020964039399020874042785294258009596917335212876725104742182177996988, + 14898657953331064524657146359621913343900897440154577299309964768812788279359, + 2094037260225570753385567402013028115218264157081728958845544426054943497065, + 18051086536715129874440142649831636862614413764019212222493256578581754875930, + 21680659279808524976004872421382255670910633119979692059689680820959727969489, + 13950668739013333802529221454188102772764935019081479852094403697438884885176, + 9703845704528288130475698300068368924202959408694460208903346143576482802458, + 12064310080154762977097567536495874701200266107682637369509532768346427148165, + 16970760937630487134309762150133050221647250855182482010338640862111040175223, + 9790997389841527686594908620011261506072956332346095631818178387333642218087, + 16314772317774781682315680698375079500119933343877658265473913556101283387175, + 82044870826814863425230825851780076663078706675282523830353041968943811739, + 21696416499108261787701615667919260888528264686979598953977501999747075085778, + 327771579314982889069767086599893095509690747425186236545716715062234528958, + 4606746338794869835346679399457321301521448510419912225455957310754258695442, + 64499140292086295251085369317820027058256893294990556166497635237544139149, + 10455028514626281809317431738697215395754892241565963900707779591201786416553, + 10421411526406559029881814534127830959833724368842872558146891658647152404488, + 18848084335930758908929996602136129516563864917028006334090900573158639401697, + 13844582069112758573505569452838731733665881813247931940917033313637916625267, + 13488838454403536473492810836925746129625931018303120152441617863324950564617, + 15742141787658576773362201234656079648895020623294182888893044264221895077688, + 6756884846734501741323584200608866954194124526254904154220230538416015199997, + 7860026400080412708388991924996537435137213401947704476935669541906823414404, + 7871040688194276447149361970364037034145427598711982334898258974993423182255, + 20758972836260983284101736686981180669442461217558708348216227791678564394086, + 21723241881201839361054939276225528403036494340235482225557493179929400043949, + 19428469330241922173653014973246050805326196062205770999171646238586440011910, + 7969200143746252148180468265998213908636952110398450526104077406933642389443, + 10950417916542216146808986264475443189195561844878185034086477052349738113024, + 18149233917533571579549129116652755182249709970669448788972210488823719849654, + 3729796741814967444466779622727009306670204996071028061336690366291718751463, + 5172504399789702452458550583224415301790558941194337190035441508103183388987, + 6686473297578275808822003704722284278892335730899287687997898239052863590235, + 19426913098142877404613120616123695099909113097119499573837343516470853338513, + 5120337081764243150760446206763109494847464512045895114970710519826059751800, + 5055737465570446530938379301905385631528718027725177854815404507095601126720, + 14235578612970484492268974539959119923625505766550088220840324058885914976980, + 653592517890187950103239281291172267359747551606210609563961204572842639923, + 5507360526092411682502736946959369987101940689834541471605074817375175870579, + 7864202866011437199771472205361912625244234597659755013419363091895334445453, + 21294659996736305811805196472076519801392453844037698272479731199885739891648, + 13767183507040326119772335839274719411331242166231012705169069242737428254651, + 810181532076738148308457416289197585577119693706380535394811298325092337781, + 14232321930654703053193240133923161848171310212544136614525040874814292190478, + 16796904728299128263054838299534612533844352058851230375569421467352578781209, + 16256310366973209550759123431979563367001604350120872788217761535379268327259, + 19791658638819031543640174069980007021961272701723090073894685478509001321817, + 7046232469803978873754056165670086532908888046886780200907660308846356865119, + 16001732848952745747636754668380555263330934909183814105655567108556497219752, + 9737276123084413897604802930591512772593843242069849260396983774140735981896, + 11410895086919039954381533622971292904413121053792570364694836768885182251535, + 19098362474249267294548762387533474746422711206129028436248281690105483603471, + 11013788190750472643548844759298623898218957233582881400726340624764440203586, + 2206958256327295151076063922661677909471794458896944583339625762978736821035, + 7171889270225471948987523104033632910444398328090760036609063776968837717795, + 2510237900514902891152324520472140114359583819338640775472608119384714834368, + 8825275525296082671615660088137472022727508654813239986303576303490504107418, + 1481125575303576470988538039195271612778457110700618040436600537924912146613, + 16268684562967416784133317570130804847322980788316762518215429249893668424280, + 4681491452239189664806745521067158092729838954919425311759965958272644506354, + 3131438137839074317765338377823608627360421824842227925080193892542578675835, + 7930402370812046914611776451748034256998580373012248216998696754202474945793, + 8973151117361309058790078507956716669068786070949641445408234962176963060145, + 10223139291409280771165469989652431067575076252562753663259473331031932716923, + 2232089286698717316374057160056566551249777684520809735680538268209217819725, + 16930089744400890347392540468934821520000065594669279286854302439710657571308, + 21739597952486540111798430281275997558482064077591840966152905690279247146674, + 7508315029150148468008716674010060103310093296969466203204862163743615534994, + 11418894863682894988747041469969889669847284797234703818032750410328384432224, + 10895338268862022698088163806301557188640023613155321294365781481663489837917, + 18644184384117747990653304688839904082421784959872380449968500304556054962449, + 7414443845282852488299349772251184564170443662081877445177167932875038836497, + 5391299369598751507276083947272874512197023231529277107201098701900193273851, + 10329906873896253554985208009869159014028187242848161393978194008068001342262, + 4711719500416619550464783480084256452493890461073147512131129596065578741786, + 11943219201565014805519989716407790139241726526989183705078747065985453201504, + 4298705349772984837150885571712355513879480272326239023123910904259614053334, + 9999044003322463509208400801275356671266978396985433172455084837770460579627, + 4908416131442887573991189028182614782884545304889259793974797565686968097291, + 11963412684806827200577486696316210731159599844307091475104710684559519773777, + 20129916000261129180023520480843084814481184380399868943565043864970719708502, + 12884788430473747619080473633364244616344003003135883061507342348586143092592, + 20286808211545908191036106582330883564479538831989852602050135926112143921015, + 16282045180030846845043407450751207026423331632332114205316676731302016331498, + 4332932669439410887701725251009073017227450696965904037736403407953448682093, + 11105712698773407689561953778861118250080830258196150686012791790342360778288, + 21853934471586954540926699232107176721894655187276984175226220218852955976831, + 9807888223112768841912392164376763820266226276821186661925633831143729724792, + 13411808896854134882869416756427789378942943805153730705795307450368858622668, + 17906847067500673080192335286161014930416613104209700445088168479205894040011, + 14554387648466176616800733804942239711702169161888492380425023505790070369632, + 4264116751358967409634966292436919795665643055548061693088119780787376143967, + 2401104597023440271473786738539405349187326308074330930748109868990675625380, + 12251645483867233248963286274239998200789646392205783056343767189806123148785, + 15331181254680049984374210433775713530849624954688899814297733641575188164316, + 13108834590369183125338853868477110922788848506677889928217413952560148766472, + 6843160824078397950058285123048455551935389277899379615286104657075620692224, + 10151103286206275742153883485231683504642432930275602063393479013696349676320, + 7074320081443088514060123546121507442501369977071685257650287261047855962224, + 11413928794424774638606755585641504971720734248726394295158115188173278890938, + 7312756097842145322667451519888915975561412209738441762091369106604423801080, + 7181677521425162567568557182629489303281861794357882492140051324529826589361, + 15123155547166304758320442783720138372005699143801247333941013553002921430306, + 13409242754315411433193860530743374419854094495153957441316635981078068351329, + ...[0; 302] + ], + [ + 11633431549750490989983886834189948010834808234699737327785600195936805266405, + 17353750182810071758476407404624088842693631054828301270920107619055744005334, + 11575173631114898451293296430061690731976535592475236587664058405912382527658, + 9724643380371653925020965751082872123058642683375812487991079305063678725624, + 20936725237749945635418633443468987188819556232926135747685274666391889856770, + 6427758822462294912934022562310355233516927282963039741999349770315205779230, + 16782979953202249973699352594809882974187694538612412531558950864304931387798, + 8979171037234948998646722737761679613767384188475887657669871981433930833742, + 5428827536651017352121626533783677797977876323745420084354839999137145767736, + 507241738797493565802569310165979445570507129759637903167193063764556368390, + 6711578168107599474498163409443059675558516582274824463959700553865920673097, + 2197359304646916921018958991647650011119043556688567376178243393652789311643, + 4634703622846121403803831560584049007806112989824652272428991253572845447400, + 17008376818199175111793852447685303011746023680921106348278379453039148937791, + 18430784755956196942937899353653692286521408688385681805132578732731487278753, + 4573768376486344895797915946239137669624900197544620153250805961657870918727, + 5624865188680173294191042415227598609140934495743721047183803859030618890703, + 8228252753786907198149068514193371173033070694924002912950645971088002709521, + 17586714789554691446538331362711502394998837215506284064347036653995353304693, + 12985198716830497423350597750558817467658937953000235442251074063454897365701, + 13480076116139680784838493959937969792577589073830107110893279354229821035984, + 480609231761423388761863647137314056373740727639536352979673303078459561332, + 19503345496799249258956440299354839375920540225688429628121751361906635419276, + 16837818502122887883669221005435922946567532037624537243846974433811447595173, + 5492108497278641078569490709794391352213168666744080628008171695469579703581, + 11365311159988448419785032079155356000691294261495515880484003277443744617083, + 13876891705632851072613751905778242936713392247975808888614530203269491723653, + 10660388389107698747692475159023710744797290186015856503629656779989214850043, + 18876318870401623474401728758498150977988613254023317877612912724282285739292, + 15543349138237018307536452195922365893694804703361435879256942490123776892424, + 2839988449157209999638903652853828318645773519300826410959678570041742458201, + 7566039810305694135184226097163626060317478635973510706368412858136696413063, + 6344830340705033582410486810600848473125256338903726340728639711688240744220, + 12475357769019880256619207099578191648078162511547701737481203260317463892731, + 13337401254840718303633782478677852514218549070508887338718446132574012311307, + 21161869193849404954234950798647336336709035097706159414187214758702055364571, + 20671052961616073313397254362345395594858011165315285344464242404604146448678, + 2772189387845778213446441819361180378678387127454165972767013098872140927416, + 3339032002224218054945450150550795352855387702520990006196627537441898997147, + 14919705931281848425960108279746818433850049439186607267862213649460469542157, + 17056699976793486403099510941807022658662936611123286147276760381688934087770, + 16144580075268719403964467603213740327573316872987042261854346306108421013323, + 15582343953927413680541644067712456296539774919658221087452235772880573393376, + 17528510080741946423534916423363640132610906812668323263058626230135522155749, + 3190600034239022251529646836642735752388641846393941612827022280601486805721, + 8463814172152682468446984305780323150741498069701538916468821815030498611418, + 16533435971270903741871235576178437313873873358463959658178441562520661055273, + 11845696835505436397913764735273748291716405946246049903478361223369666046634, + 18391057370973634202531308463652130631065370546571735004701144829951670507215, + 262537877325812689820791215463881982531707709719292538608229687240243203710, + 2187234489894387585309965540987639130975753519805550941279098789852422770021, + 19189656350920455659006418422409390013967064310525314160026356916172976152967, + 15839474183930359560478122372067744245080413846070743460407578046890458719219, + 1805019124769763805045852541831585930225376844141668951787801647576910524592, + 323592203814803486950280155834638828455175703393817797003361354810251742052, + 9780393509796825017346015868945480913627956475147371732521398519483580624282, + 14009429785059642386335012561867511048847749030947687313594053997432177705759, + 13749550162460745037234826077137388777330401847577727796245150843898019635981, + 19497187499283431845443758879472819384797584633472792651343926414232528405311, + 3708428802547661961864524194762556064568867603968214870300574294082023305587, + 1339414413482882567499652761996854155383863472782829777976929310155400981782, + 6396261245879814100794661157306877072718690153118140891315137894471052482309, + 2069661495404347929962833138824526893650803079024564477269192079629046031674, + 15793521554502133342917616035884588152451122589545915605459159078589855944361, + 17053424498357819626596285492499512504457128907932827007302385782133229252374, + 13658536470391360399708067455536748955260723760813498481671323619545320978896, + 21546095668130239633971575351786704948662094117932406102037724221634677838565, + 21411726238386979516934941789127061362496195649331822900487557574597304399109, + 1944776378988765673004063363506638781964264107780425928778257145151172817981, + 15590719714223718537172639598316570285163081746016049278954513732528516468773, + 1351266421179051765004709939353170430290500926943038391678843253157009556309, + 6772476224477167317130064764757502335545080109882028900432703947986275397548, + 10670120969725161535937685539136065944959698664551200616467222887025111751992, + 4731853626374224678749618809759140702342195350742653173378450474772131006181, + 14473527495914528513885847341981310373531349450901830749157165104135412062812, + 16937191362061486658876740597821783333355021670608822932942683228741190786143, + 5656559696428674390125424316117443507583679061659043998559560535270557939546, + 8897648276515725841133578021896617755369443750194849587616503841335248902806, + 14938684446722672719637788054570691068799510611164812175626676768545923371470, + 15284149043690546115252102390417391226617211133644099356880071475803043461465, + 2623479025068612775740107497276979457946709347831661908218182874823658838107, + 6809791961761836061129379546794905411734858375517368211894790874813684813988, + 2417620338751920563196799065781703780495622795713803712576790485412779971775, + 4445143310792944321746901285176579692343442786777464604312772017806735512661, + 1429019233589939118995503267516676481141938536269008901607126781291273208629, + 19874283200702583165110559932895904979843482162236139561356679724680604144459, + 13426632171723830006915194799390005513190035492503509233177687891041405113055, + 10582332261829184460912611488470654685922576576939233092337240630493625631748, + 21233753931561918964692715735079738969202507286592442257083521969358109931739, + 15570526832729960536088203016939646235070527502823725736220985057263010426410, + 9379993197409194016084018867205217180276068758980710078281820842068357746159, + 20771047769547788232530761122022227554484215799917531852224053856574439035591, + 20468066117407230615347036860121267564735050776924839007390915936603720868039, + 5488458379783632930817704196671117722181776789793038046303454621235628350505, + 1394272944960494549436156060041871735938329188644910029274839018389507786995, + 5147716541319265558364686380685869814344975511061045836883803841066664401308, + 14583556014436264794011679557180458872925270147116325433110111823036572987256, + 11881598145635709076820802010238799308467020773223027240974808290357539410246, + 1566675577370566803714158020143436746360531503329117352692311127363508063658, + 212097210828847555076368799807292486212366234848453077606919035866276438405, + 7447795983723838393344606913699113402588250391491430720006009618589586043349, + 7626475329478847982857743246276194948757851985510858890691733676098590062312, + 148936322117705719734052984176402258788283488576388928671173547788498414614, + 15456385653678559339152734484033356164266089951521103188900320352052358038156, + 18207029603568083031075933940507782729612798852390383193518574746240484434885, + 2783356767974552799246444090988849933848968900471538294757665724820698962027, + 2721136724873145834448711197875719736776242904173494370334510875996324906822, + 2101139679159828164567502977338446902934095964116292264803779234163802308621, + 8995221857405946029753863203034191016106353727035116779995228902499254557482, + 502050382895618998241481591846956281507455925731652006822624065608151015665, + 4998642074447347292230083981705092465562944918178587362047610976950173759150, + 9349925422548495396957991080641322437286312278286826683803695584372829655908, + 11780347248050333407713097022607360765169543706092266937432199545936788840710, + 17875657248128792902343900636176628524337469245418171053476833541334867949063, + 10366707960411170224546487410133378396211437543372531210718212258701730218585, + 16918708725327525329474486073529093971911689155838787615544405646587858805834, + 18845394288827839099791436411179859406694814287249240544635770075956540806104, + 9838806160073701591447223014625214979004281138811495046618998465898136914308, + 10285680425916086863571101560978592912547567902925573205991454216988033815759, + 1292119286233210185026381033809498665433650491423040630240164455269575958565, + 2665524343601461489082054230426835550060387413710679950970616347092017688857, + 13502286133892103192305476866434484921895765252706158317341618311553476426306, + 686854655578191041672292972738875170071982317195092845673566320025160026512, + 9315942923163981372372434957632152754092082859001311184186702151150554806508, + 17166793131238158480636170455452575971861309825745828685724097210995239015581, + 4443784618760852757287735236046535266034706880634443644576653970979377878608, + 21470445782021672615018345703580059646973568891521510437236903770708690160080, + 6932852445473908850835611723958058203645654625170962537129706393570586565567, + 17078326120157725640173982185667969009350208542843294226397809921509565607842, + 19251873001736801921864956728611772738233338338726553113352118847732921831266, + 13062907978694932362695258750558734366820802962383346229947907261606619788585, + 16576609187793673559170206379939616900133457644695219057683704871664434872406, + 17140499059660867342372156843620845644831519603574612796639429147195776838516, + 16226688173010504218547945848523900236290532501559570164276462499487632388445, + 2806068123803905806401128967330263340459046260107112845068533446899070326517, + 17788735370835052317224182711467216134690146479710634688273650370951230404901, + 9840665370904113434661468973557421114403401847108482949465899631150766783733, + 17357287363046228581837055771327121704742940914150998420465281177406182088510, + 8956082469997974864521346025916496675956939495318858500685756691488425559998, + 10583741436561099911914917245130852199607666337956354910388730829023746895549, + 15241902639811607164983030447109332729761435946009172128089506810551693978973, + 10889882303914055687481932975789161945462141459528413507160087442461090813788, + 19789561133254944544821898921133697408237804586549835559829396563401674817160, + 20741336668287037026472434608739333171202674306575625457456116338034432647230, + 17864073449995977742930566850933082711031717858550870842712972350665650521079, + 6017691253505466300212182439349954426085752315661098358839308909771637792741, + 5209125836207196173669497054522582922896061838702136844305036341250990710540, + 8138726312837322624537330169363664364899441867118983214176695868443641051381, + 15491983986041746833254372934846748393213690608865689646440909282144232382678, + 5054332867608171303802774230688792431028169804536607979111644888500809938980, + 15427030776591294577308915282298854681562344215287630895931797573417982096417, + 21754057982677295571284116502193272661309010996970316384923307174180521790164, + 16265286590463120486705206231835953324076688991892805307349612983237844034032, + 17679791107777049796013011282788633179411040182820636236163074053597517790779, + 4281652562868629887097957174897458165728741859103571825874408386197225591996, + 9168010397863299719604788533602757515513214141450093775967322808686129400625, + 17584182367226175071087689123358883902969885218985589531538416263709138156515, + 15671512310414658663135385639435845966109237059155734764323312289873534719186, + 10536294659491685326297777845632759824567028904726211134518740400643540109527, + 13431319759608247201135260841651365578663315527795431484765940626659812285319, + 9584697124715190200241839387725546204368618031045071660911490086723434692561, + 5180327104839158483066851400960171505063442195966219343315555549982472660055, + 18888217223053385111625483360538133292128748730565502371803782424772027937822, + 19535732913737027522540340630296365525208404217634392013266346283017745945894, + 8577759627886344995887423695190093296190181539234301534326157005220006624466, + 16793670928407147476673650839110019799844249677846432113010280456483595763987, + 13926032620965299897272071104154310460519723329016284975305942957859374938463, + 4794697578055472890255676575927616606591024075768967985031137397587590174501, + 3529566190782060578446859853852791941913086545101307988176595267965876143250, + 3975008029239568933166738482470827494289192118694622729549964538823092192163, + 17739094873244464728483944474780943281491793683051033330476367597242349886622, + 7367136451127531266518046223598095299278392589059366687082785080179161005418, + 11175297939460631138047404082172242706491354303440776362693987984031241399771, + 21687543815463985355165197827968086406938428974327951792877419032069230058777, + 21156136641989461785420005321350884477682466566148802533375726181416623358719, + 17347558768803521970212188258074365309929638984714303299899732035040892048478, + 16293716234695956076322008955071091921491953458541407305955104663269677475740, + 4206144021605871396668976569508168522675546062304959729829228403361714668567, + 19988050626299122864942213847548542155670073758974734015174045163059179151544, + 747972634423324369570795147739377097591383105262743308036321386836856106229, + 4612470951309047869982067912468200581649949743307592869671537990797895413707, + 9630852913694079049153027193127278569487291430069466630362958024525616303220, + 17941539917430916523930519432495442476511211427972760202450248798031711471474, + 20332911350443969653703295317915788278109458962706923653715140186132935894113, + 21764801803055897327474057344100833670291402543384934706514147201527191846513, + 18792043166429470991157980448329308661526906138700725174612608941551872082876, + 12308177224490762720061048892842527800271687977085172836705858261595655154325, + 6234555076867437297776538521925679658360922070165740193866337972293380196151, + 4651047048822067434403056477377459986292934655827821636179452835839127581305, + 4762047093602693619418269784972874862577325737690375448572644958129932507374, + 12373514879531674477721132062882065826558811149582829246378921774344318418269, + 452512704634345955634014968317367844987135264395068376894497483188243356523, + 21642936370936057063268550589361090955573362743817395689260298777690935495218, + 16170209200627740434842090607802586195654207376087117044989637541681675086276, + 11682826760471401430136435257946377996085824742031456481961511737883954750045, + 20628055165039718158878805520495324869838279647796500565701893698896698211929, + 16438375313036818694140277721632185529697783132872683043559674569424388375143, + 4855690425141732729622202649174026736476144238882856677953515240716341676853, + 11680269552161854836013784579325442981497075865007420427279871128110023581360, + 7052688838948398479718163301866620773458411881591190572311273079833122884040, + 10339199500986679207942447430230758709198802637648680544816596214595887890122, + 16310974164366557619327768780809157500356605306298690718711623172209302167675, + 4572051236178600578566286373491186377601851723137133424312445102215267283375, + 20933392620931420860078756859763708025350478446661033451436796955762857910093, + 10145870387395991071594748880090507240612313913083518483680901820696866812598, + 11173854866888110108878560284050142518686158431744851782991510385755602063727, + 3895357290105797542988795070918100785105415165483657264407967118738833241858, + 16358886674154007883356717944805100413481233709808000948036974385803613296849, + 10544067501284177518983466437755150442726536257903869254459488412549270232123, + 10495171258604974589451578238018388630585794890815982293891430761424812600427, + 13820724103604550843562070971473423552484851063169471886037640613650155173554, + 2334954333435579600152488915208745055087482119087065911968347050969338669409, + 15100284614446277058846085121308897497066957549089629374506920751044105723791, + 8493821960754696376711287628276980042183127459347650448500304251148421115590, + 18612435536889941393944858783110719304584209891406420832295898519317994950798, + 362101794940079733974215941991047456600874474038781578925062694203564740952, + 11020033081956343850903875701444955317664141075326494650405276926536449284939, + 9396289482656518627529185765935649373549564165735162258912975312413185691167, + 6879055176150676925438486069371149089824290576271090206945130252868108043422, + 12466610601804566637227883322591924115458766539177061670432424956205788935144, + 6570302110526154075173287644133038486970998888099669190857256824048085590052, + 20997862990590350605775941983360263378441519274215787225587679916056749626824, + 2642485040919927233352421501444361753154137311893617974318977215281720542724, + 18832940311494549247524002614969382413324906834787422940144532352384742506504, + 18751288968473015103659806087408412890105261892140397690496125593160830694164, + 13938622158186434739533995447553824444480420613323252752005511269934155122652, + 12878982657080117316101160964182202074759312554860119090514406868768962707099, + 13757859113119127982418426758782225628393556023865807897214601826218702003247, + 11817871682869491875135867072669251115204978941736982465520516648114811792373, + 11336448548896065624515261709306933490181794458266726453198857687608284871020, + 194970717714150352477887371297168267861902418496792228400198694925721020795, + 4999282817977533227652305360183045040853565298259070645110453061034932285549, + 17094174197873140035316532568922652294881600587639905417701074492648767414173, + 8484251464872873032022789624790167173458682056313339863651348894878144808746, + 10260366716129057466862964875306868898686918428814373470382979997177852668590, + 549263552864476084904464374701167884060947403076520259964592729731619317724, + 10052714818439832487575851829190658679562445501271745818931448693381812170889, + 1735373362835209096342827192021124337509188507323448903608623506589963950966, + 7998373949540733111485892137806629484517602009122941425332571732658301689428, + 9035170288660659483243066011612158174896974797912618405030929911180945246244, + 6458619567307414386633203375143968061892762498463026121155477954682976784731, + 12314261817227551876673777186352972884847144237148169773300066404053441924532, + 19869454329688183813243851218196625862680921049019496233616575272637276975230, + 20326917073492686652690019138603910654692396590122884746951129061818467704300, + 20403270805536666081472738304916561119325397964511536801752236086414818653063, + 2865941730880218719188224311916978807415673142487507504983320505748719154068, + 20614246027521726470902405957496110178017768563127335842405314212897493119848, + 12060194341463088508348622863463208827312128863463014006529428845777217660299, + 1128906798719793375274166820235650701301189774851381709919492584451845983197, + 19670876372911656158743764425809421400123168087389888660308456184201759209723, + 5647230694522866559497222129254930524469944430191328619422533907417776118543, + 318629082509194371490189248876734616088516535434806492900653650176451776632, + 13685970881538585172319228162662520285656571966985351768743970447782846353365, + 8283840607829148567836919316142994745766280854211662326632930274668867638198, + 8968895518159422029900464138741638511289476298837958524156654785428413265371, + 10061801991000917366002570579819627134666386452411986168205986791283562415829, + ...[0; 241] + ], + [ + 6652655389322448471317061533546982911992554640679550674058582942754771150993, + 2411464732857349694082092299330329691469354396507353145272547491824343787723, + 21491443688002139478732659842894153142870918973450440713149176834049574486740, + 20196926676989483530222124573030747187074792043523478381149800153065505592963, + 12986278951352369831003505493892366673723882190521699331613883287145355738793, + 21126146258242782643168619000295062005037298340836817770565977031890883232034, + 15509665795506578582538177431401381655815033647735781734613703976071034655246, + 6989769181472743404364681671283889685042701491627165526899522083327752110839, + 7062179885254277466334896166987547257487047183881628199983668518000910197987, + 13842521112365108087725039904948872289730786568469683976372377853164252494752, + 3830559505943186272618534143266118508463381443414165428900505002474439179836, + 17704863473432653834041116667846189591617394753001613253930974854399793083900, + 875580502229441633079974792778818749112423694973231971690365132230865385439, + 1971134273535892826573832061354985059300866001765691176219451252512658771248, + 4865738840363990164915013008693722144676933915103280504727326977328013515878, + 1148603338028060679975883868174895825055359423662532941509525326937127571764, + 17506086433923270253695698017062834613463718526046463655503742220257039588796, + 21580033018107258179208198773211859664893072138803756118939260252922297665067, + 15411900706973212043830142913959920716501447427702082030760032355626616412240, + 12219699506725448409610279620972339448030565224304464695714944121760832152291, + 4525719544192047521328360848269156485222470829314314216955024799558286708479, + 19667371373588322336224317159113441765198420040800065314868656839300028747331, + 18916925604689704279265158984702141998345424765142129953154245912230835240445, + 12789343981741773931665143789673052782408749041041266509485929045869073416222, + 3094428508959717445577232225505810354980663487713729230015754183012845687401, + 18544590634480965569098056786078005630500574069468005220462377474861119476492, + 20990087440247450018723844204951613913840993427110495085701200965767234569705, + 17552251989761134508416634118845221324472178264364440017634233349418103869223, + 21000797802575507763447855752602183842956182733750968489641741136166640639409, + 19292751508591545849778577901067988044973302547209758604667395356943370737868, + 18314088316445539319869442180584299715533304874169767778761887632882728399870, + 15003745150856597539000559910957155642193629735521291045949652201905498569732, + 7839443900003691950104175747634267110464104444913379977500178134209666299140, + 13568305490393393394812598233983935295266242465548739772708079888867621061127, + 6453005227995051361096639028742707098785560656441339640433794156400437698140, + 1420171596348195609536167209221442141824294918625468780931400849866478645240, + 8347329128252205996443084339884155586061343024498283583400215109265013719709, + 7893774494551056447960817286805128884970061671041428326788899872964096959040, + 8970476243368194065341537088653900235777512204874037182428362347342487241690, + 239049405935404678508864874854718951364753739466303321590415544572014148257, + 15772878921699764223771017074289335629553777447709755479885293350677783703695, + 5416082112919155131434995906647355834510201879607888732259087164602171650389, + 4384524908062410354304345761652962203632712291085564157560146286207296352050, + 4210984612917608245844011498198864216639269565627982123611519493203177283139, + 18816442907032290878644773027005263628136050677095986565400687355912498966559, + 21443510232279945782338486087712914668515437675585863788610958361560172084515, + 3234314779308300525339049581669531363375743827111579883853941968586490182859, + 11029499234949696730080035941750777601416171837281021031653841244636590396063, + 11145210633226924132308292113124660576759662647204939721872338908644906571564, + 4583160563963432761409369246361117506465307518522062239686649163525543782173, + 9813992026757562966842771727657080117609486122615087352428596024939855084450, + 10084171857039480706430282187972782725948479260179367780776125786119489581409, + 3874212709197875589640151274548083098712939093643165182881681226579903752816, + 21595542491397091124739711708612983479307589335640792812157875295064235960610, + 2068530815441314105493629066002923150651375034543842424822712297257260726954, + 2673459852071215292298131389250564595426361004231758522146794940265552265806, + 8591046256746588406353455230465605224309754008961178558834659065898923355164, + 1020055192431352394776887540248098706183934464205704158014904833376067287118, + 11085709480582865378042656141271006552092494690130782253913953070642865919312, + 5673844083530503489429922596812992664928167369104420134641855283771127716005, + 10492199162275168254265892158402955076490959375050993042712629236807564461542, + 2280843393156259739329331366624245275580688891778782679394848304764573859886, + 6807797027131305026345508953353882265754363485246407959111359919046340709440, + 12692191384043938397944633973317584101723715998700063415107128429315536223446, + 19818676957110967644349139912613239435706480354664804036688552936554140369382, + 18055602608192644695569077694296748842203151828348990995792087204755925787339, + 20934555391215769430553078793246717148484784880715746179415906355043590089450, + 11420705181439111353998210442417752592951340005396931802449360401461783159557, + 19878854521263746227125001670931867821366047088989510542865511663910116386085, + 8568201846715449867087132677683368912214864824182424933182820310911278496552, + 19198701614488576617610339232794062430644024620523684127268879880793305460015, + 15262122764244854433806270478871594904740306012582364033343126589996733802868, + 6412758421155818207287638337822550233376667015263373809976157264137577776202, + 17371585001641430978766734501830788427263945848682170096055857509304472649262, + 20262970042379497707724791203314262108784948621691331141565359315001027736581, + 3859750447119748295302212198327542106766447958113540005985799287718502362717, + 1172269945800307665458943534144481495673510885455899148864236015097947176746, + 8164247467959680477306326470118519335673181279975551434197731340070491876250, + 4513977811114181395323888111232002391599397736872779927267726121435887238972, + 1075250595927474080680862736233039825365918646878264905022213616210377518447, + 18658420120424372681792175914064174056413842231969276203770574969914576681364, + 17769673440848360838244654765103041739044212539359630263894092078288342647801, + 4319086204044362848967484441065231939136453667264715596505827197873119273506, + 11221173270629292820060668122527062274557317856738971635698169204652845111606, + 8635411372759272135249379415383299350267629947167809163276219879514948820576, + 926977621651476360285369760355547766944001783780761167546467658394097283069, + 17702143780592866375901805387463459229828093905183622296234691441436877570082, + 629612289140842594504574984021125242351317893847688437087866691775821981724, + 19990548577495092294245865870717186004301934545721835081514347926537975465539, + 7124830628609719908679298707909792306162298058570958688501370177898647946696, + 14620227791860703231425817538142948793892390269806790476396226159679984968174, + 18495581997440241868332244230687799183899751339442721677540757155760745277888, + 16922065056093401385376103551657968760602009001905886435813054626317776258714, + 9969610601962874779035054685661667941954971427956866645694064022029705170229, + 15281641269114187762159685323068136816556739502211864119670902056596295644116, + 12114994625438879103001132949163961965524612903017200394727056658298824651596, + 4840986177718281128440833017205097196672382395936939379498412745183060615212, + 12847307562796769659308999092658905656250954898192781948610713494470441775991, + 20290096217351155282642224215178246911041509999959311313223857240001143893317, + 16151664509646153154405691138084115125600386733136285504828908979176781265710, + 13848845391482751436287906247470303487958950799995701248612703022979890932133, + 6335716166231441585596963683321661194889815181545222079376536449814718259931, + 1824302750039354704619545544386637317858342555634601563660279997221547953768, + 11327469654081586239268713126961534952233559223228327222485848924908493444712, + 10077703415170135154603829433031861799853903739210136452726077323833067256620, + 16368073884579385814331927334821006319227867093692644942500207970751483237405, + 10621580796499573269115131164341885791299038227955222944695715163010783205295, + 2099241376651019397894434242565225315652133572870234550073686122343103853816, + 17104632243449417396641550271977294699471083572885397875525767745512335891599, + 1935453754847256492223646005402770357836971113012418013930273797463411526183, + 7492761611332930896292052363224494314920390056637668407353957465667515477934, + 16836705924460095689555600825174696605443212968244843485187771119291716736958, + 16995495500678141665340056658079449793587669420913589967848082091551329904176, + 16097379973857697753436437302681608056543122759719328497348770844548177814262, + 17476569537128329379528694049566216604638194592812108658767104922628767500420, + 17997217989870184804787026924935938133194070033518938653831611194683423549591, + 17573343771046232580761295935281170028624495346579002725814597714902588657750, + 2450087639204541254902859018960918562514681200270997307467560465282168310665, + 17288084325555056222618040923753050382954155896826087372317882602328092535440, + 21837047676579063581498107773514419735425738753079336764356909012851439336687, + 370061273472837873736743292149368449614309676635341873070086681342317566380, + 420725183996224279379885018872359102189091670793820517618337092091910692771, + 4966571645678139143731798992823327185758562224229132271884647901363447388530, + 5039558223429273757296118284876763395391635773837549121798873235133698166026, + 14663152729953724779401067486012084029581847325524052152795817923033297673686, + 7201040456590575809960214033959496417566605177095808543357813677845263237276, + 16872945504528960415453618286121813996587432836152082188694652370255998768595, + 4914824783780909279212078186433590922437371437384817332713271291839616026466, + 17503018483514413315464207189113334433424965178631599286655188843769810245465, + 4087750571011463387872022799241315348852213278729592692674275176152296405923, + 4006961923780091252337105595934918049936238157468198971234322013673884171131, + 4481908842184366902145805444001507554481032302978790080019710161108326487967, + 13532316826436461968093937893872910736305115143550039673102602344678825540956, + 11602986656925867325907196773754426955346837006705269228226729102186031417465, + 15306992574062791537454541745213815567999895856471097922112648012979731636068, + 4497571735611504561173050536899411999551839050319538712220770383407135602945, + 2571242673174714867278075260451133687893879636121064640779554188161591611843, + 7070272070524747733177730083966686149849667613589868731851816020060781720851, + 1308310289745495626002351437755820460104812708071634598163946330870933261232, + 9483468192990391193401121929514821570714432121414330663623018046165053411090, + 7317568349845215930675847155716598288688799068821709820024570206796617676748, + 1918505733423704616434273602054555051755671749253598966287072464475922854850, + 15158168161084905689406532256983805923258003804476527617207287404280855731962, + 6855540174355511438343304861678411868002455139032857270673849263857877330771, + 5989863238360846166935911112885654223487221280254816980802479355446167746774, + 20283337058688740322296928691341300752003492063748410749625272920572074851396, + 18957132189629332408653055312790838576277703952267542471751593810468444454136, + 15764518568966520670995753676429154315765754748131847346608706222194564055358, + 7192524197002826721654253762628934164676539329903087107420445743247046038858, + 142950766663597487919643890566358241353679421113406309294925836697585309311, + 15012262168187689680572958978610204856600235635916074406168861726626292993057, + 20795666834671497603181209610179324236645779324677512349797033323222380300794, + 12650341271833683789775531792948185319868795529390391267833516836256688318306, + 5597700232877580665749288204589530549415282468176625525368428476461504532052, + 20949303924691159143653175365242293984396858344688574262804199947001630916385, + 10746523145835332938672833282581864816136388045771578294905302886974358762209, + 4998982766221590779170630035756820066555357949247521575936385387288356143784, + 6936999580131731861735955554005106460473097800566952971315565150681540640020, + 6670695360676548472482680016233507548657051302712214051977034166870814430578, + 12210816592786563975173850937247594401582085430897698766795696447223454826466, + 14933901149105284237676334791785996160108290333321693498322435129559137152007, + 3848529433916624869590379003597911090976938589461403388133685310398004369431, + 12778805225074604003024964969486878839359935515509480774809299341511161183802, + 3288267180428684202786697419666969564766921974531343432588030535602163038467, + 1272672432174256751826350693883913844502039730140570583479554071765667798207, + 21130828804874452930669244946376257892693846272313548250936991077452679117587, + 21254559353072473881932828401787134230282801383134765683324465204971002861493, + 4116075860631781527931204624078712926526805345818156200756399332393348685924, + 17435888597009729827411190999389277840088354756277916760187756022854497211746, + 15837398163415665169712832984380121382150588321621493928953938599666110830812, + 17988638446757562417082379159769772097890681265659458369075768452342579854303, + 8144561030363576879343874888624208577604401139613622673042754207987577727758, + 20020299925602421262203305284307419339160247406220693128040712457114283033661, + 2945951415037890626891130390523013930737768652394758977777336357159436605764, + 1505954324723537402640844232704189835623922400329086438898375859826553573763, + 11851584491756305117491374581845512067704002072833714119284164514457248861803, + 14471204965036278214508938537949717553799007630471016532866101610339050785912, + 7163557293233604902868673807221391042191134560333950452577270522828534690707, + 17291625782465108601367695465389799786592304061550212130987221355832952230827, + 10240907112109243116543462081552827576656826251172050843989873656917271396422, + 20702261919346727858635106264046787321170414155594199951578791234276181642650, + 16678253307828004252292273162411388452019952018258857370242272543091326285541, + 19810917631941180098047817620026253706643400683524412974923209268916769874447, + 3357220165225360610202375608872621445880880830154732998557832689480921421791, + 4392285438534542495332422274902727975330102148971785438164412161504066619105, + 14642025133729666610167675086855441462580619607677226879159952689184960379911, + 18142623439987890999821892559271093087005885278955082040377769578204898750505, + 11769399023330099592616157336702104329646487200891911089287290893650532639221, + 7261353756299584174448625214367175510387913706095214313669922259027644778060, + 10406994568199070863112470594593301582798997458844791396920771226539013327304, + 7475277967562870216712397220016587384793504784585573136176313471517144184018, + 9598064630327104406929367986473441777975480987434868213697837347643980267620, + 21137410002545951849752865514437404724653771608225272412595423069852350320648, + 12345612867231779996383303763804719815752861524077922121654106906093103051400, + 16461750199070055335468534730937701659470268635084522644824623393184528879703, + 7829250842543018165409887731515254191943527926556191989558018633300783421935, + 19801151644322693878208767560968285812646931156576102755771403150148125880648, + 808770634664491371274943928223981161442027957963181999892266696287962813461, + 2298122748772261447929855283951027113218922003687701626762072351622993276571, + 17407798064458858450209051887305178872029674498718760624162479511390762310526, + 18585562277464562541666582720366573863334618817908062612923861658144918595030, + 733976598693219656339731904831283238690050114241501938501377743874139460889, + 11316063986696838098122262534148335669847478050407756877728672233736962269417, + 17614529714381496379478130066245111825610297227468263851608027100133421612826, + 12110694197729365219340374599835523099651939156213930558791147158357810646901, + 4337343008663255658976574468931581484970687989356019720784093082313510905405, + 1379188959674402095268172673987199124815512095460112504778179157481327937561, + 3116148242507754420428768481157196067508084836097458698846114802493377512591, + 13306507137873332434793374848948087993544118494881134631519748904811343155566, + 18496878480807017010077624766326681523549495609998881196570603040242554712562, + 3940126764022508707486095199473913866137718790062498893812401335738707507732, + 10030078765792498033316282784150304209584388923549357286679864120250994473810, + 18519871685760382462428068450331593474924737719734568498029727699878543899254, + 12599428893576891013523136950822667754415283296587096197120138265392279834128, + 16038578953099895530943034305356008247313649524436132877362941968861459073483, + 14319233878082524834510736727226054073026413911339853399113450188859080424272, + 13710161613540579690732775978855380876556751245265568031703536595040993113748, + 14958726446649273856607176275240008023824615720456760403465034344703779274727, + 20935428111942360630758629263346308597806819928838924586682307174931367773605, + 5826394436548487315966647466017047216786257295199620110266250301500717796281, + 31401797997389676486806123612280306684597605608110075525648021056710776011, + 10784171495708237485952707518956314344821522727746927291389338644844400581452, + 11604345371765580191117799693565193618158448665352599382713281103552305960442, + 1378145039624937931836538950217364481423707761527018494355648047365613434790, + 10284294167221806561993937798090888689421933711157676807977401896199778472860, + 8233695574758520342808807499924062869636681352769371531557726871630696672029, + 6570581391072134029876349038190171593169496519436674767949949730275868319732, + 4026501263908027819614805027945064360196399012004574117767831931274788631138, + 21091098569404004244061462065218203986433580687172854429523306262593782053656, + 20711772916118045406356429185975897495222240215931761100801599257137350834799, + 3165519312799351250309462589160165591299333587158531489859211268084164422251, + 16470663723473939739601217501478624726068461799539012562455639586886033078064, + 15672299304945968727435591100602007503785845873606917887638890765525875123857, + 21393538327627889838198844493522533627143658125568123117776524944297103649079, + 7688819203734248199049004650451546300187194458173935784579101984183800649342, + 6609663518412297884695057080546416278366560290439222127471462938252865438638, + 3476303650597281786976907813110835564442121684386467570637538230409080744769, + 20633582549754495054832414039299188930065286005370053173386561254823483851717, + 18067076834611402459142612082327591538480657933568191619109271502102126814407, + 157209609820117793892254328219308970217366919934739036156851508233236414461, + 1848396116513925340973398423998379465460554039715233953825786874352442451413, + 188642786730195655565401615804782553245486295156304142809552609651873793325, + 540089254487190924787439362270708251103955915909358626209177199653451469720, + 12796274768956950589847157187031845061404119522843128177103898080653493269942, + 1785666356337148874573621868025910291826158842346617719666738769156993598966, + 20649919247042517528354490854561347316237285929352042389729444382153378749538, + 9568390566108569727471722677925269460696523515877621230569682954652430518787, + 8590683334740232786825518158771304803451657249486419816607179533515442407283, + 9321198393538172042803957409292145345834077448228642847843261373640165958582, + 3651905214805616378360839954289447530035139753215923648216350128870943481828, + 1324345422558073117779462079218851558068746895262914344818945294328678893083, + 6666363895154434021620869731925915051086919707989020578203743660669796175288, + 9850757893972463103359995012900314323213006625927501272997539940766979170137, + 10214293226445704940138790188111862069675188797488928722469679760666574484266, + 16862124085118494177559484642483513597285992646267864845521573612482278871023, + 9172340118369291059693735314505606817316211450324955429310200429408035954801, + 1968992755714619414656181112336357119271845800144345284299978250769356388249, + 17192498940296212027365280042755701662136570107224000496521552617655679821443, + 10063385968535643122430064779260670089120686456635080613693015398478175344193, + 20101961459945738562625328882763768836449780661345042148985756598106706734632, + 12704305975772252539534386080950631076046431529894091327218544197389260775334, + 3008242816727585639441748210631464697850194693570485141354082562181236010097, + 7797705698071555811456747812384107102104184812467361013142453143842134807658, + 19323240331433203844038522035479659453946066968727795017745942269828428751105, + 1698137797127320576751729191866734754105401103859852376273763815257758421427, + 17656850887825900397821271738817912328294075224643535784810269137125067875996, + 20755447986835730799031196367323817361150623932048563112034040627213597261325, + 6221130271964372280138992636208062417325313096379273438539556580491430711297, + 11042709376363248213366896208587241517252100440844476816212498352999929578287, + 987361321094619571176752720390429919723900732295551211263814448408232028205, + 15077982986114392945859048373768437818569856001604485167476360943078774679228, + 6278894644165961404521866714059972066255652200107181684047812674333675794053, + 2649747800006903047073625320829560088088800522557851927539477888486006072675, + 2636278052351769676017824297717609512488651850924228608531372135635042762078, + 816232991472315395984098922575496846552245086608787214581606973359616326446, + 14372687274434205592004117128588852491871014819273428668840779210928924573820, + 7351401720390274950322621121981079413650308506660552567079785209176949174210, + 10275293929161727274572318228903710245677747557851999483919909420098936352013, + 14869686444606195206734119702227763209172799407142930791211203702643805341518, + 937617196362766626935279232045712623531859540210120280128165029613358941709, + 21331527351771920568751070369057714014285398281585036009305608379072813379081, + 4305436470381074948146072259605215282335211631970525440530773004228212378618, + 5894273721571292784412707230481346442881109207745969297947253583203466014760, + 6512250441044591603946512492071171861967500633638753443182294740883123881284, + 20863871952569294813936866452848141274047362082838805921071316386912981651979, + 18788566662709810970880679984141390717017951403407913908833463086244783373013, + 7784927597396249543149135503684024377171301321636804832597181795981969626201, + 13818519831569592521516488188127966399245767953522268350556654747680372036664, + 10515208647860053151690062640705322684876580250632027862984821874343071549235, + 797604926079325807488629085866693514275115789253871397971708541758696512985, + 8741784289526985522570446847275649913333939699807282742190607491216732972386, + 20966712704043418981047968701828936463778140093909973286855779694780086635828, + 11359697297415630167449040380538108774924967116147664240213257348125754475868, + 8070907838094569287067982462230761680706116783989613960066342967469297961118, + 1868550288036217638713133945402464194193242298015503906068429633793800456561, + 198709459347510170000840600179608479136663571567208109852828485236018304733, + 1601154135701845545733926027872374554514541574822026314034696802419388627041, + 4363994778006302991481199477873248350039564117453810275561422974475581105893, + 773054378219982710451611471050404495804413666789496412742983455527754059148, + 5209426340109575519362014651321132459061755868557415513439993327176584352934, + 16124961412020675839394907565568143713078242978522632778625312854364651991011, + 20812496670075231301471694692369245988519082317145989298573032859079075730004, + 3312489967581906638742585802390894285073229440039144559060030129184388053832, + 2967475373447822846542676378804990140732835322255774209561143670843223463335, + 19744585401442299381952694102570931935735276268739851233412754166721728873141, + 20026293345566344685499234599699178313754630774489046573312844763673073616936, + 2611303659034102517884318354550433047021831422518437228002960700934925644951, + 6230291832603218406134986471162106408091661326026848531605999413028246206577, + 9126162046556730019959291776456914453189657463686708035601186672661595109020, + 18827736146609035067773173111376739253733288103277133456626928961785293662143, + 2328703958261360872869074208611873245571971231035163763965210852182760438390, + 13796410059666172174899788866809560044715551934510722965495280798363043241416, + 1593663256684781552813616365605526150610454082601584196604084376715746899324, + 1565874145189898288764434737762721576951043839540107044892767693968417810945, + 8709849304563896945461696717753976956465219721409993781555147204068634555572, + 2994256803561260177499267243802460581941891553208150783951937342406846377191, + 10452746656507347152042187616753027475507881362159944564077673851918869542550, + 20130580998875572619695450234900655050996104101008767761546912649074040426200, + 18926933358104691474037431437316089682088433006245222723356764715400831411716, + 3783551594057498940671877156409957274854990650480535806320220142873170375307, + 7919031943604095374667473717154511882451510130166237539514111182596247372692, + 14518552587329209714850286012780632801030157943402419401997576700600952906519, + 4770764028263701271241862755569969531641408032906982530346384375773459918490, + 10866502826034731763529371496585294375373238783964914673031891984092997621879, + 4234148117462322266937279401468367908013627589417699250592523530383852950379, + 10747942066055887965185603234524367638106812660210378090215017248140719240336, + 2587411532912868255102795810490361867789634574022411742057853375399270197531, + 17350061113113681344498080520518808976916692173267298878258722510332360424059, + 16490282364669098969805528215926442920328903121380947471680517193373377657129, + 9274691782659584680377375192682066090127280485689527337429804211265749864190, + 7630965482352419767782717986075793694403609453648729580916814032587325374653, + 9483872310024003776681196467845329825094379763716541754956796450187787638623, + 12182966986735661215639970080491757244218854808156498220088212871061979325833, + 1853790963611367149183440339188924598268644281518961106776656221408171642714, + 17425077915972423995335545370701802959607559878032910147159424242864219303096, + 14571075346526399549826264845894977639678567831720652860528738036970272895919, + 5627701855249158721927849603102149698163511782011562166637339712383551336091, + 3620805686755372260289125555061886982808014642356719556961142525373021656729, + 11556995641752009899073583627136467840237831247117281278719511600076965602980, + 18960242154096055221658318882298412299294886669455506299567210308762501113202, + ...[0; 157] + ], + [ + 9174141306060971809979631725764298697615039980311809306145004207410652431953, + 4847693924685156250211477469465516228032151306221739650606132660616428517315, + 19669833054057639609249840291533340493211768292967819468538893000195036768991, + 19800508893433268850924828171290876015556093796000695603651522426066333836892, + 8244699449852279148780456022144420353408196866113049322676048275081354214716, + 1563672068712965454176533719400672258364596155638916268717470967009721945171, + 12723223712027468580318230235559705540011996847167975439677647504573149248849, + 19944398841194165937952509356635863229327574447452745793253427406349161295763, + 21218058308392585368594275702746106483411305671883946244077923955757637296177, + 18442884961885927579732373746933397748806426938144021013884176466434407012116, + 11138408360119814115926439449668526422561003790198269766757675305576549475808, + 12724564576884231109847024566806896391934587839830522481308995309797961575379, + 4897733190252075532660075013731462724561461746919488679609618967302541674417, + 4797748331306263412471031924618974997396620231469532262170060449304337691527, + 8626839560132907403537141283531395025838110825355541158539075100658769738351, + 6096293906324574249636975851522292408228519044739444932687579741964974917617, + 2351617695830568421216396081605990689071283678701192113347036659596049514149, + 3045682390398203085155257535118136303069379656645406266260961816947178911890, + 6935829264874515341379952008241845470659188886156484974987865751370715745075, + 19847439266968955911971997829840067368072860877451092633069920565944933744280, + 12795097343831149148337906863235678514689648096503928066579129201713661539889, + 10424580232112390318877053133877999442988769389050776486274146627765228950235, + 11651452649618223740363812212607761589812354035139843126315028745587570714609, + 21307929358023177131550002602820591970791247513576735567457471459920519084552, + 2579908580162153663820021562014873149811195641589016321720930006635393981680, + 8198198178555784054784079137247244121807775986273563786249987394640289859893, + 17176088986876377315956611075288620878117708836881362200541916957398026761276, + 671389874397910339333118510595007038137908096657753354622355890021074216004, + 19161949137729278558310070194809106779119877882343914445178348849980058405327, + 10827554013954037091657804154642286174226562252063767377995268439458401752538, + 11693672899474469123468133710607776304784343543318650064064636202512816205843, + 7026547767612627656560992117440221331093280829523426249915938274837157551621, + 14422968137896343032446633683271253661000603582016449215470992885331170459671, + 7685352543184863430081115767111935982586458632527708735083385591291346555502, + 14089009391529192464370954954330128327830078875414722902347666490457756695535, + 8424161061743752192085022963953944100289245618074575727145394775891645849043, + 9809236779073852557054640507912802523501426410996355424610807253990040160483, + 14100245203768962710288059230665566265892855964739454261791429988929622355986, + 7775683622333704945225255741567928967674629526812606133980425422182282014012, + 8739247215686497264451630351996892836638898510934389758205488381695687859658, + 9431876969679115468275053745264413939426444105271849398322497961102606290132, + 257914055321743732506701382989022126153391940932933566664491918941925247878, + 21801414068435960590201256257290267142214176965736081788536576642934903066059, + 9465495933537134443327560834432669768951376466867005153580146079082722525723, + 7862366214258716333873810314803222267215825847232397599183717032713290878315, + 10701164906390193792620967030790214270231326273599373762943959252633779929633, + 11951628827727068395937910010248864431667047516686609553745879936868276916066, + 14268744039571470490378560085356767818183790841094115879980723591887874138419, + 14468215915818797151199796266933432577607248341385185700017147731054148927023, + 1523824033338639123415809477892820349580561577160869448927791050266158538520, + 13559991428776910947424645696251487328999214391124402586267086012691140984198, + 18151203063828433535061866995346135260543721730169485344610433976436663085882, + 13436242600153492361692256644258899977135098134175123174795293078081801647137, + 9384556671429507406657070680351030238568956203341356106463890924933167416522, + 20321079285577981781556986944841048777999006905303986053275199507771332527205, + 13510502130738135726695195328780836716597947131948116750163533622597187969844, + 20903049289119144354363108865308751668897757360882852151457514926552553533040, + 5611953645512225417723205546533389174830971368309601830751921473015551069534, + 8816886019615642422040038431962872654062471314244185285424018745071289038220, + 16751828354835345790163611999302863949792305206769993810746019449909446216365, + 10421654749141018171116296259626916395875529220250947127973888230084671091757, + 6065225315766552671037285757918350882361743810888619479819895087632281975681, + 5737755346739850738724717271213687543479332312420206954339242459110768587128, + 14770522272891919220644639305274656491731294860310497013287297810648680944682, + 2777394791070450473479179489594969793054480209411136328689318984981401732197, + 10039559932930709555975364107098145624058027439566384376771787183526929807647, + 20757756003754261934858081777796652436155530474748550156383127600004580439167, + 13253166894715452480712170898662712132411702335275401581167208877688374856806, + 2037004052447343668129085129987646907388123739343356363273464870501805506884, + 21829471491172175426560705585746893969222010633542962882847909490991398830669, + 5130395545419191392223692116621486075405299333195732914002649716762739787586, + 20333821730990393095934147177227294218344864602777744425090741435432040213391, + 13629653802252084129446975515814037702423511189484562534040643669977716900228, + 18489091892360842692678715136565494502607711254719045543684163289077857041829, + 21380328601365035012832876315565064374684993115210423862017233170195286906080, + 2280052193465635727584791148501382679094142036232980037838088033232747821762, + 21415541711468815972744677841317235994302058341802530962394281077076174148777, + 17146992672828650459975820445250769505470616910596779130798889014378635881076, + 21676475584514120109058208398560066698690773910598518925936412952356431597439, + 18337052978997482578725645166749278142628133291693686105612531426715865276143, + 14864089429815580405957698645045711801464462794754089671996837547347950054532, + 10834607317840698149140890207826430113987295440254355899459691878793978994131, + 1157143498448645320415276909137008396665083714591338741616893578930275511205, + 5027542104048754930085470328670427788489455916338375169351586496298129661248, + 1922685817237874482932428650501872692326329693528175054457715565489676406535, + 3071473720617798005831658342971536643616129392641449174655528578463370685788, + 21091078808046042460442535848913779439792606439995062001271357804782672390627, + 19773167374024045118471391738750949555178717045037157435777574972149053404157, + 6418695831178793575992210834992785624340084513619644969535805236049937971859, + 6317875495482489567338519005308431806047606843913867465201005132273298011425, + 18001249545956637376455848019549801116909661454019565655561439372098476761813, + 15530167556609139699164228289904946047951254183080358784988008899829027775935, + 8702757129830652230304011519426558036441096750485189115358314568895250616455, + 6369986882953061252605652398893489899416599935424066958291402945530517772170, + 6842894437627604179732847187262933342846269043996061072487488027804029200046, + 20951621154051947571647917571547811655800779287153833018533872651413529893817, + 1219277535080749134805291725937516331501172121638812333911793209536894469364, + 11704605822590166851511022757496386950530399074796545751042566537118336773236, + 5983427701962592508775640503988144495847156070437130549832329402380170245893, + 20169091361583397776908351163571343158517532527313940288212943504015977979442, + 3347733015762117176159731683196584632702931062411889821726902331981723958255, + 16217509027282489850987935065936382820558307489954122630844029918951230268972, + 10781269196927764524006466217779648732772805761839205677745819812868343369087, + 10568911823766972365218731330080733630028238366288098114239172953421915095075, + 5568774544682750792074131352530555554984876659733959079036284517928264996437, + 17854353469028651373397049175548228061144941710027186166132671198740388767529, + 6573034112757039329551886086829829282007989555105157401271097204633906940776, + 14069627287078359391137554212536883450595451640858724555679971658981340584258, + 21119713641590541511025673864154852875977162278614553796484277752677323191505, + 12802116677235410441672624559825044917295689876859311183079161588690810005363, + 16037054471696658545113065872215787085337497333273419984439267709950724531124, + 11698654309680908244303850432833183602706804558317993513795996394673734185716, + 15147889780127043019188099948246961619198549928908180192590946633702778981583, + 3657342516407201801006680507925024451922115018712017224805778401726428603983, + 19776786467141868744713630352693556348834540992018636838044610844396164981103, + 7980994848490005281733955776875257044050741738176865989521982608944874160873, + 12415191330803073018395217955802011585094769098717180100014182475381600382452, + 9300986814650530426668152137665814177758578011365736727321578452726378799933, + 4412208980274764197258090802604347599791567698589180187154608728755887977460, + 2582317668924231956058541757507620542434237159213236485179804217989764223164, + 19860814395849792324574773787600734118308975251437485131415273418632757301303, + 2765909129639570206766170018363951893338720647679193401532780051354569922989, + 5402210382809272147099442645489124829067576777592680891367494969197685281513, + 21011104174655621871977821285307554463403659856745964274018020456838460357574, + 7018364707286303918877589672878574811337524823085078243421192184715151775983, + 136380103284908296988715215087018020601815024625535396780012012453684253071, + 15953315437474610448052466140270091879233956524793052736202793153707558909889, + 5912305909658884889781037379491781973092020933879206417274479331390062715252, + 21575635295587180789566592951559325743281772394055590203112195979769645712827, + 1541325805478255472079288730846072146731241030100908414806224735345400173350, + 17207219201921814683730773200330679841907450967511507012179337438654141678023, + 18266907794578843029196926509122804272900478710738403531664855427655744759655, + 1204224895193276222782842236712348692319665277014183965830735736728887994581, + 4023246588034712778784328407820569751989619386134504404739514704773521558127, + 9064437981037864995763386367268294611921404895425171966596873454090899491243, + 18733802217274421976148972926716884457128521840010001893311936746027998476583, + 684088380644531080099595788833220377905013807951051638705160997709156627273, + 11994830816367980341637110785269531718699655485484715851375754143223090344544, + 1831724566362300629700078416489434571462666430381219293205871349415506993475, + 476710745682537342427691635955087951551678644045621275039835625280220347951, + 3586272766499559446129476613035465343616602918105042144185864609818186807939, + 21220348736799044560439132291243370111879983677197111626309132298278891334631, + 13683795063599185801186093771702503913590598475095473714851383723199050309401, + 16118007386401646906425171859166434660243697555307927508268622819509657450614, + 20930641024767526790605168032291665313905337763598128831404465184891980632233, + 8098646212401100552303711812039666794078834386731698810205195111722330322418, + 11585783577173465460243373201831086724911159484415020913089605532852648999143, + 6939053275662244505087635417541857793206828446247848992283188764105131966721, + 12798043540382494855660472922674138947867597503468216532170157050160462426199, + 20713389801600667412553956346192236970217099413304167366340548074880917096741, + 8708207547232102069057776099666995672015399188924281674772351753887161579745, + 16016293152251662056020528248861487281148011452459422778601663166015837379163, + 14324897997637439510797191208789711173129460994362368408063402682894248793270, + 5652996184880208428967511742390474289004021508049280419259474250332590598159, + 9877106633097964013050071703002221796318046172981334418310092241450453368579, + 5385816971548914185604875069230499528103133871233951354186676373318036241822, + 8683091293306949708478955451280670950858818602696102489349595054818146782362, + 16854975838650963077652189417311897888852709425835763860743171659164792100482, + 2485160816649177905834265823672532710299580013309324666453183278408904845122, + 13571692148185502188613896013359942531817915076247598483272449919094247957149, + 11899399615412173136098732970606292047945698835588882297719609812145308198009, + 16827672312681684936590464376780346837611857292837989006980972390576065571472, + 15588237822592586948064701827497915157359094833395277985658706133691498343174, + 18356642512438827417103800170157877145465512961188328254773957819312191285168, + 21642368145757804795143182901389223409544979732781450480847315495418822041608, + 13104082060493963869934085622104709047787444250961437496674916673804812287386, + 1561532086277971111804773016487251313460788916643968126116038406859074212104, + 2718320602791009266532615731130512762296058687816604986701989820504700684864, + 6182683520717583142027400659687593712743548729948584058329789905227082638908, + 5757242145794370726637363237313640925174531077560764545993554185332488520899, + 13688467192244237790806289073845563960119021610896694359815485764764608925981, + 12528461541936459922472167643986446262977222390263675720335825628163511159437, + 4897268894447399415795897967133432014527122426051771866816059363418177665482, + 764332419588242767884018802335623760055144509861323437945071732931233600264, + 11755468878196093893190753985692714003062307843033761257593209352165323938879, + 6006022813561851182403581780143813226749481175437001910923100661321563995672, + 13901542382190510449243772206670622017835690746895066410475076631498053123535, + 17648853891656481911225897080296737974064729032668806126284849597245044343224, + 15106333841965710929952896897521673254279668876709612770907537801609875568099, + 20899315415025260484895459315726322363345188136910564549344894025053466430346, + 1409310408943258102775009950750654615881913956151269414096059752250092035807, + 3899088673345731523976816322438172722785832982334214339521575164464706226294, + 21406686765584824639201351330529610299177537976609066339927938099572420696135, + 9121591670793901722224770893633585291275002987585289305307167711146944200595, + 10711764678410479049841945177317023555168593838022414378232020467195337241279, + 6599257303974597452501135281719536074294806740553273627128065549267140155175, + 2142616913275380526921597026822750992917222975992774063376747381991404337593, + 16361086527663411948363284957489078505159658832010445114438602510508720771278, + 17122647864721668762640781848678028227021534122268561738445496382823789619088, + 21708018685042482318786273055293241752114005312590172460099480713746031274624, + 8303630654111760473056607545365338851734309857718959193970615705292826806179, + 3658686547507488906491014260011151850549759409901579684176172268581462329020, + 7720024124908065424512743488999250878143598904717873371853608249805302871508, + 8805244918657836956533473437651380347005779399042661429698187314657501156241, + 6303681354794120075893215838935586592706844702088252970663343726024171795351, + 21512507181643408509426104627003618425209526633080701556628608990726677651135, + 11835373417333287523801757951049679177935522717858158305516568595764125190183, + 13059698839045014411602727811400239840163533672024084777768305507840091151855, + 17635240655824524168378284083397931667938326555447077097306236826752492079430, + 3374412791113107178205006579112630099131939030015047870738873452427211677886, + 649711083340882271985565833699379436167716866997851102439037906608755280128, + 20002805138014565226408902156524463368767807620908543995020210484077706418135, + 11071355197960433041624284534649121637702414580710232237233568479006159191217, + 1105441595020980635809093220782460032826849883993030969714432603468135735502, + 9652765957610682812348919340146799318537766051849796416434577860126024594091, + 19248299650856496267902926731608572596705132576830681367365128976226233392929, + 15285802367070100569572399512275861017714681455564415244982064571963339715277, + 19970416835730683993734843405673457882587154729456022607061085470691843864556, + 1017865638757684714433500504002748241987153668285974836527484933462490771227, + 17284848056169793253916338792235498052654877955690514601079806604278964099314, + 11718277105372928962350331838305733149270432706448484259807630484543527733952, + 6670793378364949883511003949124179112275066568088468958915163969545409700112, + 17088789393958965094855662340742013087397643056458490270185660553870734946796, + 1930788514812600942005320214284180860980345276633471423966020111188605196111, + 8844343159753729614645407314580317697758296041737296276765583948670245312842, + 16657939543606018325703787748629433167511611178952563626096990460124133990109, + 15333343644239485619497914931918504163396626751908652058758135581206765801100, + 16533875915742793452819179569144271760125646811168930162441077117553849625884, + 19679534317472082858641184998487299940737032844519038845860980362664393659234, + 16385719932525604857740698205965045007053424961009717093945644387917936681719, + 14490521084213123170781774542655088188106794646066074998587858678154251198444, + 6386781978322405984893078797365492485297499058328348606653460996474947075858, + 17508047533433736707046937662428611868296556965172642086594091783148965906980, + 14904597000414815084666285064575232635645852687797347860862157463159487771060, + 14979972442969995336727018758631782107138089738395941038626891064816880204567, + 5299243186271864957800928637599294208954109271450189950375274196644046222516, + 16189884555052883188473617525411302750109401983487269295700675997730645714379, + 1645560170870292006287241616671417605853047420339675073261660626733726665673, + 17866745974872498136933906591373095763114066893081150553715211393380040095383, + 5744849574386643500716045532645657520001448510343827372577217716983339773799, + 14021966200238971589811034967347517039341058556783068950884921208853167419283, + 1201178089866013320759085637098781870734315826415474628546655403142858044361, + 5875644793836087035760988842421852197052681650818034527831700615895391179258, + 10875065950479466897559006840696567433921014267247530366235539292597441428702, + 2221662399199449388725697795500999209427453463134383582414172135385907744785, + 9758513532658579204941116584445291102215928928145103503086996542188799521709, + 20879593323317766577775570558015407573466986714590017262168011643343469361329, + 17225846522404915080676699509636264825833159640824918876741681229188434930856, + 15189442986691997434021855855358620506645387296294217783597931695143376252483, + 15973617135551858849206811241799666696907820418171736027820254766840973764431, + 11888113439449420418408437784450952639345990804839507528208325036625374967083, + 12365920814385241227394825974928370916184942218042429533600397623369545597697, + 11966175169612449906889690852332416255478894176917636726028104087408060623141, + 11163554022908212145274813635928762748847331295589087669583554722521180712379, + 15273476004030808005186443499782264987539818978741159793745891769358221570633, + 2013969196885866182480519514425192091338553670034650196068995589691938248955, + 5008975446746271526106846692137145404766553748264648461545948417006052208130, + 3926749194225734582453671614337621250954608160208554883789519551411469033731, + 1635544156808471185144068767649088695307748439189898784051754434524720057896, + 17144944482517962143604430553750908864860079758005337246916094084534304051981, + 13823503533305241872793740090687668844401004819859520464168798913603662683770, + 16335911272023134851779534303717879370955813837529588982953758998930285394340, + 14467284210444150699969889681308566002886261365990840091849371665183151060295, + 10578205764525658336257882813734672799527733392763965031628376897794294290414, + 18771425328697137255453620743509164311086906349726510394566012237817674245865, + 21804626093983212038528370352039806004465345685985435415809095637323683466452, + 12056805308954301132385034564357716323176447186932453788072119595595483786736, + 14307195735327805282612857510308008767450554777122724855715789120735513378827, + 6848201070063637295416045855906784325422580350462489495889308309540335269587, + 631364713487758647973016689203003205602593076699875191323345338325349259049, + 16214655556434201961140525501007839859074077768660052713461045928979956365067, + 20940788212183642266181811368870506130164462254923655617893660245551698033523, + 8257440848494309435270838240795567828478627302119374684511017376568090372435, + 13701089242130867705897643891164147923878521147124165292045879194108024940909, + 6895272953337895406509859406973110417619874994579965619097329249292199573333, + 530437169778092455975584310016745919549274205817234464915791595041990209639, + 9008612822403008353420189298381046023002474279157557733428254452507266389025, + 14863423501786052071018008300345884780479084379412157784789951872243409629758, + 20091026239041315645045502002997446404106877721183777765607724358538559881231, + 11103877261161399045807234470901399725912406134008627937945079980590775715243, + 21529163495181909351665093277427712610965764606448489357319207727176092439794, + 19540446772694448035410067193880900774391072899517686330271100773183944540294, + 17549510450820803306426739851959754252204444648959723652883552677325100583689, + 12252518814610348662318155253547558779974557529822012236107550517806390105567, + 8058115132085119666951861652409945532276905989404523986413207631657437321956, + 15916100116790431839835734530362130437167135501074855072245598938219364570910, + 14256533476494466694764843270015662315303617568641801280831873052211753536970, + 17865471381417606502707639037418669122823481329049436020149405646709537112534, + 14015711483636570179335132940981982618090553643653746531174110949872682031017, + 6075776171664976866533080327142904134938121198707020111533599997509054627652, + 6357981809351565370498807027309828058036389418343890944791766504532174516243, + 15145296985037303761634018005118672316118004891352906450983918852209191841446, + 2473672396516437070485250176897956191104549656554290725379242542480862701754, + 11059085933391482002269653121188853142706883316754376424538662772943167665341, + 14804069155713123448375113552227724310276294677318593116834685772120057819258, + 10146378656966122923223443263705119557842694560695035707977826044606938090895, + 21828309590915152213768434346306434851424116996828875020020066586363340244814, + 15568879616082229996551157805731419126872501425454775741945679993142071548779, + 17504079509060638501918729619244098692140123800571022969294759717277257664716, + 2998311560047298465700351970612785742605093777116697796464434026101441410385, + 20229972737818088327107446854254558628041027965197447598027135778783710740259, + 14884874200763033520375899992902136897590350894844904733314191389520252900641, + 9619409751736964504139815024141276029474791187139050183491749032619248817404, + 11534029087676783672833531415041588991838838078174102967049055562568798961925, + 17106297093375816944137015955705541133308466659538554159312635106186252148471, + 21676736161168806529097919794022110433487869702564846859065695507460463414524, + 12596447704589377083704857810305080195761099125652005594925931498073219198049, + 310943124066162607352831846280730445558498286205117614171844835745706684432, + 16013029710570597613246104892930389004941711962070683476555063566372534206859, + 14282564976066063966062366540992448474634085812789771416509095817495183298269, + 20757241092771652500911491636894210910134068426068355089789205706892703219255, + 17084251309147907751212619949757520468224028014308500329099194408342072624132, + 14680350698112448759886861002622963534698534998651150537754386791270019720748, + 17739512731440543100681958009173086667000199263945053345384367808940651002571, + 8967486063900234709994801661246451094429250620940593387993430620369318619734, + 3906067814916986286272005884942051451306945488494283077675304366798199289520, + 2517004675157816404807349457307096161030587393097616279110332574293494030636, + 9995302877359286298434340810356550712107485295049220989690824504445305103587, + 12849909876017357260683411536833847986127911582040960825577300322066595609115, + 18074515800779889507358182860997188274134395074469953155084226981497567860114, + 6692811728183968363967959295970424292426462800383828091752006855360167264617, + 17859827663908740084792157440799065184931609649811664442236242315795442091367, + 12243409340804252499520308602187370739653046835019551522661290645230850934962, + 3009118420068966587115224335717185828292538080040896739662684632413054772046, + 15856202298588272962175258696610233941787471472716811521132004805327415486141, + 7549804594729480554341356998842376772514802673462970334329441043324983960866, + 6390806437030742378988258255983502109201709511321162596105974797942236431761, + 17370236522182003753669946647208335160124999930136364231371998757664000198520, + 2261672244214630177095236704932243497157963117166120717011661647779055001646, + 17325026196605130064689259977831126468940872193987407658419640959345091161632, + 3631641025220845885502691330008982895233731506600778684638817282531001457735, + 8656561399441987116927438675277763317789561532507396244334062468892541066084, + 4069166732330197412844703565599514109399373916243310212229125901351402003915, + 19808198732373520522982274785888742523226720967259539531129335924093928174880, + 8555796834031869022510134190573521699378201702450788201649007358450530423866, + 17759660636058865290579521740750449606781204755231964378855563896473545202303, + 1335826395218609619260020055566056869243760115287254209950063597653055872566, + 21596200365241795669701682696176077888309278223833581800772036945674858315765, + 12619752319673193899296833725747186284394167228468888029626464753793997178599, + 17420588547980145067421969830249755561311178399975476925894947008643385243007, + 10337481272389772505654575850886249605422739785111225132545740838911222864209, + 17928431631046752749930349099366498612885288622404560316665023363985966878427, + 3075798659324203306711977985120251896073145961913793478792728028765206521425, + 4639500613932181914847461422373341918892878975546430906324216810326467690534, + 15396322795715441250300995201889120935591602515487993982711884319616897970533, + 6391276937505284102735701938724106665734769352007891548547667448647832351929, + 6811373320779057384916660178551330838095673247430496448933336925226142036083, + 6590973140323934807800215988687710942074412987201753370126190631819398102173, + 19364648614154949386936259588484266535262135334799266379433252509193375956715, + 4702754284612371917466042550086249683933140314858807272591351280832918881874, + 1081036249074169248236179367049085684430282426446509768147097371368406374049, + 18548093223441988703029589168425055383154624592689171393242936199350770119589, + 11098999608073377668352846814752381891400020647878345005629685447730764310163, + 16001262992680194260590639872321865154716987495605624862471107193457192704714, + 21696229443869118415905915570780926763029898831113534481730746953640692230062, + 11716215712634983607563947056324900205144202447594949676250978337464771243867, + 1778908113733035314726603632369389424542091991692308812147944884836647395775, + 4019081204388123040098634987844274011285321286777408246805308194144238418480, + 3473266952388383063447927231564219811787341139731701190625605897592140631276, + 10457881304788072618845101933412333126160339089704353596608910674508961127232, + 14926101732700077295531234099443522459232814784151318061435025890154852791802, + 4036967072197259618286839959572768559469665646019907384624959071646231971399, + 12776716624632228928613396031717959431597335742467953143594165782617234803915, + 18894783424164609284436913400522166453255844750192864579927645453695213022195, + 6303809107919167113924303987533838414137996606980561570652539716097058487126, + 4729698693443803882717817492985796053343431875965792864932005291979914613160, + 1645790034267553926884568714540144778649055395816210525904813567839945991808, + 8138260225269705405100573121045873922755899939885385491610389913906979427176, + 680936760009829486282006800072001712155424246576949107399338687767760991887, + 17240357869291182045663678468827695873425113788704614245279840174870850373113, + 19100963939745621863641468371111320143895293700517367016077996431570157414340, + 16188989656090417148189510820963186890780289777598053654241741803194118100843, + 18027402882394597868782011288920739982398714370069420860949975937357531046151, + 17780529984916796963712255733293310230026423072958099290880849386941451922559, + 20004531511171838591303710792081846238092292916166965045929062171308088520097, + 13855731634251510230399834192704620793850325654395687428672253016405315169901, + 16872938837392115669581040432902657478544143723662502779821325505282093696739, + 2541555081244462826761076743762714962901590548271316707071685417008817634653, + 5136424039269088350807839181761422963254683236279333039713142751702136147963, + 19216238128964101420135465007632926445321991494181045543846024053552797518994, + 18868537488540023742258053821537824724371813776839672880900985865823137839953, + 18246710415801024039719497716350501105591286880983169809863166130543617917249, + 20608694004331631709610739723463009412162748201282986294016482926528443868949, + 11318113915971658853560322943565673154831611543653209084299774855226816037778, + 16240989418312335385576389959938922684406585560688799437547298624184839261343, + 16171299673760267132909753100946681733778389681324959987573199154235691694977, + 8036823955656422391918380552495301547890420665617977624790236120392727764522, + 20269862530534739231936251654244170650781428788816658397167110617927916774329, + 2368678892744667199202318323282128737449992006513656480477288092472671147090, + 4618078962163037429845764284139891171861860687111566735174912070413086829215, + 12695350627501306162901105159009497730633599768443844225981772758225613194238, + 16356283146491744069785034066388746989409816380917535719898337817088223419024, + 6407893217596287850421377738867081146106659458551198123106454022096864887316, + 18168868018352364136212098098453930600797374324006271488950341490483455519349, + 18352629174410142476418438008157117497168118524562206830585500251463010761689, + 4344169393287991961961456515301754172943022039566219343212376057129143739343, + 19424839806870716108478074501405697296961947409763509419111261767390677718987, + 5796037897847804302272999466834285170265203646465480652521088328457333766863, + 17402105801450379889120987010453669096275392789725153915905747267778100864362, + 15540989618743824352651126288511222263828123668208146479603617243655978402205, + 945810410725426921570254447269595873973858272778720657523509910503434094174, + 6962323734045776666289031609372270190654631739266635759799844631053633876675, + 11382945272742312954364642163371436855283161775445664525053938433459897196647, + 18940251871958826726849623572811640436342841713786099464305053400421580490631, + 13969540696178305383564753026163726563325318478290740131984853424331762285147, + 4841983966001277917879506889862519614692143906356361564304719688757862622407, + 8939049562492171082419559182596894186639203815268680721033389307282239000385, + 19265363396776097866041313346787101192508520582744521467413665478819721956884, + 337106861429123598189388456471513480497137213511877011021531147545809512194, + 251367482782327915297484770356856386307188967585026711663629212746150191478, + 19506616511267234489421548744907283107923549136620297132842391511025844759064, + 20633589633280372440758096707466273580151526293980868749421563697429194761212, + 18833062060138888612708634036427140134887774731041742144004707524569102994071, + 2927291160590267909596732410727396533948837350308818016906834558527125752899, + 7095572562193114209617459307511041110255341231707924363346373597653253806883, + 14274988113217913224290208839851596837329960221329537670822013510325939323091, + 9965830780560026128320556230399915681196410289456547935188741323403719404039, + 10333365845496980935202034863900757172839454015352626511769637076650624839070, + ...[0; 89] + ], + [ + 15193892625865514930501893609026366493846449603945567488151250645948827690215, + 8655680243784803430516500496316192098841666200175185895457692057709359214457, + 11710807066713707084726423334946631888369490193496350458331067367713412617049, + 15442364818086019103203999366702499670382575019009657513015496640703659810202, + 1358747428976145481402682338881091555771254635226375581638965497131373838774, + 15658002471767984962034589730824699545808755102240624650914676102923421241582, + 6420480504329990097173256112095253518339231893829818344055438052479612135029, + 15457172495394305353698644252424643614748461590123908880271021612601244389162, + 5745943350537490600340174787616110056830333091917248931684290284533019091654, + 3877253492903478989342845512796806320713689655633086736499730391667425329322, + 11257677301507982757739320943403112189613848490812422490591766717141506751601, + 16906586852467953445509312290627525856126394969718997799028223470195783329296, + 15263589725854108297280528692120758129000336125328939290924952731952242586386, + 21735940039489460025710098364749096267519151075908323637361429746399161905338, + 20023056608360522105358681147781839024069418874082333862551226466128829664291, + 5677500725280079960679484373333947430817198394184436922575072427342643665917, + 3080516739494460477657748111767941482024045797587058388950619118994388252853, + 21486496065617100719537932626843898998311175055335457507845650282870586541596, + 5371049178920102602305531530023787518286335086323221270202212974241707302466, + 3074817222296007572297581554183445947239252698770067839721345984255386069425, + 19180807038569629573914331337874446591506172622522351734982093457681161813141, + 16937785199372956273358037645552299688842385008757508130180245705952406225194, + 1688218397616770248184651775433764527272029131542529408516364801909017591719, + 16315958669815317541884966612581197291281164499674338063931623110684590850347, + 6218230753007070123505625054833158632732536069700963073464625252554943737669, + 17774528060285257656595928889288330429565059134928074258373583886985960212139, + 16197131592052727313460949906369199026477758140133103701908949020106767192893, + 13418604038232148873269488320329340508522225417123160144993642839875173062296, + 7265658443160253752317166706266927598319661172006072732797351716897681315157, + 17200150079219747370109251547638276280610591698078334228421747259741754887, + 8627121890622175767416692555014275717515106888840919734160364408960047296494, + 14546964505431549758350267964924534495477687922558528647552728692912697049247, + 17132720822762740343718421124251772119916072270451579802112353604446214831761, + 234333065870376500756753915306346778417056884715946003873280290982247600083, + 18375643491701271245209094287106352436174133929245169725584150600992143374298, + 5158448692161567615645197008737390561357077078129599243188536485308363800282, + 614161645152783610732075198073600394068518413590650990586931263981193439341, + 12661793104597977909223565537293318966803153852970198322604479648383643541371, + 13041905650419760925682179803296711066088286278603171065755078690359168540579, + 15006023590144168506070897325649191051975999212058008674224953860265667513015, + 4983349941266961584317889823965291023669365981564144622292227613558024302012, + 482274340065333833495445682213681402212945945150526736364263233985449810602, + 3966893131006556898236790392613869798057510088913626163333804949895810673044, + 20923301526284527685000591080290190641416245135554916208054502046381491809443, + 20838692384005825835959734210506718428443540957544929066941550833051093000166, + 8282357714606447781782716442854085217089572080066047419459610560432999443766, + 5410651444876169088887579490283094453001167796545260026969919887357676973543, + 15276966646285075387317940436655285872037988805762800567413073418506412856419, + 15066911464727337689573664613158712498015597773345106524271610486257089622849, + 14583790985054968382519116885383608902981814292128186470697458065499359610203, + 12059090796146479535492139954279038037217093044815277624197659219529427760034, + 7273811886044732271171500579064359282424476926867187108258957006777685922641, + 1463086899665237074608503061872751147444637332808872866814340325832200880984, + 4403177494620214359779479537027014449448686844655371530169401219256448130398, + 10860968418848589590932601250051274256181778387706764281989724391784015147562, + 5268786978207139542368199165627108325282167169564314266747401266496556301775, + 10683355823176907476704511935094343405052640940909677712096702771871787224727, + 12998090263935761477316698114799901126086030852595294916463464609721875730852, + 21401280461419124637791689956622923839426783908187419462727763377498739154778, + 9827224472048063173905906705579289843819400982583185823840008976971109664519, + 6215804144039763858354471461864183189301201862376216122255322421321775987311, + 15461308489200344015891625455653488930440613755785081602434124530381300882814, + 19336334695450889400681207491394600659946256404722006637851709906131899294790, + 1712331165786355540802697725399423752392267480553199895882357858951999960061, + 18153038525983970702748717571053178456148003321236490384959117581005013333018, + 1080183517033034908031748897211289245459330899463186432840251241943892326023, + 8948022108193679628295152361559653763100984324221629445749311939820327674857, + 9553342289560502306921915013446606435600388298465288181461633559299564421155, + 12714965617376828547637017050548818007690047452402682720666099310241001848988, + 10945704657865102635748104464461970844653553427083981539165832149959193156197, + 17511714411688352203059545713591160825310809755917403629838415797949261359373, + 9253691969419856285051096287845246422848295397226841130282244592511676512433, + 12218945350859454581754463621617733341764245716874083264842931063272433793037, + 15268139709971695434346690496076067658968455677120655340969837725391575270485, + 7948825129295102283421620705853168119104356217418364837218892682579042520651, + 6887299291348589691868712194070626390224806410428583073294593431810559288717, + 3610235157455454109573625364057240708256027358184031380521552355839155549623, + 16532488069063334064099666525339953823111673083177894678898823509406678724969, + 19317517725107761280217103201908049748015068578935276576200982249386084367574, + 14980901224290526859762385599553818204548992110637275324411078408232697158492, + 7741797285700915051013289492475875831764653137095445146268474269974647962596, + 11964233864746181868467810392101989052496076326472717372132104394243614334823, + 12746657111181947224582102380049766839578185276220682311596480990298620200286, + 6408726946032901840418309506578019708113712492100046332894630652186614300568, + 20959261828945984489015610988397031913577918654575078054490013338416801523934, + 3173674599420546165852740604987014294355430358334465189504551707066179193914, + 16110281513253204315524614633789708146700074483476149119440509845258215816735, + 17135377580103690088853370572199271964414896742342749305424508776150797285064, + 1405769920008485935711505753346340073052795087429311991287498566024570212365, + 19088073362945853867763169651582894739272002359692597239222895238839593467749, + 19897231284455588615416169252449008151349728648961637517447194842672488184146, + 20476415629812014715153863754869742189693986277342067785614833846523246536739, + 11074321446706734150375041020583051611133090415774365192315805856051215270782, + 15231367549323128694183572409135806408519505225209496441892541205465727777072, + 10515952069292929457050921929301902464262874744159361114100398880194109971971, + 3216370118771824418364829250073852356774095079734089790620447714552849459645, + 1940445924652458480775282556203659335417827058983719042726494187979000691704, + 7899310668555694144370607061960060230071621529123669746309839400642332452086, + 3125410912833939638823760577011271607678545358020637189655641109813198731542, + 2980079409624774815878860133121670095839651294537928173829312563570356348730, + 3766498515736372882285796238406751547889526137955288498682767455795237989580, + 21751217522789414135074956130080241003845828660310903627224390345319859795839, + 4947229586642010378772262640583556676497656670779800090478805824039760706318, + 2168676839236948809859825591626629233985269801981092020040909992251312517552, + 21172906642114648036685108008020762271569381607092920279879047961076646303327, + 882675742500939602754673078407141697482716600335919344527751158504426951699, + 20942968937722199705624825492102184647835614761458159157410261242387423597787, + 21880640497503102067412608072166388563991106464538369680846671301780353850077, + 17593472026567804917122179982860735087124786197105685847979050530954084564297, + 4492875530722152383516030266828166766820778742874238188105265500984280376666, + 6799763500412433367637987497601148507907071065930142757525839585946238894092, + 7812331664758167657763399273963290017340604299019483750344476103319142702775, + 2222332747647756867926707541092465789402467819000336747029352557749400316077, + 20438798382149666667185974604464532451975024544676922060351031604444896151494, + 16155157103796724378615022758633778903205872772589663310774455593497441785913, + 20281325298063880945091623185126257485818350714264176365501683813650871716911, + 4922178080989486450454493110764936742315495846015561426329316977670113220071, + 19579063976700768282784922967523980346960151903154507737857728349662090787824, + 2458828873355000645851832396764221987760639423132968569631493912353159373462, + 21166618206785010755521994106737991950548963896649678270059527421944129497211, + 9131643699583013708059191290958290089892787165715294157378879201986981390031, + 1820371114511473946932363841206094088983972935646887524223011276305844153307, + 7264184404232663540867032945940974372967974872966180860960243405462016972362, + 11228656105550475045610757902396386402555430893045183008968975441800824215261, + 7151503559113638565935009743218857812859208253653498318591469659718664783964, + 16876040581364499037941813142092448836399042253618385783944016186340703846779, + 10334125383426918152464737478646460879481305348617711177774418125714273980769, + 18900559046103390399749767994653107625464807708680067464279674225251110804100, + 18685667289312169245526749652972366835289568864080726348092618145885982989561, + 19970582871354083670567197978171723431124602481748785146813441774826500485907, + 15873472427137024971035326229485784626398898771525077832924901475242073457867, + 9090803292122260583635467396769157643561973206888822931647063181944243467413, + 10156295009710074552070572489422360071526675259143523597882131082376797944708, + 18600630374968456966046654667577076758720435487386724419578803020365834014000, + 21292291483064245088298314957584631356250347533568992016547598449487977536460, + 2784266893057214755054197979675795184619614089277590464548240934105557638370, + 21206743389683892419024645604723431382001453245850423743581664552645211926469, + 7915761821775326316473924816837591351530533394717381318596295803119061411675, + 21881095237485064870468603451853549262304643738646051878343976465227744077912, + 2011784725603622472271597952122938645154942022107573948889667939904597454410, + 21059869383015715705096974077910228193608826877524913363323189378554601804559, + 13660545486380051482020817701263881806531607595506890631732662177505270213284, + 10831091042775967380899180760062457635694790868286967266013231823406639854653, + 149288128407476550494800886735600251983375852319258454101603889073198917321, + 4032475033542195421623899365282946172767274020529645277615759958662043553317, + 17860535012887415629230166789742533149365132198763199254812432302158542514395, + 611194463774512114860065022851497908950074400927073001695280142990812150583, + 5518364261187313845085346561539515049557757056751872639492957432879259341390, + 783263978868449790737487156609432867806742277074765259237378374864740012575, + 19059339826992310300213673274315612374137067865428300882729551175173242291657, + 3179709304184015397125565132235783368222831063701934511986753856772139349894, + 10954198701843076039176000728742415722273043852061382139560487789741501275316, + 16411266672500930935370066093245284646483148609897099268661795671514664627451, + 14614816948231085620934132277599546641612327229810158468490195811014141518325, + 2458257206135880430320027516329707989817636936777744813891328347210486074414, + 13549483340434455515002570470395006683062583844603627042649952800864870013910, + 14465927800403373425828183741641078057513049263889255157342086762479739044711, + 4039391352709218793104596256671892882216573882631238721514928981154171136548, + 12750457082077152291009387792121930725761848879916565703854704756389714536037, + 20703941646953337308096638741387402857948436803334980867971163138332859477843, + 20148755487317949638981041809982361196106823990400472213765926589941031736503, + 19035096428824471222963574043396024781574056587456391309795571372815435282399, + 13597108420431213178364236660710194375344287228654817880431599113069659963625, + 16737817219786305757887002253067607822378794077688837656791543060369162185533, + 5164935079689729145670846016031605160169301936105766707946436049006171651941, + 21653381930704765824477248798502813954284378782353810890869232482999795586793, + 2062605478140760101860087118379474541965619844748678233207247884294051836812, + 6841505950265078437298089354417829781031272459823272323626556598403583002674, + 18723551101558427097952125661588457059960574026361073828482106612260297969553, + 7898804490983679270754258611113569895515918945891808074921872907759024464249, + 10882278698112390755842292529204069263813359338030917602809789513528936860051, + 19447560013395173052961224723195565400117958329259001072560983848146677205053, + 6251288025262210726686494480483550276704856797649458538460443509657307219922, + 13176666617050786358406074057104742181338809005466316548399895981897535342946, + 20703225796049910173111490454489910459787604528779911406172217267261190895618, + 20336720518722954780604743873837334696992422089627753769439653667292899832714, + 21420427865372074512365684526694872695798980614525900481233709853915806389425, + 2498895690812694987926199054702295457557454143930759961192198950277119149872, + 18753512301709603592612141197073246313430368834576850495154922324845448997662, + 13229612292359498096055458608547157785066962647476451239567069089111704445000, + 2690879919643532184588441383789963956137193400890598777054187145581183393168, + 14142396602342548413722428497204107502988046500369932366351553161157672540408, + 20448725195660080278132534867269279218381543910636641344871383714386318629041, + 2559459540570011016181396098001618067535109329950570139376049832813577592045, + 2209294835847631004298393339896770055851570184195462947318472391473531519454, + 14610669112573509857774678749257346364319969641690596877040685661582231189775, + 15281088465087253563674405311018738676067395725444151577815750152538449780965, + 8600553033773805414817363397077178137667131851961144771667772828459236208319, + 2748346039979601666392027583251905158817539034260921486084376270967628661657, + 6854960712378511006304629447898292218014632388505703802374806527561178043857, + 20207552563190343462280438839438087615024485494479390954719687107061991587248, + 10281541252271366635718295778088948309847900730867531177275273130071062184625, + 18855605847424121529776135453072696981767402526737712879984848146282568841809, + 4160214035780913418097601322951078913381556877408879904436917334405689553255, + 2122867135885631508183413043949777333811557914428796322029495785048111325437, + 18793959580906171893053069386015945646795465354959679615181136313144978078417, + 1043591673717355695648236328597936528752358227297053230241551190351813693314, + 15686469257015275311444450012704351019335987785561570672026138336552980987277, + 14048856209379833670666148034655599475317994357805584661156301746235313941815, + 1011563953969880478397969933799483261900428580241502003261587014788238280391, + 19240556623066672446907714818724971233422104071815927265423017590508305430997, + 2121904286573815063480388650799381683473766736407678915747169455786741101182, + 6724437969134367395210139771738563153857495313330774537559578422672993498270, + 20206855573383441961836932177838081339503382415601366823182724056749038447809, + 3659051978213562322887447057085386386485486575515693147713900345497451171308, + 21246119528547168535908718411570119652856799993958321864163737649108920924448, + 10446114322905404392321651684574668727564081327779662579984472408056125404335, + 10052242287865403393859620372179811039720807230902452334457123873762222543944, + 6373462744579965543231173757071025010089494620309953425653057223643612177083, + 11716070974813426833631730493593924834405915845847679294742728105127112594434, + 6451284530793440411577197006976867289209413848762574411101073727224316913966, + 20143217291446069633369261481904349401356557325260758866598205109039367201468, + 7741896897172494958877302103827661518814930985518070029789560123401964418102, + 7414486245715284930410091802521351113719159777210731898112598211035848096490, + 6480506916211642204624111742530825907262535747743645014149694168805302825019, + 18349725066341807634895742572304899830893334427067633858521634672944685466440, + 1838291082333887710851505844271184097051704051003105078056248035350245616867, + 19201915197596065583046168024521824662441686729039260890206806469763190071269, + 11253788423541320580105520117231178489492440242200599071301755928628199128159, + 6048832714406694444296771635481934823208451249770515560893368035838759154821, + 6398008918881249487422929614611145638894557821587972164243877575640548705346, + 7013037564266297435879776776659289982125632651326438965546874242685502904730, + 5942504790082366811245813670914617310604940200824079289270465669331434165301, + 14344789199380317440464969138686896230070901882253997360605407637865754361287, + 19920212380356573378521292048728904573841049083972983190424200459025557666792, + 8983390577894750782268266038315113359711163721228398686939390484499979421166, + 14953991148867572055684497824790735528852361750007063016470842397064705671772, + 5592033578501586280289038012647352732276003389059749788953239057845882297561, + 14076883072716069263619564306953450824526010844333044566762059693672378725675, + 11108270411921226463443318601950168860230077781212396032908932369105145901793, + 3681277588815101350213324449908372578846563884174807724121308021640034446476, + 7194753190480156904207319938161903897566477363779122267985209483435838216959, + 21241255448366937244332942306324590869759761073985963892514045368815880517382, + 6203071960722514588958553813186803009742459823360660333787981951206442471249, + 19041823565851118046937769551785013706136778514067168239416647071096062639366, + 4928136619692555022185087228378238193895894009623071873887735418398682287593, + 16266329364886004534411977872528706660422476743809029518681886596981922182359, + 8814684891729998059175829142248330760704444206534875755023421115211106199303, + 11072277000652722690981202459933101924925520292174200155471966778637063588914, + 15889576313969861857250394875354819627977602318110620311480656842740292435237, + 6934515229262494305594741689326968268143898236690173897991110238064230886755, + 16212991575388366798683594066983659236103186124339324856776288894513503543244, + 21100508914867482363389012032457112622475533432309937238082785660233880354422, + 10381104469089401657446748653199843213201270332853172509558263968565255702795, + 8849389605935865968361613766905708889092097013638425059146677490704442276611, + 4826404934194100291623537890117339503344940312401101713754206109744511979962, + 9981819567268652304810465083896863711149056310505889216307212434682251812603, + 16218484218588441290424553684558267080330286201433140852298971691458926313766, + 21317661296916247018967238829275056855142711494630067664736600708605437812892, + 19523923008662567951910986132173659591346561824926093935331274289896011695634, + 21439241836891927940168832009944210084078628922824257988298290967895179737163, + 3818036890597976956138669961319975835941979944306305168232209375279960168960, + 10212547715001519604442389033695156945619060410131175896383181616280631586732, + 956283172524544133830416114111944076629240232397666924807554743752464221045, + 8545109273807246425343308224167362024331960554428088718932211551700420545275, + 5647769597708100114837534314408246331518385631750569421373379085922684908872, + 21776221280695269311212391423788179027868152904973644113087833004348746215729, + 15989020831232836203074762591626149244364214836699154611339161287030952623233, + 9384665943619921791886218744024370375464874104981653298499433530463000935024, + 15469006121097295841026542766455781293432005131673839148320165243166330403027, + 16103671377537767724271717097892044266704736999841135349844319906338275108222, + 842367229428650719054831004741080336526228967970570607897528985803108607790, + 8752325400224955775788313769797750158375262384121380328719514077259567119347, + 4803861091350023344885030428100876947830986453029412601567992550504530969575, + 7917553047944370948250445233027936387189889293110390303835890604428798853681, + 16378323148632546424902611135263436821435778030958161546757828745002247975096, + 19873719885630097137106352132870659633926425645300622070145979694717581586592, + 20324790419158243246762098227260178678767896786893299456278167341205663612964, + 4358908354524026935988729716331497263147669784003421920394531784876541301801, + 14403952632095852077754539203207047943619815438482171213105824864831554185165, + 16410713482142323347391147127545553384558868490870150984280601225023662513809, + 7304216341846662695189617252648753140769311862815448449926830269690397729157, + 16792943782280077475956215580025612636120139194657275471595325031090407485768, + 18494329391227402645175320826355306995912366111176422593669423022411884295357, + 3277597348237827068690736756050060740435013727549848360800059544123155276133, + 9396765756719511114743964794180256605700037182617127755220919249774110852382, + 5637053961584389263881381098869862042993858662768294676971865632259649027245, + 1752142832257643043564515360000718468888861086573246457619082905919623770956, + 14504506574384680785750882507533398260948836347427103366421836731538357314790, + 18947994518078004413210940685748534988014581551965984303066903086446389273117, + 8931855168578615387850254663107425567403115805663142600825724478150698936342, + 10982092525200624040399870568387498905840578524691489797530932831401946309626, + 4738907023206802373255186532236849256768509848242049657234258536668430260775, + 10888145285628319545262252531874405309329869513560101920454793431198094714989, + 4767721624212785367044047554655794533816937807005608600525762243335180089923, + 4054394679973840378112083329204220302222586590732553688297938891619998137578, + 15390471663419625573793381445844013245022413344196724396864223784781333233143, + 690498740448849288977645176879593806019080276382495160049117613302192708860, + 3326968907274045758110436838010900592335267522219473049427145975873344598768, + 19461545874830130561487975864151403334363998126023624462211037468138940028328, + 2255249425919459031033123095731665691066980364231819200773725596456576056043, + 17139538647342063569964264947811360956712827863014723985947727876623459280539, + 262834317961189780923232082352297808796511874872711860311746704570027370416, + 17784213646586812350819691264737755884800773322574478474130308351003659945289, + 9206479615073686723914227166450906925650471865894639492301222855979337534393, + 5955379232184076713510750681781395826148323482009739159408415185190732125682, + 16345512244217240951729073298135981012471478596479891072149124888060645303490, + 20053701095030547796310908765544502773063879272854547881438596069907281565287, + 11519146559536679602608982593432194283609736022486509747046459824035493513614, + 10868663839942247532249591973192159672852196011910414460124452013501564199585, + 12668355291693420029179738224611760713369106517542315102687346083105601320689, + 4091011252347209563858280520339886760216002486858313383741839652119084430270, + 11416347683590132388448480763970462739172261435271326798646502987745949753371, + 4462763980178675172541782335457125059884067698347130082276003539434128058577, + 21728891122467658477520865529973242372850367356840114983386033432316519759391, + 9556106604731806817435679463077765288658189491612307664294729425381901530224, + 5086982973132652080709554654284904229374030594786774699435814748257879554118, + 2278505454992311041650060186856758463754878439802195559533882189615578260695, + 16123495070352975934848591912315341924608875638550779884194576881433498909405, + 13177225503435100563531015597038445430211235761527278782674200718068329833622, + 11626932451843299545922103072142674578946680165802341368625957942237790110177, + 8872973246419344365802198448930136062421718851114220299577394844231810068090, + 11920016786052130191738519934437207519332291620474831138559948859328822621221, + 2773753221970604083383541092979093729869734021029185810064937974430862835870, + 1194583082499114147792330367943150006952486615245506995832323057119894886077, + 15293312601348482070373672684782686300692505365845870624263228679370968807837, + 2292156760291800990693425534213440357167359161992251338587906324724034592198, + 20920049766730284147153707151387304988393631464951398563908410768221002588086, + 3587899345078220957148828249287269521408604837648269936718299413697642586126, + 5857527906708110948691023855516662527925762284342493618496858248142623857037, + 18312267494676788897591109008609888960798722042916784593521762607767538629817, + 18354455618287562133438807735729369657256664914390381320892039403006410339493, + 18594037435499535688023807489676900345345731643180370940972090155512943637000, + 6361231157299815359812386352981667048590510979947935475914610076041390336883, + 6503045850716008738909204934356093641022474278658078426701342798380459107813, + 15826908470360778431798326530563200301151807861414464213699967513881040969457, + 913167165738148713876672473302437265273760468892350716109373788573860454641, + 5163418960719047707254162004625467116036830361107107814320243058319914687515, + 1852750695670141634014249062360862036043602867770163972096325792863710036947, + 16164029969996795952250343426848596535809001568622155377829217918121790073916, + 42291476149937488089591434144089904529405222471677684973768504172369443350, + 1329340386229357940610579826659090359930768580941108555938139535621252899508, + 14087936453397725507000489457270864434699508074557952952329368237400407748133, + 11454917885298514922755456675259734718428103879515668717779418480236210705323, + 17749966508430836878443008025013283275306943216523661550528505419303121693213, + 16617298839486771009961431205770630163409905047728421465641369616889696635464, + 5622873871440608391107520706189063847917690892897751818294742462879871297589, + 13537715561706278379083684257583804567523085149672090320983273122424669242274, + 12609629910090871112615676094781247031353826207267723991911250780907380059468, + 11881347692420971451998583525696964339513193164613288356598017302547676912004, + 3620434358220496198439193226313617496907852030586214671337652678218740406153, + 16586456872124455799862826347901525401871594428044067424833235946565396779382, + 19602593015746956165116919928045364895525104709835703557292833702385934632182, + 2465427491077301663150648330772125184470808854603184374760649420983178107738, + 12521323976712195518272978277895155774288446093713549157148428964880747896725, + 361951232333654306694462853852464888974834703718677826403016226307188397185, + 20048343816024297162848487251896481827914904696805156112188099141327595641104, + 997638030405613623344188782838773314122493364653596616029491564227193697621, + 10932007654988104622042938184134556963651043067553327861790671211490960094259, + 47171599193060570819891696279547021610376047998583333086685382152080932821, + 14669115378939104862697280661831896914139331878760241858539421915983017116504, + 17868874372855679948405169936193924176514630305572838555185339642210810710203, + 10178296575837129106771098084407669500326673901243393867574658658064222502028, + 11497182727976130924559852428316615034304736115488257034951588831868596612725, + 18847036158089242140209840241495282890278502700082131513222116906134183113862, + 15514518995390761662346743876733004358408187550386554449789531199638765348953, + 11474102901522012346251529527050392650125347221410246734211005177721289856415, + 6612195415835443084676700243243174090072629504450965229103970796390091290688, + 11572474094368358234669561324969692616275099241307798860733942350364532366113, + 3855324911963410548772360326122995145790506408472649961229511965629894550308, + 8802640003128749594245736338745752744580147773009816234644244502373660889677, + 15676839305513015047736600040932186843826469281853634239081282896349443894145, + 11124722103091011602185413968164672678635980457394627450785290630813993266691, + 15087674670944618980358596427703842917302233637812357643695687556421910213028, + 457555060782651847600218200815104907046227486293278645126081160142069992497, + 5340353060455057701755599760342180989590806327490432497082435572367648024359, + 3289809733259936118731355294329652879189400852472418229718273887860572748363, + 1821386174933044868215348232606758690922944887434531299978498726875279584854, + 17399236630582894158137572250502674699298844870791766041927951699287421557453, + 16772722824042046255416248879357647708113647471330900665176012648038469814744, + 331374066696126093678097185404981758791664151917354547180452342655690460271, + 5482079579065945934120471179616600325379965440378196448353560421120276746028, + 11861638874356162254375133266687016527365630872709665703116365332534843803431, + 19751278476934230895840638614095718373810690662562196455711240141902305648888, + 21017623330912840225230534280017695045717261514215145256795880310933667407841, + 9692530233397639077769939390011937602190121885296235066426091743618448584134, + 7914031992737639503490179289412369887137436318696390718781298556229610513180, + 5046304088054212585035723354298412694927209198400753780585596829596665931980, + 12735457541003664856181534137486291132119134214862779086936585300598349629287, + 8144204472889944485922664106370529127382213990656088602566223875490414163362, + 5526161442679804982165840590640681348630369336752481706044759543203459722566, + 4665464612431440885211271075488840033628676516298384234452346107374012633528, + 8451965709652752887539585363308640999657377914501438391781526068371105983117, + 18990458193856163728406448194111866469438835810342179114684453609893347662421, + 14602960690767985987882800342208585041637986661619503513589079723840776294824, + 294650277854196485752526848096008214721988745350555311479128101695333774927, + 9930361494944692931597991649915857642608730961125454734483697613693272941776, + 17972565769620820679641368732920396905240248490243886868922250461473059009007, + 11842743032528966560856860268344505094861546674985872961254820091273444880060, + 2260251491209762630871337015316066081541066308706934094017641769176593121838, + 21336986809148977544823484666876006147697590184356254785752148187171367963063, + 15637234083283356311249527335446193685599985235080555266374006156231977517227, + 7637477891046186378249227336975234440873859617986704147458186423096226771577, + 10435340982947407847927678888878882924793449778165415690957335683641419176012, + 21071574044063633264442120715854514033847137356154103023224485568597330648075, + 20085745552872944745120547909310789275453780111307008151203836541147270866122, + 2369255222739182549768488367357061329939116877812397072967912842660453854658, + 3320710154094663715463854219978294133429318041799642537800174050047893035878, + 2437552820481788519744888712380245016748276158860265401041560980354471184914, + 6687580113987208531705167517979176727449238324356562435678492283111952291541, + 13835828959457330678345759960614663723017667326485961761361157914420441377430, + 1823843951353887792473925888956554516299304358703549730900495356152013614424, + 18229384804985230011714562427207966412342158903455811854157839446374012856695, + 4983049472282717134994110428470567601005310848076496400503178535459679438524, + 2047051967230753763135778305592853785901616983565528680886843131244871631064, + 17059505494771925862841990046823342770591010831955480339095397897088168520686, + 5845823714127413134610517798305104245114036685335948729450609519089263487144, + 19810252752845594230307894817800427820113926573704856490871938876757561680148, + 20741340243371419379519807725035036726040739024854919427690724405113594586449, + 17305746835229988220561638584011917989169628535378748397361130724475478785704, + 16273970657972145440112726408308019138099820274904080726219726815138597785735, + 4927605725478881247988642936459897069651251926499343645614635597380235002430, + 4076655226193629464789557616268492785057128805549395585385432329518368497686, + 18134767316186963456589895259454813585756254459227058992203617493951135964914, + 20798436806114056077588608064161229365173163847083955162560624566238528904361, + 8811900287453512972593412116532745098600991077158875340182906101108258578231, + 1611466530857794066271650650204918615746591649578992581483080164777650137733, + 19520757346022691586967284723955378385034675472244175822936613026597514818901, + 8258287931139503595713718829279050060190693609290797346704848518381891359704, + 13807143439443425137076128013998009581746894329904809421858222329599144124143, + 2034200548964915935625429760202284220693125881760822084201315022529206424506, + 20594375914400911567795140472107624446159181622166676420027082349633992663301, + 17773828019575037451999782968066986504577459910353828196403976545023426528432, + 10645884969014005687699860915213473815514464399964009808411811895545112650817, + 3135829883501342672772973577699379927756997243617424917654928164800203666496, + 21807676600134151299257078976418813484444183016737321278512745883771478511369, + 14168063038909284721702678019083222059818438340503980617872573468231611140141, + 19022539506931505257153342575586362988716958060936788031721967221986624233067, + 919797128086310623571009200546035983274688764270933413427846490906074137487, + 10651353481391913627770814216074873532920753703051075188645774021198634943682, + 21601553598752750925049978818528421110707879819831249175157596816870100048288, + 9544964974935674319204796617933096476421551193682156030394816088243121582636, + 17113833205578964054057051521784698139661258340576694677296240312431808476286, + 9889647672195559279745677506312894570402108521106900082889976819798270827735, + 16028191999932520938901585234936954312994452706490572504997534210876573833649, + 19224701772787524647172128751148104366752057774529591812815327738829591289117, + 8065294760892477625290114823800398061529770004833832691347498933238361039736, + 8385011404987806129246014860479833290406969218526611328586242951296814426438, + 17626526623257098006524211054563886193098683828265081734658432468695686509315, + 9760584950604786147191288118087660976225563461953070125437519145090832114537, + 3282956645059793949082172795607530130101621492305193365378997603911833418463, + 3788543541342252822847978185963388795825378340921321139695221828685330606335, + 5728277403393912877393143174229934529937061751983246730506397742038949251701, + 20532577038632159357383817240596922896191478140446876998140515404169184846609, + 6138500779693128517529525961343097735306947649093633133232282430353593175172, + 16387038830089541476468870208162294639575042754761542956218362331966004300870, + 10184264376398708852688445921404363179240954227345322711923845040842165453208, + 12576299651793170522912156101640799825541149618303513174146382191633847258859, + 1340015400080181141720946234858756484323564628916867888877667239334982793481, + 733959369856163480135680991009606990817015555938726628110611986599242143578, + 11467033813562140192244869512537566463715027496952375979909160849747976831918, + 4619667645046391146577435774790188488541561222783010406420406869960248783331, + 58552761198135931030902257754896948615688045302818928845814661296914920622, + 1199849881730507352706524556330002080538296688430736582840314007371442152147, + 7124502590511184113044595527748024819132713282667933641439666531514739645089, + 8623660134669459112474551498616256867375253975034970808437732784494772311361, + 12655669439191191182341423414424342421477486764113555800095493091893820045534, + 18432703875775002490514477493898870315422995231506677048275960580528644904682, + 15467220287938881354678249472400749704814316816035426814619089032223454845193, + 2851120240492392321044027263769720216640877441121430445737594074121655318176, + 20519914249934881206828098454303256358482675671718589102535780334267934987941, + 17275124961392392047135728713829752470490098022504524438869454049765356211723, + 3323710067527231515807603961736782048796606296990840839366613937968342331886, + 4468708240622802562056471128793253296493002925988003094771284205007772045098, + 9006494818135081033869830730030943407240565201693254355620348420258773924028, + 2624130417875598753127999576825019766166727976335690685433712946223008520912, + 164131399455376615654870570697119442360078693174350746600132391198500093412, + 14931668887432843139264972187415200544679230597820424081936926034478502874299, + 1638753880783574431267395352024193675000113296497173968722590753809640941864, + 15505380865926802396097545843811910443367233632805651511272732002583232431557, + 17973744614207669251901495093091561913998272050499760575282030108740677066624, + 6137688223696761009295745609563284204827706564566466060484103844265403078408, + 14774243062532823236792831566222119634320864630838624098798648826842418775856, + 15864970393171078370207775103899428499600152663946379517190945807315353544891, + 19010063123357565300336230971672519561204810737546730911549311353159512986740, + 12607162829921425080830052984475623157169603642577010527391007035133383807243, + 17803108634879437217723652777640120469990779759700458421844361066182881628345, + 10065874953507223318296028499872542865030107611981933577973812883589535269142, + 3276471432535144390388324850641020151392959100393035635141206272558418581928, + 7532054601401798035926415744768772852833516520318445183340725930886329458991, + 18893822928119227829016544343228228897166113682019317256005502643243867377334, + 15940597493253236451533839310728876441657428995464658827726295547815292644378, + 4268009387843764409267791203070919313017052533005657826253994943184768120896, + 21611251949238422413354051947529388972078300717392131751061464498329326474580, + 12516447001729804412674006874184731098280474050775388553768469608793631490618, + 49838549447142926741568525697026885045023997277705726329780325103507790978, + 19763902910323896567698991616245963026306943100978479625077573937114135803058, + 12029297973430627253212633299020402005457460023136429653800185001711727387314, + 17676997725594777991384952086633589048516371093397126876621255518370680168503, + 10567543371894667303450346380722020266352683222046730266924342174164712049360, + 14583364850544999818712646438016435003942847076919084667364987497592599663937, + 17348091487238815837308569582101875357715798351834275089190053280855958465528, + 8743083090296259283603789316855921930102444739264013461469099560398359267240, + 15114064505647935792598848256320570567717917317803629185764147361301698519005, + 18332675991829764561879941291908436508530604635608341316693114747813051532006, + 1757567731797951053080580099911774643896363235228742197150882457231133285549, + 6526388717947413328592956348507481629843816325885832861915399601868279124246 + ] + ]; + +const field[6][7][7] POSEIDON_M = [ + [ + [ + 2910766817845651019878574839501801340070030115151021261302834310722729507541, + 19727366863391167538122140361473584127147630672623100827934084310230022599144, + 0, 0, 0, 0, 0 + ], + [ + 5776684794125549462448597414050232243778680302179439492664047328281728356345, + 8348174920934122550483593999453880006756108121341067172388445916328941978568, + 0, 0, 0, 0, 0 + ], + ...[[0; 7]; 5] + ], + [ + [ + 7511745149465107256748700652201246547602992235352608707588321460060273774987, + 10370080108974718697676803824769673834027675643658433702224577712625900127200, + 19705173408229649878903981084052839426532978878058043055305024233888854471533, + 0, 0, 0, 0 + ], + [ + 18732019378264290557468133440468564866454307626475683536618613112504878618481, + 20870176810702568768751421378473869562658540583882454726129544628203806653987, + 7266061498423634438633389053804536045105766754026813321943009179476902321146, + 0, 0, 0, 0 + ], + [ + 9131299761947733513298312097611845208338517739621853568979632113419485819303, + 10595341252162738537912664445405114076324478519622938027420701542910180337937, + 11597556804922396090267472882856054602429588299176362916247939723151043581408, + 0, 0, 0, 0 + ], + ...[[0; 7]; 4] + ], + [ + [ + 16023668707004248971294664614290028914393192768609916554276071736843535714477, + 17849615858846139011678879517964683507928512741474025695659909954675835121177, + 1013663139540921998616312712475594638459213772728467613870351821911056489570, + 13211800058103802189838759488224684841774731021206389709687693993627918500545, + 0, 0, 0 + ], + [ + 19204974983793400699898444372535256207646557857575315905278218870961389967884, + 3722304780857845144568029505892077496425786544014166938942516810831732569870, + 11920634922168932145084219049241528148129057802067880076377897257847125830511, + 6085682566123812000257211683010755099394491689511511633947011263229442977967, + 0, 0, 0 + ], + [ + 14672613178263529785795301930884172260797190868602674472542654261498546023746, + 20850178060552184587113773087797340350525370429749200838012809627359404457643, + 7082289538076771741936674361200789891432311337766695368327626572220036527624, + 1787876543469562003404632310460227730887431311758627706450615128255538398187, + 0, 0, 0 + ], + [ + 21407770160218607278833379114951608489910182969042472165261557405353704846967, + 16058955581309173858487265533260133430557379878452348481750737813742488209262, + 593311177550138061601452020934455734040559402531605836278498327468203888086, + 341662423637860635938968460722645910313598807845686354625820505885069260074, + 0, 0, 0 + ], + ...[[0; 7]; 3] + ], + [ + [ + 16789463359527776692258765063233607350971630674230623383979223533600140787105, + 17179611066821656668705197789232102741366879862607190942874777813024566441829, + 18653277315487164762584377009009109585010878033606596417396490909822722930739, + 7373070639853668650581790286343199505413793790160702463077019294817051722180, + 4823864393442908763804841692709014014130031798360007432734996408628916373879, + 0, 0 + ], + [ + 19196309854577132760746782449135315310664418272926255500908899397538686486585, + 18123132816088485879885148351452823314623055244145916622592591084094232513914, + 18436594886553181913092702411547018228276047601279727265790147051821171174455, + 15167500404313194506503404655898040457721633218143681920692711693000769735187, + 9437986152015460505719924283993842205604222075968464846270136901243896809793, + 0, 0 + ], + [ + 21445376105821232747280055223032050399373725161014449207033808524504027971613, + 49684738714301073369749035791061182456037935161360748355432247732088942674, + 9826409059947591908303145327284336313371973037536805760095514429930589897515, + 8494798325496773219358794086647759478982958403252584257436898618394561204124, + 21251937175072447337747316555423152807036003235223125066270735279039060889959, + 0, 0 + ], + [ + 5539100337780919206842837176908516952801756637410959104376645017856664270896, + 6297628909516159190915174165284309160976659474973668336571577778869958189934, + 12792263637464508665199868777503118105486490400267592501708855807938962470650, + 17254685306085558791725544672172906900581495686070720065168939143671412445514, + 3590396502942934679818900672232030233017710909687947858184099000783280809247, + 0, 0 + ], + [ + 19055249881366445073616526879263250763682650596233071589085239500077496415637, + 7367697936402141224946246030743627391716576575953707640061577218995381577033, + 1322791522030759131093883057746095061798181102708855007233180025036972924046, + 20456741074925985565499300081580917471340328842103779922028754640077047587707, + 9059147312071680695674575245237100802111605600478121517359780850134328696420, + 0, 0 + ], + ...[[0; 7]; 2] + ], + [ + [ + 8266021233794274332054729525918686051968756165685671155584565440479247355160, + 7947823415909040438587565055355894256799314737783432792935458921778371169026, + 16508811191852041977017821887204137955816331040385276110261643892701458724933, + 1804800467126006102677564831888710635194614232739335985819349312754063580223, + 11189892034806587650995829160516587240879881493093022855087765921356611070470, + 20567450145123179140729389574352706949280207113956641415022972885523439610844, + 0 + ], + [ + 4666756311257455192796774305229624459258864488677689058174087310651786875914, + 11389253665835451896363091846189307652796786468610595637047377864063404843117, + 18793736599347263150867965517898541872137378991464725717839931503944801692688, + 4206344588923325482680116848820594823631536459347642329098796888497153867720, + 1739462481670645248707834504605096139894257554120906850613041004917967456145, + 18514227342636266640333254638454588508118462110178719555586534011641424431745, + 0 + ], + [ + 17887039315911403193186866703775654467672391491657957999455462537283842145802, + 2824959020572825365047639014537190268717891749361604043531643698340708119767, + 12521547103713919592301476538318318223836047611311454785951907894055964264287, + 8658146183671258251984364885894342376430874614261222570603159082682815800788, + 154390145585284450772861151318029820117470958184878116158462181541183085587, + 7593705166056392393963956710828665339496927193740869686529339432486182720653, + 0 + ], + [ + 5529559239163081088908568555890212324771345012509269613465629182165427812002, + 3729910453162885538930719732708124491456460687048972152311428493400220125686, + 11942815243552870715777415109008273807076911177089425348095503288499102855779, + 498938524453430895689241565973888863905147713935369405079343247530256066618, + 3976257517234324421403708035200810671331954932478384823208414346189926720724, + 723540703523219510043977323240437576248315561543814629392162302024056718473, + 0 + ], + [ + 13306548824219676333032339487546407241767961556934015003605485324283250885682, + 7970147269291664639740298762956131361316495463191268382513594527221399186752, + 20633313939958767604804835838065337107615699351647541991788258289962727735454, + 17162090859520817529294904484646695645841022315617926715432606252643123848792, + 9181379842957190051440498041153333325098774266789773971685141362947015398641, + 7051606617662816798224904133351061549832959857069896192072217769241273559278, + 0 + ], + [ + 16619522548478824222688310091434959542211899852679631815023615875678448806029, + 14965311177811968100298579672135357167599499478246106482433786066289128683961, + 9792733250919070275775594069208673385381167169182805600474820364274865306108, + 2069253833779081039049908513863485270550301879399727430830923273191877809560, + 15847298987712771667136245955631872888473964330474501593909263901393348546986, + 12244443532166430060291409356011430759892629145539185535677568234713942157668, + 0 + ], + [0; 7] + ], + [ + [ + 19332164824128329382868318451458022991369413618825711961282217322674570624669, + 12346323761995603285640868741615937712088302657627126374070962894016296466118, + 3913895681115272361294397190916803190924061797587910478563401817340941991811, + 7048322889096718105055545382948709082135086733564574465991576956878202831861, + 10375086910057323893637057154182902576957472442368661576421122036461645295833, + 12765622911241487148932810040772504127756393086809438933166282251044289864727, + 266900212758702307861826326591090138389415348463003233900705815890364224151 + ], + [ + 14435131616556129905356866638030823183270286404767286105643513738132789033353, + 5780976801287540146775934937953368730928109502001687434229528186520268917700, + 1618320442446662026869390273942730786145909339107736579759397243640902802126, + 3818399583522206096165108192531271582827953520684743806492664825009577810261, + 11764506724346386316602508039052965575734225646587104133777798242528580374987, + 2414215974836165993714858157462355581258152126063378817495129367240311967136, + 17609437036230923129211608175600293197801044251801590649435913902851695334081 + ], + [ + 363438080029711424794236047863047716381155074181485245036621530063262917196, + 535766679023716739184211613469394818313893958493710642899297971974381051070, + 5305068908469731303772738758164870877638068032868328180355958394150421214337, + 10807632568240507366657354568432178961148417327580695024415275247652313539292, + 15964415873358391713354948903242729080763777490509563223190335273158191600135, + 20700362719972015883260687302741075186857660623182772413609788566925949033885, + 10135127975676256977820296631533839366076919827597067890970660746228807376456 + ], + [ + 4251490167543116819728642817282216847143714366441358372252125244838181656331, + 7745587495915033527847242564710473705100826890903278244320948416581724663023, + 11741113129223221800185946819924457344647035336264986754437921049066977440806, + 11630296782890656599545188109639399768829653360050213193782325240600583381364, + 16861140446185941149398487176581839232380972247302922484807333229513905651035, + 365879246117123675211400356410703684399715291171114630107795112994207447819, + 21725607857580053522363567649763546934441685061337033780528788383243719579033 + ], + [ + 9222866548596464928765000608129177609426964853736257576074550520759533736918, + 10261578281201197531384003420612639018011405529775212563256392340336951230146, + 15644037447921591571869862919382888810859308861783088910843592577202362807673, + 12752004188139535619565478547449108772137477456363099481095747591698702436636, + 4205805109630387448825516813913983509046636797101589615147198457314360427718, + 21047095155106717901091873146599497621258071512562421967648909471775919992713, + 15624165295872926124160584750951090817255240214488120310950503163805737026315 + ], + [ + 15064589937731741958666763896598138037875460434244947486199623542160035749721, + 1801577872277160959016940766173040841160105238799805406938450020949902989173, + 2896766420608048344829901127120623317655260981420052771341833288256800199953, + 12828791469509204618898135640019714232831708508424682785876476343251730674999, + 21363471986981372923191391880511344708743312828234098289107697080824665183315, + 21372706354350795416381912271616633829725494570576895047490974943034914894898, + 16006531510217730955981102005088687858079561573088629102219485906666961331083 + ], + [ + 2389357602244845938251345005183369360523566673990464798041306722747500447645, + 15275955107196234672088664710679934029171843237458844492987233368659104714648, + 8038797517535218686870517662905230585331773059774130312418943649247287196930, + 17923922393436914864421862212181654800719733137689602673604754147078808030201, + 12890519745320143484176500044628647247549456778462652469313611980363507314914, + 8058516556024397257577081553178859094042894928866720408652077334516681924252, + 768425396034382182896247252731538808045254601036758108993106260984310129743 + ] + ] + ]; \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/poseidon/poseidon.zok b/zokrates_prover/.zokrates/stdlib/hashes/poseidon/poseidon.zok new file mode 100644 index 0000000..1b0e007 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/poseidon/poseidon.zok @@ -0,0 +1,62 @@ +// https://eprint.iacr.org/2019/458.pdf + +from "./constants.zok" import POSEIDON_C, POSEIDON_M; + +def ark(field[N] mut state, field[497] c, u32 it) -> field[N] { + for u32 i in 0..N { + state[i] = state[i] + c[it + i]; + } + return state; +} + +def sbox(field[N] mut state, u32 f, u32 p, u32 r) -> field[N] { + state[0] = state[0]**5; + for u32 i in 1..N { + state[i] = ((r < f/2) || (r >= f/2 + p)) ? state[i]**5 : state[i]; + } + return state; +} + +def mix(field[N] state, field[7][7] m) -> field[N] { + field[N] mut out = [0; N]; + for u32 i in 0..N { + field mut acc = 0; + for u32 j in 0..N { + acc = acc + (state[j] * m[i][j]); + } + out[i] = acc; + } + return out; +} + +def main(field[N] inputs) -> field { + assert(N > 0 && N <= 6); // max 6 inputs + + u32 t = N + 1; + u32[8] rounds_p = [56, 57, 56, 60, 60, 63, 64, 63]; + + u32 f = 8; + u32 p = rounds_p[(t - 2)]; + + // Constants are padded with zeroes to the maximum value calculated by + // t * (f + p) = 497, where `t` (number of inputs + 1) is a max of 7. + // This is done to keep the function generic, as resulting array size depends on `t` + // and we do not want callers passing down constants. + // This should be revisited once compiler limitations are gone. + + field[497] c = POSEIDON_C[t - 2]; + field[7][7] m = POSEIDON_M[t - 2]; + + field[t] mut state = [0; t]; + for u32 i in 1..t { + state[i] = inputs[i - 1]; + } + + for u32 r in 0..f+p { + state = ark(state, c, r * t); + state = sbox(state, f, p, r); + state = mix(state, m); + } + + return state[0]; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/1024bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/1024bit.zok new file mode 100644 index 0000000..fa4acae --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/1024bit.zok @@ -0,0 +1,10 @@ +import "./sha256" as sha256; + +// A function that takes 4 u32[8] arrays as inputs, concatenates them, +// and returns their sha256 compression as a u32[8]. +// Note: no padding is applied + +def main(u32[8] a, u32[8] b, u32[8] c, u32[8] d) -> u32[8] { + u32[8] res = sha256([[...a, ...b], [...c, ...d]]); + return res; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/1024bitPadded.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/1024bitPadded.zok new file mode 100644 index 0000000..b2e50eb --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/1024bitPadded.zok @@ -0,0 +1,33 @@ +import "./1536bit" as sha256; + +// A function that takes four u32[8] array as input, concatenates them, pads the result, +// and returns the sha256 output as a u32[8] +def main(u32[8] a, u32[8] b, u32[8] c, u32[8] d) -> u32[8] { + + // Hash is computed on the full 1024bit block size + // padding does not fit in the first two blocks + // add dummy block (single "1" followed by "0" + total length) + u32[8] dummyblock1 = [ \ + 0x80000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 + ]; + + u32[8] dummyblock2 = [ \ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000400 + ]; + + return sha256(a, b, c, d, dummyblock1, dummyblock2); +} diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/1536bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/1536bit.zok new file mode 100644 index 0000000..2cc6b20 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/1536bit.zok @@ -0,0 +1,10 @@ +import "./sha256" as sha256; + +// A function that takes 6 u32[8] arrays as inputs, concatenates them, +// and returns their sha256 compression as a u32[8]. +// Note: no padding is applied + +def main(u32[8] a, u32[8] b, u32[8] c, u32[8] d, u32[8] e, u32[8] f) -> u32[8] { + u32[8] res = sha256([[...a, ...b], [...c, ...d], [...e, ...f]]); + return res; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/256bitPadded.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/256bitPadded.zok new file mode 100644 index 0000000..e7fca10 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/256bitPadded.zok @@ -0,0 +1,22 @@ +import "./512bit" as sha256; + +// A function that takes a u32[8] array as input, pads it, +// and returns the sha256 output as a u32[8] +def main(u32[8] a) -> u32[8] { + + // Hash is computed on 256 bits of input + // padding fits in the remaining 256 bits of the first block + // add dummy block (single "1" followed by "0" + total length) + u32[8] dummyblock1 = [ \ + 0x80000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000100 + ]; + + return sha256(a, dummyblock1); +} diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/512bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/512bit.zok new file mode 100644 index 0000000..36496da --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/512bit.zok @@ -0,0 +1,9 @@ +import "./sha256" as sha256; + +// A function that takes 2 u32[8] arrays as inputs, concatenates them, +// and returns their sha256 compression as a u32[8]. +// Note: no padding is applied + +def main(u32[8] a, u32[8] b) -> u32[8] { + return sha256([[...a, ...b]]); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/512bitPacked.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/512bitPacked.zok new file mode 100644 index 0000000..903f6e1 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/512bitPacked.zok @@ -0,0 +1,20 @@ +import "../../utils/pack/u32/pack128" as pack128; +import "../../utils/pack/u32/unpack128" as unpack128; +import "./512bitPadded" as sha256; + +// A function that takes an array of 4 field elements as input, unpacks each of them to 128 +// bits (big endian), concatenates them and applies sha256. +// It then returns an array of two field elements, each representing 128 bits of the result. +def main(field[4] preimage) -> field[2] { + u32[4] a_bits = unpack128(preimage[0]); + u32[4] b_bits = unpack128(preimage[1]); + u32[4] c_bits = unpack128(preimage[2]); + u32[4] d_bits = unpack128(preimage[3]); + + u32[8] lhs = [...a_bits, ...b_bits]; + u32[8] rhs = [...c_bits, ...d_bits]; + + u32[8] r = sha256(lhs, rhs); + + return [pack128(r[0..4]), pack128(r[4..8])]; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/512bitPadded.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/512bitPadded.zok new file mode 100644 index 0000000..6999b8b --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/512bitPadded.zok @@ -0,0 +1,33 @@ +import "./1024bit" as sha256; + +// A function that takes 2 u32[8] arrays as inputs, concatenates them, pads them, +// and returns their sha256 hash as a u32[8] +def main(u32[8] a, u32[8] b) -> u32[8] { + + // Hash is computed on the full 512bit block size + // padding does not fit in the primary block + // add dummy block (single "1" followed by "0" + total length) + u32[8] dummyblock1 = [ + 0x80000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 + ]; + + u32[8] dummyblock2 = [ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000200 + ]; + + return sha256(a, b, dummyblock1, dummyblock2); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/1024bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/1024bit.zok new file mode 100644 index 0000000..c4b13b7 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/1024bit.zok @@ -0,0 +1,14 @@ +import "./IVconstants" as IVconstants; +import "./shaRoundNoBoolCheck" as sha256; + +// A function that takes 4 bool[256] arrays as inputs +// and applies 2 rounds of sha256 compression. +// It returns an array of 256 bool. +def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d) -> bool[256] { + + bool[256] IV = IVconstants(); + bool[256] digest1 = sha256(a, b, IV); + bool[256] digest2 = sha256(c, d, digest1); + + return digest2; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/1024bitPadded.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/1024bitPadded.zok new file mode 100644 index 0000000..a4bd52e --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/1024bitPadded.zok @@ -0,0 +1,17 @@ +import "./1536bit" as sha256; + +// Take two bool[256] arrays as input +// and returns their sha256 full round output as an array of 256 bool. +def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d) -> bool[256] { + + // Hash is computed on the full 1024bit block size + // padding does not fit in the first two blocks + // add dummy block (single "1" followed by "0" + total length) + bool[256] dummyblock1 = [true, ...[false; 255]]; + + // Total length of message is 1024 bits: 0b10000000000 + bool[256] dummyblock2 = [...[false; 245], true, ...[false; 10]]; + + bool[256] digest = sha256(a, b, c, d, dummyblock1, dummyblock2); + return digest; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/1536bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/1536bit.zok new file mode 100644 index 0000000..511b2a5 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/1536bit.zok @@ -0,0 +1,15 @@ +import "./IVconstants" as IVconstants; +import "./shaRoundNoBoolCheck" as sha256; + +// A function that takes 6 bool[256] arrays as inputs +// and applies 3 rounds of sha256 compression. +// It returns an array of 256 bool. +def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d, bool[256] e, bool[256] f) -> bool[256] { + + bool[256] IV = IVconstants(); + bool[256] digest1 = sha256(a, b, IV); + bool[256] digest2 = sha256(c, d, digest1); + bool[256] digest3 = sha256(e, f, digest2); + + return digest3; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/256bitPadded.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/256bitPadded.zok new file mode 100644 index 0000000..5dd8bd5 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/256bitPadded.zok @@ -0,0 +1,14 @@ +import "./512bit" as sha256; + +// A function that takes 1 bool[256] array as input +// and returns the sha256 full round output as an array of 256 bool. +def main(bool[256] a) -> bool[256] { + + // Hash is computed on 256 bits of input + // padding fits in the remaining 256 bits of the first block + // add dummy block (single "true" followed by "false" + total length) + bool[256] dummyblock1 = [true, ...[false; 246], true, ...[false; 8]]; + + bool[256] digest = sha256(a, dummyblock1); + return digest; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/512bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/512bit.zok new file mode 100644 index 0000000..3d6d9ce --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/512bit.zok @@ -0,0 +1,11 @@ +import "./IVconstants" as IVconstants; +import "./shaRoundNoBoolCheck" as sha256; + +// A function that takes 2 bool[256] arrays as inputs +// and returns their sha256 compression function as an array of 256 bool. +// No padding is being applied +def main(bool[256] a, bool[256] b) -> bool[256] { + bool[256] IV = IVconstants(); + bool[256] digest = sha256(a, b, IV); + return digest; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/512bitPacked.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/512bitPacked.zok new file mode 100644 index 0000000..6d596d2 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/512bitPacked.zok @@ -0,0 +1,24 @@ +import "../../../utils/pack/bool/pack128" as pack128; +import "../../../utils/pack/bool/unpack128" as unpack128; +import "./512bitPadded" as sha256; + +// A function that takes an array of 4 field elements as inputs, unpacks each of them to 128 +// bits (big endian), concatenates them and applies sha256. +// It then returns an array of two field elements, each representing 128 bits of the result. +def main(field[4] preimage) -> field[2] { + + bool[128] a = unpack128(preimage[0]); + bool[128] b = unpack128(preimage[1]); + bool[128] c = unpack128(preimage[2]); + bool[128] d = unpack128(preimage[3]); + + bool[256] lhs = [...a, ...b]; + bool[256] rhs = [...c, ...d]; + + bool[256] r = sha256(lhs, rhs); + + field res0 = pack128(r[..128]); + field res1 = pack128(r[128..]); + + return [res0, res1]; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/512bitPadded.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/512bitPadded.zok new file mode 100644 index 0000000..6b19a02 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/512bitPadded.zok @@ -0,0 +1,17 @@ +import "./1024bit" as sha256; + +// A function that takes 2 bool[256] arrays as inputs +// and returns their sha256 full round output as an array of 256 bool. +def main(bool[256] a, bool[256] b) -> bool[256] { + + // Hash is computed on the full 512bit block size + // padding does not fit in the primary block + // add dummy block (single "1" followed by "0" + total length) + bool[256] dummyblock1 = [true, ...[false; 255]]; + + // Total length of message is 512 bits: 0b1000000000 + bool[256] dummyblock2 = [...[false; 246], true, ...[false; 9]]; + + bool[256] digest = sha256(a, b, dummyblock1, dummyblock2); + return digest; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/IVconstants.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/IVconstants.zok new file mode 100644 index 0000000..99e6506 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/IVconstants.zok @@ -0,0 +1,15 @@ +// SHA-256 is specified in FIPS 180-3 and initial values are listed in section 5.3.3 +// https://csrc.nist.gov/csrc/media/publications/fips/180/3/archive/2008-10-31/documents/fips180-3_final.pdf +def main() -> bool[256] { + bool[32] h0 = [false, true, true, false, true, false, true, false, false, false, false, false, true, false, false, true, true, true, true, false, false, true, true, false, false, true, true, false, false, true, true, true]; + bool[32] h1 = [true, false, true, true, true, false, true, true, false, true, true, false, false, true, true, true, true, false, true, false, true, true, true, false, true, false, false, false, false, true, false, true]; + bool[32] h2 = [false, false, true, true, true, true, false, false, false, true, true, false, true, true, true, false, true, true, true, true, false, false, true, true, false, true, true, true, false, false, true, false]; + bool[32] h3 = [true, false, true, false, false, true, false, true, false, true, false, false, true, true, true, true, true, true, true, true, false, true, false, true, false, false, true, true, true, false, true, false]; + bool[32] h4 = [false, true, false, true, false, false, false, true, false, false, false, false, true, true, true, false, false, true, false, true, false, false, true, false, false, true, true, true, true, true, true, true]; + bool[32] h5 = [true, false, false, true, true, false, true, true, false, false, false, false, false, true, false, true, false, true, true, false, true, false, false, false, true, false, false, false, true, true, false, false]; + bool[32] h6 = [false, false, false, true, true, true, true, true, true, false, false, false, false, false, true, true, true, true, false, true, true, false, false, true, true, false, true, false, true, false, true, true]; + bool[32] h7 = [false, true, false, true, true, false, true, true, true, true, true, false, false, false, false, false, true, true, false, false, true, true, false, true, false, false, false, true, true, false, false, true]; + + bool[256] IV = [...h0, ...h1, ...h2, ...h3, ...h4, ...h5, ...h6, ...h7]; + return IV; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/shaRoundNoBoolCheck.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/shaRoundNoBoolCheck.zok new file mode 100644 index 0000000..b3f2e7a --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/embed/shaRoundNoBoolCheck.zok @@ -0,0 +1,10 @@ +#pragma curve bn128 + +from "EMBED" import sha256round; + +// a and b is NOT checked to be 0 or 1 +// the return value is checked to be 0 or 1 +// IV vector is checked to be of type bool +def main(bool[256] a, bool[256] b, bool[256] IV) -> bool[256] { + return sha256round([...a, ...b], IV); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/sha256.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/sha256.zok new file mode 100644 index 0000000..e7850f8 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/sha256.zok @@ -0,0 +1,21 @@ +import "./shaRound" as shaRound; + +// Initial values, FIPS 180-3, section 5.3.3 +// https://csrc.nist.gov/csrc/media/publications/fips/180/3/archive/2008-10-31/documents/fips180-3_final.pdf +const u32[8] IV = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 +]; + +// A function that takes N u32[16] arrays as inputs, concatenates them, +// and returns their sha256 compression as a u32[8]. +// Note: no padding is applied +def main(u32[N][16] a) -> u32[8] { + u32[8] mut current = IV; + + for u32 i in 0..N { + current = shaRound(a[i], current); + } + + return current; +} diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/sha256Padded.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/sha256Padded.zok new file mode 100644 index 0000000..60dea98 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/sha256Padded.zok @@ -0,0 +1,48 @@ +import "hashes/sha256/sha256"; +import "utils/casts/u8_to_bits"; +import "utils/casts/u32_to_bits"; +import "utils/casts/u32_from_bits"; + +// A padding function that takes a bool[L] array as input and pads it to 512-bit blocks +def pad(bool[L] m) -> u32[M][16] { + u32 length = L + 64 + 1; + assert(length / 512 + 1 == M); + + u32 r = length % 512; + u32 k = 512 - r; + bool[M * 512] result_in_bits = [...m, true, ...[false; k + 32], ...u32_to_bits(L)]; + u32[M][16] mut result = [[0; 16]; M]; + + for u32 i in 0..M { + for u32 j in 0..16 { + u32 start = i * 512 + j * 32; + u32 end = start + 32; + result[i][j] = u32_from_bits(result_in_bits[start..end]); + } + } + return result; +} + +// A function that takes a bool[N] array as input, pads it, +// and returns the sha256 output as a u32[8] +def sha256Padded(bool[N] input) -> u32[8] { + u32 block_count = (N + 64 + 1) / 512 + 1; + u32[block_count][16] padded = pad(input); + return sha256(padded); +} + +// A function that takes a u8[N] array as input, pads it, +// and returns the sha256 output as a u32[8] +def main(u8[N] input) -> u32[8] { + u32 L = N * 8; + bool[L] mut input_bits = [false; L]; + + for u32 i in 0..N { + bool[8] bits = u8_to_bits(input[i]); + for u32 j in 0..8 { + input_bits[i * 8 + j] = bits[j]; + } + } + + return sha256Padded(input_bits); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha256/shaRound.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha256/shaRound.zok new file mode 100644 index 0000000..3c42903 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha256/shaRound.zok @@ -0,0 +1,98 @@ +// FIPS 180-3, section 4.2.2 +// https://csrc.nist.gov/csrc/media/publications/fips/180/3/archive/2008-10-31/documents/fips180-3_final.pdf +const u32[64] K = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +]; + +def rotr32(u32 x) -> u32 { + return (x >> N) | (x << (32 - N)); +} + +def extend(u32[64] w, u32 i) -> u32 { + u32 s0 = rotr32::<7>(w[i-15]) ^ rotr32::<18>(w[i-15]) ^ (w[i-15] >> 3); + u32 s1 = rotr32::<17>(w[i-2]) ^ rotr32::<19>(w[i-2]) ^ (w[i-2] >> 10); + return w[i-16] + s0 + w[i-7] + s1; +} + +def temp1(u32 e, u32 f, u32 g, u32 h, u32 k, u32 w) -> u32 { + // ch := (e and f) xor ((not e) and g) + u32 ch = (e & f) ^ ((!e) & g); + + // S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25) + u32 S1 = rotr32::<6>(e) ^ rotr32::<11>(e) ^ rotr32::<25>(e); + + // temp1 := h + S1 + ch + k + w + return h + S1 + ch + k + w; +} + +def temp2(u32 a, u32 b, u32 c) -> u32 { + // maj := (a and b) xor (a and c) xor (b and c) + u32 maj = (a & b) ^ (a & c) ^ (b & c); + + // S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22) + u32 S0 = rotr32::<2>(a) ^ rotr32::<13>(a) ^ rotr32::<22>(a); + + // temp2 := S0 + maj + return S0 + maj; +} + +// A function that computes one round of the SHA256 compression function given an input and the current value of the hash +// this is used by other components however many times needed +def main(u32[16] input, u32[8] current) -> u32[8] { + u32 mut h0 = current[0]; + u32 mut h1 = current[1]; + u32 mut h2 = current[2]; + u32 mut h3 = current[3]; + u32 mut h4 = current[4]; + u32 mut h5 = current[5]; + u32 mut h6 = current[6]; + u32 mut h7 = current[7]; + + u32[64] mut w = [...input, ...[0u32; 48]]; + + for u32 i in 16..64 { + w[i] = extend(w, i); + } + + u32 mut a = h0; + u32 mut b = h1; + u32 mut c = h2; + u32 mut d = h3; + u32 mut e = h4; + u32 mut f = h5; + u32 mut g = h6; + u32 mut h = h7; + + for u32 i in 0..64 { + u32 t1 = temp1(e, f, g, h, K[i], w[i]); + u32 t2 = temp2(a, b, c); + + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + + h0 = h0 + a; + h1 = h1 + b; + h2 = h2 + c; + h3 = h3 + d; + h4 = h4 + e; + h5 = h5 + f; + h6 = h6 + g; + h7 = h7 + h; + + return [h0, h1, h2, h3, h4, h5, h6, h7]; +} + diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha3/224bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha3/224bit.zok new file mode 100644 index 0000000..daca1ed --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha3/224bit.zok @@ -0,0 +1,5 @@ +from "hashes/keccak/keccak" import main as keccak; + +def main(u8[N] input) -> u8[28] { + return keccak::<_, 28>(input, 0x06); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha3/256bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha3/256bit.zok new file mode 100644 index 0000000..55eb5d7 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha3/256bit.zok @@ -0,0 +1,5 @@ +from "hashes/keccak/keccak" import main as keccak; + +def main(u8[N] input) -> u8[32] { + return keccak::<_, 32>(input, 0x06); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha3/384bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha3/384bit.zok new file mode 100644 index 0000000..acd07e3 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha3/384bit.zok @@ -0,0 +1,5 @@ +from "hashes/keccak/keccak" import main as keccak; + +def main(u8[N] input) -> u8[48] { + return keccak::<_, 48>(input, 0x06); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/sha3/512bit.zok b/zokrates_prover/.zokrates/stdlib/hashes/sha3/512bit.zok new file mode 100644 index 0000000..0ab6bab --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/sha3/512bit.zok @@ -0,0 +1,5 @@ +from "hashes/keccak/keccak" import main as keccak; + +def main(u8[N] input) -> u8[64] { + return keccak::<_, 64>(input, 0x06); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/hashes/utils/256bitsDirectionHelper.zok b/zokrates_prover/.zokrates/stdlib/hashes/utils/256bitsDirectionHelper.zok new file mode 100644 index 0000000..d78aabf --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/hashes/utils/256bitsDirectionHelper.zok @@ -0,0 +1,4 @@ +// Concatenate two u32[8] arrays in an order defined by a boolean selector +def main(bool selector, u32[8] lhs, u32[8] rhs) -> u32[16] { + return selector ? [...rhs, ...lhs] : [...lhs, ...rhs]; +} diff --git a/zokrates_prover/.zokrates/stdlib/signatures/verifyEddsa.zok b/zokrates_prover/.zokrates/stdlib/signatures/verifyEddsa.zok new file mode 100644 index 0000000..e6e2f80 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/signatures/verifyEddsa.zok @@ -0,0 +1,51 @@ +import "hashes/sha256/1024bitPadded" as sha256; +import "ecc/edwardsScalarMult" as scalarMult; +import "ecc/edwardsAdd" as add; +import "utils/pack/bool/nonStrictUnpack256" as unpack256bool; +import "utils/pack/u32/nonStrictUnpack256" as unpack256u; +import "ecc/edwardsOnCurve" as onCurve; +import "ecc/edwardsOrderCheck" as orderCheck; +from "ecc/babyjubjubParams" import BabyJubJubParams; +import "utils/casts/u32_8_to_bool_256"; + +/// Verifies an EdDSA Signature. +/// +/// Checks the correctness of a given EdDSA Signature (R,S) for the provided +/// public key A and message (M0, M1). +/// This python repo provides the tooling for creating valid signatures: +/// https://github.com/Zokrates/pycrypto +/// +/// For more information see: +/// https://en.wikipedia.org/wiki/EdDSA +/// https://eprint.iacr.org/2015/677.pdf +/// +/// Arguments: +/// R: Curve point. Hidden version of the per-message nonce. +/// S: Field element. Signature to be verified. +/// A: Curve point. Public part of the key used to create S. +/// M0: 256bit array. First 256bits of the message used to create S . +/// M1: 256bit array. Trailing 256bits of the message used to create S . +/// context: Curve parameters used to create S. +/// +/// Returns: +/// Return true for S being a valid EdDSA Signature, false otherwise. +def main(field[2] R, field S, field[2] A, u32[8] M0, u32[8] M1, BabyJubJubParams context) -> bool { + field[2] G = [context.Gu, context.Gv]; + + // Check if R is on curve and if it is not in a small subgroup. A is public input and can be checked offline + assert(onCurve(R, context)); // throws if R is not on curve + assert(orderCheck(R, context)); + + u32[8] Rx = unpack256u(R[0]); + u32[8] Ax = unpack256u(A[0]); + bool[256] hRAM = u32_8_to_bool_256(sha256(Rx, Ax, M0, M1)); + + bool[256] sBits = unpack256bool(S); + field[2] lhs = scalarMult(sBits, G, context); + + field[2] AhRAM = scalarMult(hRAM, A, context); + field[2] rhs = add(R, AhRAM, context); + + bool out = rhs[0] == lhs[0] && rhs[1] == lhs[1]; + return out; +} diff --git a/zokrates_prover/.zokrates/stdlib/snark/gm17.zok b/zokrates_prover/.zokrates/stdlib/snark/gm17.zok new file mode 100644 index 0000000..f4b6e2a --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/snark/gm17.zok @@ -0,0 +1,56 @@ +#pragma curve bw6_761 + +from "EMBED" import snark_verify_bls12_377 as verify; + +struct ProofInner { + field[2] a; + field[2][2] b; + field[2] c; +} + +struct Proof { + ProofInner proof; + field[N] inputs; +} + +struct VerificationKey { + field[2][2] h; + field[2] g_alpha; + field[2][2] h_beta; + field[2] g_gamma; + field[2][2] h_gamma; + field[N][2] query; // input length + 1 +} + +def flat(field[N][2] input) -> field[F] { + assert(F == N * 2); + field[F] mut out = [0; F]; + for u32 i in 0..N { + for u32 j in 0..2 { + out[(i * 2) + j] = input[i][j]; + } + } + return out; +} + +def main(Proof proof, VerificationKey vk) -> bool { + assert(Q == N + 1); // query length (Q) should be N + 1 + field[8] flat_proof = [ + ...proof.proof.a, + ...flat::<2, 4>(proof.proof.b), + ...proof.proof.c + ]; + + u32 two_Q = 2 * Q; + + field[16 + (2 * Q)] flat_vk = [ + ...flat::<2, 4>(vk.h), + ...vk.g_alpha, + ...flat::<2, 4>(vk.h_beta), + ...vk.g_gamma, + ...flat::<2, 4>(vk.h_gamma), + ...flat::(vk.query) + ]; + + return verify(proof.inputs, flat_proof, flat_vk); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts.zok b/zokrates_prover/.zokrates/stdlib/utils/casts.zok new file mode 100644 index 0000000..6cfe6ae --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts.zok @@ -0,0 +1,532 @@ +from "EMBED" import u64_to_bits, u32_to_bits, u16_to_bits, u8_to_bits, u8_from_bits, u16_from_bits, u32_from_bits, u64_from_bits; + +// Cast a boolean array of size 8 to an 8-bit unsigned integer (u8) +def cast(bool[8] input) -> u8 { + return u8_from_bits(input); +} + +// Cast a boolean array of size N to an array of 8-bit unsigned integers (u8) of size P +// The following condition must be true `N == 8 * P`, otherwise the cast will fail +def cast(bool[N] input) -> u8[P] { + assert(N == 8 * P); + u8[P] mut r = [0; P]; + for u32 i in 0..P { + r[i] = u8_from_bits(input[i * 8..(i + 1) * 8]); + } + return r; +} + +// Cast a boolean array of size 16 to a 16-bit unsigned integer (u16) +def cast(bool[16] input) -> u16 { + return u16_from_bits(input); +} + +// Cast a boolean array of size N to an array of 16-bit unsigned integers (u16) of size P +// The following condition must be true `N == 16 * P`, otherwise the cast will fail +def cast(bool[N] input) -> u16[P] { + assert(N == 16 * P); + u16[P] mut r = [0; P]; + for u32 i in 0..P { + r[i] = u16_from_bits(input[i * 16..(i + 1) * 16]); + } + return r; +} + +// Cast a boolean array of size 32 to a 32-bit unsigned integer (u32) +def cast(bool[32] input) -> u32 { + return u32_from_bits(input); +} + +// Cast a boolean array of size N to an array of 32-bit unsigned integers (u32) of size P +// The following condition must be true `N == 32 * P`, otherwise the cast will fail +def cast(bool[N] input) -> u32[P] { + assert(N == 32 * P); + u32[P] mut r = [0; P]; + for u32 i in 0..P { + r[i] = u32_from_bits(input[i * 32..(i + 1) * 32]); + } + return r; +} + +// Cast a boolean array of size 64 to a 64-bit unsigned integer (u64) +def cast(bool[64] input) -> u64 { + return u64_from_bits(input); +} + +// Cast a boolean array of size N to an array of 64-bit unsigned integers (u64) of size P +// The following condition must be true `N == 64 * P`, otherwise the cast will fail +def cast(bool[N] input) -> u64[P] { + assert(N == 64 * P); + u64[P] mut r = [0; P]; + for u32 i in 0..P { + r[i] = u64_from_bits(input[i * 64..(i + 1) * 64]); + } + return r; +} + +// Cast an 8-bit unsigned integer (u8) to a boolean array of size 8 (bool[8]) +def cast(u8 input) -> bool[8] { + return u8_to_bits(input); +} + +// Cast an array of 8-bit unsigned integers (u8) of size N to a boolean array of size P +// The following condition must be true `P == 8 * N`, otherwise the cast will fail +def cast(u8[N] input) -> bool[P] { + assert(P == 8 * N); + bool[P] mut r = [false; P]; + for u32 i in 0..N { + bool[8] bits = u8_to_bits(input[i]); + for u32 j in 0..8 { + r[i * 8 + j] = bits[j]; + } + } + return r; +} + +// Cast an 8-bit unsigned integer (u8) to a field element +def cast(u8 input) -> field { + bool[8] bits = u8_to_bits(input); + field mut r = 0; + for u32 i in 0..8 { + u32 exponent = 8 - i - 1; + r = r + (bits[i] ? 2 ** exponent : 0); + } + return r; +} + +// Cast an array of 8-bit unsigned integers (u8) to an array of field elements +def cast(u8[N] input) -> field[N] { + field[N] mut r = [0; N]; + for u32 i in 0..N { + r[i] = cast(input[i]); + } + return r; +} + +// Upcast an 8-bit unsigned integer (u8) to a 16-bit unsigned integer (u16) +def cast(u8 input) -> u16 { + bool[8] bits = u8_to_bits(input); + return u16_from_bits([...[false; 8], ...bits]); +} + +// Cast an array of two 8-bit unsigned integers (u8[2]) to a 16-bit unsigned integer (u16) +def cast(u8[2] input) -> u16 { + bool[16] bits = [ + ...u8_to_bits(input[0]), + ...u8_to_bits(input[1]) + ]; + return u16_from_bits(bits); +} + +// Cast an array of 8-bit unsigned integers (u8) of size N to an array of 16-bit unsigned integers (u16) of size P +// The following condition must be true `N == 2 * P`, otherwise the cast will fail +def cast(u8[N] input) -> u16[P] { + assert(N == 2 * P); + u16[P] mut r = [0; P]; + for u32 i in 0..P { + r[i] = cast(input[i * 2..(i + 1) * 2]); + } + return r; +} + +// Upcast an 8-bit unsigned integer (u8) to a 32-bit unsigned integer (u32) +def cast(u8 input) -> u32 { + bool[8] bits = u8_to_bits(input); + return u32_from_bits([...[false; 24], ...bits]); +} + +// Cast an array of four 8-bit unsigned integers (u8[4]) to a 32-bit unsigned integer (u32) +def cast(u8[4] input) -> u32 { + bool[32] bits = [ + ...u8_to_bits(input[0]), + ...u8_to_bits(input[1]), + ...u8_to_bits(input[2]), + ...u8_to_bits(input[3]) + ]; + return u32_from_bits(bits); +} + +// Cast an array of 8-bit unsigned integers (u8) of size N to an array of 32-bit unsigned integers (u32) of size P +// The following condition must be true `N == 4 * P`, otherwise the cast will fail +def cast(u8[N] input) -> u32[P] { + assert(N == 4 * P); + u32[P] mut r = [0; P]; + for u32 i in 0..P { + r[i] = cast(input[i * 4..(i + 1) * 4]); + } + return r; +} + +// Upcast an 8-bit unsigned integer (u8) to a 64-bit unsigned integer (u64) +def cast(u8 input) -> u64 { + bool[8] bits = u8_to_bits(input); + return u64_from_bits([...[false; 56], ...bits]); +} + +// Cast an array of eight 8-bit unsigned integers (u8[8]) to a 64-bit unsigned integer (u64) +def cast(u8[8] input) -> u64 { + bool[64] bits = [ + ...u8_to_bits(input[0]), + ...u8_to_bits(input[1]), + ...u8_to_bits(input[2]), + ...u8_to_bits(input[3]), + ...u8_to_bits(input[4]), + ...u8_to_bits(input[5]), + ...u8_to_bits(input[6]), + ...u8_to_bits(input[7]) + ]; + return u64_from_bits(bits); +} + +// Cast an array of 8-bit unsigned integers (u8) of size N to an array of 64-bit unsigned integers (u64) of size P +// The following condition must be true `N == 8 * P`, otherwise the cast will fail +def cast(u8[N] input) -> u64[P] { + assert(N == 8 * P); + u64[P] mut r = [0; P]; + for u32 i in 0..P { + r[i] = cast(input[i * 8..(i + 1) * 8]); + } + return r; +} + +// Cast a 16-bit unsigned integer (u16) to a boolean array of size 16 (bool[16]) +def cast(u16 input) -> bool[16] { + return u16_to_bits(input); +} + +// Cast an array of 16-bit unsigned integers (u16) of size N to a boolean array of size P +// The following condition must be true `P == 16 * N`, otherwise the cast will fail +def cast(u16[N] input) -> bool[P] { + assert(P == 16 * N); + bool[P] mut r = [false; P]; + for u32 i in 0..N { + bool[16] bits = u16_to_bits(input[i]); + for u32 j in 0..16 { + r[i * 16 + j] = bits[j]; + } + } + return r; +} + +// Cast a 16-bit unsigned integer (u16) to a field element +def cast(u16 input) -> field { + bool[16] bits = u16_to_bits(input); + field mut r = 0; + for u32 i in 0..16 { + u32 exponent = 16 - i - 1; + r = r + (bits[i] ? 2 ** exponent : 0); + } + return r; +} + +// Cast an array of 16-bit unsigned integers (u16) to an array of field elements +def cast(u16[N] input) -> field[N] { + field[N] mut r = [0; N]; + for u32 i in 0..N { + r[i] = cast(input[i]); + } + return r; +} + +// Cast a 16-bit unsigned integer (u16) to an array of two 8-bit unsigned integers (u8[2]) +def cast(u16 input) -> u8[2] { + bool[16] bits = u16_to_bits(input); + return [ + u8_from_bits(bits[0..8]), + u8_from_bits(bits[8..16]) + ]; +} + +// Cast an array of 16-bit unsigned integers (u16) of size N to an array of 8-bit unsigned integers of size P +// The following condition must be true `P == 2 * N`, otherwise the cast will fail +def cast(u16[N] input) -> u8[P] { + assert(P == 2 * N); + u8[P] mut r = [0; P]; + for u32 i in 0..N { + u8[2] t = cast(input[i]); + r[i * 2] = t[0]; + r[i * 2 + 1] = t[1]; + } + return r; +} + +// Upcast a 16-bit unsigned integer (u16) to a 32-bit unsigned integer (u32) +def cast(u16 input) -> u32 { + bool[16] bits = u16_to_bits(input); + return u32_from_bits([...[false; 16], ...bits]); +} + +// Cast an array of two 16-bit unsigned integers (u16[2]) to a 32-bit unsigned integer (u32) +def cast(u16[2] input) -> u32 { + bool[32] bits = [ + ...u16_to_bits(input[0]), + ...u16_to_bits(input[1]) + ]; + return u32_from_bits(bits); +} + +// Cast an array of 16-bit unsigned integers (u16) of size N to an array of 32-bit unsigned integers (u32) of size P +// The following condition must be true `N == 2 * P`, otherwise the cast will fail +def cast(u16[N] input) -> u32[P] { + assert(N == 2 * P); + u32[P] mut r = [0; P]; + for u32 i in 0..P { + r[i] = cast(input[i * 2..(i + 1) * 2]); + } + return r; +} + +// Upcast a 16-bit unsigned integer (u16) to a 64-bit unsigned integer (u64) +def cast(u16 input) -> u64 { + bool[16] bits = u16_to_bits(input); + return u64_from_bits([...[false; 48], ...bits]); +} + +// Cast an array of four 16-bit unsigned integers (u16[4]) to a 64-bit unsigned integer (u64) +def cast(u16[4] input) -> u64 { + bool[64] bits = [ + ...u16_to_bits(input[0]), + ...u16_to_bits(input[1]), + ...u16_to_bits(input[2]), + ...u16_to_bits(input[3]) + ]; + return u64_from_bits(bits); +} + +// Cast an array of 16-bit unsigned integers (u16) of size N to an array of 64-bit unsigned integers (u64) of size P +// The following condition must be true `N == 4 * P`, otherwise the cast will fail +def cast(u16[N] input) -> u64[P] { + assert(N == 4 * P); + u64[P] mut r = [0; P]; + for u32 i in 0..P { + r[i] = cast(input[i * 4..(i + 1) * 4]); + } + return r; +} + +// Cast a 32-bit unsigned integer (u32) to a boolean array of size 32 (bool[32]) +def cast(u32 input) -> bool[32] { + return u32_to_bits(input); +} + +// Cast an array of 32-bit unsigned integers (u32) of size N to a boolean array of size P +// The following condition must be true `P == 32 * N`, otherwise the cast will fail +def cast(u32[N] input) -> bool[P] { + assert(P == 32 * N); + bool[P] mut r = [false; P]; + for u32 i in 0..N { + bool[32] bits = u32_to_bits(input[i]); + for u32 j in 0..32 { + r[i * 32 + j] = bits[j]; + } + } + return r; +} + +// Cast a 32-bit unsigned integer (u32) to a field element +def cast(u32 input) -> field { + bool[32] bits = u32_to_bits(input); + field mut r = 0; + for u32 i in 0..32 { + u32 exponent = 32 - i - 1; + r = r + (bits[i] ? 2 ** exponent : 0); + } + return r; +} + +// Cast an array of 32-bit unsigned integers (u32) to an array of field elements +def cast(u32[N] input) -> field[N] { + field[N] mut r = [0; N]; + for u32 i in 0..N { + r[i] = cast(input[i]); + } + return r; +} + +// Cast a 32-bit unsigned integer (u32) to an array of four 8-bit unsigned integers (u8[4]) +def cast(u32 input) -> u8[4] { + bool[32] bits = u32_to_bits(input); + return [ + u8_from_bits(bits[0..8]), + u8_from_bits(bits[8..16]), + u8_from_bits(bits[16..24]), + u8_from_bits(bits[24..32]) + ]; +} + +// Cast an array of 32-bit unsigned integers (u32) of size N to an array of 8-bit unsigned integers of size P +// The following condition must be true `P == 4 * N`, otherwise the cast will fail +def cast(u32[N] input) -> u8[P] { + assert(P == 4 * N); + u8[P] mut r = [0; P]; + for u32 i in 0..N { + u8[4] t = cast(input[i]); + for u32 j in 0..4 { + r[i * 4 + j] = t[j]; + } + } + return r; +} + +// Cast a 32-bit unsigned integer (u32) to an array of two 16-bit unsigned integers (u16[2]) +def cast(u32 input) -> u16[2] { + bool[32] bits = u32_to_bits(input); + return [ + u16_from_bits(bits[0..16]), + u16_from_bits(bits[16..32]) + ]; +} + +// Cast an array of 32-bit unsigned integers (u32) of size N to an array of 16-bit unsigned integers of size P +// The following condition must be true `P == 2 * N`, otherwise the cast will fail +def cast(u32[N] input) -> u16[P] { + assert(P == 2 * N); + u16[P] mut r = [0; P]; + for u32 i in 0..N { + u16[2] t = cast(input[i]); + r[i * 2] = t[0]; + r[i * 2 + 1] = t[1]; + } + return r; +} + +// Upcast a 32-bit unsigned integer (u32) to a 64-bit unsigned integer (u64) +def cast(u32 input) -> u64 { + bool[32] bits = u32_to_bits(input); + return u64_from_bits([...[false; 32], ...bits]); +} + +// Cast an array of two 32-bit unsigned integers (u32[2]) to a 64-bit unsigned integer (u64) +def cast(u32[2] input) -> u64 { + bool[64] bits = [ + ...u32_to_bits(input[0]), + ...u32_to_bits(input[1]) + ]; + return u64_from_bits(bits); +} + +// Cast an array of 32-bit unsigned integers (u32) of size N to an array of 64-bit unsigned integers (u64) of size P +// The following condition must be true `N == 2 * P`, otherwise the cast will fail +def cast(u32[N] input) -> u64[P] { + assert(N == 2 * P); + u64[P] mut r = [0; P]; + for u32 i in 0..P { + r[i] = cast(input[i * 2..(i + 1) * 2]); + } + return r; +} + +// Cast a 64-bit unsigned integer (u64) to a boolean array of size 64 (bool[64]) +def cast(u64 input) -> bool[64] { + return u64_to_bits(input); +} + +// Cast an array of 64-bit unsigned integers (u64) of size N to a boolean array of size P +// The following condition must be true `P == 64 * N`, otherwise the cast will fail +def cast(u64[N] input) -> bool[P] { + assert(P == 64 * N); + bool[P] mut r = [false; P]; + for u32 i in 0..N { + bool[64] bits = u64_to_bits(input[i]); + for u32 j in 0..64 { + r[i * 64 + j] = bits[j]; + } + } + return r; +} + +// Cast 64-bit unsigned integer (u64) to a field element +def cast(u64 input) -> field { + bool[64] bits = u64_to_bits(input); + field mut r = 0; + for u32 i in 0..64 { + u32 exponent = 64 - i - 1; + r = r + (bits[i] ? 2 ** exponent : 0); + } + return r; +} + +// Cast an array of 64-bit unsigned integers (u64) to an array of field elements +def cast(u64[N] input) -> field[N] { + field[N] mut r = [0; N]; + for u32 i in 0..N { + r[i] = cast(input[i]); + } + return r; +} + +// Cast a 64-bit unsigned integer (u64) to an array of 8 8-bit unsigned integers (u8[8]) +def cast(u64 input) -> u8[8] { + bool[64] bits = u64_to_bits(input); + return [ + u8_from_bits(bits[0..8]), + u8_from_bits(bits[8..16]), + u8_from_bits(bits[16..24]), + u8_from_bits(bits[24..32]), + u8_from_bits(bits[32..40]), + u8_from_bits(bits[40..48]), + u8_from_bits(bits[48..56]), + u8_from_bits(bits[56..64]) + ]; +} + +// Cast an array of 64-bit unsigned integers (u64) of size N to an array of 8-bit unsigned integers of size P +// The following condition must be true `P == 8 * N`, otherwise the cast will fail +def cast(u64[N] input) -> u8[P] { + assert(P == 8 * N); + u8[P] mut r = [0; P]; + for u32 i in 0..N { + u8[8] t = cast(input[i]); + for u32 j in 0..8 { + r[i * 8 + j] = t[j]; + } + } + return r; +} + +// Cast a 64-bit unsigned integer (u64) to an array of 4 16-bit unsigned integers (u16[4]) +def cast(u64 input) -> u16[4] { + bool[64] bits = u64_to_bits(input); + return [ + u16_from_bits(bits[0..16]), + u16_from_bits(bits[16..32]), + u16_from_bits(bits[32..48]), + u16_from_bits(bits[48..64]) + ]; +} + +// Cast an array of 64-bit unsigned integers (u64) of size N to an array of 16-bit unsigned integers of size P +// The following condition must be true `P == 4 * N`, otherwise the cast will fail +def cast(u64[N] input) -> u16[P] { + assert(P == 4 * N); + u16[P] mut r = [0; P]; + for u32 i in 0..N { + u16[4] t = cast(input[i]); + for u32 j in 0..4 { + r[i * 4 + j] = t[j]; + } + } + return r; +} + +// Cast a 64-bit unsigned integer (u64) to an array of 2 32-bit unsigned integers (u32[2]) +def cast(u64 input) -> u32[2] { + bool[64] bits = u64_to_bits(input); + return [ + u32_from_bits(bits[0..32]), + u32_from_bits(bits[32..64]) + ]; +} + +// Cast an array of 64-bit unsigned integers (u64) of size N to an array of 32-bit unsigned integers of size P +// The following condition must be true `P == 2 * N`, otherwise the cast will fail +def cast(u64[N] input) -> u32[P] { + assert(P == 2 * N); + u32[P] mut r = [0; P]; + for u32 i in 0..N { + u32[2] t = cast(input[i]); + r[i * 2] = t[0]; + r[i * 2 + 1] = t[1]; + } + return r; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/bool_128_to_u32_4.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/bool_128_to_u32_4.zok new file mode 100644 index 0000000..12ee4cb --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/bool_128_to_u32_4.zok @@ -0,0 +1,6 @@ +import "./bool_array_to_u32_array" as bool_to_u32; + +def main(bool[128] bits) -> u32[4] { + u32[4] res = bool_to_u32(bits); + return res; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/bool_256_to_u32_8.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/bool_256_to_u32_8.zok new file mode 100644 index 0000000..1e8b2ad --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/bool_256_to_u32_8.zok @@ -0,0 +1,6 @@ +import "./bool_array_to_u32_array" as bool_to_u32; + +def main(bool[256] bits) -> u32[8] { + u32[8] res = bool_to_u32(bits); + return res; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/bool_array_to_u32_array.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/bool_array_to_u32_array.zok new file mode 100644 index 0000000..e04ffda --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/bool_array_to_u32_array.zok @@ -0,0 +1,15 @@ +from "EMBED" import u32_from_bits; + +// convert an array of bool to an array of u32 +// the sizes must match (one u32 for 32 bool) otherwise an error will happen +def main(bool[N] bits) -> u32[P] { + assert(N == 32 * P); + + u32[P] mut res = [0; P]; + + for u32 i in 0..P { + res[i] = u32_from_bits(bits[32 * i..32 * (i + 1)]); + } + + return res; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/field_to_u16.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/field_to_u16.zok new file mode 100644 index 0000000..ffa1509 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/field_to_u16.zok @@ -0,0 +1,8 @@ +from "field" import FIELD_SIZE_IN_BITS; +import "utils/pack/bool/unpack"; +import "utils/casts/u16_from_bits"; + +def main(field input) -> u16 { + bool[FIELD_SIZE_IN_BITS] bits = unpack(input); + return u16_from_bits(bits[FIELD_SIZE_IN_BITS-16..]); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/field_to_u32.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/field_to_u32.zok new file mode 100644 index 0000000..02be679 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/field_to_u32.zok @@ -0,0 +1,8 @@ +from "field" import FIELD_SIZE_IN_BITS; +import "utils/pack/bool/unpack"; +import "utils/casts/u32_from_bits"; + +def main(field input) -> u32 { + bool[FIELD_SIZE_IN_BITS] bits = unpack(input); + return u32_from_bits(bits[FIELD_SIZE_IN_BITS-32..]); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/field_to_u64.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/field_to_u64.zok new file mode 100644 index 0000000..6c50e6a --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/field_to_u64.zok @@ -0,0 +1,8 @@ +from "field" import FIELD_SIZE_IN_BITS; +import "utils/pack/bool/unpack"; +import "utils/casts/u64_from_bits"; + +def main(field input) -> u64 { + bool[FIELD_SIZE_IN_BITS] bits = unpack(input); + return u64_from_bits(bits[FIELD_SIZE_IN_BITS-64..]); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/field_to_u8.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/field_to_u8.zok new file mode 100644 index 0000000..dcb0db0 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/field_to_u8.zok @@ -0,0 +1,8 @@ +from "field" import FIELD_SIZE_IN_BITS; +import "utils/pack/bool/unpack"; +import "utils/casts/u8_from_bits"; + +def main(field input) -> u8 { + bool[FIELD_SIZE_IN_BITS] bits = unpack(input); + return u8_from_bits(bits[FIELD_SIZE_IN_BITS-8..]); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u16_from_bits.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u16_from_bits.zok new file mode 100644 index 0000000..48c7fa6 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u16_from_bits.zok @@ -0,0 +1,5 @@ +from "EMBED" import u16_from_bits; + +def main(bool[16] a) -> u16 { + return u16_from_bits(a); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u16_to_bits.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u16_to_bits.zok new file mode 100644 index 0000000..928c36a --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u16_to_bits.zok @@ -0,0 +1,5 @@ +from "EMBED" import u16_to_bits; + +def main(u16 a) -> bool[16] { + return u16_to_bits(a); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u16_to_field.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u16_to_field.zok new file mode 100644 index 0000000..181b3b7 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u16_to_field.zok @@ -0,0 +1,11 @@ +from "EMBED" import u16_to_bits; + +def main(u16 i) -> field { + bool[16] bits = u16_to_bits(i); + field mut res = 0; + for u32 j in 0..16 { + u32 exponent = 16 - j - 1; + res = res + (bits[j] ? 2 ** exponent : 0); + } + return res; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u32_4_to_bool_128.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u32_4_to_bool_128.zok new file mode 100644 index 0000000..2bbdcf2 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u32_4_to_bool_128.zok @@ -0,0 +1,6 @@ +import "./u32_array_to_bool_array" as to_bool_array; + +def main(u32[4] input) -> bool[128] { + bool[128] res = to_bool_array(input); + return res; +} diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u32_8_to_bool_256.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u32_8_to_bool_256.zok new file mode 100644 index 0000000..798c260 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u32_8_to_bool_256.zok @@ -0,0 +1,6 @@ +import "./u32_array_to_bool_array" as to_bool_array; + +def main(u32[8] input) -> bool[256] { + bool[256] res = to_bool_array(input); + return res; +} diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u32_array_to_bool_array.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u32_array_to_bool_array.zok new file mode 100644 index 0000000..1fa4e97 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u32_array_to_bool_array.zok @@ -0,0 +1,16 @@ +from "EMBED" import u32_to_bits; + +def main(u32[N] input) -> bool[P] { + assert(P == 32 * N); + + bool[P] mut res = [false; P]; + + for u32 i in 0..N { + bool[32] bits = u32_to_bits(input[i]); + for u32 j in 0..32 { + res[i * 32 + j] = bits[j]; + } + } + + return res; +} diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u32_from_bits.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u32_from_bits.zok new file mode 100644 index 0000000..3b8bc35 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u32_from_bits.zok @@ -0,0 +1,5 @@ +from "EMBED" import u32_from_bits; + +def main(bool[32] a) -> u32 { + return u32_from_bits(a); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u32_to_bits.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u32_to_bits.zok new file mode 100644 index 0000000..921031a --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u32_to_bits.zok @@ -0,0 +1,5 @@ +from "EMBED" import u32_to_bits; + +def main(u32 a) -> bool[32] { + return u32_to_bits(a); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u32_to_field.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u32_to_field.zok new file mode 100644 index 0000000..a643f83 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u32_to_field.zok @@ -0,0 +1,11 @@ +from "EMBED" import u32_to_bits; + +def main(u32 i) -> field { + bool[32] bits = u32_to_bits(i); + field mut res = 0; + for u32 j in 0..32 { + u32 exponent = 32 - j - 1; + res = res + (bits[j] ? 2 ** exponent : 0); + } + return res; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u64_from_bits.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u64_from_bits.zok new file mode 100644 index 0000000..3672f96 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u64_from_bits.zok @@ -0,0 +1,5 @@ +from "EMBED" import u64_from_bits; + +def main(bool[64] a) -> u64 { + return u64_from_bits(a); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u64_to_bits.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u64_to_bits.zok new file mode 100644 index 0000000..6e83d83 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u64_to_bits.zok @@ -0,0 +1,5 @@ +from "EMBED" import u64_to_bits; + +def main(u64 a) -> bool[64] { + return u64_to_bits(a); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u64_to_field.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u64_to_field.zok new file mode 100644 index 0000000..a928b6e --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u64_to_field.zok @@ -0,0 +1,11 @@ +from "EMBED" import u64_to_bits; + +def main(u64 i) -> field { + bool[64] bits = u64_to_bits(i); + field mut res = 0; + for u32 j in 0..64 { + u32 exponent = 64 - j - 1; + res = res + (bits[j] ? 2 ** exponent : 0); + } + return res; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u8_from_bits.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u8_from_bits.zok new file mode 100644 index 0000000..f48f992 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u8_from_bits.zok @@ -0,0 +1,5 @@ +from "EMBED" import u8_from_bits; + +def main(bool[8] a) -> u8 { + return u8_from_bits(a); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u8_to_bits.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u8_to_bits.zok new file mode 100644 index 0000000..ae87dca --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u8_to_bits.zok @@ -0,0 +1,5 @@ +from "EMBED" import u8_to_bits; + +def main(u8 a) -> bool[8] { + return u8_to_bits(a); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/casts/u8_to_field.zok b/zokrates_prover/.zokrates/stdlib/utils/casts/u8_to_field.zok new file mode 100644 index 0000000..22c3b24 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/casts/u8_to_field.zok @@ -0,0 +1,11 @@ +from "EMBED" import u8_to_bits; + +def main(u8 i) -> field { + bool[8] bits = u8_to_bits(i); + field mut res = 0; + for u32 j in 0..8 { + u32 exponent = 8 - j - 1; + res = res + (bits[j] ? 2 ** exponent : 0); + } + return res; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/multiplexer/lookup1bit.zok b/zokrates_prover/.zokrates/stdlib/utils/multiplexer/lookup1bit.zok new file mode 100644 index 0000000..7c9ec07 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/multiplexer/lookup1bit.zok @@ -0,0 +1,5 @@ +// One-bit window lookup table using one constraint +def main(bool selector, field[2] target) -> field { + field out = selector ? target[1] : target[0]; + return out; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/multiplexer/lookup2bit.zok b/zokrates_prover/.zokrates/stdlib/utils/multiplexer/lookup2bit.zok new file mode 100644 index 0000000..29f8d52 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/multiplexer/lookup2bit.zok @@ -0,0 +1,7 @@ +// Two-bit window lookup table using one constraint +// Maps the bits `b` to a list of field elements `c` +def main(bool[2] b, field[4] c) -> field { + field alpha = c[1] - c[0] + (b[1] ? (c[3] - c[2] - c[1] + c[0]) : 0); + field out = (b[0] ? alpha : 0) + c[0] - (b[1] ? (0 - c[2] + c[0]) : 0); + return out; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/multiplexer/lookup3bitSigned.zok b/zokrates_prover/.zokrates/stdlib/utils/multiplexer/lookup3bitSigned.zok new file mode 100644 index 0000000..3320504 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/multiplexer/lookup3bitSigned.zok @@ -0,0 +1,9 @@ +import "./lookup2bit" as lookup; + +// Three-bit window lookup (2bits + signature bit) in 2bit table +// using two constraints. Maps the bits `b` to a list of constants `c` +def main(bool[3] b, field[4] c) -> field { + field alpha = lookup([b[0], b[1]], c); + field out = alpha - 2 * (b[2] ? alpha : 0); + return out; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/pack/bool/nonStrictUnpack256.zok b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/nonStrictUnpack256.zok new file mode 100644 index 0000000..c0f0b81 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/nonStrictUnpack256.zok @@ -0,0 +1,11 @@ +#pragma curve bn128 + +import "./unpack_unchecked"; + +// Unpack a field element as 256 big-endian bits +// Note: uniqueness of the output is not guaranteed +// For example, `0` can map to `[0, 0, ..., 0]` or to `bits(p)` +def main(field i) -> bool[256] { + bool[254] b = unpack_unchecked(i); + return [false, false, ...b]; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/pack/bool/pack.zok b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/pack.zok new file mode 100644 index 0000000..1c5cee5 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/pack.zok @@ -0,0 +1,8 @@ +def main(bool[N] bits) -> field { + field mut out = 0; + for u32 j in 0..N { + u32 i = N - (j + 1); + out = out + (bits[i] ? 2 ** j : 0); + } + return out; +} diff --git a/zokrates_prover/.zokrates/stdlib/utils/pack/bool/pack128.zok b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/pack128.zok new file mode 100644 index 0000000..0001d88 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/pack128.zok @@ -0,0 +1,8 @@ +#pragma curve bn128 + +import "./pack" as pack; + +// pack 128 big-endian bits into one field element +def main(bool[128] bits) -> field { + return pack(bits); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/pack/bool/pack256.zok b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/pack256.zok new file mode 100644 index 0000000..c84ff0c --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/pack256.zok @@ -0,0 +1,10 @@ +#pragma curve bn128 + +import "./pack" as pack; + +// pack 256 big-endian bits into one field element +// Note: This is not a injective operation as `p` is smaller than `2**256 - 1` for bn128 +// For example, `[0, 0,..., 0]` and `bits(p)` both point to `0` +def main(bool[256] bits) -> field { + return pack(bits); +} diff --git a/zokrates_prover/.zokrates/stdlib/utils/pack/bool/unpack.zok b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/unpack.zok new file mode 100644 index 0000000..dbfba7b --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/unpack.zok @@ -0,0 +1,12 @@ +import "./unpack_unchecked.zok"; +from "field" import FIELD_SIZE_IN_BITS; +from "EMBED" import bit_array_le; + +// Unpack a field element as N big endian bits +def main(field i) -> bool[N] { + bool[N] res = unpack_unchecked(i); + assert(N >= FIELD_SIZE_IN_BITS \ + ? bit_array_le(res, [...[false; N - FIELD_SIZE_IN_BITS], ...unpack_unchecked::(-1)]) \ + : true); + return res; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/pack/bool/unpack128.zok b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/unpack128.zok new file mode 100644 index 0000000..e6b81c0 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/unpack128.zok @@ -0,0 +1,8 @@ +import "./unpack" as unpack; + +// Unpack a field element as 128 big-endian bits +// If the input is larger than `2**128 - 1`, the output is truncated. +def main(field i) -> bool[128] { + bool[128] res = unpack(i); + return res; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/pack/bool/unpack256.zok b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/unpack256.zok new file mode 100644 index 0000000..7dcf9c7 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/unpack256.zok @@ -0,0 +1,8 @@ +import "./unpack" as unpack; + +// Unpack a field element as 256 big-endian bits +// If the input is larger than `2**256 - 1`, the output is truncated. +def main(field i) -> bool[256] { + bool[256] res = unpack::<256>(i); + return res; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/pack/bool/unpack_unchecked.zok b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/unpack_unchecked.zok new file mode 100644 index 0000000..73b5b64 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/pack/bool/unpack_unchecked.zok @@ -0,0 +1,8 @@ +from "EMBED" import unpack; + +// Unpack a field element as N big endian bits without checking for overflows +// This does *not* guarantee a single output: for example, 0 can be decomposed as 0 or as P and this function does not enforce either +def main(field i) -> bool[N] { + bool[N] res = unpack(i); + return res; +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/pack/u32/nonStrictUnpack256.zok b/zokrates_prover/.zokrates/stdlib/utils/pack/u32/nonStrictUnpack256.zok new file mode 100644 index 0000000..37311a5 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/pack/u32/nonStrictUnpack256.zok @@ -0,0 +1,11 @@ +#pragma curve bn128 + +import "../bool/nonStrictUnpack256" as unpack; +import "../../casts/bool_256_to_u32_8" as from_bits; + +// Unpack a field element as a u32[8] (big-endian) +// Note: uniqueness of the output is not guaranteed +// For example, `0` can map to `[0, 0, ..., 0]` or to `bits(p)` +def main(field i) -> u32[8] { + return from_bits(unpack(i)); +} \ No newline at end of file diff --git a/zokrates_prover/.zokrates/stdlib/utils/pack/u32/pack.zok b/zokrates_prover/.zokrates/stdlib/utils/pack/u32/pack.zok new file mode 100644 index 0000000..0c8f453 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/pack/u32/pack.zok @@ -0,0 +1,8 @@ +import "../../casts/u32_array_to_bool_array" as to_bits; +import "../bool/pack"; + +// pack N big-endian bits into one field element +def main(u32[N] input) -> field { + bool[N * 32] bits = to_bits(input); + return pack(bits); +} diff --git a/zokrates_prover/.zokrates/stdlib/utils/pack/u32/pack128.zok b/zokrates_prover/.zokrates/stdlib/utils/pack/u32/pack128.zok new file mode 100644 index 0000000..dafc519 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/pack/u32/pack128.zok @@ -0,0 +1,6 @@ +import "./pack" as pack; + +// pack 128 big-endian bits into one field element +def main(u32[4] input) -> field { + return pack(input); +} diff --git a/zokrates_prover/.zokrates/stdlib/utils/pack/u32/pack256.zok b/zokrates_prover/.zokrates/stdlib/utils/pack/u32/pack256.zok new file mode 100644 index 0000000..74c4a3d --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/pack/u32/pack256.zok @@ -0,0 +1,19 @@ +import "../../casts/u32_to_bits"; +import "../bool/pack256"; + +// pack 256 big-endian bits into one field element +// Note: This is not a injective operation as `p` is smaller than `2**256 - 1 for bn128 +// For example, `[0, 0,..., 0]` and `bits(p)` both point to `0` +def main(u32[8] input) -> field { + bool[256] bits = [ + ...u32_to_bits(input[0]), + ...u32_to_bits(input[1]), + ...u32_to_bits(input[2]), + ...u32_to_bits(input[3]), + ...u32_to_bits(input[4]), + ...u32_to_bits(input[5]), + ...u32_to_bits(input[6]), + ...u32_to_bits(input[7]) + ]; + return pack256(bits); +} diff --git a/zokrates_prover/.zokrates/stdlib/utils/pack/u32/unpack128.zok b/zokrates_prover/.zokrates/stdlib/utils/pack/u32/unpack128.zok new file mode 100644 index 0000000..88aed42 --- /dev/null +++ b/zokrates_prover/.zokrates/stdlib/utils/pack/u32/unpack128.zok @@ -0,0 +1,10 @@ +#pragma curve bn128 + +import "../bool/unpack128" as unpack; +import "../../casts/bool_128_to_u32_4" as from_bits; + +// Unpack a field element as 128 big-endian bits +// Precondition: the input is smaller or equal to `2**128 - 1` +def main(field i) -> u32[4] { + return from_bits(unpack(i)); +} \ No newline at end of file diff --git a/zokrates_prover/abi.json b/zokrates_prover/abi.json new file mode 100644 index 0000000..6d10023 --- /dev/null +++ b/zokrates_prover/abi.json @@ -0,0 +1,28 @@ +{ + "inputs": [ + { + "name": "a", + "public": false, + "type": "array", + "components": { + "size": 8, + "type": "u8" + } + }, + { + "name": "b", + "public": true, + "type": "array", + "components": { + "size": 8, + "type": "u32" + } + } + ], + "output": { + "type": "tuple", + "components": { + "elements": [] + } + } +} \ No newline at end of file diff --git a/zokrates_prover/build.gradle.kts b/zokrates_prover/build.gradle.kts new file mode 100644 index 0000000..cf671f4 --- /dev/null +++ b/zokrates_prover/build.gradle.kts @@ -0,0 +1,31 @@ + +val ktor_version: String by project +val kotlin_version: String by project +val logback_version: String by project + +plugins { + kotlin("jvm") version "1.9.21" + id("io.ktor.plugin") version "2.3.6" +} + +group = "hu.bme" +version = "0.0.1" + +application { + mainClass.set("hu.bme.ApplicationKt") + + val isDevelopment: Boolean = project.ext.has("development") + applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment") +} + +repositories { + mavenCentral() +} + +dependencies { + implementation("io.ktor:ktor-server-core-jvm") + implementation("io.ktor:ktor-server-netty-jvm") + implementation("ch.qos.logback:logback-classic:$logback_version") + testImplementation("io.ktor:ktor-server-tests-jvm") + testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version") +} diff --git a/zokrates_prover/gradle.properties b/zokrates_prover/gradle.properties new file mode 100644 index 0000000..377e30b --- /dev/null +++ b/zokrates_prover/gradle.properties @@ -0,0 +1,4 @@ +ktor_version=2.3.6 +kotlin_version=1.9.21 +logback_version=1.4.11 +kotlin.code.style=official diff --git a/zokrates_prover/gradle/wrapper/gradle-wrapper.jar b/zokrates_prover/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..7454180 Binary files /dev/null and b/zokrates_prover/gradle/wrapper/gradle-wrapper.jar differ diff --git a/zokrates_prover/gradle/wrapper/gradle-wrapper.properties b/zokrates_prover/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..e411586 --- /dev/null +++ b/zokrates_prover/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/zokrates_prover/gradlew b/zokrates_prover/gradlew new file mode 100644 index 0000000..1b6c787 --- /dev/null +++ b/zokrates_prover/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/zokrates_prover/gradlew.bat b/zokrates_prover/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/zokrates_prover/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/zokrates_prover/out b/zokrates_prover/out new file mode 100644 index 0000000..45d4152 Binary files /dev/null and b/zokrates_prover/out differ diff --git a/zokrates_prover/out.r1cs b/zokrates_prover/out.r1cs new file mode 100644 index 0000000..9cac149 Binary files /dev/null and b/zokrates_prover/out.r1cs differ diff --git a/zokrates_prover/out.wtns b/zokrates_prover/out.wtns new file mode 100644 index 0000000..8727174 Binary files /dev/null and b/zokrates_prover/out.wtns differ diff --git a/zokrates_prover/proof.json b/zokrates_prover/proof.json new file mode 100644 index 0000000..477fd81 --- /dev/null +++ b/zokrates_prover/proof.json @@ -0,0 +1,34 @@ +{ + "scheme": "g16", + "curve": "bls12_381", + "proof": { + "a": [ + "0x0258a8ab2e4cb1316fa8f7c5de33e319fff8c9377050ed554c5cd8fe2ee7bd495fb1007000c8f41739dad250aba60502", + "0x07389f88dbd974621d074c7491d16a40ef41f89a168b37210856f6a45bf75769bd592eee211fedfd8f72d98afac0fe32" + ], + "b": [ + [ + "0x14fa0106d6ef9ac5ea0a48a02b019d2cc0f83df79c3c3ca0d6d99df6389b98237ff7a59955b0f87573edf93537a47b11", + "0x01c6c4fdc9f5842538cc769e70ccf39aa9edd18fcb6738454d01304aa2fb97b60cfce710c57c8cfb732f8392f377c10b" + ], + [ + "0x092d8053ac7742b400039c4ca8a5c89a776619a0cd31cf28321baa0dc283dacefd8ba36ee2bf1167d1a3f7db3e4299ec", + "0x027a0ec533046eda2e44d4820dfda1fbc5364d788d11c0de10026d06e0dbbaa6a2fbca3111b36723a18e2771f9df9a9d" + ] + ], + "c": [ + "0x172f056b545cfb45a6101f004d1320d5b65e9a08a20e6125e9ec39ef85cc02d323bda1b68d9b0c301c633401bea02670", + "0x13ac0d34cf9ea52507187fffb5c3e050f736687e3ff4c6c9601c1a3356ac3dd69c8ed03531ab945502f65a5fec3d0507" + ] + }, + "inputs": [ + "0x0000000000000000000000000000000000000000000000000000000004abc882", + "0x000000000000000000000000000000000000000000000000000000001a06e5a3", + "0x000000000000000000000000000000000000000000000000000000000937967d", + "0x0000000000000000000000000000000000000000000000000000000011ad1022", + "0x000000000000000000000000000000000000000000000000000000001cb5ac3b", + "0x000000000000000000000000000000000000000000000000000000005273e434", + "0x00000000000000000000000000000000000000000000000000000000f1284ee8", + "0x000000000000000000000000000000000000000000000000000000007129a061" + ] +} \ No newline at end of file diff --git a/zokrates_prover/proving.key b/zokrates_prover/proving.key new file mode 100644 index 0000000..dd46a8e Binary files /dev/null and b/zokrates_prover/proving.key differ diff --git a/zokrates_prover/root.zok b/zokrates_prover/root.zok new file mode 100644 index 0000000..79b18b4 --- /dev/null +++ b/zokrates_prover/root.zok @@ -0,0 +1,8 @@ +import "hashes/sha256/sha256Padded"; + +def main(private u8[8] a, u32[8] b) { + u32[8] hash = sha256Padded(a); + log("The hash: {}", hash); + assert(hash == b); + return; +} diff --git a/zokrates_prover/settings.gradle.kts b/zokrates_prover/settings.gradle.kts new file mode 100644 index 0000000..f266289 --- /dev/null +++ b/zokrates_prover/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "hu.bme.zokrates_prover" diff --git a/zokrates_prover/src/main/kotlin/hu/bme/Application.kt b/zokrates_prover/src/main/kotlin/hu/bme/Application.kt new file mode 100644 index 0000000..aac69ce --- /dev/null +++ b/zokrates_prover/src/main/kotlin/hu/bme/Application.kt @@ -0,0 +1,18 @@ +package hu.bme + +import hu.bme.plugins.* +import io.ktor.server.application.* +import io.ktor.server.engine.* +import io.ktor.server.netty.* + +fun main() { + Zokrates.initZokrates() + Zokrates.compile("root.zok", curve = "bls12_381") + Zokrates.setup() + embeddedServer(Netty, port = 8081, host = "0.0.0.0", module = Application::module) + .start(wait = true) +} + +fun Application.module() { + configureRouting() +} diff --git a/zokrates_prover/src/main/kotlin/hu/bme/Exceptions.kt b/zokrates_prover/src/main/kotlin/hu/bme/Exceptions.kt new file mode 100644 index 0000000..81efd6e --- /dev/null +++ b/zokrates_prover/src/main/kotlin/hu/bme/Exceptions.kt @@ -0,0 +1,28 @@ +package hu.bme + +/* + * Copyright 2023 Contributors of the zkWF project + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +class ZokratesNotInititialised : Exception() + +class ZokratesInstallFailed : Exception() + +class ZokratesCompileFailed(output: String) : Exception(output) + +class ZokratesComputeWitnessFailed(output: String) : Exception(output) + +class ZokratesSetupFailed(output: String) : Exception(output) diff --git a/zokrates_prover/src/main/kotlin/hu/bme/Zokrates.kt b/zokrates_prover/src/main/kotlin/hu/bme/Zokrates.kt new file mode 100644 index 0000000..83cc350 --- /dev/null +++ b/zokrates_prover/src/main/kotlin/hu/bme/Zokrates.kt @@ -0,0 +1,144 @@ +package hu.bme + +/* + * Copyright 2023 Contributors of the zkWF project + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + + +import java.io.File +import java.net.URL + +object Zokrates { + private var isInitDone = false + private lateinit var zokratesPath: String + + private fun checkInit() { + if (isInitDone.not()) { + throw ZokratesNotInititialised() + } + } + + private fun installZokrates() { + val tmp = File(System.getProperty("user.dir") + "/tmp").also { file -> + file.mkdir() + } + val dlFile = File(tmp, "zokrates.sh").also { + it.writeText(URL("https://raw.githubusercontent.com/ZoKrates/ZoKrates/master/scripts/one_liner.sh").readText()) + it.setExecutable(true) + } + + val pb = ProcessBuilder(dlFile.absoluteFile.absolutePath.toString(), "--to", ".zokrates") + val process = pb.start() + + val exitCode = process.waitFor() + if (exitCode != 0) { + throw ZokratesInstallFailed() + } + + dlFile.delete() + tmp.delete() + } + + fun initZokrates() { + if (File(System.getProperty("user.dir") + "/.zokrates/bin/zokrates").exists().not()) { + installZokrates() + } + + zokratesPath = System.getProperty("user.dir") + "/.zokrates/bin/zokrates" + isInitDone = true + } + + fun compile(path: String, outPut: String = "out",curve: String = "bn128") { + checkInit() + compile(File(path), outPut,curve) + } + + fun compile(file: File, outPut: String = "out",curve: String = "bn128") { + checkInit() + val pb = ProcessBuilder(zokratesPath, "compile", "-i", file.absoluteFile.absolutePath.toString(), "-o", outPut,"--curve",curve) + + val process = pb.start() + + val exitCode = process.waitFor() + if (exitCode != 0) { + val output = process.inputStream.bufferedReader().use { it.readText() } + throw ZokratesCompileFailed(output) + } + } + + fun computeWithness(args: List, input: String = "out", output: String = "witness"): List { + checkInit() + val sb = StringBuilder() + var prefix = "" + args.forEach { + sb.append(prefix) + prefix = " " + sb.append(it) + } + println(sb.toString()) + val command = mutableListOf(zokratesPath, "compute-witness", "-i", input, "-o", output, "-a").apply { + addAll(args) + } + val processBuilder = ProcessBuilder(command) + + val process = processBuilder.start() + + val exitCode = process.waitFor() + if (exitCode != 0) { + val output1 = process.inputStream.bufferedReader().use { it.readText() } + println("Error $output1") + throw ZokratesComputeWitnessFailed(output1) + } + return readWitness(output) + } + + fun readWitness(witness: String = "witness"): List { + return File(witness).readText().split("\n").filter { it.startsWith("~out_") }.sorted().map { it.split(' ')[1] } + } + + fun setup(input: String = "out") { + val pb = ProcessBuilder(zokratesPath, "setup", "-i", input) + val process = pb.start() + val exitCode = process.waitFor() + if (exitCode != 0) { + val output = process.inputStream.bufferedReader().use { it.readText() } + println("Error $output") + throw ZokratesSetupFailed(output) + } + } + + fun generateProof(input: String = "out", witness: String = "witness", proof: String = "proof.json") { + val pb = ProcessBuilder(zokratesPath, "generate-proof", "-i", input, "-w", witness, "-j", proof) + val process = pb.start() + val exitCode = process.waitFor() + if (exitCode != 0) { + val output = process.inputStream.bufferedReader().use { it.readText() } + println("Error $output") + throw ZokratesSetupFailed(output) + } + } + + fun exportVerifier(input: String = "out", output: String = "verifier.sol") { + val pb = ProcessBuilder(zokratesPath, "export-verifier") + val process = pb.start() + val exitCode = process.waitFor() + if (exitCode != 0) { + val output = process.inputStream.bufferedReader().use { it.readText() } + println("Error $output") + throw ZokratesSetupFailed(output) + } + } +} diff --git a/zokrates_prover/src/main/kotlin/hu/bme/plugins/Routing.kt b/zokrates_prover/src/main/kotlin/hu/bme/plugins/Routing.kt new file mode 100644 index 0000000..b53355b --- /dev/null +++ b/zokrates_prover/src/main/kotlin/hu/bme/plugins/Routing.kt @@ -0,0 +1,41 @@ +package hu.bme.plugins + +import hu.bme.Zokrates +import io.ktor.http.* +import io.ktor.server.application.* +import io.ktor.server.response.* +import io.ktor.server.routing.* +import java.io.File + +fun Application.configureRouting() { + routing { + get("/") { + call.respondText("Hello World!") + } + + get("/prove/{secret}") { + // Get the secret from the path + val secret = call.parameters["secret"] ?: return@get call.respondText("No secret provided") + val expectedHash = "78366850 436659619 154637949 296554530 481668155 1383326772 4045950696 1898553441".split(" ").map { it.toLong() } + val params = secret.split(" ").map { it.toLong() }.toMutableList() + while (params.size < 8) { + params.add(0) + } + + params.addAll(expectedHash) + try { + Zokrates.computeWithness(params.map { it.toString() }) + } catch (e: Exception) { + return@get call.respondText("Error: ${e.message}") + } + + Zokrates.generateProof() + + + + call.respondText(contentType = ContentType.Application.Json) { + File("proof.json").readText() + } + } + } +} diff --git a/zokrates_prover/src/main/resources/logback.xml b/zokrates_prover/src/main/resources/logback.xml new file mode 100644 index 0000000..3e11d78 --- /dev/null +++ b/zokrates_prover/src/main/resources/logback.xml @@ -0,0 +1,12 @@ + + + + %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/zokrates_prover/src/test/kotlin/hu/bme/ApplicationTest.kt b/zokrates_prover/src/test/kotlin/hu/bme/ApplicationTest.kt new file mode 100644 index 0000000..71b79b4 --- /dev/null +++ b/zokrates_prover/src/test/kotlin/hu/bme/ApplicationTest.kt @@ -0,0 +1,4 @@ +package hu.bme + +class ApplicationTest { +} diff --git a/zokrates_prover/verification.key b/zokrates_prover/verification.key new file mode 100644 index 0000000..9a9140f --- /dev/null +++ b/zokrates_prover/verification.key @@ -0,0 +1,76 @@ +{ + "scheme": "g16", + "curve": "bls12_381", + "alpha": [ + "0x1928e2f0ad43df96457d5a5417c16ebbcfdd56f4ddbba22c071222655741169b5dae40a477e4dbdf66c5d2d9d1197aa9", + "0x146b21c16a24c61f9bb8189c08e727ec90145b3e363db2b03bfc671f11b53bb01d03245a3438a37fa03eafd7e965524b" + ], + "beta": [ + [ + "0x08f9c05b639b64dc136a5cb757a4ea96ec3e58bb36fd6ed4b27888242691f55dd54fa3d78e9733bea86e39a012689a29", + "0x18f5f5f6832765e55f0010106b4268656f01674fed4acd53ff321b7346070376dd85aec1c456fcd3422c3dcf63ecf801" + ], + [ + "0x015f9735d4c40fd252a540a721134aa9d520afd84880051fa0ab8291b5c8b32107e9ebff93ca96056cbe984fc608ebe7", + "0x0679e24c60aa11a00c9bc71651b27d19373759dc9610c4c600a0e1522da9a9a4185256e3c2bf1bd16e2f7f3d84338b18" + ] + ], + "gamma": [ + [ + "0x0563abef7d7eb1fe3aff6db75735efae8fd690a5e0028658a0cc092fe3222cb1c8d141dd696b30e7abc1e0bcd84047a3", + "0x0ef2e9a7f344f1b824ec441a84ed5375ec8c526933435768a45cf6382a7ef7f70086601707cf2b74f644a91a76b13426" + ], + [ + "0x04d35822376bde5bcf8438cd9a00c50f07635a5d9270ac88066976ac18a6fdd9b566648f4247e97115df9280d334e496", + "0x18a76e98145d71130cc784b5dba9cf6f8478527f56a5111719ca4bbd807f22fc913e4d3cdd625694266a26b95d642aed" + ] + ], + "delta": [ + [ + "0x028e8f00d8e1cb9c61ec5ebbd65d182ad0c15f52a2c3ae5dee6d321ae614dfe4fb5ffbfa7b781d7cfd2c6e9c863da356", + "0x17a0c22ac9f46aa7371b65b5fbd476841c445c951835e119fc79480e06b5e6b90d6e7e34d1c44627c3a8fa3e6cd139e3" + ], + [ + "0x015cde577b61e40926eb5692abbd83deff8be8dbf422f26eb16c36188fd0fd5b1502e6fc19f0a99dee13e0d2e56119ad", + "0x0045898f7b5cd8ef4dfe3e1d482a56621076a1c4bb10a6aaa81067302323b6a4167e9534fdbf1d742fbdd0fd4c35e2ea" + ] + ], + "gamma_abc": [ + [ + "0x0c7c45d776894df7d49c25a97f10ccba49f28624f631d6ba6ff583520b2f6508749d61cf22bca0b97427d6cf16d82cb5", + "0x01f0a5732fb10fb975e6ed08c53c237c413e1d0d533c538d18ecdf7c163cbc62a08c989448a8d927825ee3df45e2a8d4" + ], + [ + "0x0a8a1650b803f913ac74d48493d4f43521c086e9d1f63e34622506138bc405d356c31674fb15e810d1669b58da02fb5f", + "0x07815f65a1d750b21d149e75bde88829498c72cb7b5d8f9bff7123f9fcf42b30236d186903f7cde96e61273df67a57c3" + ], + [ + "0x0579fdef63c80f9a33cd4d3dda79fa2d79fdc1afe048b3d944d9b53dbe7f9b228cc5994be24ed5dea053031802b53c85", + "0x11f4b09a7e57c3e878b5fd15e4e7ae36fe5548a75631b5ad9d764e9d727c69f4fdc066f6f5dcc9ae3068483ecbffdea2" + ], + [ + "0x18698ed26ec350dfcc09a8916d41f9edeeeeddd3e857db0d29f5a099c6dee0e8abd0aff7a7030d36192af98dcc4e3ffa", + "0x1584a7d18bddff7515a50d35bfc78558ab907e99ecdfcdb8964f689a10e56a93e68c6fd05c80ada833a726fa923c2ad7" + ], + [ + "0x146394fc19ccb6add749fa2395ae8a6efa03f9aa163aeb8a50cd88cf513012a4c960e0eec2aeb875a3891ca8eac6dbc7", + "0x05e1c0afd75fb240ee5aa6a20182e9cace10c9d0f5862185a5d5cbb5f00edbbb9f36e8b431eb5f20cca1b2b60a09880f" + ], + [ + "0x0d16725e01b97f3185590724b348c4709ae2aede5cd8abb7c91835ac21f0bf7a7c7d993cbc3471f76f783240decf553e", + "0x03a0da8548b1d1dc6de7ca41e8e4687d46e1d85a34ef1dc15dd56d67b712e876cdf634ca1236918fef60bf6c768d632c" + ], + [ + "0x0811cf2eda04983be25f25756edd59871dd34704a886db4e7444b1e7f890d3912d3c8498e7dcdfa8ef5d6241a3bb189a", + "0x1113e15eb10e7a3e731859327410224a715ba59d3752be11989165732b1118a9ed046e57fb7b5ccb26d872dc23256a50" + ], + [ + "0x0ac1d81a337330c55f2609d66dd80f6229ad61c732e6f324476daeb34d1b56731f613984ffe085cc3b00de75124e0c42", + "0x042f6850d8820057cde367f31c6bf2e45b514850c5c353670137970230c6125c3b0b7f45d76473ad7dad017d5f734eff" + ], + [ + "0x14ef809ef4d855edc0adc34803e539e1000840a1a0bc0dc5c4ff842130322bb5f72d2457158ab8e28f073bf2c2e87526", + "0x02c0f33c8bcf10a0870f69c2afae12f550c12d1d93ff2206926cf686a54299348554eea6004d4c45097b6b0b06348381" + ] + ] +} \ No newline at end of file diff --git a/zokrates_prover/witness b/zokrates_prover/witness new file mode 100644 index 0000000..3fe50ce Binary files /dev/null and b/zokrates_prover/witness differ