Commit 671a85fd authored by John Doe's avatar John Doe
Browse files

🟣🏴

parent aff1f6e0
Pipeline #49 failed with stages
in 0 seconds
This diff is collapsed.
/* Autogenerated file, do not edit! */
/* eslint-disable */
import { Noir, InputMap, CompiledCircuit, ForeignCallHandler } from "@noir-lang/noir_js"
export type { ForeignCallHandler } from "@noir-lang/noir_js"
export type Field = string;
export type PublicInputs = {
current_root: Field;
utxo_root: Field;
deposit_amount: Field;
withdrawals: Field;
commitment_in: Field[];
commitment_out: Field[];
nullifier_hashes: Field[];
contract_only_inputs: Field;
};
export const tx_as_hash_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"tx","type":{"kind":"struct","path":"structs::PublicInputs","fields":[{"name":"current_root","type":{"kind":"field"}},{"name":"utxo_root","type":{"kind":"field"}},{"name":"deposit_amount","type":{"kind":"field"}},{"name":"withdrawals","type":{"kind":"field"}},{"name":"commitment_in","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"commitment_out","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"nullifier_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"contract_only_inputs","type":{"kind":"field"}}]},"visibility":"private"}],"param_witnesses":{"tx":[{"start":0,"end":53}]},"return_type":{"abi_type":{"kind":"field"},"visibility":"private"},"return_witnesses":[53]},"bytecode":"H4sIAAAAAAAA/13R1QpCURRFUdtrd3d36///mag4FPGADLlve65w6P1uz1/Y/5eBb5939/1lhFHGGGeCSQZMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuv/Oz4a8huEXvF7JSwT2CXtD2ydsjrX9S9rHdV57q+TV3benZ17Os31G2s11SnuT5LXdZ6bHXYu//o7rN7r393/d/6fQ/p5LXj2QIAAA=="};
export async function tx_as_hash(tx: PublicInputs, foreignCallHandler?: ForeignCallHandler): Promise<Field> {
const program = new Noir(tx_as_hash_circuit);
const args: InputMap = { tx };
const { returnValue } = await program.execute(args, foreignCallHandler);
return returnValue as Field;
}
/* Autogenerated file, do not edit! */
/* eslint-disable */
import { Noir, InputMap, CompiledCircuit, ForeignCallHandler } from "@noir-lang/noir_js"
export type { ForeignCallHandler } from "@noir-lang/noir_js"
export type Field = string;
export type UTXO_New = {
secret: Field;
amount: Field;
asset_type: Field;
};
export const utxo_to_commitment_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"utxo","type":{"kind":"struct","path":"structs::UTXO_New","fields":[{"name":"secret","type":{"kind":"field"}},{"name":"amount","type":{"kind":"field"}},{"name":"asset_type","type":{"kind":"field"}}]},"visibility":"private"}],"param_witnesses":{"utxo":[{"start":0,"end":3}]},"return_type":{"abi_type":{"kind":"field"},"visibility":"private"},"return_witnesses":[4]},"bytecode":"H4sIAAAAAAAA/11MWwoAMAjqsY/d/8CyYAaWIJaKbh+nGLy9eKkNUFPyFA/0wR3Irkm392P92h14YkM2CqEAAAA="};
export async function utxo_to_commitment(utxo: UTXO_New, foreignCallHandler?: ForeignCallHandler): Promise<Field> {
const program = new Noir(utxo_to_commitment_circuit);
const args: InputMap = { utxo };
const { returnValue } = await program.execute(args, foreignCallHandler);
return returnValue as Field;
}
use dep::std;
use crate::structs;
fn field_to_u8(_value: Field) -> [u8; 32] {
let _array = _value.to_be_bytes(32);
let mut array: [u8; 32] = [0; 32];
for i in 0 .. 32 {
array[i] = _array[i];
}
array
}
fn hash<N>(data: [Field; N]) -> Field {
std::hash::pedersen_hash(data)
}
#[export]
fn utxo_to_commitment(utxo: structs::UTXO_New) -> Field {
utxo.to_commitment()
}
#[export]
fn pedersen_left_right(left: Field, right: Field) -> Field {
std::hash::pedersen_hash([left, right])
}
#[export]
fn keccak_tx(tx: structs::PublicInputs) -> Field {
let mut hash_array: [Field; 53] = [0; 53];
hash_array[0] = tx.current_root;
hash_array[1] = tx.utxo_root;
hash_array[2] = tx.deposit_amount;
hash_array[3] = tx.contract_only_inputs;
hash_array[4] = tx.withdrawals;
for i in 0..16 {
hash_array[5 + i] = tx.commitment_in[i];
hash_array[21 + i] = tx.commitment_out[i];
hash_array[37 + i] = tx.nullifier_hashes[i];
}
let u8_array = tx_to_u8(hash_array);
hash_to_field(std::hash::keccak256(u8_array, u8_array.len() as u32))
}
fn bytes_tx_without_deposit(tx: structs::PublicInputs) -> [u8; 1696] {
let mut hash_array: [Field; 53] = [0; 53];
hash_array[0] = tx.current_root;
hash_array[1] = tx.utxo_root;
hash_array[2] = tx.deposit_amount;
hash_array[3] = tx.contract_only_inputs;
hash_array[4] = tx.withdrawals;
for i in 0..16 {
hash_array[5 + i] = tx.commitment_in[i];
hash_array[21 + i] = tx.commitment_out[i];
hash_array[37 + i] = tx.nullifier_hashes[i];
}
tx_to_u8(hash_array)
}
#[export]
fn keccak_contract_only_inputs(contract_only_inputs: structs::ContractOnlyInputs) -> Field {
let mut hash_array: [Field; 100] = [0; 100];
hash_array[0] = contract_only_inputs.timestamp;
hash_array[1] = contract_only_inputs.deadline;
hash_array[2] = contract_only_inputs.signature_hash;
hash_array[3] = contract_only_inputs.price_limit;
for i in 0..16 {
hash_array[4 + i] = contract_only_inputs.recipients[i];
hash_array[20 + i] = contract_only_inputs.swap_amounts[i];
hash_array[36 + i] = contract_only_inputs.uids[i];
hash_array[52 + (i * 3)] = contract_only_inputs.encrypted_utxo[i].secret;
hash_array[53 + (i * 3)] = contract_only_inputs.encrypted_utxo[i].amount;
hash_array[54 + (i * 3)] = contract_only_inputs.encrypted_utxo[i].data;
}
let u8_array = contract_only_to_u8(hash_array);
hash_to_field(std::hash::keccak256(u8_array, u8_array.len() as u32))
}
#[export]
fn keccak_contract_only_inputs_without_deposit(contract_only_inputs: structs::ContractOnlyInputs) -> Field {
let mut hash_array: [Field; 99] = [0; 99];
hash_array[0] = contract_only_inputs.timestamp;
hash_array[1] = contract_only_inputs.deadline;
hash_array[2] = contract_only_inputs.price_limit;
for i in 0..16 {
hash_array[3 + i] = contract_only_inputs.recipients[i];
hash_array[19 + i] = contract_only_inputs.swap_amounts[i];
hash_array[35 + i] = contract_only_inputs.uids[i];
hash_array[51 + (i * 3)] = contract_only_inputs.encrypted_utxo[i].secret;
hash_array[52 + (i * 3)] = contract_only_inputs.encrypted_utxo[i].amount;
hash_array[53 + (i * 3)] = contract_only_inputs.encrypted_utxo[i].data;
}
let u8_array = contract_only_without_deposit_to_u8(hash_array);
hash_to_field(std::hash::keccak256(u8_array, u8_array.len() as u32))
}
fn bytes_contract_only_inputs_without_deposit(contract_only_inputs: structs::ContractOnlyInputs) -> [u8; 3168] {
let mut hash_array: [Field; 99] = [0; 99];
hash_array[0] = contract_only_inputs.timestamp;
hash_array[1] = contract_only_inputs.deadline;
hash_array[2] = contract_only_inputs.price_limit;
for i in 0..16 {
hash_array[3 + i] = contract_only_inputs.recipients[i];
hash_array[19 + i] = contract_only_inputs.swap_amounts[i];
hash_array[35 + i] = contract_only_inputs.uids[i];
hash_array[51 + (i * 3)] = contract_only_inputs.encrypted_utxo[i].secret;
hash_array[52 + (i * 3)] = contract_only_inputs.encrypted_utxo[i].amount;
hash_array[53 + (i * 3)] = contract_only_inputs.encrypted_utxo[i].data;
}
contract_only_without_deposit_to_u8(hash_array)
}
#[export]
fn contract_only_inputs_with_signature_hash(contract_only_inputs: structs::ContractOnlyInputs) -> structs::ContractOnlyInputs {
let mut hash_array: [Field; 99] = [0; 99];
hash_array[0] = contract_only_inputs.timestamp;
hash_array[1] = contract_only_inputs.deadline;
hash_array[2] = contract_only_inputs.price_limit;
for i in 0..16 {
hash_array[3 + i] = contract_only_inputs.recipients[i];
hash_array[19 + i] = contract_only_inputs.swap_amounts[i];
hash_array[35 + i] = contract_only_inputs.uids[i];
hash_array[51 + (i * 3)] = contract_only_inputs.encrypted_utxo[i].secret;
hash_array[52 + (i * 3)] = contract_only_inputs.encrypted_utxo[i].amount;
hash_array[53 + (i * 3)] = contract_only_inputs.encrypted_utxo[i].data;
}
let u8_array = contract_only_without_deposit_to_u8(hash_array);
let contract_only_inputs_with_hash = structs::ContractOnlyInputs {
timestamp: contract_only_inputs.timestamp,
deadline: contract_only_inputs.deadline,
signature_hash: hash_to_field(std::hash::keccak256(u8_array, u8_array.len() as u32)),
price_limit: contract_only_inputs.price_limit,
recipients: contract_only_inputs.recipients,
swap_amounts: contract_only_inputs.swap_amounts,
uids: contract_only_inputs.uids,
encrypted_utxo: contract_only_inputs.encrypted_utxo
};
contract_only_inputs_with_hash
}
fn hash_tx(tx: structs::PublicInputs) -> Field {
let mut hash_array: [Field; 53] = [0; 53];
hash_array[0] = tx.current_root;
hash_array[1] = tx.utxo_root;
hash_array[2] = tx.deposit_amount;
hash_array[3] = tx.withdrawals;
for i in 0..16 {
hash_array[4 + i] = tx.commitment_in[i];
hash_array[20 + i] = tx.commitment_out[i];
hash_array[36 + i] = tx.nullifier_hashes[i];
}
hash_array[52] = tx.contract_only_inputs;
hash(hash_array)
}
fn hash_to_field(hash: [u8; 32]) -> Field {
let mut keccak_field: Field = 0;
for p in 0..32 {
let bytes_field: Field = hash[31 - p] as Field;
keccak_field += bytes_field * 256.pow_32(p as Field);
}
keccak_field
}
fn tx_to_u8(pi_fields: [Field; 53]) -> [u8; 1696] {
let mut keccak_array: [u8; 1696] = [0; 1696];
for i in 0..pi_fields.len() {
let mut byte_slice = pi_fields[i].to_be_bytes(32);
for j in 0..32 {
keccak_array[32*i + j] = byte_slice[j];
}
}
keccak_array
}
fn contract_only_to_u8(pi_fields: [Field; 100]) -> [u8; 3200] {
let mut keccak_array: [u8; 3200] = [0; 3200];
for i in 0..pi_fields.len() {
let mut byte_slice = pi_fields[i].to_be_bytes(32);
for j in 0..32 {
keccak_array[32*i + j] = byte_slice[j];
}
}
keccak_array
}
fn contract_only_without_deposit_to_u8(pi_fields: [Field; 99]) -> [u8; 3168] {
let mut keccak_array: [u8; 3168] = [0; 3168];
for i in 0..pi_fields.len() {
let mut byte_slice = pi_fields[i].to_be_bytes(32);
for j in 0..32 {
keccak_array[32*i + j] = byte_slice[j];
}
}
keccak_array
}
fn batch_to_u8(pi_fields: [Field; 19]) -> [u8; 608] {
let mut keccak_array: [u8; 608] = [0; 608];
for i in 0..pi_fields.len() {
let mut byte_slice = pi_fields[i].to_be_bytes(32);
for j in 0..32 {
keccak_array[32*i + j] = byte_slice[j];
}
}
keccak_array
}
fn hash_tree_four(leaves: [Field; 16]) -> Field {
let mut tx_tree: [Field; 16] = leaves;
for l in 0..8 { tx_tree[l] = hash([tx_tree[2*l], tx_tree[2*l + 1]]); }
for l in 0..4 { tx_tree[l] = hash([tx_tree[2*l], tx_tree[2*l + 1]]); }
for l in 0..2 { tx_tree[l] = hash([tx_tree[2*l], tx_tree[2*l + 1]]); }
hash([tx_tree[0], tx_tree[1]])
}
fn compute_merkle_root<N>(leaf: Field, index: Field, hash_path: [Field; N]) -> Field {
let n = hash_path.len();
let index_bits = index.to_le_bits(n as u32);
let mut current = leaf;
for i in 0..n {
let path_bit = index_bits[i] as bool;
let (hash_left, hash_right) = if path_bit {
(hash_path[i], current)
} else {
(current, hash_path[i])
};
current = hash([hash_left, hash_right]);
}
current
}
fn compute_sibling_path<N>(sibling_path: [Field; N], new_leaf: Field, insertion_index: Field) -> [Field; N] {
let index_bits: [u1] = insertion_index.to_le_bits(N as u32);
let mut new_sibling_path: [Field; N] = [0; N];
let mut current_hash: Field = new_leaf;
let mut zero_found: bool = false;
for i in 0..N {
let path_bit = index_bits[i] as bool;
if (!zero_found) {
if (!path_bit) {
zero_found = true;
new_sibling_path[i] = current_hash;
} else {
new_sibling_path[i] = structs::zero_hashes[i];
}
} else {
new_sibling_path[i] = sibling_path[i];
}
if (path_bit) {
current_hash = hash([sibling_path[i], current_hash]);
} else {
current_hash = hash([current_hash, sibling_path[i]]);
}
}
new_sibling_path
}
\ No newline at end of file
use dep::std;
mod structs;
mod hash;
global utxo_depth = 4;
global batch_depth = 4;
global state_depth = 20;
global ZERO_VALUE = 0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720;
// Levels of an empty pedersen Merkle tree with zero_leaf = sha256("Momiji") % Field Modulus
global zero_hashes: [Field; 20] = [
0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720,
0x018d39625c19fa2cfbebdb940a66d7040bb0ef1b59ff6afd92a13a6b9b2d9865,
0x096c00ebc0c52478316b6b9fd16d0cd94c5f45bbe45bbfa8c606197c6119d41f,
0x2eaefd3bdd1bfbddd8fc5d972ded58617f752b3e88bd17b791e85e7b8eaacb47,
0x11d25ff6aa8a431fbce8e8d9a87a2d7986adf38e724fbe47f15752d0931f14d8,
0x01e8677aa02546bd7105a7a9fd31c4ef16b69d1bde90f36e97585d7cc31d50e4,
0x2520a755a532994c78f35b89938fbc864ec31ec4fc00363f83f9b12f04980c6a,
0x21a666842842d5323e51fdda10300c763d6b07e1b797ef3b0bd3690d667445bc,
0x1ce681d6f42b70668c369e7f786166e421dc840f0529bbd065d6b02d14ae0fe8,
0x1819b90a43ee28f652735708b2ef01428e21b84872bb3c7576de6e35d107c8ed,
0x063d7001431110a5949f5946a501fd28f64159f36ab4b80601ca305ac107b3db,
0x09aeef7a06f7daf368d797c2e686c7e9884f000de0bd9d8e73392378b0b1be38,
0x137121fd5d795eeecc61ec6a6de66abc589d241540139178cd5408b6ccb32a6e,
0x01a93f70a1b7482e0b32e76ce49a1e3c1fc2b5cd4789b6af749d78c42791c21a,
0x217bf2cc1f1b505a29b162a7889866af2728f5c6708560c9cc5e987b194c9c81,
0x1461dae57d7df7e580279637e5d94e0d734b908dc22aec5c52ed00187050a030,
0x295933dd65294cbf4b2c64d8a0daa6983d35d1f64d5adc2c44bd9d370086d7dc,
0x24650084f0db0fa4e8234fb251ad046b3ddcb7d6f59160b35cc4086e9e196b80,
0x15086d0394bd68847e3e36241cc7b3966f96efdd30a37e9e1e85027a6dacbed2,
0x1f87a17564f06581c1e1b2d716120990f898893ecc0e076363c56c5e3b56ef7b
];
global zero_root: Field = 0x06f93f503e77fcdcacfe622e66adc639b63e8c0083f5cab5d71d461aa4562c92;
#[export]
fn keccak_tx_with_deposit(
current_root: Field,
deposit_amount: Field,
withdrawals: [Field; 16],
utxo_spendable: [structs::UTXO_Spendable; 16],
utxo_new: [structs::UTXO_New; 16],
contract_only_inputs: structs::ContractOnlyInputs
) -> Field {
let withdrawal_amount: Field = withdrawals.reduce(|a,b| a + b);
let mut commitment_in: [Field; 16] = [ZERO_VALUE; 16];
let mut commitment_out: [Field; 16] = [ZERO_VALUE; 16];
let mut utxo_root: Field = 0;
let empty_utxo = structs::UTXO {owner: 0, amount: ZERO_VALUE, asset_type: 0};
let mut utxo_out: [structs::UTXO; 16] = [empty_utxo; 16];
let mut secrets: [Field; 16] = [0; 16];
let mut oracle: [Field; 16] = [ZERO_VALUE; 16];
let mut old_root_proof: [Field; 16] = [0; 16];
let mut utxo_in: [structs::UTXO; 16] = [empty_utxo; 16];
let mut nullifier_hashes: [Field; 16] = [ZERO_VALUE; 16];
let empty_merkle_proofs = structs::MerkleProof {
path_utxo: [0; utxo_depth],
path_tx: [0; batch_depth],
path_historic: [0; state_depth],
index_utxo: 0,
index_tx: 0,
index_historic: 0
};
let mut merkle_proofs: [structs::MerkleProof; 16] = [empty_merkle_proofs; 16];
for i in 0..16 {
if (utxo_spendable[i].amount != ZERO_VALUE) {
utxo_in[i] = structs::UTXO {owner: utxo_spendable[i].owner(), amount: utxo_spendable[i].amount, asset_type: utxo_spendable[i].asset_type};
secrets[i] = utxo_spendable[i].secret;
nullifier_hashes[i] = utxo_spendable[i].nullifier_hash();
commitment_in[i] = utxo_spendable[i].to_commitment();
if (utxo_spendable[i].spend_in_same_batch == false) {
commitment_in[i] = ZERO_VALUE;
old_root_proof[i] = utxo_spendable[i].old_root_proof;
merkle_proofs[i] = utxo_spendable[i].merkle_proof;
}
}
if (utxo_new[i].secret != 0) {
commitment_out[i] = utxo_new[i].to_commitment();
utxo_out[i] = structs::UTXO { owner: utxo_new[i].owner(), amount: utxo_new[i].amount, asset_type: utxo_new[i].asset_type };
}
}
utxo_root = hash::hash_tree_four(commitment_out);
let public_inputs = structs::PublicInputs {
current_root: current_root,
utxo_root: utxo_root,
deposit_amount: deposit_amount,
withdrawals: withdrawal_amount,
commitment_in: commitment_in,
commitment_out: commitment_out,
nullifier_hashes: nullifier_hashes,
contract_only_inputs: contract_only_inputs.as_keccak()
};
public_inputs.as_keccak()
}
#[export]
fn keccak_tx_no_deposit(
current_root: Field,
deposit_amount: Field,
withdrawals: [Field; 16],
utxo_spendable: [structs::UTXO_Spendable; 16],
utxo_new: [structs::UTXO_New; 16],
contract_only_inputs: structs::ContractOnlyInputs
) -> Field {
let withdrawal_amount: Field = withdrawals.reduce(|a,b| a + b);
let mut commitment_in: [Field; 16] = [ZERO_VALUE; 16];
let mut commitment_out: [Field; 16] = [ZERO_VALUE; 16];
let mut utxo_root: Field = 0;
let empty_utxo = structs::UTXO {owner: 0, amount: ZERO_VALUE, asset_type: 0};
let mut utxo_out: [structs::UTXO; 16] = [empty_utxo; 16];
let mut secrets: [Field; 16] = [0; 16];
let mut oracle: [Field; 16] = [ZERO_VALUE; 16];
let mut old_root_proof: [Field; 16] = [0; 16];
let mut utxo_in: [structs::UTXO; 16] = [empty_utxo; 16];
let mut nullifier_hashes: [Field; 16] = [ZERO_VALUE; 16];
let empty_merkle_proofs = structs::MerkleProof {
path_utxo: [0; utxo_depth],
path_tx: [0; batch_depth],
path_historic: [0; state_depth],
index_utxo: 0,
index_tx: 0,
index_historic: 0
};
let mut merkle_proofs: [structs::MerkleProof; 16] = [empty_merkle_proofs; 16];
for i in 0..16 {
if (utxo_spendable[i].amount != ZERO_VALUE) {
utxo_in[i] = structs::UTXO {owner: utxo_spendable[i].owner(), amount: utxo_spendable[i].amount, asset_type: utxo_spendable[i].asset_type};
secrets[i] = utxo_spendable[i].secret;
nullifier_hashes[i] = utxo_spendable[i].nullifier_hash();
commitment_in[i] = utxo_spendable[i].to_commitment();
if (utxo_spendable[i].spend_in_same_batch == false) {
commitment_in[i] = ZERO_VALUE;
old_root_proof[i] = utxo_spendable[i].old_root_proof;
merkle_proofs[i] = utxo_spendable[i].merkle_proof;
}
}
if (utxo_new[i].secret != 0) {
commitment_out[i] = utxo_new[i].to_commitment();
utxo_out[i] = structs::UTXO { owner: utxo_new[i].owner(), amount: utxo_new[i].amount, asset_type: utxo_new[i].asset_type };
}
}
utxo_root = hash::hash_tree_four(commitment_out);
let public_inputs = structs::PublicInputs {
current_root: current_root,
utxo_root: utxo_root,
deposit_amount: deposit_amount,
withdrawals: withdrawal_amount,
commitment_in: commitment_in,
commitment_out: commitment_out,
nullifier_hashes: nullifier_hashes,
contract_only_inputs: contract_only_inputs.as_keccak_without_deposit()
};
public_inputs.as_keccak()
}
#[export]
fn create_transaction(
current_root: Field,
deposit_amount: Field,
withdrawals: [Field; 16],
utxo_spendable: [structs::UTXO_Spendable; 16],
utxo_new: [structs::UTXO_New; 16],
contract_only_inputs: structs::ContractOnlyInputs
) -> pub structs::TransactionInputs {
let withdrawal_amount: Field = withdrawals.reduce(|a,b| a + b);
let mut commitment_in: [Field; 16] = [ZERO_VALUE; 16];
let mut commitment_out: [Field; 16] = [ZERO_VALUE; 16];
let mut utxo_root: Field = 0;
let empty_utxo = structs::UTXO {owner: 0, amount: ZERO_VALUE, asset_type: 0};
let mut utxo_out: [structs::UTXO; 16] = [empty_utxo; 16];
let mut secrets: [Field; 16] = [0; 16];
let mut oracle: [Field; 16] = [ZERO_VALUE; 16];
let mut old_root_proof: [Field; 16] = [0; 16];
let mut utxo_in: [structs::UTXO; 16] = [empty_utxo; 16];
let mut nullifier_hashes: [Field; 16] = [ZERO_VALUE; 16];
let empty_merkle_proofs = structs::MerkleProof {
path_utxo: [0; utxo_depth],
path_tx: [0; batch_depth],
path_historic: [0; state_depth],
index_utxo: 0,
index_tx: 0,
index_historic: 0
};
let mut merkle_proofs: [structs::MerkleProof; 16] = [empty_merkle_proofs; 16];
for i in 0..16 {
if (utxo_spendable[i].amount != ZERO_VALUE) {
utxo_in[i] = structs::UTXO {owner: utxo_spendable[i].owner(), amount: utxo_spendable[i].amount, asset_type: utxo_spendable[i].asset_type};
secrets[i] = utxo_spendable[i].secret;
nullifier_hashes[i] = utxo_spendable[i].nullifier_hash();
commitment_in[i] = utxo_spendable[i].to_commitment();
if (utxo_spendable[i].spend_in_same_batch == false) {
commitment_in[i] = ZERO_VALUE;
old_root_proof[i] = utxo_spendable[i].old_root_proof;
merkle_proofs[i] = utxo_spendable[i].merkle_proof;
}
}
if (utxo_new[i].secret != 0) {
commitment_out[i] = utxo_new[i].to_commitment();
utxo_out[i] = structs::UTXO { owner: utxo_new[i].owner(), amount: utxo_new[i].amount, asset_type: utxo_new[i].asset_type };
}
}
utxo_root = hash::hash_tree_four(commitment_out);
let public_inputs = structs::PublicInputs {
current_root: current_root,
utxo_root: utxo_root,
deposit_amount: deposit_amount,
withdrawals: withdrawal_amount,
commitment_in: commitment_in,
commitment_out: commitment_out,
nullifier_hashes: nullifier_hashes,
contract_only_inputs: contract_only_inputs.as_keccak()
};
let private_inputs = structs::PrivateInputs {
oracle: oracle,
old_root_proof: old_root_proof,
secrets: secrets,
utxo_in: utxo_in,
merkle_proofs: merkle_proofs,
utxo_out: utxo_out
};
let public_inputs_hash: Field = hash::hash_tx(public_inputs);
let transaction_inputs = structs::TransactionInputs {
public_inputs_hash: public_inputs_hash,
public_inputs: public_inputs,
private_inputs: private_inputs
};
transaction_inputs
}
#[export]
fn tx_as_hash(
tx: structs::PublicInputs
) -> Field {
tx.as_hash()
}
#[export]
fn rollup_transaction(
tx_verifier: structs::VerifierTx,
recursion_verifier: structs::Verifier,
previous_accumulator: Field,
tx: structs::PublicInputs
) -> pub structs::RecursionInputs {
let tx_as_keccak: Field = tx.as_keccak();
let mut accumulator_preimage: [u8; 128] = [0; 128];
for i in 0..32 {
accumulator_preimage[i] = hash::field_to_u8(previous_accumulator)[i];
accumulator_preimage[i + 32] = hash::field_to_u8(tx_as_keccak)[i];
accumulator_preimage[i + 64] = hash::field_to_u8(tx_verifier.key_hash)[i];
accumulator_preimage[i + 96] = hash::field_to_u8(recursion_verifier.key_hash)[i];
}
let accumulator: Field = hash::hash_to_field(std::hash::keccak256(accumulator_preimage, accumulator_preimage.len() as u32));
let recursion_inputs = structs::RecursionInputs {
accumulator: accumulator,
tx_verifier: tx_verifier,
recursion_verifier: recursion_verifier,
previous_accumulator: previous_accumulator,
tx: tx
};
recursion_inputs
}
#[export]
fn publish_batch(
accumulator: Field,
hist_tree_input: structs::HistoricTreeInput,
tx_verifier: structs::VerifierTx,
recursion_verifier: structs::Verifier
) -> pub structs::PublishInputs {
let old_state_root: Field = hist_tree_input.leaf;
let tx_root: Field = hash::hash_tree_four(hist_tree_input.utxo_roots);
let batch_oracle: Field = ZERO_VALUE;
let batch_root: Field = hash::hash([tx_root, batch_oracle]);
let new_state_root: Field = hash::hash([batch_root, old_state_root]);
let new_historic_path: [Field; state_depth] = hash::compute_sibling_path(
hist_tree_input.path,
hist_tree_input.leaf,
hist_tree_input.index
);
let new_historic_root: Field = hash::compute_merkle_root(
new_state_root,
hist_tree_input.index + 1,
new_historic_path
);
let hist_tree = structs::HistoricTree {
root: hist_tree_input.root,
new_root: new_historic_root,
leaf: hist_tree_input.leaf,
index: hist_tree_input.index,
old_path: hist_tree_input.path,
new_path: new_historic_path
};
let batch = structs::Batch {
hist_tree: hist_tree,
old_state_root: old_state_root,
new_state_root: new_state_root,
batch_oracle: batch_oracle,
utxo_roots: hist_tree_input.utxo_roots
};
let mut hash_validation: [u8; 832] = [0; 832];
for i in 0..32 {
hash_validation[i] = hash::field_to_u8(batch.new_state_root)[i];
hash_validation[i + 32] = hash::field_to_u8(batch.hist_tree.root)[i];
hash_validation[i + 64] = hash::field_to_u8(batch.hist_tree.new_root)[i];
hash_validation[i + 96] = hash::field_to_u8(accumulator)[i];
hash_validation[i + 128] = hash::field_to_u8(tx_verifier.key_hash)[i];
hash_validation[i + 160] = hash::field_to_u8(recursion_verifier.key_hash)[i];
for j in 0..20 {
hash_validation[i + 192 + (32 * j)] = hash::field_to_u8(batch.hist_tree.new_path[j])[i];
}
}
let pi_contract_hash: Field = hash::hash_to_field(std::hash::keccak256(hash_validation, hash_validation.len() as u32));
let publish_inputs = structs::PublishInputs {
pi_contract_hash: pi_contract_hash,
accumulator: accumulator,
batch: batch,
tx_verifier: tx_verifier,
recursion_verifier: recursion_verifier
};
publish_inputs
}
\ No newline at end of file
use crate::hash;
global utxo_depth = 4;
global batch_depth = 4;
global state_depth = 20;
global ZERO_VALUE = 0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720;
// Levels of an empty pedersen Merkle tree with zero_leaf = sha256("Momiji") % Field Modulus
global zero_hashes: [Field; 20] = [
0x016a430aa58685aba1311244a973a3bc358859da86784be51094368e8fb6f720,
0x018d39625c19fa2cfbebdb940a66d7040bb0ef1b59ff6afd92a13a6b9b2d9865,
0x096c00ebc0c52478316b6b9fd16d0cd94c5f45bbe45bbfa8c606197c6119d41f,
0x2eaefd3bdd1bfbddd8fc5d972ded58617f752b3e88bd17b791e85e7b8eaacb47,
0x11d25ff6aa8a431fbce8e8d9a87a2d7986adf38e724fbe47f15752d0931f14d8,
0x01e8677aa02546bd7105a7a9fd31c4ef16b69d1bde90f36e97585d7cc31d50e4,
0x2520a755a532994c78f35b89938fbc864ec31ec4fc00363f83f9b12f04980c6a,
0x21a666842842d5323e51fdda10300c763d6b07e1b797ef3b0bd3690d667445bc,
0x1ce681d6f42b70668c369e7f786166e421dc840f0529bbd065d6b02d14ae0fe8,
0x1819b90a43ee28f652735708b2ef01428e21b84872bb3c7576de6e35d107c8ed,
0x063d7001431110a5949f5946a501fd28f64159f36ab4b80601ca305ac107b3db,
0x09aeef7a06f7daf368d797c2e686c7e9884f000de0bd9d8e73392378b0b1be38,
0x137121fd5d795eeecc61ec6a6de66abc589d241540139178cd5408b6ccb32a6e,
0x01a93f70a1b7482e0b32e76ce49a1e3c1fc2b5cd4789b6af749d78c42791c21a,
0x217bf2cc1f1b505a29b162a7889866af2728f5c6708560c9cc5e987b194c9c81,
0x1461dae57d7df7e580279637e5d94e0d734b908dc22aec5c52ed00187050a030,
0x295933dd65294cbf4b2c64d8a0daa6983d35d1f64d5adc2c44bd9d370086d7dc,
0x24650084f0db0fa4e8234fb251ad046b3ddcb7d6f59160b35cc4086e9e196b80,
0x15086d0394bd68847e3e36241cc7b3966f96efdd30a37e9e1e85027a6dacbed2,
0x1f87a17564f06581c1e1b2d716120990f898893ecc0e076363c56c5e3b56ef7b
];
// sha256("Momiji") % Field Modulus
global zero_root: Field = 0x06f93f503e77fcdcacfe622e66adc639b63e8c0083f5cab5d71d461aa4562c92;
struct Verifier {
key_hash: Field,
verification_key: [Field; 114],
proof: [Field; 109],
aggregation_object: [Field; 16]
}
struct VerifierTx {
key_hash: Field,
verification_key: [Field; 114],
proof: [Field; 93]
}
impl Verifier {
fn as_fields(self) -> [Field; 208] {
let mut verifier_as_fields: [Field; 208] = [0; 208];
verifier_as_fields[0] = self.key_hash;
for i in 0..114 {
verifier_as_fields[i + 1] = self.verification_key[i];
}
for j in 0..93 {
verifier_as_fields[j + 115] = self.proof[j];
}
verifier_as_fields
}
fn concatenate(self) -> [Field; 109] {
let mut proof_with_agg: [Field; 109] = [0; 109];
for i in 0..16 {
proof_with_agg[i] = self.aggregation_object[i];
}
for j in 0..93 {
proof_with_agg[j + 16] = self.proof[j];
}
proof_with_agg
}
}
struct UTXO {
owner: Field,
amount: Field,
asset_type: Field
}
struct UTXO_New {
secret: Field,
amount: Field,
asset_type: Field
}
impl UTXO_New {
fn owner(self) -> Field {
hash::hash([self.secret])
}
fn nullifier_hash(self) -> Field {
hash::hash([self.secret, self.secret])
}
fn to_commitment(self) -> Field {
hash::hash([self.owner(), self.amount, self.asset_type])
}
}
struct UTXO_Spendable {
secret: Field,
amount: Field,
asset_type: Field,
oracle: Field,
old_root_proof: Field,
merkle_proof: MerkleProof,
spend_in_same_batch: bool
}
impl UTXO_Spendable {
fn owner(self) -> Field {
hash::hash([self.secret])
}
fn nullifier_hash(self) -> Field {
hash::hash([self.secret, self.secret])
}
fn to_commitment(self) -> Field {
hash::hash([self.owner(), self.amount, self.asset_type])
}
}
struct PublicInputs {
current_root: Field,
utxo_root: Field,
deposit_amount: Field,
withdrawals: Field,
commitment_in: [Field; 16],
commitment_out: [Field; 16],
nullifier_hashes: [Field; 16],
contract_only_inputs: Field
}
impl PublicInputs {
fn as_fields(self) -> [Field; 53] {
let mut public_fields: [Field; 53] = [0; 53];
public_fields[0] = self.current_root;
public_fields[1] = self.utxo_root;
public_fields[2] = self.deposit_amount;
public_fields[3] = self.withdrawals;
for i in 0..16 {
public_fields[4 + i] = self.commitment_in[i];
public_fields[20 + i] = self.commitment_out[i];
public_fields[36 + i] = self.nullifier_hashes[i];
}
public_fields[50] = self.contract_only_inputs;
public_fields
}
fn as_hash(self) -> Field {
hash::hash_tx(self)
}
fn as_keccak(self) -> Field {
hash::keccak_tx(self)
}
fn as_u8(self) -> [u8; 1696] {
hash::tx_to_u8(self.as_fields())
}
}
struct PrivateInputs {
oracle: [Field; 16],
old_root_proof: [Field; 16],
secrets: [Field; 16],
utxo_in: [UTXO; 16],
merkle_proofs: [MerkleProof; 16],
utxo_out: [UTXO; 16],
}
struct TransactionInputs {
public_inputs_hash: Field,
public_inputs: PublicInputs,
private_inputs: PrivateInputs
}
struct RecursionInputs {
accumulator: Field,
tx_verifier: VerifierTx,
recursion_verifier: Verifier,
previous_accumulator: Field,
tx: PublicInputs
}
struct PublishInputs {
pi_contract_hash: Field,
accumulator: Field,
batch: Batch,
tx_verifier: VerifierTx,
recursion_verifier: Verifier
}
struct Batch {
hist_tree: HistoricTree,
old_state_root: Field,
new_state_root: Field,
batch_oracle: Field,
utxo_roots: [Field; 16]
}
struct EncryptedUTXO {
secret: Field,
amount: Field,
data: Field
}
struct ContractOnlyInputs {
timestamp: Field,
deadline: Field,
signature_hash: Field,
price_limit: Field,
recipients: [Field; 16],
swap_amounts: [Field; 16],
uids: [Field; 16],
encrypted_utxo: [EncryptedUTXO; 16]
}
impl ContractOnlyInputs {
fn as_keccak_without_deposit(self) -> Field {
hash::keccak_contract_only_inputs_without_deposit(self)
}
fn as_keccak(self) -> Field {
hash::keccak_contract_only_inputs(self)
}
}
struct MerkleProof {
path_utxo: [Field; utxo_depth],
path_tx: [Field; batch_depth],
path_historic: [Field; state_depth],
index_utxo: Field,
index_tx: Field,
index_historic: Field
}
struct HistoricTree {
root: Field,
new_root: Field,
leaf: Field,
index: Field,
old_path: [Field; state_depth],
new_path: [Field; state_depth],
}
struct HistoricTreeInput {
root: Field,
leaf: Field,
index: Field,
path: [Field; state_depth],
utxo_roots: [Field; 16],
}
\ No newline at end of file
[package]
name = "publish"
type = "bin"
authors = [""]
compiler_version = ">=0.19.2"
[dependencies]
helpers = { path = "../helpers" }
\ No newline at end of file
This diff is collapsed.
0x
\ No newline at end of file
use dep::std;
use dep::helpers;
use dep::helpers::hash;
use dep::helpers::structs;
fn main(
pi_contract_hash: pub Field,
accumulator: Field,
batch: structs::Batch,
tx_verifier: structs::VerifierTx,
recursion_verifier: structs::Verifier
) {
let tx_root_calc: Field = hash::hash_tree_four(batch.utxo_roots);
assert(batch.batch_oracle == helpers::ZERO_VALUE);
let batch_root_calc: Field = hash::hash([tx_root_calc, batch.batch_oracle]);
let new_root_calc: Field = hash::hash([batch_root_calc, batch.old_state_root]);
let new_path_calc: [Field; 20] = hash::compute_sibling_path(
batch.hist_tree.old_path,
batch.hist_tree.leaf,
batch.hist_tree.index
);
assert(batch.new_state_root == new_root_calc);
let calc_hist_root = hash::compute_merkle_root(
batch.hist_tree.leaf,
batch.hist_tree.index,
batch.hist_tree.old_path
);
assert(calc_hist_root == batch.hist_tree.root);
let hist_root_calc = hash::compute_merkle_root(
new_root_calc,
batch.hist_tree.index + 1,
new_path_calc
);
assert(hist_root_calc == batch.hist_tree.new_root);
let mut hash_validation: [u8; 832] = [0; 832];
for i in 0..32 {
hash_validation[i] = hash::field_to_u8(batch.new_state_root)[i];
hash_validation[i + 32] = hash::field_to_u8(batch.hist_tree.root)[i];
hash_validation[i + 64] = hash::field_to_u8(batch.hist_tree.new_root)[i];
hash_validation[i + 96] = hash::field_to_u8(accumulator)[i];
hash_validation[i + 128] = hash::field_to_u8(tx_verifier.key_hash)[i];
hash_validation[i + 160] = hash::field_to_u8(recursion_verifier.key_hash)[i];
for j in 0..20 {
hash_validation[i + 192 + (32 * j)] = hash::field_to_u8(new_path_calc[j])[i];
}
}
let hash_generated: Field = hash::hash_to_field(std::hash::keccak256(hash_validation, hash_validation.len() as u32));
assert(pi_contract_hash == hash_generated);
std::verify_proof(
recursion_verifier.verification_key.as_slice(),
recursion_verifier.proof.as_slice(),
[accumulator].as_slice(),
recursion_verifier.key_hash
)
}
\ No newline at end of file
[package]
name = "recursion"
type = "bin"
authors = [""]
compiler_version = ">=0.19.2"
[dependencies]
helpers = { path = "../helpers" }
use dep::std;
use dep::helpers;
use dep::helpers::structs;
use dep::helpers::hash;
#[recursive]
fn main(
accumulator: pub Field,
tx_verifier: structs::VerifierTx,
recursion_verifier: structs::Verifier,
previous_accumulator: Field,
tx: structs::PublicInputs
) {
let tx_as_keccak = tx.as_keccak();
let mut generated_accumulator_preimage: [u8; 128] = [0; 128];
for i in 0..32 {
generated_accumulator_preimage[i] = hash::field_to_u8(previous_accumulator)[i];
generated_accumulator_preimage[i + 32] = hash::field_to_u8(tx_as_keccak)[i];
generated_accumulator_preimage[i + 64] = hash::field_to_u8(tx_verifier.key_hash)[i];
generated_accumulator_preimage[i + 96] = hash::field_to_u8(recursion_verifier.key_hash)[i];
}
let generated_accumulator = hash::hash_to_field(std::hash::keccak256(generated_accumulator_preimage, generated_accumulator_preimage.len() as u32));
assert(accumulator == generated_accumulator);
let mut recursion_pi: Field = previous_accumulator;
let mut recursive_proof: [Field] = recursion_verifier.proof.as_slice();
if (previous_accumulator == helpers::ZERO_VALUE) {
assert(recursion_verifier.key_hash == 0x083764da4a71646a7c2d27cf8f17adc4f9e4f3d2c5a574b643f79864c280b4ce);
recursion_pi = tx.as_hash();
}
std::verify_proof(
recursion_verifier.verification_key.as_slice(),
recursive_proof,
[recursion_pi].as_slice(),
recursion_verifier.key_hash
);
std::verify_proof(
tx_verifier.verification_key.as_slice(),
tx_verifier.proof.as_slice(),
[tx.as_hash()].as_slice(),
tx_verifier.key_hash
);
}
\ No newline at end of file
File added
File added
["0x1727d9cce8edf8b1d7228edf940be5ab221dc023f0e21785e634f5dcf9718007","0x26125da10a0ed06327508aba06d1e303ac616632dbed349f53422da953337857","0x0000000000000000000000000000000000000000000000000000000000100000","0x0000000000000000000000000000000000000000000000000000000000000005","0x0000000000000000000000000000000000000000000000000000000000100000","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000003","0x0000000000000000000000000000000000000000000000000000000000000004","0x0000000000000000000000000000000000000000000000000000000000000005","0x0000000000000000000000000000000000000000000000000000000000000006","0x0000000000000000000000000000000000000000000000000000000000000007","0x0000000000000000000000000000000000000000000000000000000000000008","0x0000000000000000000000000000000000000000000000000000000000000009","0x000000000000000000000000000000000000000000000000000000000000000a","0x000000000000000000000000000000000000000000000000000000000000000b","0x000000000000000000000000000000000000000000000000000000000000000c","0x000000000000000000000000000000000000000000000000000000000000000d","0x000000000000000000000000000000000000000000000000000000000000000e","0x000000000000000000000000000000000000000000000000000000000000000f","0x0000000000000000000000000000000000000000000000000000000000000010","0x0000000000000000000000000000001ed8a02482426d263a4ecb0ef896ce89aa","0x00000000000000000000000000000000002dd82b96a445a3d48db46e78fd1fe5","0x0000000000000000000000000000001a810690ec0eb9e6cb49dd68aed57b9a2c","0x00000000000000000000000000000000002979d0f3b9cbc56e6a5eed0176979c","0x000000000000000000000000000000ece4843dd3e3cb41a29ffcc72d49376ac5","0x000000000000000000000000000000000013f586937d9e92ad01910eaf7267fe","0x000000000000000000000000000000832de083f2aea887e5b0b3e07195bf3369","0x0000000000000000000000000000000000020d7d6640cc6909b63450357223cd","0x0000000000000000000000000000001a1e30f8051c1e84c165acf80086e8dfca","0x00000000000000000000000000000000002c77a04e17e8644f9b7053b4bb08fa","0x000000000000000000000000000000accbe6a903bb7bfaf1909074da32f28e74","0x000000000000000000000000000000000010ef1c64b5aa796d3218d20cfdb0a4","0x000000000000000000000000000000cbc1cc027a33d219526471449d9049146a","0x00000000000000000000000000000000000735dd552cfe8a4cf17f17049626d0","0x000000000000000000000000000000f3576e636ff3ebaff43f0d1c8294b67a8c","0x00000000000000000000000000000000001bb99e027a879809200c2f3e9992da","0x00000000000000000000000000000004f1b4950d8b0919092c8b596a63e9396e","0x00000000000000000000000000000000001e031462c21a2937998d8ab726051a","0x000000000000000000000000000000618474ad492a93435a82a433a1ae1b5c04","0x00000000000000000000000000000000001beb3c3937fc9ff20499d59cc4665e","0x000000000000000000000000000000053a4799f326db1157b41ba75481ac65ce","0x00000000000000000000000000000000002a6cafad02233a289b5ee0dac52d24","0x00000000000000000000000000000029b0e33ec90e9b6e7c0c774b2a394f5c90","0x00000000000000000000000000000000000ff63c1bf54473c34651e117d63bbb","0x000000000000000000000000000000a0098ac613ba3629b0421d7894f0bc65d8","0x00000000000000000000000000000000001f58e2dbf833ed8c21a5ac822a390e","0x000000000000000000000000000000ad30140ddc344a8ac7a49d29b0b600d888","0x000000000000000000000000000000000000b0088164d522367583c90f73bcd7","0x0000000000000000000000000000004a05d497f585103d826b8a133761cc79ef","0x000000000000000000000000000000000011888c79e6b006e1a7d293898b9842","0x00000000000000000000000000000039b41a3dfe9e948d33fd4a759e9e8a7b30","0x00000000000000000000000000000000000427be5203eb43e160d9635925f64a","0x000000000000000000000000000000c0b125470d496d55ec3d8678b1efcc0b14","0x00000000000000000000000000000000000a346d061bfa2ad56a322a81a8be06","0x000000000000000000000000000000e36f8d9132dccbddbcbc4eca6bdb70583a","0x000000000000000000000000000000000006e53484e1a4f26129c00c5afdf4d4","0x000000000000000000000000000000d56ff07f6c8d054cf78d713a5f4399313b","0x000000000000000000000000000000000009fa75fa397a889177953777b32ad7","0x000000000000000000000000000000a9eba193f17a0cbcfd5cd786e8fc93e044","0x0000000000000000000000000000000000231e1180c41ca9fcad8207beb4aeb2","0x000000000000000000000000000000439f7eb6e39f8ef36735fde1563efc018c","0x0000000000000000000000000000000000131bb8b31246156eac5a9632b1c44c","0x000000000000000000000000000000ff14d910386a5d634a00deb8432bd230bd","0x0000000000000000000000000000000000032cf0e4f77b2c32b39804b2e836a1","0x00000000000000000000000000000059d45db08da921eb51ee629b37eaac3804","0x00000000000000000000000000000000001351c4d6ee97e5a13968cd8b575376","0x000000000000000000000000000000a1fef20a9e9baae03c66b387855786961c","0x00000000000000000000000000000000000087e919ca347c14bae58f2a007979","0x00000000000000000000000000000068c2dee24bf49f48ca91a9b31cf489100a","0x00000000000000000000000000000000002ebbec213fd5e638e763bf574db1dd","0x000000000000000000000000000000405686bb9661ab548fc6490de8273991c1","0x00000000000000000000000000000000000f55573e8cc6debc7e4ad36f55f0a3","0x00000000000000000000000000000016c8911d3abcc99956cfafd2469e57d352","0x000000000000000000000000000000000023987c17049de9e6e90534922b068d","0x000000000000000000000000000000310a00459798915e70bb5f6c0d93950c61","0x0000000000000000000000000000000000190404b6761da87bbb58c68adf9c07","0x0000000000000000000000000000007003780317cc6fecafa2529793ea4d856a","0x00000000000000000000000000000000000c49e1acc2e2a5ed2523a68e13bcc7","0x0000000000000000000000000000004564d9adecd904030f441c500bea3a54e8","0x0000000000000000000000000000000000118e887dc7827a303ae4efd884289f","0x00000000000000000000000000000055bcb8484f4bfca2d81c1a7a08f92dcc1e","0x0000000000000000000000000000000000192d66138ef5fb5cbd60d25910fa8b","0x0000000000000000000000000000006ce36390303806bf1667cac7fd3a0a911f","0x000000000000000000000000000000000025719fd7b4f27bd77387d4580c46ef","0x000000000000000000000000000000e15e5e8edb26147b877fd483a9be1ee557","0x00000000000000000000000000000000000d4744317ff703c20132134b9af145","0x00000000000000000000000000000097931bbb683b832edaedfb84ae020a3e6c","0x000000000000000000000000000000000024e913db937478f592ff958369c33b","0x000000000000000000000000000000aad0edb65a7896339ad92cb7bdda5bc0cb","0x00000000000000000000000000000000001f13f1759e514b1f053da73837b9bf","0x000000000000000000000000000000b5928facba6909a6cb9d3f99b451dbb0da","0x0000000000000000000000000000000000140e3a61cbd87e23e9f59c0c8a5f92","0x0000000000000000000000000000000c542c4e643211a206a43e3c82940ce012","0x0000000000000000000000000000000000073ab903217225282916b264ffbd6f","0x000000000000000000000000000000362a93230a711f6dff86b1a347c978b220","0x00000000000000000000000000000000001a14bd51e9dc0b4b973e46910d2b6f","0x000000000000000000000000000000e13a606550f2c61830bf9da814621581ee","0x00000000000000000000000000000000001297f1e111cc1ea7a2221affb5eecd","0x00000000000000000000000000000000aa60b3f6dc00be97871878c40d04a293","0x000000000000000000000000000000000007f762063f0123fba74c4cd66e7559","0x000000000000000000000000000000541c1db7e3c80a294ea50b24011999fe4e","0x00000000000000000000000000000000002e238e496f9533c8fe3a9342fcf1f6","0x000000000000000000000000000000f65f2ad1025c0ec713b29b2db4c57e83d6","0x000000000000000000000000000000000013ff20a10295d07fd0b16253a6775a","0x00000000000000000000000000000026d344ed7a87caa6087967171876052349","0x00000000000000000000000000000000002626bea2de7026dd6dd4e1df614a65","0x000000000000000000000000000000b264d3a3a6bb7a41d57f96e6877e5bb37d","0x0000000000000000000000000000000000275f1c996d71439acf76f03932c52c","0x000000000000000000000000000000c8b2af388b1f0b0832ca8f2a0154be54ce","0x00000000000000000000000000000000003020cfd271da8c447e2ccff6908c3a","0x00000000000000000000000000000008e8f770eef342595ebce4b42811af4966","0x000000000000000000000000000000000002ae8005a2c1cc97d4cdc896b54e70"]
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment