diff --git a/backend/Cargo.toml b/backend/Cargo.toml index eec1ddec..11918d69 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3.28" num-bigint = "0.4.3" serde = { version = "1.0.166", features = ["derive"] } snark-verifier-sdk = { git = "https://github.com/privacy-scaling-explorations/snark-verifier", version = "0.1.1" } -ethers = { version = "2.0.7", default-features = false, features = ["ethers-solc"] } +ethers = { version = "2.0.7", default-features = false, features = ["ethers-solc","legacy"] } reqwest = { version = "0.11", features = ["json"] } serde_json = "1.0.64" tokio = { version = "1.7.1", features = ["full"] } @@ -21,4 +21,4 @@ base64 = "0.13" bincode = "1.3.3" [build-dependencies] -ethers = { version = "2.0.7", default-features = false, features = ["ethers-solc"] } +ethers = { version = "2.0.7", default-features = false, features = ["ethers-solc", "legacy"] } diff --git a/backend/README.md b/backend/README.md index 17511021..735a52f4 100644 --- a/backend/README.md +++ b/backend/README.md @@ -6,10 +6,11 @@ This directory contains the backend implementation for the Summa Proof of Solven ### Round -The `Round` component represents a specific period or cycle in the Summa Proof of Solvency protocol. It encapsulates the state of the system at a given time, including the snapshot of assets and liabilities, as well as the associated proofs. - The `Round` struct integrates with the `Snapshot` and `SummaSigner` to facilitate the generation and submission of proofs to the contract. +The `Round` component represents a specific period or cycle in the Summa Proof of Solvency protocol. It encapsulates the state of the system at a given time, including the snapshot of assets and liabilities, as well as the associated proofs. +The `Round` struct integrates with the `Snapshot` and `SummaSigner` to facilitate the generation and submission of proofs to the contract. Key Features: + - Initialization of a new round with specific parameters. - Building a snapshot of the current state. - Submitting commitment to the contract. @@ -20,6 +21,7 @@ Key Features: The `AddressOwnership` component is responsible for managing and verifying the ownership of addresses. It ensures that addresses used in the protocol owned by the respective participants. This component interacts with the `SummaSigner` to submit proofs of address ownership to on-chain. Key Features: + - Initialization with specific signer details. - Dispatching proofs of address ownership to the contract. @@ -49,8 +51,8 @@ cargo test --release -- --nocapture ### Generating and updating verifier contract for Backend The verifier contract in the backend were generated using a predefined set of parameters: `N_ASSETS = 2` and `N_BYTES=14`, as indicated [here](https://github.com/summa-dev/summa-solvency/blob/master/zk_prover/examples/gen_inclusion_verifier.rs#L21-L22). -If you intend to work with different parameters, you'll need to adjust these hard-coded values and then generate new verifier contract. - +If you intend to work with different parameters, you'll need to adjust these hard-coded values and then generate new verifier contract. + The process described below assists in both generating the verifier and updating the Summa contract, which integrates the new verifier as constructors. #### Using the Bash Script @@ -91,7 +93,6 @@ If executed successfully, you'll see: 1. Ownership proofs are submitted successfully! ``` - ### 2. Submit Commitment The CEX must submit a commitment to the Summa contract for each round. This commitment consists of a `timestamp`, the root hash of the Merkle Sum Tree (`mst_root`), and `balances`. @@ -101,11 +102,10 @@ Without publishing the commitment, users cannot verify their inclusion proof on In here, we'll introduce you through the process of submitting a commitment using the `Round` to the Summa contract. The Round serves as the core of the backend in Summa, and we have briefly described it in the Components section. -To initialize the `Round` instance, you'll need paths to specific CSV files (`assets.csv` and `entry_16.csv`) and the `ptau/hermez-raw-11` file. Here's what each file does: +To initialize the `Round` instance, you'll need paths to the liabilities CSV file (`entry_16.csv`) and the `ptau/hermez-raw-11` file. The files serve the following purpose: -- `assets.csv`: Calculates the total balance of assets for the solvency proof. Only the CEX can generate this file. -- `entry_16.csv`: Used to build the Merkle sum tree, with each leaf element derived from sixteen entries in the CSV. -- `ptau/hermez-raw-11`: Contains parameters for constructing the zk circuits. +- `entry_16.csv`: contains the username and liabilities entries for each CEX user (necessary to build the commitment). Liabilities column names have the following format: `balance__`, where and are the names of the cryptocurrencies and their corresponding blockchains. values are the same as in the Address Ownership Proof step; +- `ptau/hermez-raw-11`: contains parameters for constructing the zk circuits. Using the `Round` instance, the solvency proof is dispatched to the Summa contract with the `dispatch_solvency_proof` method. @@ -136,12 +136,13 @@ Users receive the proof for a specific round and use methods available on the de In this step, the user has to: - Ensure the `leaf_hash` (public input of the proof) aligns with the Poseidon hash of the `username` and `balances` provided by the CEX. -- Submit the proof to the `verify_inclusion_proof` method on the Summa contract Which will: - - Retrieve the `mstRoot` from the Summa contract and match it with the `root_hash` in the proof. - - Retrieve the `rootBalances` from the Summa contract and match it with the `root_balances` in the proof - - Verify the zk Proof +- Submit the proof to the `verify_inclusion_proof` method on the Summa contract Which will: + - Retrieve the `mstRoot` from the Summa contract and match it with the `root_hash` in the proof. + - Retrieve the `rootBalances` from the Summa contract and match it with the `root_balances` in the proof + - Verify the zk Proof The result will display as: + ``` 4. Verifying the proof on contract verifier for User #0: true ``` diff --git a/backend/examples/summa_solvency_flow.rs b/backend/examples/summa_solvency_flow.rs index 9fcb6595..92d17cae 100644 --- a/backend/examples/summa_solvency_flow.rs +++ b/backend/examples/summa_solvency_flow.rs @@ -57,20 +57,12 @@ async fn main() -> Result<(), Box> { // // Initialize the `Round` instance to submit the liability commitment. let params_path = "ptau/hermez-raw-11"; - let assets_csv_path = "src/apis/csv/assets.csv"; let entry_csv = "../zk_prover/src/merkle_sum_tree/csv/entry_16.csv"; let mst = MerkleSumTree::new(entry_csv).unwrap(); // Using the `round` instance, the commitment is dispatched to the Summa contract with the `dispatch_commitment` method. let timestamp = 1u64; - let mut round = Round::<4, 2, 14>::new( - &signer, - Box::new(mst), - assets_csv_path, - params_path, - timestamp, - ) - .unwrap(); + let mut round = Round::<4, 2, 14>::new(&signer, Box::new(mst), params_path, timestamp).unwrap(); // Sends the commitment, which should ideally complete without errors. round.dispatch_commitment().await?; diff --git a/backend/src/apis/csv/assets.csv b/backend/src/apis/csv/assets.csv deleted file mode 100644 index 0f3fc849..00000000 --- a/backend/src/apis/csv/assets.csv +++ /dev/null @@ -1,3 +0,0 @@ -chain;asset_name -ETH;ETH -ETH;USDT diff --git a/backend/src/apis/csv_parser.rs b/backend/src/apis/csv_parser.rs index ca2467cb..ff65681a 100644 --- a/backend/src/apis/csv_parser.rs +++ b/backend/src/apis/csv_parser.rs @@ -3,7 +3,7 @@ use std::{error::Error, fs::File, path::Path}; use ethers::{abi::AbiEncode, types::Bytes}; use serde::{Deserialize, Serialize}; -use crate::contracts::generated::summa_contract::{AddressOwnershipProof, Asset}; +use crate::contracts::generated::summa_contract::AddressOwnershipProof; #[derive(Debug, Deserialize, Serialize)] pub struct SignatureRecord { @@ -46,39 +46,6 @@ pub fn parse_signature_csv>( Ok(address_ownership_proofs) } -#[derive(Debug, Deserialize)] -struct AssetRecord { - chain: String, - asset_name: String, -} - -pub fn parse_asset_csv, const N_ASSETS: usize>( - path: P, -) -> Result<[Asset; N_ASSETS], Box> { - let file = File::open(path)?; - let mut rdr = csv::ReaderBuilder::new().delimiter(b';').from_reader(file); - - let mut assets_vec = Vec::with_capacity(N_ASSETS); - - for result in rdr.deserialize() { - let record: AssetRecord = result?; - - assets_vec.push(Asset { - asset_name: record.asset_name, - chain: record.chain, - }); - } - - let assets_array: [Asset; N_ASSETS] = assets_vec.try_into().map_err(|v: Vec| { - format!( - "The number of assets in CSV file does not match the expected count {:?}", - v - ) - })?; - - Ok(assets_array) -} - #[cfg(test)] mod tests { use super::*; @@ -98,25 +65,4 @@ mod tests { assert_eq!(address_ownership[0], first_address_ownership); } - - #[test] - fn test_parse_csv_to_assets() { - let path = "src/apis/csv/assets.csv"; - let assets = parse_asset_csv::<&str, 2>(path).unwrap(); - - assert_eq!( - assets[0], - Asset { - chain: "ETH".to_string(), - asset_name: "ETH".to_string(), - } - ); - assert_eq!( - assets[1], - Asset { - chain: "ETH".to_string(), - asset_name: "USDT".to_string(), - } - ); - } } diff --git a/backend/src/apis/round.rs b/backend/src/apis/round.rs index 926e647b..88e1c6e7 100644 --- a/backend/src/apis/round.rs +++ b/backend/src/apis/round.rs @@ -7,8 +7,7 @@ use halo2_proofs::{ use serde::{Deserialize, Serialize}; use std::error::Error; -use super::csv_parser::parse_asset_csv; -use crate::contracts::{generated::summa_contract::summa::Asset, signer::SummaSigner}; +use crate::contracts::{generated::summa_contract::summa::Cryptocurrency, signer::SummaSigner}; use summa_solvency::{ circuits::{ merkle_sum_tree::MstInclusionCircuit, @@ -40,8 +39,7 @@ impl MstInclusionProof { } pub struct Snapshot { - mst: Box>, - assets_state: [Asset; N_ASSETS], + pub mst: Box>, trusted_setup: SetupArtifacts, } @@ -60,14 +58,12 @@ where pub fn new<'a>( signer: &'a SummaSigner, mst: Box>, - asset_csv_path: &str, params_path: &str, timestamp: u64, ) -> Result, Box> { Ok(Round { timestamp, - snapshot: Snapshot::::new(mst, asset_csv_path, params_path) - .unwrap(), + snapshot: Snapshot::::new(mst, params_path).unwrap(), signer: &signer, }) } @@ -91,7 +87,18 @@ where .submit_commitment( mst_root, root_sums, - self.snapshot.assets_state.to_vec(), + self.snapshot + .mst + .cryptocurrencies() + .iter() + .map(|cryptocurrency| Cryptocurrency { + name: cryptocurrency.name.clone(), + chain: cryptocurrency.chain.clone(), + }) + .collect::>() + .as_slice() + .try_into() + .unwrap(), U256::from(self.get_timestamp()), ) .await?; @@ -118,11 +125,8 @@ where { pub fn new( mst: Box>, - asset_csv_path: &str, params_path: &str, ) -> Result, Box> { - let assets_state = parse_asset_csv::<&str, N_ASSETS>(asset_csv_path).unwrap(); - let mst_inclusion_circuit = MstInclusionCircuit::::init_empty(); // get k from ptau file name @@ -135,7 +139,6 @@ where Ok(Snapshot { mst, - assets_state, trusted_setup: mst_inclusion_setup_artifacts, }) } diff --git a/backend/src/contracts/abi/Summa.json b/backend/src/contracts/abi/Summa.json index 0104b223..ce7fffe1 100644 --- a/backend/src/contracts/abi/Summa.json +++ b/backend/src/contracts/abi/Summa.json @@ -1 +1 @@ -{"_format":"hh-sol-artifact-1","contractName":"Summa","sourceName":"src/Summa.sol","abi":[{"inputs":[{"internalType":"contract IVerifier","name":"_inclusionVerifier","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"components":[{"internalType":"string","name":"cexAddress","type":"string"},{"internalType":"string","name":"chain","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"indexed":false,"internalType":"struct Summa.AddressOwnershipProof[]","name":"addressOwnershipProofs","type":"tuple[]"}],"name":"AddressOwnershipProofSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mstRoot","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"rootBalances","type":"uint256[]"},{"components":[{"internalType":"string","name":"assetName","type":"string"},{"internalType":"string","name":"chain","type":"string"}],"indexed":false,"internalType":"struct Summa.Asset[]","name":"assets","type":"tuple[]"}],"name":"LiabilitiesCommitmentSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"addressOwnershipProofs","outputs":[{"internalType":"string","name":"cexAddress","type":"string"},{"internalType":"string","name":"chain","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"commitments","outputs":[{"internalType":"uint256","name":"mstRoot","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"addressHash","type":"bytes32"}],"name":"getAddressOwnershipProof","outputs":[{"components":[{"internalType":"string","name":"cexAddress","type":"string"},{"internalType":"string","name":"chain","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"internalType":"struct Summa.AddressOwnershipProof","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"mstRoot","type":"uint256"},{"internalType":"uint256[]","name":"rootBalances","type":"uint256[]"},{"components":[{"internalType":"string","name":"assetName","type":"string"},{"internalType":"string","name":"chain","type":"string"}],"internalType":"struct Summa.Asset[]","name":"assets","type":"tuple[]"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"submitCommitment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"cexAddress","type":"string"},{"internalType":"string","name":"chain","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"internalType":"struct Summa.AddressOwnershipProof[]","name":"_addressOwnershipProofs","type":"tuple[]"}],"name":"submitProofOfAddressOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"proof","type":"bytes"},{"internalType":"uint256[]","name":"publicInputs","type":"uint256[]"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"verifyInclusionProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"bytecode":"0x60a060405234801561001057600080fd5b5060405162001bd838038062001bd88339810160408190526100319161009b565b61003a3361004b565b6001600160a01b03166080526100cb565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100ad57600080fd5b81516001600160a01b03811681146100c457600080fd5b9392505050565b608051611af1620000e76000396000610b050152611af16000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063a3c4bcf811610066578063a3c4bcf814610114578063c7ddca0e14610137578063c8e581471461014a578063da64a7501461016d578063f2fde38b1461018057600080fd5b806319b339681461009857806349ce8997146100c1578063715018a6146100ef5780638da5cb5b146100f9575b600080fd5b6100ab6100a6366004611168565b610193565b6040516100b8919061123c565b60405180910390f35b6100e16100cf366004611168565b60036020526000908152604090205481565b6040519081526020016100b8565b6100f76104aa565b005b6000546040516001600160a01b0390911681526020016100b8565b610127610122366004611168565b6104be565b6040516100b89493929190611256565b6100f76101453660046113d5565b61071e565b61015d61015836600461159a565b6109bf565b60405190151581526020016100b8565b6100f761017b366004611607565b610b85565b6100f761018e36600461174e565b610f3c565b6101be6040518060800160405280606081526020016060815260200160608152602001606081525090565b6000828152600260205260409020546102155760405162461bcd60e51b81526020600482015260146024820152731059191c995cdcc81b9bdd081d995c9a599a595960621b60448201526064015b60405180910390fd5b60008281526002602052604090205460019061023290829061178d565b81548110610242576102426117a6565b906000526020600020906004020160405180608001604052908160008201805461026b906117bc565b80601f0160208091040260200160405190810160405280929190818152602001828054610297906117bc565b80156102e45780601f106102b9576101008083540402835291602001916102e4565b820191906000526020600020905b8154815290600101906020018083116102c757829003601f168201915b505050505081526020016001820180546102fd906117bc565b80601f0160208091040260200160405190810160405280929190818152602001828054610329906117bc565b80156103765780601f1061034b57610100808354040283529160200191610376565b820191906000526020600020905b81548152906001019060200180831161035957829003601f168201915b5050505050815260200160028201805461038f906117bc565b80601f01602080910402602001604051908101604052809291908181526020018280546103bb906117bc565b80156104085780601f106103dd57610100808354040283529160200191610408565b820191906000526020600020905b8154815290600101906020018083116103eb57829003601f168201915b50505050508152602001600382018054610421906117bc565b80601f016020809104026020016040519081016040528092919081815260200182805461044d906117bc565b801561049a5780601f1061046f5761010080835404028352916020019161049a565b820191906000526020600020905b81548152906001019060200180831161047d57829003601f168201915b5050505050815250509050919050565b6104b2610fb5565b6104bc600061100f565b565b600181815481106104ce57600080fd5b90600052602060002090600402016000915090508060000180546104f1906117bc565b80601f016020809104026020016040519081016040528092919081815260200182805461051d906117bc565b801561056a5780601f1061053f5761010080835404028352916020019161056a565b820191906000526020600020905b81548152906001019060200180831161054d57829003601f168201915b50505050509080600101805461057f906117bc565b80601f01602080910402602001604051908101604052809291908181526020018280546105ab906117bc565b80156105f85780601f106105cd576101008083540402835291602001916105f8565b820191906000526020600020905b8154815290600101906020018083116105db57829003601f168201915b50505050509080600201805461060d906117bc565b80601f0160208091040260200160405190810160405280929190818152602001828054610639906117bc565b80156106865780601f1061065b57610100808354040283529160200191610686565b820191906000526020600020905b81548152906001019060200180831161066957829003601f168201915b50505050509080600301805461069b906117bc565b80601f01602080910402602001604051908101604052809291908181526020018280546106c7906117bc565b80156107145780601f106106e957610100808354040283529160200191610714565b820191906000526020600020905b8154815290600101906020018083116106f757829003601f168201915b5050505050905084565b610726610fb5565b60005b8151811015610984576000828281518110610746576107466117a6565b60200260200101516000015160405160200161076291906117f6565b60408051601f1981840301815291815281516020928301206000818152600290935291205490915080156107d85760405162461bcd60e51b815260206004820152601860248201527f4164647265737320616c72656164792076657269666965640000000000000000604482015260640161020c565b60018484815181106107ec576107ec6117a6565b6020908102919091018101518254600181018455600093845291909220825160049092020190819061081e9082611861565b50602082015160018201906108339082611861565b50604082015160028201906108489082611861565b506060820151600382019061085d9082611861565b5050600154600084815260026020526040902055508351849084908110610886576108866117a6565b602002602001015160000151516000141580156108c257508383815181106108b0576108b06117a6565b60200260200101516020015151600014155b80156108ed57508383815181106108db576108db6117a6565b60200260200101516040015151600014155b80156109185750838381518110610906576109066117a6565b60200260200101516060015151600014155b61096f5760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642070726f6f66206f662061646472657373206f776e65727368604482015261069760f41b606482015260840161020c565b5050808061097c90611921565b915050610729565b507f382315d4d56a6035e1899bffe77d9becefaf5f2650e4323b27854857a0454658816040516109b4919061193a565b60405180910390a150565b6000826001815181106109d4576109d46117a6565b6020026020010151600360008481526020019081526020016000206000015414610a335760405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081354d5081c9bdbdd60821b604482015260640161020c565b60025b8351811015610aed57838181518110610a5157610a516117a6565b602002602001015160036000858152602001908152602001600020600101600283610a7c919061178d565b81548110610a8c57610a8c6117a6565b906000526020600020015414610adb5760405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726f6f742062616c616e636560601b604482015260640161020c565b80610ae581611921565b915050610a36565b50604051630bd205a960e41b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bd205a9090610b3c90869088906004016119d7565b602060405180830381865afa158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906119fc565b949350505050565b610b8d610fb5565b83600003610bd05760405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081354d5081c9bdbdd60821b604482015260640161020c565b8151835114610c335760405162461bcd60e51b815260206004820152602960248201527f526f6f742061737365742073756d7320616e64206173736574206e756d626572604482015268040dad2e6dac2e8c6d60bb1b606482015260840161020c565b6000825167ffffffffffffffff811115610c4f57610c4f6112ae565b604051908082528060200260200182016040528015610c8257816020015b6060815260200190600190039081610c6d5790505b5090506000835167ffffffffffffffff811115610ca157610ca16112ae565b604051908082528060200260200182016040528015610cd457816020015b6060815260200190600190039081610cbf5790505b50905060005b8451811015610e7157848181518110610cf557610cf56117a6565b60200260200101516020015151600014158015610d315750848181518110610d1f57610d1f6117a6565b60200260200101516000015151600014155b610d6d5760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908185cdcd95d609a1b604482015260640161020c565b858181518110610d7f57610d7f6117a6565b6020026020010151600003610de85760405162461bcd60e51b815260206004820152602960248201527f416c6c20726f6f742073756d732073686f756c642062652067726561746572206044820152687468616e207a65726f60b81b606482015260840161020c565b848181518110610dfa57610dfa6117a6565b602002602001015160000151838281518110610e1857610e186117a6565b6020026020010181905250848181518110610e3557610e356117a6565b602002602001015160200151828281518110610e5357610e536117a6565b60200260200101819052508080610e6990611921565b915050610cda565b5060408051608081018252878152602080820188815282840186905260608301859052600087815260038352939093208251815592518051929392610ebc926001850192019061105f565b5060408201518051610ed89160028401916020909101906110aa565b5060608201518051610ef49160038401916020909101906110aa565b50905050827f88bfc7389cb831ea0208ff106da6f5c9f88036ba084f1eb008d2788d3d45998d878787604051610f2c93929190611a1e565b60405180910390a2505050505050565b610f44610fb5565b6001600160a01b038116610fa95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161020c565b610fb28161100f565b50565b6000546001600160a01b031633146104bc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161020c565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b82805482825590600052602060002090810192821561109a579160200282015b8281111561109a57825182559160200191906001019061107f565b506110a69291506110fc565b5090565b8280548282559060005260206000209081019282156110f0579160200282015b828111156110f057825182906110e09082611861565b50916020019190600101906110ca565b506110a6929150611111565b5b808211156110a657600081556001016110fd565b808211156110a6576000611125828261112e565b50600101611111565b50805461113a906117bc565b6000825580601f1061114a575050565b601f016020900490600052602060002090810190610fb291906110fc565b60006020828403121561117a57600080fd5b5035919050565b60005b8381101561119c578181015183820152602001611184565b50506000910152565b600081518084526111bd816020860160208601611181565b601f01601f19169290920160200192915050565b60008151608084526111e660808501826111a5565b9050602083015184820360208601526111ff82826111a5565b9150506040830151848203604086015261121982826111a5565b9150506060830151848203606086015261123382826111a5565b95945050505050565b60208152600061124f60208301846111d1565b9392505050565b60808152600061126960808301876111a5565b828103602084015261127b81876111a5565b9050828103604084015261128f81866111a5565b905082810360608401526112a381856111a5565b979650505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff811182821017156112e7576112e76112ae565b60405290565b6040805190810167ffffffffffffffff811182821017156112e7576112e76112ae565b604051601f8201601f1916810167ffffffffffffffff81118282101715611339576113396112ae565b604052919050565b600067ffffffffffffffff82111561135b5761135b6112ae565b5060051b60200190565b600082601f83011261137657600080fd5b813567ffffffffffffffff811115611390576113906112ae565b6113a3601f8201601f1916602001611310565b8181528460208386010111156113b857600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156113e857600080fd5b823567ffffffffffffffff8082111561140057600080fd5b818501915085601f83011261141457600080fd5b813561142761142282611341565b611310565b81815260059190911b8301840190848101908883111561144657600080fd5b8585015b838110156115275780358581111561146157600080fd5b86016080818c03601f190112156114785760008081fd5b6114806112c4565b88820135878111156114925760008081fd5b6114a08d8b83860101611365565b825250604080830135888111156114b75760008081fd5b6114c58e8c83870101611365565b8b84015250606080840135898111156114de5760008081fd5b6114ec8f8d83880101611365565b838501525060808401359150888211156115065760008081fd5b6115148e8c84870101611365565b908301525084525091860191860161144a565b5098975050505050505050565b600082601f83011261154557600080fd5b8135602061155561142283611341565b82815260059290921b8401810191818101908684111561157457600080fd5b8286015b8481101561158f5780358352918301918301611578565b509695505050505050565b6000806000606084860312156115af57600080fd5b833567ffffffffffffffff808211156115c757600080fd5b6115d387838801611365565b945060208601359150808211156115e957600080fd5b506115f686828701611534565b925050604084013590509250925092565b6000806000806080858703121561161d57600080fd5b84359350602085013567ffffffffffffffff8082111561163c57600080fd5b61164888838901611534565b9450604087013591508082111561165e57600080fd5b818701915087601f83011261167257600080fd5b61167f6114228335611341565b82358082526020808301929160051b8501018a81111561169e57600080fd5b602085015b8181101561173a5784813511156116b957600080fd5b803586016040818e03601f190112156116d157600080fd5b6116d96112ed565b6020820135878111156116eb57600080fd5b6116fa8f602083860101611365565b82525060408201358781111561170f57600080fd5b61171e8f602083860101611365565b60208301525080865250506020840193506020810190506116a3565b50979a969950976060013596505050505050565b60006020828403121561176057600080fd5b81356001600160a01b038116811461124f57600080fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156117a0576117a0611777565b92915050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806117d057607f821691505b6020821081036117f057634e487b7160e01b600052602260045260246000fd5b50919050565b60008251611808818460208701611181565b9190910192915050565b601f82111561185c57600081815260208120601f850160051c810160208610156118395750805b601f850160051c820191505b8181101561185857828155600101611845565b5050505b505050565b815167ffffffffffffffff81111561187b5761187b6112ae565b61188f8161188984546117bc565b84611812565b602080601f8311600181146118c457600084156118ac5750858301515b600019600386901b1c1916600185901b178555611858565b600085815260208120601f198616915b828110156118f3578886015182559484019460019091019084016118d4565b50858210156119115787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006001820161193357611933611777565b5060010190565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561198f57603f1988860301845261197d8583516111d1565b94509285019290850190600101611961565b5092979650505050505050565b600081518084526020808501945080840160005b838110156119cc578151875295820195908201906001016119b0565b509495945050505050565b6040815260006119ea604083018561199c565b828103602084015261123381856111a5565b600060208284031215611a0e57600080fd5b8151801515811461124f57600080fd5b83815260006020606081840152611a38606084018661199c565b6040848203818601528186518084528484019150848160051b85010185890160005b83811015611aaa57868303601f1901855281518051878552611a7e888601826111a5565b918a0151858303868c0152919050611a9681836111a5565b968a01969450505090870190600101611a5a565b50909b9a505050505050505050505056fea26469706673582212207cb85ea038da5fbb4d243dafda10edb44d56ab6f16ada87b78199597fde11ce064736f6c63430008120033","deployedBytecode":"0x608060405234801561001057600080fd5b50600436106100935760003560e01c8063a3c4bcf811610066578063a3c4bcf814610114578063c7ddca0e14610137578063c8e581471461014a578063da64a7501461016d578063f2fde38b1461018057600080fd5b806319b339681461009857806349ce8997146100c1578063715018a6146100ef5780638da5cb5b146100f9575b600080fd5b6100ab6100a6366004611168565b610193565b6040516100b8919061123c565b60405180910390f35b6100e16100cf366004611168565b60036020526000908152604090205481565b6040519081526020016100b8565b6100f76104aa565b005b6000546040516001600160a01b0390911681526020016100b8565b610127610122366004611168565b6104be565b6040516100b89493929190611256565b6100f76101453660046113d5565b61071e565b61015d61015836600461159a565b6109bf565b60405190151581526020016100b8565b6100f761017b366004611607565b610b85565b6100f761018e36600461174e565b610f3c565b6101be6040518060800160405280606081526020016060815260200160608152602001606081525090565b6000828152600260205260409020546102155760405162461bcd60e51b81526020600482015260146024820152731059191c995cdcc81b9bdd081d995c9a599a595960621b60448201526064015b60405180910390fd5b60008281526002602052604090205460019061023290829061178d565b81548110610242576102426117a6565b906000526020600020906004020160405180608001604052908160008201805461026b906117bc565b80601f0160208091040260200160405190810160405280929190818152602001828054610297906117bc565b80156102e45780601f106102b9576101008083540402835291602001916102e4565b820191906000526020600020905b8154815290600101906020018083116102c757829003601f168201915b505050505081526020016001820180546102fd906117bc565b80601f0160208091040260200160405190810160405280929190818152602001828054610329906117bc565b80156103765780601f1061034b57610100808354040283529160200191610376565b820191906000526020600020905b81548152906001019060200180831161035957829003601f168201915b5050505050815260200160028201805461038f906117bc565b80601f01602080910402602001604051908101604052809291908181526020018280546103bb906117bc565b80156104085780601f106103dd57610100808354040283529160200191610408565b820191906000526020600020905b8154815290600101906020018083116103eb57829003601f168201915b50505050508152602001600382018054610421906117bc565b80601f016020809104026020016040519081016040528092919081815260200182805461044d906117bc565b801561049a5780601f1061046f5761010080835404028352916020019161049a565b820191906000526020600020905b81548152906001019060200180831161047d57829003601f168201915b5050505050815250509050919050565b6104b2610fb5565b6104bc600061100f565b565b600181815481106104ce57600080fd5b90600052602060002090600402016000915090508060000180546104f1906117bc565b80601f016020809104026020016040519081016040528092919081815260200182805461051d906117bc565b801561056a5780601f1061053f5761010080835404028352916020019161056a565b820191906000526020600020905b81548152906001019060200180831161054d57829003601f168201915b50505050509080600101805461057f906117bc565b80601f01602080910402602001604051908101604052809291908181526020018280546105ab906117bc565b80156105f85780601f106105cd576101008083540402835291602001916105f8565b820191906000526020600020905b8154815290600101906020018083116105db57829003601f168201915b50505050509080600201805461060d906117bc565b80601f0160208091040260200160405190810160405280929190818152602001828054610639906117bc565b80156106865780601f1061065b57610100808354040283529160200191610686565b820191906000526020600020905b81548152906001019060200180831161066957829003601f168201915b50505050509080600301805461069b906117bc565b80601f01602080910402602001604051908101604052809291908181526020018280546106c7906117bc565b80156107145780601f106106e957610100808354040283529160200191610714565b820191906000526020600020905b8154815290600101906020018083116106f757829003601f168201915b5050505050905084565b610726610fb5565b60005b8151811015610984576000828281518110610746576107466117a6565b60200260200101516000015160405160200161076291906117f6565b60408051601f1981840301815291815281516020928301206000818152600290935291205490915080156107d85760405162461bcd60e51b815260206004820152601860248201527f4164647265737320616c72656164792076657269666965640000000000000000604482015260640161020c565b60018484815181106107ec576107ec6117a6565b6020908102919091018101518254600181018455600093845291909220825160049092020190819061081e9082611861565b50602082015160018201906108339082611861565b50604082015160028201906108489082611861565b506060820151600382019061085d9082611861565b5050600154600084815260026020526040902055508351849084908110610886576108866117a6565b602002602001015160000151516000141580156108c257508383815181106108b0576108b06117a6565b60200260200101516020015151600014155b80156108ed57508383815181106108db576108db6117a6565b60200260200101516040015151600014155b80156109185750838381518110610906576109066117a6565b60200260200101516060015151600014155b61096f5760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642070726f6f66206f662061646472657373206f776e65727368604482015261069760f41b606482015260840161020c565b5050808061097c90611921565b915050610729565b507f382315d4d56a6035e1899bffe77d9becefaf5f2650e4323b27854857a0454658816040516109b4919061193a565b60405180910390a150565b6000826001815181106109d4576109d46117a6565b6020026020010151600360008481526020019081526020016000206000015414610a335760405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081354d5081c9bdbdd60821b604482015260640161020c565b60025b8351811015610aed57838181518110610a5157610a516117a6565b602002602001015160036000858152602001908152602001600020600101600283610a7c919061178d565b81548110610a8c57610a8c6117a6565b906000526020600020015414610adb5760405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726f6f742062616c616e636560601b604482015260640161020c565b80610ae581611921565b915050610a36565b50604051630bd205a960e41b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bd205a9090610b3c90869088906004016119d7565b602060405180830381865afa158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d91906119fc565b949350505050565b610b8d610fb5565b83600003610bd05760405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081354d5081c9bdbdd60821b604482015260640161020c565b8151835114610c335760405162461bcd60e51b815260206004820152602960248201527f526f6f742061737365742073756d7320616e64206173736574206e756d626572604482015268040dad2e6dac2e8c6d60bb1b606482015260840161020c565b6000825167ffffffffffffffff811115610c4f57610c4f6112ae565b604051908082528060200260200182016040528015610c8257816020015b6060815260200190600190039081610c6d5790505b5090506000835167ffffffffffffffff811115610ca157610ca16112ae565b604051908082528060200260200182016040528015610cd457816020015b6060815260200190600190039081610cbf5790505b50905060005b8451811015610e7157848181518110610cf557610cf56117a6565b60200260200101516020015151600014158015610d315750848181518110610d1f57610d1f6117a6565b60200260200101516000015151600014155b610d6d5760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908185cdcd95d609a1b604482015260640161020c565b858181518110610d7f57610d7f6117a6565b6020026020010151600003610de85760405162461bcd60e51b815260206004820152602960248201527f416c6c20726f6f742073756d732073686f756c642062652067726561746572206044820152687468616e207a65726f60b81b606482015260840161020c565b848181518110610dfa57610dfa6117a6565b602002602001015160000151838281518110610e1857610e186117a6565b6020026020010181905250848181518110610e3557610e356117a6565b602002602001015160200151828281518110610e5357610e536117a6565b60200260200101819052508080610e6990611921565b915050610cda565b5060408051608081018252878152602080820188815282840186905260608301859052600087815260038352939093208251815592518051929392610ebc926001850192019061105f565b5060408201518051610ed89160028401916020909101906110aa565b5060608201518051610ef49160038401916020909101906110aa565b50905050827f88bfc7389cb831ea0208ff106da6f5c9f88036ba084f1eb008d2788d3d45998d878787604051610f2c93929190611a1e565b60405180910390a2505050505050565b610f44610fb5565b6001600160a01b038116610fa95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161020c565b610fb28161100f565b50565b6000546001600160a01b031633146104bc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161020c565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b82805482825590600052602060002090810192821561109a579160200282015b8281111561109a57825182559160200191906001019061107f565b506110a69291506110fc565b5090565b8280548282559060005260206000209081019282156110f0579160200282015b828111156110f057825182906110e09082611861565b50916020019190600101906110ca565b506110a6929150611111565b5b808211156110a657600081556001016110fd565b808211156110a6576000611125828261112e565b50600101611111565b50805461113a906117bc565b6000825580601f1061114a575050565b601f016020900490600052602060002090810190610fb291906110fc565b60006020828403121561117a57600080fd5b5035919050565b60005b8381101561119c578181015183820152602001611184565b50506000910152565b600081518084526111bd816020860160208601611181565b601f01601f19169290920160200192915050565b60008151608084526111e660808501826111a5565b9050602083015184820360208601526111ff82826111a5565b9150506040830151848203604086015261121982826111a5565b9150506060830151848203606086015261123382826111a5565b95945050505050565b60208152600061124f60208301846111d1565b9392505050565b60808152600061126960808301876111a5565b828103602084015261127b81876111a5565b9050828103604084015261128f81866111a5565b905082810360608401526112a381856111a5565b979650505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff811182821017156112e7576112e76112ae565b60405290565b6040805190810167ffffffffffffffff811182821017156112e7576112e76112ae565b604051601f8201601f1916810167ffffffffffffffff81118282101715611339576113396112ae565b604052919050565b600067ffffffffffffffff82111561135b5761135b6112ae565b5060051b60200190565b600082601f83011261137657600080fd5b813567ffffffffffffffff811115611390576113906112ae565b6113a3601f8201601f1916602001611310565b8181528460208386010111156113b857600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156113e857600080fd5b823567ffffffffffffffff8082111561140057600080fd5b818501915085601f83011261141457600080fd5b813561142761142282611341565b611310565b81815260059190911b8301840190848101908883111561144657600080fd5b8585015b838110156115275780358581111561146157600080fd5b86016080818c03601f190112156114785760008081fd5b6114806112c4565b88820135878111156114925760008081fd5b6114a08d8b83860101611365565b825250604080830135888111156114b75760008081fd5b6114c58e8c83870101611365565b8b84015250606080840135898111156114de5760008081fd5b6114ec8f8d83880101611365565b838501525060808401359150888211156115065760008081fd5b6115148e8c84870101611365565b908301525084525091860191860161144a565b5098975050505050505050565b600082601f83011261154557600080fd5b8135602061155561142283611341565b82815260059290921b8401810191818101908684111561157457600080fd5b8286015b8481101561158f5780358352918301918301611578565b509695505050505050565b6000806000606084860312156115af57600080fd5b833567ffffffffffffffff808211156115c757600080fd5b6115d387838801611365565b945060208601359150808211156115e957600080fd5b506115f686828701611534565b925050604084013590509250925092565b6000806000806080858703121561161d57600080fd5b84359350602085013567ffffffffffffffff8082111561163c57600080fd5b61164888838901611534565b9450604087013591508082111561165e57600080fd5b818701915087601f83011261167257600080fd5b61167f6114228335611341565b82358082526020808301929160051b8501018a81111561169e57600080fd5b602085015b8181101561173a5784813511156116b957600080fd5b803586016040818e03601f190112156116d157600080fd5b6116d96112ed565b6020820135878111156116eb57600080fd5b6116fa8f602083860101611365565b82525060408201358781111561170f57600080fd5b61171e8f602083860101611365565b60208301525080865250506020840193506020810190506116a3565b50979a969950976060013596505050505050565b60006020828403121561176057600080fd5b81356001600160a01b038116811461124f57600080fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156117a0576117a0611777565b92915050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806117d057607f821691505b6020821081036117f057634e487b7160e01b600052602260045260246000fd5b50919050565b60008251611808818460208701611181565b9190910192915050565b601f82111561185c57600081815260208120601f850160051c810160208610156118395750805b601f850160051c820191505b8181101561185857828155600101611845565b5050505b505050565b815167ffffffffffffffff81111561187b5761187b6112ae565b61188f8161188984546117bc565b84611812565b602080601f8311600181146118c457600084156118ac5750858301515b600019600386901b1c1916600185901b178555611858565b600085815260208120601f198616915b828110156118f3578886015182559484019460019091019084016118d4565b50858210156119115787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006001820161193357611933611777565b5060010190565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561198f57603f1988860301845261197d8583516111d1565b94509285019290850190600101611961565b5092979650505050505050565b600081518084526020808501945080840160005b838110156119cc578151875295820195908201906001016119b0565b509495945050505050565b6040815260006119ea604083018561199c565b828103602084015261123381856111a5565b600060208284031215611a0e57600080fd5b8151801515811461124f57600080fd5b83815260006020606081840152611a38606084018661199c565b6040848203818601528186518084528484019150848160051b85010185890160005b83811015611aaa57868303601f1901855281518051878552611a7e888601826111a5565b918a0151858303868c0152919050611a9681836111a5565b968a01969450505090870190600101611a5a565b50909b9a505050505050505050505056fea26469706673582212207cb85ea038da5fbb4d243dafda10edb44d56ab6f16ada87b78199597fde11ce064736f6c63430008120033","linkReferences":{},"deployedLinkReferences":{}} \ No newline at end of file +{"_format":"hh-sol-artifact-1","contractName":"Summa","sourceName":"src/Summa.sol","abi":[{"inputs":[{"internalType":"contract IVerifier","name":"_inclusionVerifier","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"components":[{"internalType":"string","name":"cexAddress","type":"string"},{"internalType":"string","name":"chain","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"indexed":false,"internalType":"struct Summa.AddressOwnershipProof[]","name":"addressOwnershipProofs","type":"tuple[]"}],"name":"AddressOwnershipProofSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mstRoot","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"rootBalances","type":"uint256[]"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"chain","type":"string"}],"indexed":false,"internalType":"struct Summa.Cryptocurrency[]","name":"cryptocurrencies","type":"tuple[]"}],"name":"LiabilitiesCommitmentSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"addressOwnershipProofs","outputs":[{"internalType":"string","name":"cexAddress","type":"string"},{"internalType":"string","name":"chain","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"commitments","outputs":[{"internalType":"uint256","name":"mstRoot","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"addressHash","type":"bytes32"}],"name":"getAddressOwnershipProof","outputs":[{"components":[{"internalType":"string","name":"cexAddress","type":"string"},{"internalType":"string","name":"chain","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"internalType":"struct Summa.AddressOwnershipProof","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"mstRoot","type":"uint256"},{"internalType":"uint256[]","name":"rootBalances","type":"uint256[]"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"chain","type":"string"}],"internalType":"struct Summa.Cryptocurrency[]","name":"cryptocurrencies","type":"tuple[]"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"submitCommitment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"cexAddress","type":"string"},{"internalType":"string","name":"chain","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"internalType":"struct Summa.AddressOwnershipProof[]","name":"_addressOwnershipProofs","type":"tuple[]"}],"name":"submitProofOfAddressOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"proof","type":"bytes"},{"internalType":"uint256[]","name":"publicInputs","type":"uint256[]"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"verifyInclusionProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"bytecode":"0x60a060405234801561001057600080fd5b5060405162001bed38038062001bed8339810160408190526100319161009b565b61003a3361004b565b6001600160a01b03166080526100cb565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100ad57600080fd5b81516001600160a01b03811681146100c457600080fd5b9392505050565b608051611b06620000e76000396000610b050152611b066000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063a3c4bcf811610066578063a3c4bcf814610114578063c7ddca0e14610137578063c8e581471461014a578063da64a7501461016d578063f2fde38b1461018057600080fd5b806319b339681461009857806349ce8997146100c1578063715018a6146100ef5780638da5cb5b146100f9575b600080fd5b6100ab6100a636600461117d565b610193565b6040516100b89190611251565b60405180910390f35b6100e16100cf36600461117d565b60036020526000908152604090205481565b6040519081526020016100b8565b6100f76104aa565b005b6000546040516001600160a01b0390911681526020016100b8565b61012761012236600461117d565b6104be565b6040516100b8949392919061126b565b6100f76101453660046113ea565b61071e565b61015d6101583660046115af565b6109bf565b60405190151581526020016100b8565b6100f761017b36600461161c565b610b85565b6100f761018e366004611763565b610f51565b6101be6040518060800160405280606081526020016060815260200160608152602001606081525090565b6000828152600260205260409020546102155760405162461bcd60e51b81526020600482015260146024820152731059191c995cdcc81b9bdd081d995c9a599a595960621b60448201526064015b60405180910390fd5b6000828152600260205260409020546001906102329082906117a2565b81548110610242576102426117bb565b906000526020600020906004020160405180608001604052908160008201805461026b906117d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610297906117d1565b80156102e45780601f106102b9576101008083540402835291602001916102e4565b820191906000526020600020905b8154815290600101906020018083116102c757829003601f168201915b505050505081526020016001820180546102fd906117d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610329906117d1565b80156103765780601f1061034b57610100808354040283529160200191610376565b820191906000526020600020905b81548152906001019060200180831161035957829003601f168201915b5050505050815260200160028201805461038f906117d1565b80601f01602080910402602001604051908101604052809291908181526020018280546103bb906117d1565b80156104085780601f106103dd57610100808354040283529160200191610408565b820191906000526020600020905b8154815290600101906020018083116103eb57829003601f168201915b50505050508152602001600382018054610421906117d1565b80601f016020809104026020016040519081016040528092919081815260200182805461044d906117d1565b801561049a5780601f1061046f5761010080835404028352916020019161049a565b820191906000526020600020905b81548152906001019060200180831161047d57829003601f168201915b5050505050815250509050919050565b6104b2610fca565b6104bc6000611024565b565b600181815481106104ce57600080fd5b90600052602060002090600402016000915090508060000180546104f1906117d1565b80601f016020809104026020016040519081016040528092919081815260200182805461051d906117d1565b801561056a5780601f1061053f5761010080835404028352916020019161056a565b820191906000526020600020905b81548152906001019060200180831161054d57829003601f168201915b50505050509080600101805461057f906117d1565b80601f01602080910402602001604051908101604052809291908181526020018280546105ab906117d1565b80156105f85780601f106105cd576101008083540402835291602001916105f8565b820191906000526020600020905b8154815290600101906020018083116105db57829003601f168201915b50505050509080600201805461060d906117d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610639906117d1565b80156106865780601f1061065b57610100808354040283529160200191610686565b820191906000526020600020905b81548152906001019060200180831161066957829003601f168201915b50505050509080600301805461069b906117d1565b80601f01602080910402602001604051908101604052809291908181526020018280546106c7906117d1565b80156107145780601f106106e957610100808354040283529160200191610714565b820191906000526020600020905b8154815290600101906020018083116106f757829003601f168201915b5050505050905084565b610726610fca565b60005b8151811015610984576000828281518110610746576107466117bb565b602002602001015160000151604051602001610762919061180b565b60408051601f1981840301815291815281516020928301206000818152600290935291205490915080156107d85760405162461bcd60e51b815260206004820152601860248201527f4164647265737320616c72656164792076657269666965640000000000000000604482015260640161020c565b60018484815181106107ec576107ec6117bb565b6020908102919091018101518254600181018455600093845291909220825160049092020190819061081e9082611876565b50602082015160018201906108339082611876565b50604082015160028201906108489082611876565b506060820151600382019061085d9082611876565b5050600154600084815260026020526040902055508351849084908110610886576108866117bb565b602002602001015160000151516000141580156108c257508383815181106108b0576108b06117bb565b60200260200101516020015151600014155b80156108ed57508383815181106108db576108db6117bb565b60200260200101516040015151600014155b80156109185750838381518110610906576109066117bb565b60200260200101516060015151600014155b61096f5760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642070726f6f66206f662061646472657373206f776e65727368604482015261069760f41b606482015260840161020c565b5050808061097c90611936565b915050610729565b507f382315d4d56a6035e1899bffe77d9becefaf5f2650e4323b27854857a0454658816040516109b4919061194f565b60405180910390a150565b6000826001815181106109d4576109d46117bb565b6020026020010151600360008481526020019081526020016000206000015414610a335760405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081354d5081c9bdbdd60821b604482015260640161020c565b60025b8351811015610aed57838181518110610a5157610a516117bb565b602002602001015160036000858152602001908152602001600020600101600283610a7c91906117a2565b81548110610a8c57610a8c6117bb565b906000526020600020015414610adb5760405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726f6f742062616c616e636560601b604482015260640161020c565b80610ae581611936565b915050610a36565b50604051630bd205a960e41b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bd205a9090610b3c90869088906004016119ec565b602060405180830381865afa158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d9190611a11565b949350505050565b610b8d610fca565b83600003610bd05760405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081354d5081c9bdbdd60821b604482015260640161020c565b8151835114610c3f5760405162461bcd60e51b815260206004820152603560248201527f526f6f74206c696162696c69746965732073756d7320616e64206c696162696c6044820152740d2e8d2cae640dceadac4cae440dad2e6dac2e8c6d605b1b606482015260840161020c565b6000825167ffffffffffffffff811115610c5b57610c5b6112c3565b604051908082528060200260200182016040528015610c8e57816020015b6060815260200190600190039081610c795790505b5090506000835167ffffffffffffffff811115610cad57610cad6112c3565b604051908082528060200260200182016040528015610ce057816020015b6060815260200190600190039081610ccb5790505b50905060005b8451811015610e8657848181518110610d0157610d016117bb565b60200260200101516020015151600014158015610d3d5750848181518110610d2b57610d2b6117bb565b60200260200101516000015151600014155b610d825760405162461bcd60e51b8152602060048201526016602482015275496e76616c69642063727970746f63757272656e637960501b604482015260640161020c565b858181518110610d9457610d946117bb565b6020026020010151600003610dfd5760405162461bcd60e51b815260206004820152602960248201527f416c6c20726f6f742073756d732073686f756c642062652067726561746572206044820152687468616e207a65726f60b81b606482015260840161020c565b848181518110610e0f57610e0f6117bb565b602002602001015160000151838281518110610e2d57610e2d6117bb565b6020026020010181905250848181518110610e4a57610e4a6117bb565b602002602001015160200151828281518110610e6857610e686117bb565b60200260200101819052508080610e7e90611936565b915050610ce6565b5060408051608081018252878152602080820188815282840186905260608301859052600087815260038352939093208251815592518051929392610ed19260018501920190611074565b5060408201518051610eed9160028401916020909101906110bf565b5060608201518051610f099160038401916020909101906110bf565b50905050827f88bfc7389cb831ea0208ff106da6f5c9f88036ba084f1eb008d2788d3d45998d878787604051610f4193929190611a33565b60405180910390a2505050505050565b610f59610fca565b6001600160a01b038116610fbe5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161020c565b610fc781611024565b50565b6000546001600160a01b031633146104bc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161020c565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280548282559060005260206000209081019282156110af579160200282015b828111156110af578251825591602001919060010190611094565b506110bb929150611111565b5090565b828054828255906000526020600020908101928215611105579160200282015b8281111561110557825182906110f59082611876565b50916020019190600101906110df565b506110bb929150611126565b5b808211156110bb5760008155600101611112565b808211156110bb57600061113a8282611143565b50600101611126565b50805461114f906117d1565b6000825580601f1061115f575050565b601f016020900490600052602060002090810190610fc79190611111565b60006020828403121561118f57600080fd5b5035919050565b60005b838110156111b1578181015183820152602001611199565b50506000910152565b600081518084526111d2816020860160208601611196565b601f01601f19169290920160200192915050565b60008151608084526111fb60808501826111ba565b90506020830151848203602086015261121482826111ba565b9150506040830151848203604086015261122e82826111ba565b9150506060830151848203606086015261124882826111ba565b95945050505050565b60208152600061126460208301846111e6565b9392505050565b60808152600061127e60808301876111ba565b828103602084015261129081876111ba565b905082810360408401526112a481866111ba565b905082810360608401526112b881856111ba565b979650505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff811182821017156112fc576112fc6112c3565b60405290565b6040805190810167ffffffffffffffff811182821017156112fc576112fc6112c3565b604051601f8201601f1916810167ffffffffffffffff8111828210171561134e5761134e6112c3565b604052919050565b600067ffffffffffffffff821115611370576113706112c3565b5060051b60200190565b600082601f83011261138b57600080fd5b813567ffffffffffffffff8111156113a5576113a56112c3565b6113b8601f8201601f1916602001611325565b8181528460208386010111156113cd57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156113fd57600080fd5b823567ffffffffffffffff8082111561141557600080fd5b818501915085601f83011261142957600080fd5b813561143c61143782611356565b611325565b81815260059190911b8301840190848101908883111561145b57600080fd5b8585015b8381101561153c5780358581111561147657600080fd5b86016080818c03601f1901121561148d5760008081fd5b6114956112d9565b88820135878111156114a75760008081fd5b6114b58d8b8386010161137a565b825250604080830135888111156114cc5760008081fd5b6114da8e8c8387010161137a565b8b84015250606080840135898111156114f35760008081fd5b6115018f8d8388010161137a565b8385015250608084013591508882111561151b5760008081fd5b6115298e8c8487010161137a565b908301525084525091860191860161145f565b5098975050505050505050565b600082601f83011261155a57600080fd5b8135602061156a61143783611356565b82815260059290921b8401810191818101908684111561158957600080fd5b8286015b848110156115a4578035835291830191830161158d565b509695505050505050565b6000806000606084860312156115c457600080fd5b833567ffffffffffffffff808211156115dc57600080fd5b6115e88783880161137a565b945060208601359150808211156115fe57600080fd5b5061160b86828701611549565b925050604084013590509250925092565b6000806000806080858703121561163257600080fd5b84359350602085013567ffffffffffffffff8082111561165157600080fd5b61165d88838901611549565b9450604087013591508082111561167357600080fd5b818701915087601f83011261168757600080fd5b6116946114378335611356565b82358082526020808301929160051b8501018a8111156116b357600080fd5b602085015b8181101561174f5784813511156116ce57600080fd5b803586016040818e03601f190112156116e657600080fd5b6116ee611302565b60208201358781111561170057600080fd5b61170f8f60208386010161137a565b82525060408201358781111561172457600080fd5b6117338f60208386010161137a565b60208301525080865250506020840193506020810190506116b8565b50979a969950976060013596505050505050565b60006020828403121561177557600080fd5b81356001600160a01b038116811461126457600080fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156117b5576117b561178c565b92915050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806117e557607f821691505b60208210810361180557634e487b7160e01b600052602260045260246000fd5b50919050565b6000825161181d818460208701611196565b9190910192915050565b601f82111561187157600081815260208120601f850160051c8101602086101561184e5750805b601f850160051c820191505b8181101561186d5782815560010161185a565b5050505b505050565b815167ffffffffffffffff811115611890576118906112c3565b6118a48161189e84546117d1565b84611827565b602080601f8311600181146118d957600084156118c15750858301515b600019600386901b1c1916600185901b17855561186d565b600085815260208120601f198616915b82811015611908578886015182559484019460019091019084016118e9565b50858210156119265787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000600182016119485761194861178c565b5060010190565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156119a457603f198886030184526119928583516111e6565b94509285019290850190600101611976565b5092979650505050505050565b600081518084526020808501945080840160005b838110156119e1578151875295820195908201906001016119c5565b509495945050505050565b6040815260006119ff60408301856119b1565b828103602084015261124881856111ba565b600060208284031215611a2357600080fd5b8151801515811461126457600080fd5b83815260006020606081840152611a4d60608401866119b1565b6040848203818601528186518084528484019150848160051b85010185890160005b83811015611abf57868303601f1901855281518051878552611a93888601826111ba565b918a0151858303868c0152919050611aab81836111ba565b968a01969450505090870190600101611a6f565b50909b9a505050505050505050505056fea2646970667358221220929937337ad16c6172e2163bc45ed3913fe51f8e5ce8cac3ac8073d01593edd764736f6c63430008120033","deployedBytecode":"0x608060405234801561001057600080fd5b50600436106100935760003560e01c8063a3c4bcf811610066578063a3c4bcf814610114578063c7ddca0e14610137578063c8e581471461014a578063da64a7501461016d578063f2fde38b1461018057600080fd5b806319b339681461009857806349ce8997146100c1578063715018a6146100ef5780638da5cb5b146100f9575b600080fd5b6100ab6100a636600461117d565b610193565b6040516100b89190611251565b60405180910390f35b6100e16100cf36600461117d565b60036020526000908152604090205481565b6040519081526020016100b8565b6100f76104aa565b005b6000546040516001600160a01b0390911681526020016100b8565b61012761012236600461117d565b6104be565b6040516100b8949392919061126b565b6100f76101453660046113ea565b61071e565b61015d6101583660046115af565b6109bf565b60405190151581526020016100b8565b6100f761017b36600461161c565b610b85565b6100f761018e366004611763565b610f51565b6101be6040518060800160405280606081526020016060815260200160608152602001606081525090565b6000828152600260205260409020546102155760405162461bcd60e51b81526020600482015260146024820152731059191c995cdcc81b9bdd081d995c9a599a595960621b60448201526064015b60405180910390fd5b6000828152600260205260409020546001906102329082906117a2565b81548110610242576102426117bb565b906000526020600020906004020160405180608001604052908160008201805461026b906117d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610297906117d1565b80156102e45780601f106102b9576101008083540402835291602001916102e4565b820191906000526020600020905b8154815290600101906020018083116102c757829003601f168201915b505050505081526020016001820180546102fd906117d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610329906117d1565b80156103765780601f1061034b57610100808354040283529160200191610376565b820191906000526020600020905b81548152906001019060200180831161035957829003601f168201915b5050505050815260200160028201805461038f906117d1565b80601f01602080910402602001604051908101604052809291908181526020018280546103bb906117d1565b80156104085780601f106103dd57610100808354040283529160200191610408565b820191906000526020600020905b8154815290600101906020018083116103eb57829003601f168201915b50505050508152602001600382018054610421906117d1565b80601f016020809104026020016040519081016040528092919081815260200182805461044d906117d1565b801561049a5780601f1061046f5761010080835404028352916020019161049a565b820191906000526020600020905b81548152906001019060200180831161047d57829003601f168201915b5050505050815250509050919050565b6104b2610fca565b6104bc6000611024565b565b600181815481106104ce57600080fd5b90600052602060002090600402016000915090508060000180546104f1906117d1565b80601f016020809104026020016040519081016040528092919081815260200182805461051d906117d1565b801561056a5780601f1061053f5761010080835404028352916020019161056a565b820191906000526020600020905b81548152906001019060200180831161054d57829003601f168201915b50505050509080600101805461057f906117d1565b80601f01602080910402602001604051908101604052809291908181526020018280546105ab906117d1565b80156105f85780601f106105cd576101008083540402835291602001916105f8565b820191906000526020600020905b8154815290600101906020018083116105db57829003601f168201915b50505050509080600201805461060d906117d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610639906117d1565b80156106865780601f1061065b57610100808354040283529160200191610686565b820191906000526020600020905b81548152906001019060200180831161066957829003601f168201915b50505050509080600301805461069b906117d1565b80601f01602080910402602001604051908101604052809291908181526020018280546106c7906117d1565b80156107145780601f106106e957610100808354040283529160200191610714565b820191906000526020600020905b8154815290600101906020018083116106f757829003601f168201915b5050505050905084565b610726610fca565b60005b8151811015610984576000828281518110610746576107466117bb565b602002602001015160000151604051602001610762919061180b565b60408051601f1981840301815291815281516020928301206000818152600290935291205490915080156107d85760405162461bcd60e51b815260206004820152601860248201527f4164647265737320616c72656164792076657269666965640000000000000000604482015260640161020c565b60018484815181106107ec576107ec6117bb565b6020908102919091018101518254600181018455600093845291909220825160049092020190819061081e9082611876565b50602082015160018201906108339082611876565b50604082015160028201906108489082611876565b506060820151600382019061085d9082611876565b5050600154600084815260026020526040902055508351849084908110610886576108866117bb565b602002602001015160000151516000141580156108c257508383815181106108b0576108b06117bb565b60200260200101516020015151600014155b80156108ed57508383815181106108db576108db6117bb565b60200260200101516040015151600014155b80156109185750838381518110610906576109066117bb565b60200260200101516060015151600014155b61096f5760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642070726f6f66206f662061646472657373206f776e65727368604482015261069760f41b606482015260840161020c565b5050808061097c90611936565b915050610729565b507f382315d4d56a6035e1899bffe77d9becefaf5f2650e4323b27854857a0454658816040516109b4919061194f565b60405180910390a150565b6000826001815181106109d4576109d46117bb565b6020026020010151600360008481526020019081526020016000206000015414610a335760405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081354d5081c9bdbdd60821b604482015260640161020c565b60025b8351811015610aed57838181518110610a5157610a516117bb565b602002602001015160036000858152602001908152602001600020600101600283610a7c91906117a2565b81548110610a8c57610a8c6117bb565b906000526020600020015414610adb5760405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726f6f742062616c616e636560601b604482015260640161020c565b80610ae581611936565b915050610a36565b50604051630bd205a960e41b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bd205a9090610b3c90869088906004016119ec565b602060405180830381865afa158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d9190611a11565b949350505050565b610b8d610fca565b83600003610bd05760405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081354d5081c9bdbdd60821b604482015260640161020c565b8151835114610c3f5760405162461bcd60e51b815260206004820152603560248201527f526f6f74206c696162696c69746965732073756d7320616e64206c696162696c6044820152740d2e8d2cae640dceadac4cae440dad2e6dac2e8c6d605b1b606482015260840161020c565b6000825167ffffffffffffffff811115610c5b57610c5b6112c3565b604051908082528060200260200182016040528015610c8e57816020015b6060815260200190600190039081610c795790505b5090506000835167ffffffffffffffff811115610cad57610cad6112c3565b604051908082528060200260200182016040528015610ce057816020015b6060815260200190600190039081610ccb5790505b50905060005b8451811015610e8657848181518110610d0157610d016117bb565b60200260200101516020015151600014158015610d3d5750848181518110610d2b57610d2b6117bb565b60200260200101516000015151600014155b610d825760405162461bcd60e51b8152602060048201526016602482015275496e76616c69642063727970746f63757272656e637960501b604482015260640161020c565b858181518110610d9457610d946117bb565b6020026020010151600003610dfd5760405162461bcd60e51b815260206004820152602960248201527f416c6c20726f6f742073756d732073686f756c642062652067726561746572206044820152687468616e207a65726f60b81b606482015260840161020c565b848181518110610e0f57610e0f6117bb565b602002602001015160000151838281518110610e2d57610e2d6117bb565b6020026020010181905250848181518110610e4a57610e4a6117bb565b602002602001015160200151828281518110610e6857610e686117bb565b60200260200101819052508080610e7e90611936565b915050610ce6565b5060408051608081018252878152602080820188815282840186905260608301859052600087815260038352939093208251815592518051929392610ed19260018501920190611074565b5060408201518051610eed9160028401916020909101906110bf565b5060608201518051610f099160038401916020909101906110bf565b50905050827f88bfc7389cb831ea0208ff106da6f5c9f88036ba084f1eb008d2788d3d45998d878787604051610f4193929190611a33565b60405180910390a2505050505050565b610f59610fca565b6001600160a01b038116610fbe5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161020c565b610fc781611024565b50565b6000546001600160a01b031633146104bc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161020c565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280548282559060005260206000209081019282156110af579160200282015b828111156110af578251825591602001919060010190611094565b506110bb929150611111565b5090565b828054828255906000526020600020908101928215611105579160200282015b8281111561110557825182906110f59082611876565b50916020019190600101906110df565b506110bb929150611126565b5b808211156110bb5760008155600101611112565b808211156110bb57600061113a8282611143565b50600101611126565b50805461114f906117d1565b6000825580601f1061115f575050565b601f016020900490600052602060002090810190610fc79190611111565b60006020828403121561118f57600080fd5b5035919050565b60005b838110156111b1578181015183820152602001611199565b50506000910152565b600081518084526111d2816020860160208601611196565b601f01601f19169290920160200192915050565b60008151608084526111fb60808501826111ba565b90506020830151848203602086015261121482826111ba565b9150506040830151848203604086015261122e82826111ba565b9150506060830151848203606086015261124882826111ba565b95945050505050565b60208152600061126460208301846111e6565b9392505050565b60808152600061127e60808301876111ba565b828103602084015261129081876111ba565b905082810360408401526112a481866111ba565b905082810360608401526112b881856111ba565b979650505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff811182821017156112fc576112fc6112c3565b60405290565b6040805190810167ffffffffffffffff811182821017156112fc576112fc6112c3565b604051601f8201601f1916810167ffffffffffffffff8111828210171561134e5761134e6112c3565b604052919050565b600067ffffffffffffffff821115611370576113706112c3565b5060051b60200190565b600082601f83011261138b57600080fd5b813567ffffffffffffffff8111156113a5576113a56112c3565b6113b8601f8201601f1916602001611325565b8181528460208386010111156113cd57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156113fd57600080fd5b823567ffffffffffffffff8082111561141557600080fd5b818501915085601f83011261142957600080fd5b813561143c61143782611356565b611325565b81815260059190911b8301840190848101908883111561145b57600080fd5b8585015b8381101561153c5780358581111561147657600080fd5b86016080818c03601f1901121561148d5760008081fd5b6114956112d9565b88820135878111156114a75760008081fd5b6114b58d8b8386010161137a565b825250604080830135888111156114cc5760008081fd5b6114da8e8c8387010161137a565b8b84015250606080840135898111156114f35760008081fd5b6115018f8d8388010161137a565b8385015250608084013591508882111561151b5760008081fd5b6115298e8c8487010161137a565b908301525084525091860191860161145f565b5098975050505050505050565b600082601f83011261155a57600080fd5b8135602061156a61143783611356565b82815260059290921b8401810191818101908684111561158957600080fd5b8286015b848110156115a4578035835291830191830161158d565b509695505050505050565b6000806000606084860312156115c457600080fd5b833567ffffffffffffffff808211156115dc57600080fd5b6115e88783880161137a565b945060208601359150808211156115fe57600080fd5b5061160b86828701611549565b925050604084013590509250925092565b6000806000806080858703121561163257600080fd5b84359350602085013567ffffffffffffffff8082111561165157600080fd5b61165d88838901611549565b9450604087013591508082111561167357600080fd5b818701915087601f83011261168757600080fd5b6116946114378335611356565b82358082526020808301929160051b8501018a8111156116b357600080fd5b602085015b8181101561174f5784813511156116ce57600080fd5b803586016040818e03601f190112156116e657600080fd5b6116ee611302565b60208201358781111561170057600080fd5b61170f8f60208386010161137a565b82525060408201358781111561172457600080fd5b6117338f60208386010161137a565b60208301525080865250506020840193506020810190506116b8565b50979a969950976060013596505050505050565b60006020828403121561177557600080fd5b81356001600160a01b038116811461126457600080fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156117b5576117b561178c565b92915050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806117e557607f821691505b60208210810361180557634e487b7160e01b600052602260045260246000fd5b50919050565b6000825161181d818460208701611196565b9190910192915050565b601f82111561187157600081815260208120601f850160051c8101602086101561184e5750805b601f850160051c820191505b8181101561186d5782815560010161185a565b5050505b505050565b815167ffffffffffffffff811115611890576118906112c3565b6118a48161189e84546117d1565b84611827565b602080601f8311600181146118d957600084156118c15750858301515b600019600386901b1c1916600185901b17855561186d565b600085815260208120601f198616915b82811015611908578886015182559484019460019091019084016118e9565b50858210156119265787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000600182016119485761194861178c565b5060010190565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156119a457603f198886030184526119928583516111e6565b94509285019290850190600101611976565b5092979650505050505050565b600081518084526020808501945080840160005b838110156119e1578151875295820195908201906001016119c5565b509495945050505050565b6040815260006119ff60408301856119b1565b828103602084015261124881856111ba565b600060208284031215611a2357600080fd5b8151801515811461126457600080fd5b83815260006020606081840152611a4d60608401866119b1565b6040848203818601528186518084528484019150848160051b85010185890160005b83811015611abf57868303601f1901855281518051878552611a93888601826111ba565b918a0151858303868c0152919050611aab81836111ba565b968a01969450505090870190600101611a6f565b50909b9a505050505050505050505056fea2646970667358221220929937337ad16c6172e2163bc45ed3913fe51f8e5ce8cac3ac8073d01593edd764736f6c63430008120033","linkReferences":{},"deployedLinkReferences":{}} \ No newline at end of file diff --git a/backend/src/contracts/generated/summa_contract.rs b/backend/src/contracts/generated/summa_contract.rs index 5de6f3f5..0b13b519 100644 --- a/backend/src/contracts/generated/summa_contract.rs +++ b/backend/src/contracts/generated/summa_contract.rs @@ -11,7 +11,7 @@ pub use summa::*; )] pub mod summa { #[rustfmt::skip] - const __ABI: &str = "[{\"inputs\":[{\"internalType\":\"contract IVerifier\",\"name\":\"_inclusionVerifier\",\"type\":\"address\",\"components\":[]}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\",\"outputs\":[]},{\"inputs\":[{\"internalType\":\"struct Summa.AddressOwnershipProof[]\",\"name\":\"addressOwnershipProofs\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"string\",\"name\":\"cexAddress\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"string\",\"name\":\"chain\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\",\"components\":[]}],\"indexed\":false}],\"type\":\"event\",\"name\":\"AddressOwnershipProofSubmitted\",\"outputs\":[],\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\",\"components\":[],\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"mstRoot\",\"type\":\"uint256\",\"components\":[],\"indexed\":false},{\"internalType\":\"uint256[]\",\"name\":\"rootBalances\",\"type\":\"uint256[]\",\"components\":[],\"indexed\":false},{\"internalType\":\"struct Summa.Asset[]\",\"name\":\"assets\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"string\",\"name\":\"assetName\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"string\",\"name\":\"chain\",\"type\":\"string\",\"components\":[]}],\"indexed\":false}],\"type\":\"event\",\"name\":\"LiabilitiesCommitmentSubmitted\",\"outputs\":[],\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"components\":[],\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"components\":[],\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"outputs\":[],\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\",\"components\":[]}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"addressOwnershipProofs\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"cexAddress\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"string\",\"name\":\"chain\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\",\"components\":[]}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\",\"components\":[]}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"commitments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"mstRoot\",\"type\":\"uint256\",\"components\":[]}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"addressHash\",\"type\":\"bytes32\",\"components\":[]}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getAddressOwnershipProof\",\"outputs\":[{\"internalType\":\"struct Summa.AddressOwnershipProof\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"string\",\"name\":\"cexAddress\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"string\",\"name\":\"chain\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\",\"components\":[]}]}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\",\"components\":[]}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\",\"outputs\":[]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"mstRoot\",\"type\":\"uint256\",\"components\":[]},{\"internalType\":\"uint256[]\",\"name\":\"rootBalances\",\"type\":\"uint256[]\",\"components\":[]},{\"internalType\":\"struct Summa.Asset[]\",\"name\":\"assets\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"string\",\"name\":\"assetName\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"string\",\"name\":\"chain\",\"type\":\"string\",\"components\":[]}]},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\",\"components\":[]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"submitCommitment\",\"outputs\":[]},{\"inputs\":[{\"internalType\":\"struct Summa.AddressOwnershipProof[]\",\"name\":\"_addressOwnershipProofs\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"string\",\"name\":\"cexAddress\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"string\",\"name\":\"chain\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\",\"components\":[]}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"submitProofOfAddressOwnership\",\"outputs\":[]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"components\":[]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\",\"outputs\":[]},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\",\"components\":[]},{\"internalType\":\"uint256[]\",\"name\":\"publicInputs\",\"type\":\"uint256[]\",\"components\":[]},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\",\"components\":[]}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"verifyInclusionProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\",\"components\":[]}]}]"; + const __ABI: &str = "[{\"inputs\":[{\"internalType\":\"contract IVerifier\",\"name\":\"_inclusionVerifier\",\"type\":\"address\",\"components\":[]}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\",\"outputs\":[]},{\"inputs\":[{\"internalType\":\"struct Summa.AddressOwnershipProof[]\",\"name\":\"addressOwnershipProofs\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"string\",\"name\":\"cexAddress\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"string\",\"name\":\"chain\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\",\"components\":[]}],\"indexed\":false}],\"type\":\"event\",\"name\":\"AddressOwnershipProofSubmitted\",\"outputs\":[],\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\",\"components\":[],\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"mstRoot\",\"type\":\"uint256\",\"components\":[],\"indexed\":false},{\"internalType\":\"uint256[]\",\"name\":\"rootBalances\",\"type\":\"uint256[]\",\"components\":[],\"indexed\":false},{\"internalType\":\"struct Summa.Cryptocurrency[]\",\"name\":\"cryptocurrencies\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"string\",\"name\":\"chain\",\"type\":\"string\",\"components\":[]}],\"indexed\":false}],\"type\":\"event\",\"name\":\"LiabilitiesCommitmentSubmitted\",\"outputs\":[],\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"components\":[],\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"components\":[],\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"outputs\":[],\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\",\"components\":[]}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"addressOwnershipProofs\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"cexAddress\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"string\",\"name\":\"chain\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\",\"components\":[]}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\",\"components\":[]}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"commitments\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"mstRoot\",\"type\":\"uint256\",\"components\":[]}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"addressHash\",\"type\":\"bytes32\",\"components\":[]}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getAddressOwnershipProof\",\"outputs\":[{\"internalType\":\"struct Summa.AddressOwnershipProof\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"string\",\"name\":\"cexAddress\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"string\",\"name\":\"chain\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\",\"components\":[]}]}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\",\"components\":[]}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\",\"outputs\":[]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"mstRoot\",\"type\":\"uint256\",\"components\":[]},{\"internalType\":\"uint256[]\",\"name\":\"rootBalances\",\"type\":\"uint256[]\",\"components\":[]},{\"internalType\":\"struct Summa.Cryptocurrency[]\",\"name\":\"cryptocurrencies\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"string\",\"name\":\"chain\",\"type\":\"string\",\"components\":[]}]},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\",\"components\":[]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"submitCommitment\",\"outputs\":[]},{\"inputs\":[{\"internalType\":\"struct Summa.AddressOwnershipProof[]\",\"name\":\"_addressOwnershipProofs\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"string\",\"name\":\"cexAddress\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"string\",\"name\":\"chain\",\"type\":\"string\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\",\"components\":[]},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\",\"components\":[]}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"submitProofOfAddressOwnership\",\"outputs\":[]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"components\":[]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\",\"outputs\":[]},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\",\"components\":[]},{\"internalType\":\"uint256[]\",\"name\":\"publicInputs\",\"type\":\"uint256[]\",\"components\":[]},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\",\"components\":[]}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"verifyInclusionProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\",\"components\":[]}]}]"; ///The parsed JSON ABI of the contract. pub static SUMMA_ABI: ::ethers::contract::Lazy<::ethers::core::abi::Abi> = ::ethers::contract::Lazy::new(|| ::ethers::core::utils::__serde_json::from_str(__ABI).expect("ABI is always valid")); @@ -41,14 +41,14 @@ pub mod summa { 98, 0, 27, - 216, + 237, 56, 3, 128, 98, 0, 27, - 216, + 237, 131, 57, 129, @@ -225,8 +225,8 @@ pub mod summa { 128, 81, 97, - 26, - 241, + 27, + 6, 98, 0, 0, @@ -242,8 +242,8 @@ pub mod summa { 1, 82, 97, - 26, - 241, + 27, + 6, 96, 0, 243, @@ -412,7 +412,7 @@ pub mod summa { 4, 97, 17, - 104, + 125, 86, 91, 97, @@ -430,7 +430,7 @@ pub mod summa { 144, 97, 18, - 60, + 81, 86, 91, 96, @@ -453,7 +453,7 @@ pub mod summa { 4, 97, 17, - 104, + 125, 86, 91, 96, @@ -536,7 +536,7 @@ pub mod summa { 4, 97, 17, - 104, + 125, 86, 91, 97, @@ -557,7 +557,7 @@ pub mod summa { 144, 97, 18, - 86, + 107, 86, 91, 97, @@ -571,7 +571,7 @@ pub mod summa { 4, 97, 19, - 213, + 234, 86, 91, 97, @@ -590,7 +590,7 @@ pub mod summa { 4, 97, 21, - 154, + 175, 86, 91, 97, @@ -625,7 +625,7 @@ pub mod summa { 4, 97, 22, - 7, + 28, 86, 91, 97, @@ -644,12 +644,12 @@ pub mod summa { 4, 97, 23, - 78, + 99, 86, 91, 97, 15, - 60, + 81, 86, 91, 97, @@ -808,7 +808,7 @@ pub mod summa { 144, 97, 23, - 141, + 162, 86, 91, 129, @@ -824,7 +824,7 @@ pub mod summa { 66, 97, 23, - 166, + 187, 86, 91, 144, @@ -865,7 +865,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -909,7 +909,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1011,7 +1011,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1055,7 +1055,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1157,7 +1157,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1201,7 +1201,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1303,7 +1303,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1347,7 +1347,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1448,7 +1448,7 @@ pub mod summa { 178, 97, 15, - 181, + 202, 86, 91, 97, @@ -1458,7 +1458,7 @@ pub mod summa { 0, 97, 16, - 15, + 36, 86, 91, 86, @@ -1511,7 +1511,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1555,7 +1555,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1653,7 +1653,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1697,7 +1697,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1795,7 +1795,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1839,7 +1839,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1937,7 +1937,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -1981,7 +1981,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -2076,7 +2076,7 @@ pub mod summa { 38, 97, 15, - 181, + 202, 86, 91, 96, @@ -2108,7 +2108,7 @@ pub mod summa { 70, 97, 23, - 166, + 187, 86, 91, 96, @@ -2135,8 +2135,8 @@ pub mod summa { 145, 144, 97, - 23, - 246, + 24, + 11, 86, 91, 96, @@ -2274,7 +2274,7 @@ pub mod summa { 236, 97, 23, - 166, + 187, 86, 91, 96, @@ -2324,7 +2324,7 @@ pub mod summa { 130, 97, 24, - 97, + 118, 86, 91, 80, @@ -2345,7 +2345,7 @@ pub mod summa { 130, 97, 24, - 97, + 118, 86, 91, 80, @@ -2366,7 +2366,7 @@ pub mod summa { 130, 97, 24, - 97, + 118, 86, 91, 80, @@ -2387,7 +2387,7 @@ pub mod summa { 130, 97, 24, - 97, + 118, 86, 91, 80, @@ -2428,7 +2428,7 @@ pub mod summa { 134, 97, 23, - 166, + 187, 86, 91, 96, @@ -2470,7 +2470,7 @@ pub mod summa { 176, 97, 23, - 166, + 187, 86, 91, 96, @@ -2513,7 +2513,7 @@ pub mod summa { 219, 97, 23, - 166, + 187, 86, 91, 96, @@ -2556,7 +2556,7 @@ pub mod summa { 6, 97, 23, - 166, + 187, 86, 91, 96, @@ -2674,7 +2674,7 @@ pub mod summa { 144, 97, 25, - 33, + 54, 86, 91, 145, @@ -2730,7 +2730,7 @@ pub mod summa { 144, 97, 25, - 58, + 79, 86, 91, 96, @@ -2762,7 +2762,7 @@ pub mod summa { 212, 97, 23, - 166, + 187, 86, 91, 96, @@ -2887,7 +2887,7 @@ pub mod summa { 81, 97, 23, - 166, + 187, 86, 91, 96, @@ -2930,7 +2930,7 @@ pub mod summa { 144, 97, 23, - 141, + 162, 86, 91, 129, @@ -2946,7 +2946,7 @@ pub mod summa { 140, 97, 23, - 166, + 187, 86, 91, 144, @@ -3035,7 +3035,7 @@ pub mod summa { 129, 97, 25, - 33, + 54, 86, 91, 145, @@ -3122,7 +3122,7 @@ pub mod summa { 1, 97, 25, - 215, + 236, 86, 91, 96, @@ -3186,8 +3186,8 @@ pub mod summa { 145, 144, 97, - 25, - 252, + 26, + 17, 86, 91, 148, @@ -3203,7 +3203,7 @@ pub mod summa { 141, 97, 15, - 181, + 202, 86, 91, 131, @@ -3280,7 +3280,7 @@ pub mod summa { 20, 97, 12, - 51, + 63, 87, 96, 64, @@ -3302,7 +3302,7 @@ pub mod summa { 1, 82, 96, - 41, + 53, 96, 36, 130, @@ -3314,11 +3314,17 @@ pub mod summa { 111, 116, 32, + 108, + 105, 97, - 115, - 115, - 101, + 98, + 105, + 108, + 105, 116, + 105, + 101, + 115, 32, 115, 117, @@ -3329,25 +3335,31 @@ pub mod summa { 110, 100, 32, + 108, + 105, 97, - 115, - 115, - 101, - 116, - 32, - 110, - 117, - 109, 98, - 101, - 114, + 105, + 108, 96, 68, 130, 1, 82, - 104, - 4, + 116, + 13, + 46, + 141, + 44, + 174, + 100, + 13, + 206, + 173, + 172, + 76, + 174, + 68, 13, 173, 46, @@ -3357,7 +3369,7 @@ pub mod summa { 140, 109, 96, - 187, + 91, 27, 96, 100, @@ -3390,14 +3402,14 @@ pub mod summa { 21, 97, 12, - 79, + 91, 87, 97, 12, - 79, + 91, 97, 18, - 174, + 195, 86, 91, 96, @@ -3423,7 +3435,7 @@ pub mod summa { 21, 97, 12, - 130, + 142, 87, 129, 96, @@ -3446,7 +3458,7 @@ pub mod summa { 129, 97, 12, - 109, + 121, 87, 144, 80, @@ -3472,14 +3484,14 @@ pub mod summa { 21, 97, 12, - 161, + 173, 87, 97, 12, - 161, + 173, 97, 18, - 174, + 195, 86, 91, 96, @@ -3505,7 +3517,7 @@ pub mod summa { 21, 97, 12, - 212, + 224, 87, 129, 96, @@ -3528,7 +3540,7 @@ pub mod summa { 129, 97, 12, - 191, + 203, 87, 144, 80, @@ -3546,7 +3558,7 @@ pub mod summa { 21, 97, 14, - 113, + 134, 87, 132, 129, @@ -3555,15 +3567,15 @@ pub mod summa { 129, 16, 97, - 12, - 245, + 13, + 1, 87, 97, - 12, - 245, + 13, + 1, 97, 23, - 166, + 187, 86, 91, 96, @@ -3587,7 +3599,7 @@ pub mod summa { 21, 97, 13, - 49, + 61, 87, 80, 132, @@ -3598,14 +3610,14 @@ pub mod summa { 16, 97, 13, - 31, + 43, 87, 97, 13, - 31, + 43, 97, 23, - 166, + 187, 86, 91, 96, @@ -3628,7 +3640,7 @@ pub mod summa { 91, 97, 13, - 109, + 130, 87, 96, 64, @@ -3650,28 +3662,37 @@ pub mod summa { 1, 82, 96, - 13, + 22, 96, 36, 130, 1, 82, + 117, + 73, + 110, + 118, + 97, 108, - 18, - 91, - 157, - 152, - 91, - 26, - 89, - 8, - 24, - 92, - 220, - 217, - 93, + 105, + 100, + 32, + 99, + 114, + 121, + 112, + 116, + 111, + 99, + 117, + 114, + 114, + 101, + 110, + 99, + 121, 96, - 154, + 80, 27, 96, 68, @@ -3694,14 +3715,14 @@ pub mod summa { 16, 97, 13, - 127, + 148, 87, 97, 13, - 127, + 148, 97, 23, - 166, + 187, 86, 91, 96, @@ -3717,7 +3738,7 @@ pub mod summa { 3, 97, 13, - 232, + 253, 87, 96, 64, @@ -3816,15 +3837,15 @@ pub mod summa { 129, 16, 97, - 13, - 250, + 14, + 15, 87, 97, - 13, - 250, + 14, + 15, 97, 23, - 166, + 187, 86, 91, 96, @@ -3847,14 +3868,14 @@ pub mod summa { 16, 97, 14, - 24, + 45, 87, 97, 14, - 24, + 45, 97, 23, - 166, + 187, 86, 91, 96, @@ -3876,14 +3897,14 @@ pub mod summa { 16, 97, 14, - 53, + 74, 87, 97, 14, - 53, + 74, 97, 23, - 166, + 187, 86, 91, 96, @@ -3906,14 +3927,14 @@ pub mod summa { 16, 97, 14, - 83, + 104, 87, 97, 14, - 83, + 104, 97, 23, - 166, + 187, 86, 91, 96, @@ -3931,11 +3952,11 @@ pub mod summa { 128, 97, 14, - 105, + 126, 144, 97, 25, - 33, + 54, 86, 91, 145, @@ -3943,7 +3964,7 @@ pub mod summa { 80, 97, 12, - 218, + 230, 86, 91, 80, @@ -4007,7 +4028,7 @@ pub mod summa { 146, 97, 14, - 188, + 209, 146, 96, 1, @@ -4018,7 +4039,7 @@ pub mod summa { 144, 97, 16, - 95, + 116, 86, 91, 80, @@ -4031,7 +4052,7 @@ pub mod summa { 81, 97, 14, - 216, + 237, 145, 96, 2, @@ -4046,7 +4067,7 @@ pub mod summa { 144, 97, 16, - 170, + 191, 86, 91, 80, @@ -4058,8 +4079,8 @@ pub mod summa { 128, 81, 97, - 14, - 244, + 15, + 9, 145, 96, 3, @@ -4074,7 +4095,7 @@ pub mod summa { 144, 97, 16, - 170, + 191, 86, 91, 80, @@ -4123,14 +4144,14 @@ pub mod summa { 81, 97, 15, - 44, + 65, 147, 146, 145, 144, 97, 26, - 30, + 51, 86, 91, 96, @@ -4151,10 +4172,10 @@ pub mod summa { 91, 97, 15, - 68, + 89, 97, 15, - 181, + 202, 86, 91, 96, @@ -4169,7 +4190,7 @@ pub mod summa { 22, 97, 15, - 169, + 190, 87, 96, 64, @@ -4260,11 +4281,11 @@ pub mod summa { 91, 97, 15, - 178, + 199, 129, 97, 16, - 15, + 36, 86, 91, 80, @@ -4463,7 +4484,7 @@ pub mod summa { 21, 97, 16, - 154, + 175, 87, 145, 96, @@ -4478,7 +4499,7 @@ pub mod summa { 21, 97, 16, - 154, + 175, 87, 130, 81, @@ -4496,19 +4517,19 @@ pub mod summa { 144, 97, 16, - 127, + 148, 86, 91, 80, 97, 16, - 166, + 187, 146, 145, 80, 97, - 16, - 252, + 17, + 17, 86, 91, 80, @@ -4537,8 +4558,8 @@ pub mod summa { 130, 21, 97, - 16, - 240, + 17, + 5, 87, 145, 96, @@ -4552,8 +4573,8 @@ pub mod summa { 17, 21, 97, - 16, - 240, + 17, + 5, 87, 130, 81, @@ -4561,12 +4582,12 @@ pub mod summa { 144, 97, 16, - 224, + 245, 144, 130, 97, 24, - 97, + 118, 86, 91, 80, @@ -4582,19 +4603,19 @@ pub mod summa { 144, 97, 16, - 202, + 223, 86, 91, 80, 97, 16, - 166, + 187, 146, 145, 80, 97, 17, - 17, + 38, 86, 91, 91, @@ -4604,7 +4625,7 @@ pub mod summa { 21, 97, 16, - 166, + 187, 87, 96, 0, @@ -4614,8 +4635,8 @@ pub mod summa { 1, 1, 97, - 16, - 253, + 17, + 18, 86, 91, 128, @@ -4624,18 +4645,18 @@ pub mod summa { 21, 97, 16, - 166, + 187, 87, 96, 0, 97, 17, - 37, + 58, 130, 130, 97, 17, - 46, + 67, 86, 91, 80, @@ -4644,7 +4665,7 @@ pub mod summa { 1, 97, 17, - 17, + 38, 86, 91, 80, @@ -4652,11 +4673,11 @@ pub mod summa { 84, 97, 17, - 58, + 79, 144, 97, 23, - 188, + 209, 86, 91, 96, @@ -4669,7 +4690,7 @@ pub mod summa { 16, 97, 17, - 74, + 95, 87, 80, 80, @@ -4697,12 +4718,12 @@ pub mod summa { 144, 97, 15, - 178, + 199, 145, 144, 97, - 16, - 252, + 17, + 17, 86, 91, 96, @@ -4716,7 +4737,7 @@ pub mod summa { 21, 97, 17, - 122, + 143, 87, 96, 0, @@ -4739,7 +4760,7 @@ pub mod summa { 21, 97, 17, - 156, + 177, 87, 129, 129, @@ -4754,7 +4775,7 @@ pub mod summa { 1, 97, 17, - 132, + 153, 86, 91, 80, @@ -4775,7 +4796,7 @@ pub mod summa { 82, 97, 17, - 189, + 210, 129, 96, 32, @@ -4787,7 +4808,7 @@ pub mod summa { 1, 97, 17, - 129, + 150, 86, 91, 96, @@ -4820,7 +4841,7 @@ pub mod summa { 82, 97, 17, - 230, + 251, 96, 128, 133, @@ -4828,7 +4849,7 @@ pub mod summa { 130, 97, 17, - 165, + 186, 86, 91, 144, @@ -4847,13 +4868,13 @@ pub mod summa { 1, 82, 97, - 17, - 255, + 18, + 20, 130, 130, 97, 17, - 165, + 186, 86, 91, 145, @@ -4874,12 +4895,12 @@ pub mod summa { 82, 97, 18, - 25, + 46, 130, 130, 97, 17, - 165, + 186, 86, 91, 145, @@ -4900,12 +4921,12 @@ pub mod summa { 82, 97, 18, - 51, + 72, 130, 130, 97, 17, - 165, + 186, 86, 91, 149, @@ -4925,7 +4946,7 @@ pub mod summa { 0, 97, 18, - 79, + 100, 96, 32, 131, @@ -4933,7 +4954,7 @@ pub mod summa { 132, 97, 17, - 209, + 230, 86, 91, 147, @@ -4951,7 +4972,7 @@ pub mod summa { 0, 97, 18, - 105, + 126, 96, 128, 131, @@ -4959,7 +4980,7 @@ pub mod summa { 135, 97, 17, - 165, + 186, 86, 91, 130, @@ -4972,12 +4993,12 @@ pub mod summa { 82, 97, 18, - 123, + 144, 129, 135, 97, 17, - 165, + 186, 86, 91, 144, @@ -4992,12 +5013,12 @@ pub mod summa { 82, 97, 18, - 143, + 164, 129, 134, 97, 17, - 165, + 186, 86, 91, 144, @@ -5012,12 +5033,12 @@ pub mod summa { 82, 97, 18, - 163, + 184, 129, 133, 97, 17, - 165, + 186, 86, 91, 151, @@ -5078,14 +5099,14 @@ pub mod summa { 21, 97, 18, - 231, + 252, 87, 97, 18, - 231, + 252, 97, 18, - 174, + 195, 86, 91, 96, @@ -5119,14 +5140,14 @@ pub mod summa { 21, 97, 18, - 231, + 252, 87, 97, 18, - 231, + 252, 97, 18, - 174, + 195, 86, 91, 96, @@ -5160,14 +5181,14 @@ pub mod summa { 21, 97, 19, - 57, + 78, 87, 97, 19, - 57, + 78, 97, 18, - 174, + 195, 86, 91, 96, @@ -5194,14 +5215,14 @@ pub mod summa { 21, 97, 19, - 91, + 112, 87, 97, 19, - 91, + 112, 97, 18, - 174, + 195, 86, 91, 80, @@ -5224,7 +5245,7 @@ pub mod summa { 18, 97, 19, - 118, + 139, 87, 96, 0, @@ -5247,19 +5268,19 @@ pub mod summa { 21, 97, 19, - 144, + 165, 87, 97, 19, - 144, + 165, 97, 18, - 174, + 195, 86, 91, 97, 19, - 163, + 184, 96, 31, 130, @@ -5273,7 +5294,7 @@ pub mod summa { 1, 97, 19, - 16, + 37, 86, 91, 129, @@ -5290,7 +5311,7 @@ pub mod summa { 21, 97, 19, - 184, + 205, 87, 96, 0, @@ -5338,7 +5359,7 @@ pub mod summa { 21, 97, 19, - 232, + 253, 87, 96, 0, @@ -5362,7 +5383,7 @@ pub mod summa { 21, 97, 20, - 0, + 21, 87, 96, 0, @@ -5382,7 +5403,7 @@ pub mod summa { 18, 97, 20, - 20, + 41, 87, 96, 0, @@ -5393,19 +5414,19 @@ pub mod summa { 53, 97, 20, - 39, + 60, 97, 20, - 34, + 55, 130, 97, 19, - 65, + 86, 86, 91, 97, 19, - 16, + 37, 86, 91, 129, @@ -5432,7 +5453,7 @@ pub mod summa { 21, 97, 20, - 70, + 91, 87, 96, 0, @@ -5449,7 +5470,7 @@ pub mod summa { 21, 97, 21, - 39, + 60, 87, 128, 53, @@ -5459,7 +5480,7 @@ pub mod summa { 21, 97, 20, - 97, + 118, 87, 96, 0, @@ -5481,7 +5502,7 @@ pub mod summa { 21, 97, 20, - 120, + 141, 87, 96, 0, @@ -5491,10 +5512,10 @@ pub mod summa { 91, 97, 20, - 128, + 149, 97, 18, - 196, + 217, 86, 91, 136, @@ -5507,7 +5528,7 @@ pub mod summa { 21, 97, 20, - 146, + 167, 87, 96, 0, @@ -5517,7 +5538,7 @@ pub mod summa { 91, 97, 20, - 160, + 181, 141, 139, 131, @@ -5526,7 +5547,7 @@ pub mod summa { 1, 97, 19, - 101, + 122, 86, 91, 130, @@ -5544,7 +5565,7 @@ pub mod summa { 21, 97, 20, - 183, + 204, 87, 96, 0, @@ -5554,7 +5575,7 @@ pub mod summa { 91, 97, 20, - 197, + 218, 142, 140, 131, @@ -5563,7 +5584,7 @@ pub mod summa { 1, 97, 19, - 101, + 122, 86, 91, 139, @@ -5583,7 +5604,7 @@ pub mod summa { 21, 97, 20, - 222, + 243, 87, 96, 0, @@ -5592,8 +5613,8 @@ pub mod summa { 253, 91, 97, - 20, - 236, + 21, + 1, 143, 141, 131, @@ -5602,7 +5623,7 @@ pub mod summa { 1, 97, 19, - 101, + 122, 86, 91, 131, @@ -5623,7 +5644,7 @@ pub mod summa { 21, 97, 21, - 6, + 27, 87, 96, 0, @@ -5633,7 +5654,7 @@ pub mod summa { 91, 97, 21, - 20, + 41, 142, 140, 132, @@ -5642,7 +5663,7 @@ pub mod summa { 1, 97, 19, - 101, + 122, 86, 91, 144, @@ -5661,7 +5682,7 @@ pub mod summa { 1, 97, 20, - 74, + 95, 86, 91, 80, @@ -5687,7 +5708,7 @@ pub mod summa { 18, 97, 21, - 69, + 90, 87, 96, 0, @@ -5700,14 +5721,14 @@ pub mod summa { 32, 97, 21, - 85, + 106, 97, 20, - 34, + 55, 131, 97, 19, - 65, + 86, 86, 91, 130, @@ -5734,7 +5755,7 @@ pub mod summa { 21, 97, 21, - 116, + 137, 87, 96, 0, @@ -5751,7 +5772,7 @@ pub mod summa { 21, 97, 21, - 143, + 164, 87, 128, 53, @@ -5765,7 +5786,7 @@ pub mod summa { 1, 97, 21, - 120, + 141, 86, 91, 80, @@ -5793,7 +5814,7 @@ pub mod summa { 21, 97, 21, - 175, + 196, 87, 96, 0, @@ -5817,7 +5838,7 @@ pub mod summa { 21, 97, 21, - 199, + 220, 87, 96, 0, @@ -5826,14 +5847,14 @@ pub mod summa { 91, 97, 21, - 211, + 232, 135, 131, 136, 1, 97, 19, - 101, + 122, 86, 91, 148, @@ -5851,7 +5872,7 @@ pub mod summa { 21, 97, 21, - 233, + 254, 87, 96, 0, @@ -5860,15 +5881,15 @@ pub mod summa { 91, 80, 97, - 21, - 246, + 22, + 11, 134, 130, 135, 1, 97, 21, - 52, + 73, 86, 91, 146, @@ -5903,7 +5924,7 @@ pub mod summa { 21, 97, 22, - 29, + 50, 87, 96, 0, @@ -5934,7 +5955,7 @@ pub mod summa { 21, 97, 22, - 60, + 81, 87, 96, 0, @@ -5943,14 +5964,14 @@ pub mod summa { 91, 97, 22, - 72, + 93, 136, 131, 137, 1, 97, 21, - 52, + 73, 86, 91, 148, @@ -5968,7 +5989,7 @@ pub mod summa { 21, 97, 22, - 94, + 115, 87, 96, 0, @@ -5988,7 +6009,7 @@ pub mod summa { 18, 97, 22, - 114, + 135, 87, 96, 0, @@ -5997,15 +6018,15 @@ pub mod summa { 91, 97, 22, - 127, + 148, 97, 20, - 34, + 55, 131, 53, 97, 19, - 65, + 86, 86, 91, 130, @@ -6032,7 +6053,7 @@ pub mod summa { 21, 97, 22, - 158, + 179, 87, 96, 0, @@ -6050,7 +6071,7 @@ pub mod summa { 21, 97, 23, - 58, + 79, 87, 132, 129, @@ -6059,7 +6080,7 @@ pub mod summa { 21, 97, 22, - 185, + 206, 87, 96, 0, @@ -6083,7 +6104,7 @@ pub mod summa { 21, 97, 22, - 209, + 230, 87, 96, 0, @@ -6092,10 +6113,10 @@ pub mod summa { 91, 97, 22, - 217, + 238, 97, - 18, - 237, + 19, + 2, 86, 91, 96, @@ -6108,8 +6129,8 @@ pub mod summa { 17, 21, 97, - 22, - 235, + 23, + 0, 87, 96, 0, @@ -6117,8 +6138,8 @@ pub mod summa { 253, 91, 97, - 22, - 250, + 23, + 15, 143, 96, 32, @@ -6128,7 +6149,7 @@ pub mod summa { 1, 97, 19, - 101, + 122, 86, 91, 130, @@ -6145,7 +6166,7 @@ pub mod summa { 21, 97, 23, - 15, + 36, 87, 96, 0, @@ -6154,7 +6175,7 @@ pub mod summa { 91, 97, 23, - 30, + 51, 143, 96, 32, @@ -6164,7 +6185,7 @@ pub mod summa { 1, 97, 19, - 101, + 122, 86, 91, 96, @@ -6192,7 +6213,7 @@ pub mod summa { 80, 97, 22, - 163, + 184, 86, 91, 80, @@ -6226,7 +6247,7 @@ pub mod summa { 21, 97, 23, - 96, + 117, 87, 96, 0, @@ -6249,7 +6270,7 @@ pub mod summa { 20, 97, 18, - 79, + 100, 87, 96, 0, @@ -6287,14 +6308,14 @@ pub mod summa { 21, 97, 23, - 160, + 181, 87, 97, 23, - 160, + 181, 97, 23, - 119, + 140, 86, 91, 146, @@ -6336,7 +6357,7 @@ pub mod summa { 128, 97, 23, - 208, + 229, 87, 96, 127, @@ -6352,8 +6373,8 @@ pub mod summa { 129, 3, 97, - 23, - 240, + 24, + 5, 87, 99, 78, @@ -6389,7 +6410,7 @@ pub mod summa { 81, 97, 24, - 8, + 29, 129, 132, 96, @@ -6398,7 +6419,7 @@ pub mod summa { 1, 97, 17, - 129, + 150, 86, 91, 145, @@ -6418,7 +6439,7 @@ pub mod summa { 21, 97, 24, - 92, + 113, 87, 96, 0, @@ -6445,7 +6466,7 @@ pub mod summa { 21, 97, 24, - 57, + 78, 87, 80, 128, @@ -6468,7 +6489,7 @@ pub mod summa { 21, 97, 24, - 88, + 109, 87, 130, 129, @@ -6478,7 +6499,7 @@ pub mod summa { 1, 97, 24, - 69, + 90, 86, 91, 80, @@ -6506,34 +6527,34 @@ pub mod summa { 21, 97, 24, - 123, + 144, 87, 97, 24, - 123, + 144, 97, 18, - 174, + 195, 86, 91, 97, 24, - 143, + 164, 129, 97, 24, - 137, + 158, 132, 84, 97, 23, - 188, + 209, 86, 91, 132, 97, 24, - 18, + 39, 86, 91, 96, @@ -6549,7 +6570,7 @@ pub mod summa { 20, 97, 24, - 196, + 217, 87, 96, 0, @@ -6557,7 +6578,7 @@ pub mod summa { 21, 97, 24, - 172, + 193, 87, 80, 133, @@ -6586,7 +6607,7 @@ pub mod summa { 85, 97, 24, - 88, + 109, 86, 91, 96, @@ -6610,8 +6631,8 @@ pub mod summa { 16, 21, 97, - 24, - 243, + 25, + 8, 87, 136, 134, @@ -6633,7 +6654,7 @@ pub mod summa { 1, 97, 24, - 212, + 233, 86, 91, 80, @@ -6643,7 +6664,7 @@ pub mod summa { 21, 97, 25, - 17, + 38, 87, 135, 133, @@ -6690,14 +6711,14 @@ pub mod summa { 1, 97, 25, - 51, + 72, 87, 97, 25, - 51, + 72, 97, 23, - 119, + 140, 86, 91, 80, @@ -6752,7 +6773,7 @@ pub mod summa { 21, 97, 25, - 143, + 164, 87, 96, 63, @@ -6765,13 +6786,13 @@ pub mod summa { 82, 97, 25, - 125, + 146, 133, 131, 81, 97, 17, - 209, + 230, 86, 91, 148, @@ -6789,7 +6810,7 @@ pub mod summa { 1, 97, 25, - 97, + 118, 86, 91, 80, @@ -6831,7 +6852,7 @@ pub mod summa { 21, 97, 25, - 204, + 225, 87, 129, 81, @@ -6850,7 +6871,7 @@ pub mod summa { 1, 97, 25, - 176, + 197, 86, 91, 80, @@ -6872,7 +6893,7 @@ pub mod summa { 0, 97, 25, - 234, + 255, 96, 64, 131, @@ -6880,7 +6901,7 @@ pub mod summa { 133, 97, 25, - 156, + 177, 86, 91, 130, @@ -6893,12 +6914,12 @@ pub mod summa { 82, 97, 18, - 51, + 72, 129, 133, 97, 17, - 165, + 186, 86, 91, 96, @@ -6912,7 +6933,7 @@ pub mod summa { 21, 97, 26, - 14, + 35, 87, 96, 0, @@ -6928,7 +6949,7 @@ pub mod summa { 20, 97, 18, - 79, + 100, 87, 96, 0, @@ -6950,7 +6971,7 @@ pub mod summa { 82, 97, 26, - 56, + 77, 96, 96, 132, @@ -6958,7 +6979,7 @@ pub mod summa { 134, 97, 25, - 156, + 177, 86, 91, 96, @@ -7001,7 +7022,7 @@ pub mod summa { 21, 97, 26, - 170, + 191, 87, 134, 131, @@ -7021,14 +7042,14 @@ pub mod summa { 82, 97, 26, - 126, + 147, 136, 134, 1, 130, 97, 17, - 165, + 186, 86, 91, 145, @@ -7047,12 +7068,12 @@ pub mod summa { 80, 97, 26, - 150, + 171, 129, 131, 97, 17, - 165, + 186, 86, 91, 150, @@ -7072,7 +7093,7 @@ pub mod summa { 1, 97, 26, - 90, + 111, 86, 91, 80, @@ -7102,38 +7123,38 @@ pub mod summa { 34, 18, 32, - 124, - 184, + 146, + 153, + 55, + 51, + 122, + 209, + 108, + 97, + 114, + 226, + 22, + 59, + 196, 94, - 160, - 56, - 218, - 95, - 187, - 77, - 36, - 61, - 175, - 218, - 16, + 211, + 145, + 63, + 229, + 31, + 142, + 92, + 232, + 202, + 195, + 172, + 128, + 115, + 208, + 21, + 147, 237, - 180, - 77, - 86, - 171, - 111, - 22, - 173, - 168, - 123, - 120, - 25, - 149, - 151, - 253, - 225, - 28, - 224, + 215, 100, 115, 111, @@ -7316,7 +7337,7 @@ pub mod summa { 4, 97, 17, - 104, + 125, 86, 91, 97, @@ -7334,7 +7355,7 @@ pub mod summa { 144, 97, 18, - 60, + 81, 86, 91, 96, @@ -7357,7 +7378,7 @@ pub mod summa { 4, 97, 17, - 104, + 125, 86, 91, 96, @@ -7440,7 +7461,7 @@ pub mod summa { 4, 97, 17, - 104, + 125, 86, 91, 97, @@ -7461,7 +7482,7 @@ pub mod summa { 144, 97, 18, - 86, + 107, 86, 91, 97, @@ -7475,7 +7496,7 @@ pub mod summa { 4, 97, 19, - 213, + 234, 86, 91, 97, @@ -7494,7 +7515,7 @@ pub mod summa { 4, 97, 21, - 154, + 175, 86, 91, 97, @@ -7529,7 +7550,7 @@ pub mod summa { 4, 97, 22, - 7, + 28, 86, 91, 97, @@ -7548,12 +7569,12 @@ pub mod summa { 4, 97, 23, - 78, + 99, 86, 91, 97, 15, - 60, + 81, 86, 91, 97, @@ -7712,7 +7733,7 @@ pub mod summa { 144, 97, 23, - 141, + 162, 86, 91, 129, @@ -7728,7 +7749,7 @@ pub mod summa { 66, 97, 23, - 166, + 187, 86, 91, 144, @@ -7769,7 +7790,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -7813,7 +7834,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -7915,7 +7936,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -7959,7 +7980,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -8061,7 +8082,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -8105,7 +8126,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -8207,7 +8228,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -8251,7 +8272,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -8352,7 +8373,7 @@ pub mod summa { 178, 97, 15, - 181, + 202, 86, 91, 97, @@ -8362,7 +8383,7 @@ pub mod summa { 0, 97, 16, - 15, + 36, 86, 91, 86, @@ -8415,7 +8436,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -8459,7 +8480,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -8557,7 +8578,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -8601,7 +8622,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -8699,7 +8720,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -8743,7 +8764,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -8841,7 +8862,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -8885,7 +8906,7 @@ pub mod summa { 144, 97, 23, - 188, + 209, 86, 91, 128, @@ -8980,7 +9001,7 @@ pub mod summa { 38, 97, 15, - 181, + 202, 86, 91, 96, @@ -9012,7 +9033,7 @@ pub mod summa { 70, 97, 23, - 166, + 187, 86, 91, 96, @@ -9039,8 +9060,8 @@ pub mod summa { 145, 144, 97, - 23, - 246, + 24, + 11, 86, 91, 96, @@ -9178,7 +9199,7 @@ pub mod summa { 236, 97, 23, - 166, + 187, 86, 91, 96, @@ -9228,7 +9249,7 @@ pub mod summa { 130, 97, 24, - 97, + 118, 86, 91, 80, @@ -9249,7 +9270,7 @@ pub mod summa { 130, 97, 24, - 97, + 118, 86, 91, 80, @@ -9270,7 +9291,7 @@ pub mod summa { 130, 97, 24, - 97, + 118, 86, 91, 80, @@ -9291,7 +9312,7 @@ pub mod summa { 130, 97, 24, - 97, + 118, 86, 91, 80, @@ -9332,7 +9353,7 @@ pub mod summa { 134, 97, 23, - 166, + 187, 86, 91, 96, @@ -9374,7 +9395,7 @@ pub mod summa { 176, 97, 23, - 166, + 187, 86, 91, 96, @@ -9417,7 +9438,7 @@ pub mod summa { 219, 97, 23, - 166, + 187, 86, 91, 96, @@ -9460,7 +9481,7 @@ pub mod summa { 6, 97, 23, - 166, + 187, 86, 91, 96, @@ -9578,7 +9599,7 @@ pub mod summa { 144, 97, 25, - 33, + 54, 86, 91, 145, @@ -9634,7 +9655,7 @@ pub mod summa { 144, 97, 25, - 58, + 79, 86, 91, 96, @@ -9666,7 +9687,7 @@ pub mod summa { 212, 97, 23, - 166, + 187, 86, 91, 96, @@ -9791,7 +9812,7 @@ pub mod summa { 81, 97, 23, - 166, + 187, 86, 91, 96, @@ -9834,7 +9855,7 @@ pub mod summa { 144, 97, 23, - 141, + 162, 86, 91, 129, @@ -9850,7 +9871,7 @@ pub mod summa { 140, 97, 23, - 166, + 187, 86, 91, 144, @@ -9939,7 +9960,7 @@ pub mod summa { 129, 97, 25, - 33, + 54, 86, 91, 145, @@ -10026,7 +10047,7 @@ pub mod summa { 1, 97, 25, - 215, + 236, 86, 91, 96, @@ -10090,8 +10111,8 @@ pub mod summa { 145, 144, 97, - 25, - 252, + 26, + 17, 86, 91, 148, @@ -10107,7 +10128,7 @@ pub mod summa { 141, 97, 15, - 181, + 202, 86, 91, 131, @@ -10184,7 +10205,7 @@ pub mod summa { 20, 97, 12, - 51, + 63, 87, 96, 64, @@ -10206,7 +10227,7 @@ pub mod summa { 1, 82, 96, - 41, + 53, 96, 36, 130, @@ -10218,11 +10239,17 @@ pub mod summa { 111, 116, 32, + 108, + 105, 97, - 115, - 115, - 101, + 98, + 105, + 108, + 105, 116, + 105, + 101, + 115, 32, 115, 117, @@ -10233,25 +10260,31 @@ pub mod summa { 110, 100, 32, + 108, + 105, 97, - 115, - 115, - 101, - 116, - 32, - 110, - 117, - 109, 98, - 101, - 114, + 105, + 108, 96, 68, 130, 1, 82, - 104, - 4, + 116, + 13, + 46, + 141, + 44, + 174, + 100, + 13, + 206, + 173, + 172, + 76, + 174, + 68, 13, 173, 46, @@ -10261,7 +10294,7 @@ pub mod summa { 140, 109, 96, - 187, + 91, 27, 96, 100, @@ -10294,14 +10327,14 @@ pub mod summa { 21, 97, 12, - 79, + 91, 87, 97, 12, - 79, + 91, 97, 18, - 174, + 195, 86, 91, 96, @@ -10327,7 +10360,7 @@ pub mod summa { 21, 97, 12, - 130, + 142, 87, 129, 96, @@ -10350,7 +10383,7 @@ pub mod summa { 129, 97, 12, - 109, + 121, 87, 144, 80, @@ -10376,14 +10409,14 @@ pub mod summa { 21, 97, 12, - 161, + 173, 87, 97, 12, - 161, + 173, 97, 18, - 174, + 195, 86, 91, 96, @@ -10409,7 +10442,7 @@ pub mod summa { 21, 97, 12, - 212, + 224, 87, 129, 96, @@ -10432,7 +10465,7 @@ pub mod summa { 129, 97, 12, - 191, + 203, 87, 144, 80, @@ -10450,7 +10483,7 @@ pub mod summa { 21, 97, 14, - 113, + 134, 87, 132, 129, @@ -10459,15 +10492,15 @@ pub mod summa { 129, 16, 97, - 12, - 245, + 13, + 1, 87, 97, - 12, - 245, + 13, + 1, 97, 23, - 166, + 187, 86, 91, 96, @@ -10491,7 +10524,7 @@ pub mod summa { 21, 97, 13, - 49, + 61, 87, 80, 132, @@ -10502,14 +10535,14 @@ pub mod summa { 16, 97, 13, - 31, + 43, 87, 97, 13, - 31, + 43, 97, 23, - 166, + 187, 86, 91, 96, @@ -10532,7 +10565,7 @@ pub mod summa { 91, 97, 13, - 109, + 130, 87, 96, 64, @@ -10554,28 +10587,37 @@ pub mod summa { 1, 82, 96, - 13, + 22, 96, 36, 130, 1, 82, + 117, + 73, + 110, + 118, + 97, 108, - 18, - 91, - 157, - 152, - 91, - 26, - 89, - 8, - 24, - 92, - 220, - 217, - 93, + 105, + 100, + 32, + 99, + 114, + 121, + 112, + 116, + 111, + 99, + 117, + 114, + 114, + 101, + 110, + 99, + 121, 96, - 154, + 80, 27, 96, 68, @@ -10598,14 +10640,14 @@ pub mod summa { 16, 97, 13, - 127, + 148, 87, 97, 13, - 127, + 148, 97, 23, - 166, + 187, 86, 91, 96, @@ -10621,7 +10663,7 @@ pub mod summa { 3, 97, 13, - 232, + 253, 87, 96, 64, @@ -10720,15 +10762,15 @@ pub mod summa { 129, 16, 97, - 13, - 250, + 14, + 15, 87, 97, - 13, - 250, + 14, + 15, 97, 23, - 166, + 187, 86, 91, 96, @@ -10751,14 +10793,14 @@ pub mod summa { 16, 97, 14, - 24, + 45, 87, 97, 14, - 24, + 45, 97, 23, - 166, + 187, 86, 91, 96, @@ -10780,14 +10822,14 @@ pub mod summa { 16, 97, 14, - 53, + 74, 87, 97, 14, - 53, + 74, 97, 23, - 166, + 187, 86, 91, 96, @@ -10810,14 +10852,14 @@ pub mod summa { 16, 97, 14, - 83, + 104, 87, 97, 14, - 83, + 104, 97, 23, - 166, + 187, 86, 91, 96, @@ -10835,11 +10877,11 @@ pub mod summa { 128, 97, 14, - 105, + 126, 144, 97, 25, - 33, + 54, 86, 91, 145, @@ -10847,7 +10889,7 @@ pub mod summa { 80, 97, 12, - 218, + 230, 86, 91, 80, @@ -10911,7 +10953,7 @@ pub mod summa { 146, 97, 14, - 188, + 209, 146, 96, 1, @@ -10922,7 +10964,7 @@ pub mod summa { 144, 97, 16, - 95, + 116, 86, 91, 80, @@ -10935,7 +10977,7 @@ pub mod summa { 81, 97, 14, - 216, + 237, 145, 96, 2, @@ -10950,7 +10992,7 @@ pub mod summa { 144, 97, 16, - 170, + 191, 86, 91, 80, @@ -10962,8 +11004,8 @@ pub mod summa { 128, 81, 97, - 14, - 244, + 15, + 9, 145, 96, 3, @@ -10978,7 +11020,7 @@ pub mod summa { 144, 97, 16, - 170, + 191, 86, 91, 80, @@ -11027,14 +11069,14 @@ pub mod summa { 81, 97, 15, - 44, + 65, 147, 146, 145, 144, 97, 26, - 30, + 51, 86, 91, 96, @@ -11055,10 +11097,10 @@ pub mod summa { 91, 97, 15, - 68, + 89, 97, 15, - 181, + 202, 86, 91, 96, @@ -11073,7 +11115,7 @@ pub mod summa { 22, 97, 15, - 169, + 190, 87, 96, 64, @@ -11164,11 +11206,11 @@ pub mod summa { 91, 97, 15, - 178, + 199, 129, 97, 16, - 15, + 36, 86, 91, 80, @@ -11367,7 +11409,7 @@ pub mod summa { 21, 97, 16, - 154, + 175, 87, 145, 96, @@ -11382,7 +11424,7 @@ pub mod summa { 21, 97, 16, - 154, + 175, 87, 130, 81, @@ -11400,19 +11442,19 @@ pub mod summa { 144, 97, 16, - 127, + 148, 86, 91, 80, 97, 16, - 166, + 187, 146, 145, 80, 97, - 16, - 252, + 17, + 17, 86, 91, 80, @@ -11441,8 +11483,8 @@ pub mod summa { 130, 21, 97, - 16, - 240, + 17, + 5, 87, 145, 96, @@ -11456,8 +11498,8 @@ pub mod summa { 17, 21, 97, - 16, - 240, + 17, + 5, 87, 130, 81, @@ -11465,12 +11507,12 @@ pub mod summa { 144, 97, 16, - 224, + 245, 144, 130, 97, 24, - 97, + 118, 86, 91, 80, @@ -11486,19 +11528,19 @@ pub mod summa { 144, 97, 16, - 202, + 223, 86, 91, 80, 97, 16, - 166, + 187, 146, 145, 80, 97, 17, - 17, + 38, 86, 91, 91, @@ -11508,7 +11550,7 @@ pub mod summa { 21, 97, 16, - 166, + 187, 87, 96, 0, @@ -11518,8 +11560,8 @@ pub mod summa { 1, 1, 97, - 16, - 253, + 17, + 18, 86, 91, 128, @@ -11528,18 +11570,18 @@ pub mod summa { 21, 97, 16, - 166, + 187, 87, 96, 0, 97, 17, - 37, + 58, 130, 130, 97, 17, - 46, + 67, 86, 91, 80, @@ -11548,7 +11590,7 @@ pub mod summa { 1, 97, 17, - 17, + 38, 86, 91, 80, @@ -11556,11 +11598,11 @@ pub mod summa { 84, 97, 17, - 58, + 79, 144, 97, 23, - 188, + 209, 86, 91, 96, @@ -11573,7 +11615,7 @@ pub mod summa { 16, 97, 17, - 74, + 95, 87, 80, 80, @@ -11601,12 +11643,12 @@ pub mod summa { 144, 97, 15, - 178, + 199, 145, 144, 97, - 16, - 252, + 17, + 17, 86, 91, 96, @@ -11620,7 +11662,7 @@ pub mod summa { 21, 97, 17, - 122, + 143, 87, 96, 0, @@ -11643,7 +11685,7 @@ pub mod summa { 21, 97, 17, - 156, + 177, 87, 129, 129, @@ -11658,7 +11700,7 @@ pub mod summa { 1, 97, 17, - 132, + 153, 86, 91, 80, @@ -11679,7 +11721,7 @@ pub mod summa { 82, 97, 17, - 189, + 210, 129, 96, 32, @@ -11691,7 +11733,7 @@ pub mod summa { 1, 97, 17, - 129, + 150, 86, 91, 96, @@ -11724,7 +11766,7 @@ pub mod summa { 82, 97, 17, - 230, + 251, 96, 128, 133, @@ -11732,7 +11774,7 @@ pub mod summa { 130, 97, 17, - 165, + 186, 86, 91, 144, @@ -11751,13 +11793,13 @@ pub mod summa { 1, 82, 97, - 17, - 255, + 18, + 20, 130, 130, 97, 17, - 165, + 186, 86, 91, 145, @@ -11778,12 +11820,12 @@ pub mod summa { 82, 97, 18, - 25, + 46, 130, 130, 97, 17, - 165, + 186, 86, 91, 145, @@ -11804,12 +11846,12 @@ pub mod summa { 82, 97, 18, - 51, + 72, 130, 130, 97, 17, - 165, + 186, 86, 91, 149, @@ -11829,7 +11871,7 @@ pub mod summa { 0, 97, 18, - 79, + 100, 96, 32, 131, @@ -11837,7 +11879,7 @@ pub mod summa { 132, 97, 17, - 209, + 230, 86, 91, 147, @@ -11855,7 +11897,7 @@ pub mod summa { 0, 97, 18, - 105, + 126, 96, 128, 131, @@ -11863,7 +11905,7 @@ pub mod summa { 135, 97, 17, - 165, + 186, 86, 91, 130, @@ -11876,12 +11918,12 @@ pub mod summa { 82, 97, 18, - 123, + 144, 129, 135, 97, 17, - 165, + 186, 86, 91, 144, @@ -11896,12 +11938,12 @@ pub mod summa { 82, 97, 18, - 143, + 164, 129, 134, 97, 17, - 165, + 186, 86, 91, 144, @@ -11916,12 +11958,12 @@ pub mod summa { 82, 97, 18, - 163, + 184, 129, 133, 97, 17, - 165, + 186, 86, 91, 151, @@ -11982,14 +12024,14 @@ pub mod summa { 21, 97, 18, - 231, + 252, 87, 97, 18, - 231, + 252, 97, 18, - 174, + 195, 86, 91, 96, @@ -12023,14 +12065,14 @@ pub mod summa { 21, 97, 18, - 231, + 252, 87, 97, 18, - 231, + 252, 97, 18, - 174, + 195, 86, 91, 96, @@ -12064,14 +12106,14 @@ pub mod summa { 21, 97, 19, - 57, + 78, 87, 97, 19, - 57, + 78, 97, 18, - 174, + 195, 86, 91, 96, @@ -12098,14 +12140,14 @@ pub mod summa { 21, 97, 19, - 91, + 112, 87, 97, 19, - 91, + 112, 97, 18, - 174, + 195, 86, 91, 80, @@ -12128,7 +12170,7 @@ pub mod summa { 18, 97, 19, - 118, + 139, 87, 96, 0, @@ -12151,19 +12193,19 @@ pub mod summa { 21, 97, 19, - 144, + 165, 87, 97, 19, - 144, + 165, 97, 18, - 174, + 195, 86, 91, 97, 19, - 163, + 184, 96, 31, 130, @@ -12177,7 +12219,7 @@ pub mod summa { 1, 97, 19, - 16, + 37, 86, 91, 129, @@ -12194,7 +12236,7 @@ pub mod summa { 21, 97, 19, - 184, + 205, 87, 96, 0, @@ -12242,7 +12284,7 @@ pub mod summa { 21, 97, 19, - 232, + 253, 87, 96, 0, @@ -12266,7 +12308,7 @@ pub mod summa { 21, 97, 20, - 0, + 21, 87, 96, 0, @@ -12286,7 +12328,7 @@ pub mod summa { 18, 97, 20, - 20, + 41, 87, 96, 0, @@ -12297,19 +12339,19 @@ pub mod summa { 53, 97, 20, - 39, + 60, 97, 20, - 34, + 55, 130, 97, 19, - 65, + 86, 86, 91, 97, 19, - 16, + 37, 86, 91, 129, @@ -12336,7 +12378,7 @@ pub mod summa { 21, 97, 20, - 70, + 91, 87, 96, 0, @@ -12353,7 +12395,7 @@ pub mod summa { 21, 97, 21, - 39, + 60, 87, 128, 53, @@ -12363,7 +12405,7 @@ pub mod summa { 21, 97, 20, - 97, + 118, 87, 96, 0, @@ -12385,7 +12427,7 @@ pub mod summa { 21, 97, 20, - 120, + 141, 87, 96, 0, @@ -12395,10 +12437,10 @@ pub mod summa { 91, 97, 20, - 128, + 149, 97, 18, - 196, + 217, 86, 91, 136, @@ -12411,7 +12453,7 @@ pub mod summa { 21, 97, 20, - 146, + 167, 87, 96, 0, @@ -12421,7 +12463,7 @@ pub mod summa { 91, 97, 20, - 160, + 181, 141, 139, 131, @@ -12430,7 +12472,7 @@ pub mod summa { 1, 97, 19, - 101, + 122, 86, 91, 130, @@ -12448,7 +12490,7 @@ pub mod summa { 21, 97, 20, - 183, + 204, 87, 96, 0, @@ -12458,7 +12500,7 @@ pub mod summa { 91, 97, 20, - 197, + 218, 142, 140, 131, @@ -12467,7 +12509,7 @@ pub mod summa { 1, 97, 19, - 101, + 122, 86, 91, 139, @@ -12487,7 +12529,7 @@ pub mod summa { 21, 97, 20, - 222, + 243, 87, 96, 0, @@ -12496,8 +12538,8 @@ pub mod summa { 253, 91, 97, - 20, - 236, + 21, + 1, 143, 141, 131, @@ -12506,7 +12548,7 @@ pub mod summa { 1, 97, 19, - 101, + 122, 86, 91, 131, @@ -12527,7 +12569,7 @@ pub mod summa { 21, 97, 21, - 6, + 27, 87, 96, 0, @@ -12537,7 +12579,7 @@ pub mod summa { 91, 97, 21, - 20, + 41, 142, 140, 132, @@ -12546,7 +12588,7 @@ pub mod summa { 1, 97, 19, - 101, + 122, 86, 91, 144, @@ -12565,7 +12607,7 @@ pub mod summa { 1, 97, 20, - 74, + 95, 86, 91, 80, @@ -12591,7 +12633,7 @@ pub mod summa { 18, 97, 21, - 69, + 90, 87, 96, 0, @@ -12604,14 +12646,14 @@ pub mod summa { 32, 97, 21, - 85, + 106, 97, 20, - 34, + 55, 131, 97, 19, - 65, + 86, 86, 91, 130, @@ -12638,7 +12680,7 @@ pub mod summa { 21, 97, 21, - 116, + 137, 87, 96, 0, @@ -12655,7 +12697,7 @@ pub mod summa { 21, 97, 21, - 143, + 164, 87, 128, 53, @@ -12669,7 +12711,7 @@ pub mod summa { 1, 97, 21, - 120, + 141, 86, 91, 80, @@ -12697,7 +12739,7 @@ pub mod summa { 21, 97, 21, - 175, + 196, 87, 96, 0, @@ -12721,7 +12763,7 @@ pub mod summa { 21, 97, 21, - 199, + 220, 87, 96, 0, @@ -12730,14 +12772,14 @@ pub mod summa { 91, 97, 21, - 211, + 232, 135, 131, 136, 1, 97, 19, - 101, + 122, 86, 91, 148, @@ -12755,7 +12797,7 @@ pub mod summa { 21, 97, 21, - 233, + 254, 87, 96, 0, @@ -12764,15 +12806,15 @@ pub mod summa { 91, 80, 97, - 21, - 246, + 22, + 11, 134, 130, 135, 1, 97, 21, - 52, + 73, 86, 91, 146, @@ -12807,7 +12849,7 @@ pub mod summa { 21, 97, 22, - 29, + 50, 87, 96, 0, @@ -12838,7 +12880,7 @@ pub mod summa { 21, 97, 22, - 60, + 81, 87, 96, 0, @@ -12847,14 +12889,14 @@ pub mod summa { 91, 97, 22, - 72, + 93, 136, 131, 137, 1, 97, 21, - 52, + 73, 86, 91, 148, @@ -12872,7 +12914,7 @@ pub mod summa { 21, 97, 22, - 94, + 115, 87, 96, 0, @@ -12892,7 +12934,7 @@ pub mod summa { 18, 97, 22, - 114, + 135, 87, 96, 0, @@ -12901,15 +12943,15 @@ pub mod summa { 91, 97, 22, - 127, + 148, 97, 20, - 34, + 55, 131, 53, 97, 19, - 65, + 86, 86, 91, 130, @@ -12936,7 +12978,7 @@ pub mod summa { 21, 97, 22, - 158, + 179, 87, 96, 0, @@ -12954,7 +12996,7 @@ pub mod summa { 21, 97, 23, - 58, + 79, 87, 132, 129, @@ -12963,7 +13005,7 @@ pub mod summa { 21, 97, 22, - 185, + 206, 87, 96, 0, @@ -12987,7 +13029,7 @@ pub mod summa { 21, 97, 22, - 209, + 230, 87, 96, 0, @@ -12996,10 +13038,10 @@ pub mod summa { 91, 97, 22, - 217, + 238, 97, - 18, - 237, + 19, + 2, 86, 91, 96, @@ -13012,8 +13054,8 @@ pub mod summa { 17, 21, 97, - 22, - 235, + 23, + 0, 87, 96, 0, @@ -13021,8 +13063,8 @@ pub mod summa { 253, 91, 97, - 22, - 250, + 23, + 15, 143, 96, 32, @@ -13032,7 +13074,7 @@ pub mod summa { 1, 97, 19, - 101, + 122, 86, 91, 130, @@ -13049,7 +13091,7 @@ pub mod summa { 21, 97, 23, - 15, + 36, 87, 96, 0, @@ -13058,7 +13100,7 @@ pub mod summa { 91, 97, 23, - 30, + 51, 143, 96, 32, @@ -13068,7 +13110,7 @@ pub mod summa { 1, 97, 19, - 101, + 122, 86, 91, 96, @@ -13096,7 +13138,7 @@ pub mod summa { 80, 97, 22, - 163, + 184, 86, 91, 80, @@ -13130,7 +13172,7 @@ pub mod summa { 21, 97, 23, - 96, + 117, 87, 96, 0, @@ -13153,7 +13195,7 @@ pub mod summa { 20, 97, 18, - 79, + 100, 87, 96, 0, @@ -13191,14 +13233,14 @@ pub mod summa { 21, 97, 23, - 160, + 181, 87, 97, 23, - 160, + 181, 97, 23, - 119, + 140, 86, 91, 146, @@ -13240,7 +13282,7 @@ pub mod summa { 128, 97, 23, - 208, + 229, 87, 96, 127, @@ -13256,8 +13298,8 @@ pub mod summa { 129, 3, 97, - 23, - 240, + 24, + 5, 87, 99, 78, @@ -13293,7 +13335,7 @@ pub mod summa { 81, 97, 24, - 8, + 29, 129, 132, 96, @@ -13302,7 +13344,7 @@ pub mod summa { 1, 97, 17, - 129, + 150, 86, 91, 145, @@ -13322,7 +13364,7 @@ pub mod summa { 21, 97, 24, - 92, + 113, 87, 96, 0, @@ -13349,7 +13391,7 @@ pub mod summa { 21, 97, 24, - 57, + 78, 87, 80, 128, @@ -13372,7 +13414,7 @@ pub mod summa { 21, 97, 24, - 88, + 109, 87, 130, 129, @@ -13382,7 +13424,7 @@ pub mod summa { 1, 97, 24, - 69, + 90, 86, 91, 80, @@ -13410,34 +13452,34 @@ pub mod summa { 21, 97, 24, - 123, + 144, 87, 97, 24, - 123, + 144, 97, 18, - 174, + 195, 86, 91, 97, 24, - 143, + 164, 129, 97, 24, - 137, + 158, 132, 84, 97, 23, - 188, + 209, 86, 91, 132, 97, 24, - 18, + 39, 86, 91, 96, @@ -13453,7 +13495,7 @@ pub mod summa { 20, 97, 24, - 196, + 217, 87, 96, 0, @@ -13461,7 +13503,7 @@ pub mod summa { 21, 97, 24, - 172, + 193, 87, 80, 133, @@ -13490,7 +13532,7 @@ pub mod summa { 85, 97, 24, - 88, + 109, 86, 91, 96, @@ -13514,8 +13556,8 @@ pub mod summa { 16, 21, 97, - 24, - 243, + 25, + 8, 87, 136, 134, @@ -13537,7 +13579,7 @@ pub mod summa { 1, 97, 24, - 212, + 233, 86, 91, 80, @@ -13547,7 +13589,7 @@ pub mod summa { 21, 97, 25, - 17, + 38, 87, 135, 133, @@ -13594,14 +13636,14 @@ pub mod summa { 1, 97, 25, - 51, + 72, 87, 97, 25, - 51, + 72, 97, 23, - 119, + 140, 86, 91, 80, @@ -13656,7 +13698,7 @@ pub mod summa { 21, 97, 25, - 143, + 164, 87, 96, 63, @@ -13669,13 +13711,13 @@ pub mod summa { 82, 97, 25, - 125, + 146, 133, 131, 81, 97, 17, - 209, + 230, 86, 91, 148, @@ -13693,7 +13735,7 @@ pub mod summa { 1, 97, 25, - 97, + 118, 86, 91, 80, @@ -13735,7 +13777,7 @@ pub mod summa { 21, 97, 25, - 204, + 225, 87, 129, 81, @@ -13754,7 +13796,7 @@ pub mod summa { 1, 97, 25, - 176, + 197, 86, 91, 80, @@ -13776,7 +13818,7 @@ pub mod summa { 0, 97, 25, - 234, + 255, 96, 64, 131, @@ -13784,7 +13826,7 @@ pub mod summa { 133, 97, 25, - 156, + 177, 86, 91, 130, @@ -13797,12 +13839,12 @@ pub mod summa { 82, 97, 18, - 51, + 72, 129, 133, 97, 17, - 165, + 186, 86, 91, 96, @@ -13816,7 +13858,7 @@ pub mod summa { 21, 97, 26, - 14, + 35, 87, 96, 0, @@ -13832,7 +13874,7 @@ pub mod summa { 20, 97, 18, - 79, + 100, 87, 96, 0, @@ -13854,7 +13896,7 @@ pub mod summa { 82, 97, 26, - 56, + 77, 96, 96, 132, @@ -13862,7 +13904,7 @@ pub mod summa { 134, 97, 25, - 156, + 177, 86, 91, 96, @@ -13905,7 +13947,7 @@ pub mod summa { 21, 97, 26, - 170, + 191, 87, 134, 131, @@ -13925,14 +13967,14 @@ pub mod summa { 82, 97, 26, - 126, + 147, 136, 134, 1, 130, 97, 17, - 165, + 186, 86, 91, 145, @@ -13951,12 +13993,12 @@ pub mod summa { 80, 97, 26, - 150, + 171, 129, 131, 97, 17, - 165, + 186, 86, 91, 150, @@ -13976,7 +14018,7 @@ pub mod summa { 1, 97, 26, - 90, + 111, 86, 91, 80, @@ -14006,38 +14048,38 @@ pub mod summa { 34, 18, 32, - 124, - 184, + 146, + 153, + 55, + 51, + 122, + 209, + 108, + 97, + 114, + 226, + 22, + 59, + 196, 94, - 160, - 56, - 218, - 95, - 187, - 77, - 36, - 61, - 175, - 218, - 16, + 211, + 145, + 63, + 229, + 31, + 142, + 92, + 232, + 202, + 195, + 172, + 128, + 115, + 208, + 21, + 147, 237, - 180, - 77, - 86, - 171, - 111, - 22, - 173, - 168, - 123, - 120, - 25, - 149, - 151, - 253, - 225, - 28, - 224, + 215, 100, 115, 111, @@ -14189,13 +14231,13 @@ pub mod summa { &self, mst_root: ::ethers::core::types::U256, root_balances: ::std::vec::Vec<::ethers::core::types::U256>, - assets: ::std::vec::Vec, + cryptocurrencies: ::std::vec::Vec, timestamp: ::ethers::core::types::U256, ) -> ::ethers::contract::builders::ContractCall { self.0 .method_hash( [218, 100, 167, 80], - (mst_root, root_balances, assets, timestamp), + (mst_root, root_balances, cryptocurrencies, timestamp), ) .expect("method not found (this should never happen)") } @@ -14307,7 +14349,7 @@ pub mod summa { pub timestamp: ::ethers::core::types::U256, pub mst_root: ::ethers::core::types::U256, pub root_balances: ::std::vec::Vec<::ethers::core::types::U256>, - pub assets: ::std::vec::Vec, + pub cryptocurrencies: ::std::vec::Vec, } #[derive( Clone, @@ -14470,7 +14512,7 @@ pub mod summa { pub struct SubmitCommitmentCall { pub mst_root: ::ethers::core::types::U256, pub root_balances: ::std::vec::Vec<::ethers::core::types::U256>, - pub assets: ::std::vec::Vec, + pub cryptocurrencies: ::std::vec::Vec, pub timestamp: ::ethers::core::types::U256, } ///Container type for all input parameters for the `submitProofOfAddressOwnership` function with signature `submitProofOfAddressOwnership((string,string,bytes,bytes)[])` and selector `0xc7ddca0e` @@ -14780,7 +14822,7 @@ pub mod summa { pub signature: ::ethers::core::types::Bytes, pub message: ::ethers::core::types::Bytes, } - ///`Asset(string,string)` + ///`Cryptocurrency(string,string)` #[derive( Clone, ::ethers::contract::EthAbiType, @@ -14791,8 +14833,8 @@ pub mod summa { Eq, Hash )] - pub struct Asset { - pub asset_name: ::std::string::String, + pub struct Cryptocurrency { + pub name: ::std::string::String, pub chain: ::std::string::String, } } diff --git a/backend/src/contracts/signer.rs b/backend/src/contracts/signer.rs index 36b6e1c7..abab24ef 100644 --- a/backend/src/contracts/signer.rs +++ b/backend/src/contracts/signer.rs @@ -8,7 +8,7 @@ use serde_json::Value; use std::{error::Error, fs::File, io::BufReader, path::Path, str::FromStr, sync::Arc}; use tokio::sync::Mutex; -use super::generated::summa_contract::{AddressOwnershipProof, Asset}; +use super::generated::summa_contract::{AddressOwnershipProof, Cryptocurrency}; use crate::contracts::generated::summa_contract::Summa; pub enum AddressInput { @@ -108,14 +108,17 @@ impl SummaSigner { &self, mst_root: U256, root_sums: Vec, - assets: Vec, + cryptocurrencies: Vec, timestamp: U256, ) -> Result<(), Box> { let lock_guard = self.nonce_lock.lock().await; - let submit_liability_commitment = &self - .summa_contract - .submit_commitment(mst_root, root_sums, assets, timestamp); + let submit_liability_commitment = &self.summa_contract.submit_commitment( + mst_root, + root_sums, + cryptocurrencies, + timestamp, + ); // To prevent nonce collision, we lock the nonce before sending the transaction let tx = submit_liability_commitment.send().await?; diff --git a/backend/src/tests.rs b/backend/src/tests.rs index 70acc69e..ec0f6173 100644 --- a/backend/src/tests.rs +++ b/backend/src/tests.rs @@ -121,7 +121,7 @@ mod test { use crate::apis::{address_ownership::AddressOwnership, round::Round}; use crate::contracts::{ generated::summa_contract::{ - AddressOwnershipProof, AddressOwnershipProofSubmittedFilter, Asset, + AddressOwnershipProof, AddressOwnershipProofSubmittedFilter, Cryptocurrency, LiabilitiesCommitmentSubmittedFilter, }, signer::{AddressInput, SummaSigner}, @@ -163,16 +163,13 @@ mod test { ) .await?; - let asset_csv = "src/apis/csv/assets.csv"; let params_path = "ptau/hermez-raw-11"; let entry_csv = "../zk_prover/src/merkle_sum_tree/csv/entry_16.csv"; let mst = MerkleSumTree::new(entry_csv).unwrap(); let mut round_one = - Round::<4, 2, 14>::new(&signer, Box::new(mst.clone()), asset_csv, params_path, 1) - .unwrap(); - let mut round_two = - Round::<4, 2, 14>::new(&signer, Box::new(mst), asset_csv, params_path, 2).unwrap(); + Round::<4, 2, 14>::new(&signer, Box::new(mst.clone()), params_path, 1).unwrap(); + let mut round_two = Round::<4, 2, 14>::new(&signer, Box::new(mst), params_path, 2).unwrap(); // Checking block number before sending transaction of liability commitment let outer_provider: Provider = Provider::try_from(anvil.endpoint().as_str())?; @@ -246,12 +243,10 @@ mod test { // Initialize round let params_path = "ptau/hermez-raw-11"; - let asset_csv = "src/apis/csv/assets.csv"; let entry_csv = "../zk_prover/src/merkle_sum_tree/csv/entry_16.csv"; let mst = MerkleSumTree::new(entry_csv).unwrap(); - let mut round = - Round::<4, 2, 14>::new(&signer, Box::new(mst), asset_csv, params_path, 1).unwrap(); + let mut round = Round::<4, 2, 14>::new(&signer, Box::new(mst), params_path, 1).unwrap(); let mut liability_commitment_logs = summa_contract .liabilities_commitment_submitted_filter() @@ -278,13 +273,13 @@ mod test { .parse() .unwrap(), root_balances: vec![U256::from(556862), U256::from(556862)], - assets: vec![ - Asset { - asset_name: "ETH".to_string(), + cryptocurrencies: vec![ + Cryptocurrency { + name: "ETH".to_string(), chain: "ETH".to_string(), }, - Asset { - asset_name: "USDT".to_string(), + Cryptocurrency { + name: "USDT".to_string(), chain: "ETH".to_string(), }, ], diff --git a/contracts/README.md b/contracts/README.md index f0a061b7..783c12ac 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -1,6 +1,6 @@ # Summa Smart Contract -The [Summa smart contract](src/Summa.sol) acts as a registrar for Centralized Exchanges (CEXs) to commit to their liabilities by submitting a Merkle sum tree (MST) root of all the CEX user asset balances. Users can then verify their inclusion into the liabilities commitment, and the public can compare the committed total sums with the assets owned by the CEX onchain. +The [Summa smart contract](src/Summa.sol) acts as a registrar for Centralized Exchanges (CEXs) to commit to their liabilities by submitting a Merkle sum tree (MST) root of all the CEX liabilities owed to its users. Users can then verify their inclusion into the liabilities commitment, and the public can compare the committed total sums with the assets owned by the CEX onchain. ## Features diff --git a/contracts/src/Summa.sol b/contracts/src/Summa.sol index a2135a75..f8c2e7c2 100644 --- a/contracts/src/Summa.sol +++ b/contracts/src/Summa.sol @@ -24,27 +24,27 @@ contract Summa is Ownable { } /** - * @dev Struct representing an asset owned by the CEX - * @param assetName The name of the asset - * @param chain The name of the chain name where the asset lives (e.g., ETH, BTC) + * @dev Struct identifying a cryptocurrency traded on the CEX + * @param name The name of the cryptocurrency + * @param chain The name of the chain name where the cryptocurrency lives (e.g., ETH, BTC) */ - struct Asset { - string assetName; + struct Cryptocurrency { + string name; string chain; } /** * @dev Struct representing a commitment submitted by the CEX. * @param mstRoot Merkle sum tree root of the CEX's liabilities - * @param rootBalances The total sums of the assets included in the tree - * @param assetChains The chains where the CEX holds the assets included into the tree - * @param assetNames The names of the assets included into the tree + * @param rootBalances The total sums of the liabilities included in the tree + * @param blockchainNames The names of the blockchains where the CEX holds the cryptocurrencies included into the tree + * @param cryptocurrencyNames The names of the cryptocurrencies included into the tree */ struct Commitment { uint256 mstRoot; uint256[] rootBalances; - string[] assetNames; - string[] assetChains; + string[] cryptocurrencyNames; + string[] blockchainNames; } // User inclusion proof verifier @@ -78,7 +78,7 @@ contract Summa is Ownable { uint256 indexed timestamp, uint256 mstRoot, uint256[] rootBalances, - Asset[] assets + Cryptocurrency[] cryptocurrencies ); constructor(IVerifier _inclusionVerifier) { @@ -117,49 +117,51 @@ contract Summa is Ownable { /** * @dev Submit commitment for a CEX * @param mstRoot Merkle sum tree root of the CEX's liabilities - * @param rootBalances The total sums of the assets included into the Merkle sum tree - * @param assets The assets included into the Merkle sum tree + * @param rootBalances The total sums of the liabilities included into the Merkle sum tree + * @param cryptocurrencies The cryptocurrencies included into the Merkle sum tree * @param timestamp The timestamp at which the CEX took the snapshot of its assets and liabilities */ function submitCommitment( uint256 mstRoot, uint256[] memory rootBalances, - Asset[] memory assets, + Cryptocurrency[] memory cryptocurrencies, uint256 timestamp ) public onlyOwner { require(mstRoot != 0, "Invalid MST root"); require( - rootBalances.length == assets.length, - "Root asset sums and asset number mismatch" + rootBalances.length == cryptocurrencies.length, + "Root liabilities sums and liabilities number mismatch" ); - string[] memory assetNames = new string[](assets.length); - string[] memory assetChains = new string[](assets.length); - for (uint i = 0; i < assets.length; i++) { + string[] memory cryptocurrencyNames = new string[]( + cryptocurrencies.length + ); + string[] memory blockchainNames = new string[](cryptocurrencies.length); + for (uint i = 0; i < cryptocurrencies.length; i++) { require( - bytes(assets[i].chain).length != 0 && - bytes(assets[i].assetName).length != 0, - "Invalid asset" + bytes(cryptocurrencies[i].chain).length != 0 && + bytes(cryptocurrencies[i].name).length != 0, + "Invalid cryptocurrency" ); require( rootBalances[i] != 0, "All root sums should be greater than zero" ); - assetNames[i] = assets[i].assetName; - assetChains[i] = assets[i].chain; + cryptocurrencyNames[i] = cryptocurrencies[i].name; + blockchainNames[i] = cryptocurrencies[i].chain; } commitments[timestamp] = Commitment( mstRoot, rootBalances, - assetNames, - assetChains + cryptocurrencyNames, + blockchainNames ); emit LiabilitiesCommitmentSubmitted( timestamp, mstRoot, rootBalances, - assets + cryptocurrencies ); } diff --git a/contracts/test/Summa.ts b/contracts/test/Summa.ts index 7eee13d2..65c21f1c 100644 --- a/contracts/test/Summa.ts +++ b/contracts/test/Summa.ts @@ -13,21 +13,21 @@ describe("Summa Contract", () => { summa: Summa, mstRoot: BigNumber, rootBalances: BigNumber[], - assets = [ + cryptocurrencies = [ { chain: "ETH", - assetName: "ETH", + name: "ETH", }, { chain: "BTC", - assetName: "BTC", + name: "BTC", }, ] ): any { return summa.submitCommitment( mstRoot, rootBalances, - assets, + cryptocurrencies, BigNumber.from(1693559255) ); } @@ -37,12 +37,12 @@ describe("Summa Contract", () => { inclusionProof: string, leafHash: BigNumber, mstRoot: BigNumber, - assetBalance1: BigNumber, - assetBalance2: BigNumber + balance1: BigNumber, + balance2: BigNumber ): any { return summa.verifyInclusionProof( inclusionProof, - [leafHash, mstRoot, assetBalance1, assetBalance2], + [leafHash, mstRoot, balance1, balance2], 1693559255 ); } @@ -277,8 +277,11 @@ describe("Summa Contract", () => { BigNumber.from(1693559255), mstRoot, rootBalances, - (assets: [Summa.AssetStruct]) => { - return assets[0].chain == "ETH" && assets[0].assetName == "ETH"; + (cryptocurrencies: [Summa.CryptocurrencyStruct]) => { + return ( + cryptocurrencies[0].chain == "ETH" && + cryptocurrencies[0].name == "ETH" + ); } ); }); @@ -291,7 +294,7 @@ describe("Summa Contract", () => { [ { chain: "ETH", - assetName: "ETH", + name: "ETH", }, ], BigNumber.from(1693559255) @@ -309,34 +312,34 @@ describe("Summa Contract", () => { ).to.be.revertedWith("All root sums should be greater than zero"); }); - it("should revert with invalid assets", async () => { + it("should revert with invalid cryptocurrencies", async () => { await summa.submitProofOfAddressOwnership(ownedAddresses); await expect( submitCommitment(summa, mstRoot, rootBalances, [ { chain: "BTC", - assetName: "BTC", + name: "BTC", }, { chain: "", - assetName: "ETH", + name: "ETH", }, ]) - ).to.be.revertedWith("Invalid asset"); + ).to.be.revertedWith("Invalid cryptocurrency"); await expect( submitCommitment(summa, mstRoot, rootBalances, [ { chain: "ETH", - assetName: "ETH", + name: "ETH", }, { chain: "BTC", - assetName: "", + name: "", }, ]) - ).to.be.revertedWith("Invalid asset"); + ).to.be.revertedWith("Invalid cryptocurrency"); }); it("should not submit invalid root", async () => { @@ -345,11 +348,13 @@ describe("Summa Contract", () => { ).to.be.revertedWith("Invalid MST root"); }); - it("should revert if asset and sum count don't match", async () => { + it("should revert if cryptocurrency and liability counts don't match", async () => { rootBalances = [BigNumber.from(10000000)]; await expect( submitCommitment(summa, mstRoot, rootBalances) - ).to.be.revertedWith("Root asset sums and asset number mismatch"); + ).to.be.revertedWith( + "Root liabilities sums and liabilities number mismatch" + ); }); }); @@ -358,8 +363,8 @@ describe("Summa Contract", () => { let rootBalances: BigNumber[]; let inclusionMstRoot: BigNumber; let leafHash: BigNumber; - let assetBalance1: BigNumber; - let assetBalance2: BigNumber; + let balance1: BigNumber; + let balance2: BigNumber; let summa: Summa; let account1: SignerWithAddress; let account2: SignerWithAddress; @@ -405,8 +410,8 @@ describe("Summa Contract", () => { inclusionProof = inclusionCalldata.proof; leafHash = inclusionCalldata.public_inputs[0]; inclusionMstRoot = inclusionCalldata.public_inputs[1]; - assetBalance1 = inclusionCalldata.public_inputs[2]; - assetBalance2 = inclusionCalldata.public_inputs[3]; + balance1 = inclusionCalldata.public_inputs[2]; + balance2 = inclusionCalldata.public_inputs[3]; const commitmentCalldataJson = fs.readFileSync( path.resolve( @@ -430,8 +435,8 @@ describe("Summa Contract", () => { inclusionProof, leafHash, inclusionMstRoot, - assetBalance1, - assetBalance2 + balance1, + balance2 ) ).to.be.equal(true); }); @@ -446,8 +451,8 @@ describe("Summa Contract", () => { inclusionProof, leafHash, inclusionMstRoot, - assetBalance1, - assetBalance2 + balance1, + balance2 ) ).to.be.revertedWith("Invalid MST root"); }); @@ -460,14 +465,14 @@ describe("Summa Contract", () => { inclusionProof, leafHash, inclusionMstRoot, - assetBalance1, - assetBalance2 + balance1, + balance2 ) ).to.be.revertedWith("Invalid MST root"); }); it("should not verify with invalid root balances", async () => { - assetBalance1 = BigNumber.from(0); + balance1 = BigNumber.from(0); await summa.submitProofOfAddressOwnership(ownedAddresses); await submitCommitment(summa, commitmentMstRoot, rootBalances); @@ -477,8 +482,8 @@ describe("Summa Contract", () => { inclusionProof, leafHash, inclusionMstRoot, - assetBalance1, - assetBalance2 + balance1, + balance2 ) ).to.be.revertedWith("Invalid root balance"); }); @@ -494,8 +499,8 @@ describe("Summa Contract", () => { inclusionProof, leafHash, inclusionMstRoot, - assetBalance1, - assetBalance2 + balance1, + balance2 ) ).to.be.equal(false); }); @@ -511,8 +516,8 @@ describe("Summa Contract", () => { inclusionProof, leafHash, inclusionMstRoot, - assetBalance1, - assetBalance2 + balance1, + balance2 ) ).to.be.equal(false); }); diff --git a/zk_prover/src/merkle_sum_tree/csv/entry_16.csv b/zk_prover/src/merkle_sum_tree/csv/entry_16.csv index 917a3849..c0d4ebc9 100644 --- a/zk_prover/src/merkle_sum_tree/csv/entry_16.csv +++ b/zk_prover/src/merkle_sum_tree/csv/entry_16.csv @@ -1,17 +1,17 @@ -username;balances -dxGaEAii;11888,41163 -MBlfbBGI;67823,18651 -lAhWlEWZ;18651,2087 -nuZweYtO;22073,55683 -gbdSwiuY;34897,83296 -RZNneNuP;83296,16881 -YsscHXkp;31699,35479 -RkLzkDun;2087,79731 -HlQlnEYI;30605,11888 -RqkZOFYe;16881,14874 -NjCSRAfD;41163,67823 -pHniJMQY;14874,22073 -dOGIMzKR;10032,10032 -HfMDmNLp;55683,34897 -xPLKzCBl;79731,30605 -AtwIxZHo;35479,31699 +username,balance_ETH_ETH,balance_USDT_ETH +dxGaEAii,11888,41163 +MBlfbBGI,67823,18651 +lAhWlEWZ,18651,2087 +nuZweYtO,22073,55683 +gbdSwiuY,34897,83296 +RZNneNuP,83296,16881 +YsscHXkp,31699,35479 +RkLzkDun,2087,79731 +HlQlnEYI,30605,11888 +RqkZOFYe,16881,14874 +NjCSRAfD,41163,67823 +pHniJMQY,14874,22073 +dOGIMzKR,10032,10032 +HfMDmNLp,55683,34897 +xPLKzCBl,79731,30605 +AtwIxZHo,35479,31699 diff --git a/zk_prover/src/merkle_sum_tree/csv/entry_16_bigints.csv b/zk_prover/src/merkle_sum_tree/csv/entry_16_bigints.csv index e39b5bcc..04e2e247 100644 --- a/zk_prover/src/merkle_sum_tree/csv/entry_16_bigints.csv +++ b/zk_prover/src/merkle_sum_tree/csv/entry_16_bigints.csv @@ -1,17 +1,17 @@ -username;balances -dxGaEAii;18446744073709551616,79731 -MBlfbBGI;67823,55683 -lAhWlEWZ;18651,22073 -nuZweYtO;22073,35479 -gbdSwiuY;34897,10032 -RZNneNuP;83296,2087 -YsscHXkp;31699,34897 -RkLzkDun;2087,67823 -HlQlnEYI;30605,31699 -RqkZOFYe;16881,16881 -NjCSRAfD;41163,14874 -pHniJMQY;14874,18651 -dOGIMzKR;10032,41163 -HfMDmNLp;55683,83296 -xPLKzCBl;79731,18446744073709551616 -AtwIxZHo;35479,30605 +username,balance_ETH_ETH,balance_USDT_ETH +dxGaEAii,18446744073709551616,79731 +MBlfbBGI,67823,55683 +lAhWlEWZ,18651,22073 +nuZweYtO,22073,35479 +gbdSwiuY,34897,10032 +RZNneNuP,83296,2087 +YsscHXkp,31699,34897 +RkLzkDun,2087,67823 +HlQlnEYI,30605,31699 +RqkZOFYe,16881,16881 +NjCSRAfD,41163,14874 +pHniJMQY,14874,18651 +dOGIMzKR,10032,41163 +HfMDmNLp,55683,83296 +xPLKzCBl,79731,18446744073709551616 +AtwIxZHo,35479,30605 diff --git a/zk_prover/src/merkle_sum_tree/csv/entry_16_modified.csv b/zk_prover/src/merkle_sum_tree/csv/entry_16_modified.csv index cacf3c69..b5496bf2 100644 --- a/zk_prover/src/merkle_sum_tree/csv/entry_16_modified.csv +++ b/zk_prover/src/merkle_sum_tree/csv/entry_16_modified.csv @@ -1,17 +1,17 @@ -username;balances -dxGaEAii;11888,41163 -MBlfbBGI;67823,18651 -lAhWlEWZ;18651,2087 -nuZweYtO;22073,55683 -gbdSwiuY;34897,83296 -RZNneNuP;83296,16881 -YsscHXkp;31699,35479 -RkLzkDun;2086,79732 -HlQlnEYI;30605,11888 -RqkZOFYe;16881,14874 -NjCSRAfD;41163,67823 -pHniJMQY;14874,22073 -dOGIMzKR;10032,10032 -HfMDmNLp;55683,34897 -xPLKzCBl;79731,30605 -AtwIxZHo;35479,31699 +username,balance_ETH_ETH,balance_USDT_ETH +dxGaEAii,11888,41163 +MBlfbBGI,67823,18651 +lAhWlEWZ,18651,2087 +nuZweYtO,22073,55683 +gbdSwiuY,34897,83296 +RZNneNuP,83296,16881 +YsscHXkp,31699,35479 +RkLzkDun,2086,79732 +HlQlnEYI,30605,11888 +RqkZOFYe,16881,14874 +NjCSRAfD,41163,67823 +pHniJMQY,14874,22073 +dOGIMzKR,10032,10032 +HfMDmNLp,55683,34897 +xPLKzCBl,79731,30605 +AtwIxZHo,35479,31699 diff --git a/zk_prover/src/merkle_sum_tree/csv/entry_16_no_overflow.csv b/zk_prover/src/merkle_sum_tree/csv/entry_16_no_overflow.csv index 49dc9358..f55f626b 100644 --- a/zk_prover/src/merkle_sum_tree/csv/entry_16_no_overflow.csv +++ b/zk_prover/src/merkle_sum_tree/csv/entry_16_no_overflow.csv @@ -1,17 +1,17 @@ -username;balances -dxGaEAii;18446744073709551615,0 -MBlfbBGI;0,18446744073709551615 -lAhWlEWZ;0,0 -nuZweYtO;0,0 -gbdSwiuY;0,0 -RZNneNuP;0,0 -YsscHXkp;0,0 -RkLzkDun;0,0 -HlQlnEYI;0,0 -RqkZOFYe;0,0 -NjCSRAfD;0,0 -pHniJMQY;0,0 -dOGIMzKR;0,0 -HfMDmNLp;0,0 -xPLKzCBl;0,0 -AtwIxZHo;0,0 +username,balance_ETH_ETH,balance_USDT_ETH +dxGaEAii,18446744073709551615,0 +MBlfbBGI,0,18446744073709551615 +lAhWlEWZ,0,0 +nuZweYtO,0,0 +gbdSwiuY,0,0 +RZNneNuP,0,0 +YsscHXkp,0,0 +RkLzkDun,0,0 +HlQlnEYI,0,0 +RqkZOFYe,0,0 +NjCSRAfD,0,0 +pHniJMQY,0,0 +dOGIMzKR,0,0 +HfMDmNLp,0,0 +xPLKzCBl,0,0 +AtwIxZHo,0,0 diff --git a/zk_prover/src/merkle_sum_tree/csv/entry_16_overflow.csv b/zk_prover/src/merkle_sum_tree/csv/entry_16_overflow.csv index 1f1e2141..772993d4 100644 --- a/zk_prover/src/merkle_sum_tree/csv/entry_16_overflow.csv +++ b/zk_prover/src/merkle_sum_tree/csv/entry_16_overflow.csv @@ -1,17 +1,17 @@ -username;balances -dxGaEAii;18446744073709551616,0 -MBlfbBGI;0,18446744073709551616 -lAhWlEWZ;0,0 -nuZweYtO;0,0 -gbdSwiuY;0,0 -RZNneNuP;0,0 -YsscHXkp;0,0 -RkLzkDun;0,0 -HlQlnEYI;0,0 -RqkZOFYe;0,0 -NjCSRAfD;0,0 -pHniJMQY;0,0 -dOGIMzKR;0,0 -HfMDmNLp;0,0 -xPLKzCBl;0,0 -AtwIxZHo;0,0 +username,balance_ETH_ETH,balance_USDT_ETH +dxGaEAii,18446744073709551616,0 +MBlfbBGI,0,18446744073709551616 +lAhWlEWZ,0,0 +nuZweYtO,0,0 +gbdSwiuY,0,0 +RZNneNuP,0,0 +YsscHXkp,0,0 +RkLzkDun,0,0 +HlQlnEYI,0,0 +RqkZOFYe,0,0 +NjCSRAfD,0,0 +pHniJMQY,0,0 +dOGIMzKR,0,0 +HfMDmNLp,0,0 +xPLKzCBl,0,0 +AtwIxZHo,0,0 diff --git a/zk_prover/src/merkle_sum_tree/csv/entry_16_overflow_2.csv b/zk_prover/src/merkle_sum_tree/csv/entry_16_overflow_2.csv index 3b3ecf62..1a7cc314 100644 --- a/zk_prover/src/merkle_sum_tree/csv/entry_16_overflow_2.csv +++ b/zk_prover/src/merkle_sum_tree/csv/entry_16_overflow_2.csv @@ -1,17 +1,17 @@ -username;balances -dxGaEAii;18446744073709551615,0 -MBlfbBGI;0,18446744073709551615 -lAhWlEWZ;0,0 -nuZweYtO;0,0 -gbdSwiuY;0,0 -RZNneNuP;0,0 -YsscHXkp;0,0 -RkLzkDun;0,0 -HlQlnEYI;0,0 -RqkZOFYe;0,0 -NjCSRAfD;0,0 -pHniJMQY;0,0 -dOGIMzKR;0,0 -HfMDmNLp;0,0 -xPLKzCBl;0,0 -AtwIxZHo;1,1 +username,balance_ETH_ETH,balance_USDT_ETH +dxGaEAii,18446744073709551615,0 +MBlfbBGI,0,18446744073709551615 +lAhWlEWZ,0,0 +nuZweYtO,0,0 +gbdSwiuY,0,0 +RZNneNuP,0,0 +YsscHXkp,0,0 +RkLzkDun,0,0 +HlQlnEYI,0,0 +RqkZOFYe,0,0 +NjCSRAfD,0,0 +pHniJMQY,0,0 +dOGIMzKR,0,0 +HfMDmNLp,0,0 +xPLKzCBl,0,0 +AtwIxZHo,1,1 diff --git a/zk_prover/src/merkle_sum_tree/csv/entry_16_switched_order.csv b/zk_prover/src/merkle_sum_tree/csv/entry_16_switched_order.csv index 4c318183..a83d2b46 100644 --- a/zk_prover/src/merkle_sum_tree/csv/entry_16_switched_order.csv +++ b/zk_prover/src/merkle_sum_tree/csv/entry_16_switched_order.csv @@ -1,17 +1,17 @@ -username;balances -dxGaEAii;11888,79731 -MBlfbBGI;67823,22073 -lAhWlEWZ;18651,18651 -nuZweYtO;22073,35479 -gbdSwiuY;34897,83296 -RZNneNuP;83296,34897 -YsscHXkp;31699,55683 -RkLzkDun;2087,30605 -HlQlnEYI;30605,10032 -RqkZOFYe;16881,16881 -NjCSRAfD;41163,41163 -pHniJMQY;14874,31699 -dOGIMzKR;10032,11888 -HfMDmNLp;55683,14874 -AtwIxZHo;35479,67823 -xPLKzCBl;79731,2087 +username,balance_ETH_ETH,balance_USDT_ETH +dxGaEAii,11888,79731 +MBlfbBGI,67823,22073 +lAhWlEWZ,18651,18651 +nuZweYtO,22073,35479 +gbdSwiuY,34897,83296 +RZNneNuP,83296,34897 +YsscHXkp,31699,55683 +RkLzkDun,2087,30605 +HlQlnEYI,30605,10032 +RqkZOFYe,16881,16881 +NjCSRAfD,41163,41163 +pHniJMQY,14874,31699 +dOGIMzKR,10032,11888 +HfMDmNLp,55683,14874 +AtwIxZHo,35479,67823 +xPLKzCBl,79731,2087 diff --git a/zk_prover/src/merkle_sum_tree/mod.rs b/zk_prover/src/merkle_sum_tree/mod.rs index d185ef50..b756d431 100644 --- a/zk_prover/src/merkle_sum_tree/mod.rs +++ b/zk_prover/src/merkle_sum_tree/mod.rs @@ -16,6 +16,7 @@ pub struct MerkleProof { } pub use entry::Entry; +pub use mst::Cryptocurrency; pub use mst::MerkleSumTree; pub use node::Node; pub use tree::Tree; diff --git a/zk_prover/src/merkle_sum_tree/mst.rs b/zk_prover/src/merkle_sum_tree/mst.rs index dd914542..c3f5edf9 100644 --- a/zk_prover/src/merkle_sum_tree/mst.rs +++ b/zk_prover/src/merkle_sum_tree/mst.rs @@ -9,12 +9,12 @@ use num_bigint::BigUint; /// A Merkle Sum Tree is a binary Merkle Tree with the following properties: /// * Each Entry of a Merkle Sum Tree is a pair of a username and #N_ASSETS balances. /// * Each Leaf Node contains a hash and #N_ASSETS balances. The hash is equal to `H(username, balance[0], balance[1], ... balance[N_ASSETS])`. -/// * Each Middle Node contains a hash and #N_ASSETS balances. The hash is equal to `H(LeftChild.hash, LeftChild.balance[0], LeftChild.balance[1], LeftChild.balance[N_ASSETS], RightChild.hash, RightChild.balance[0], RightChild.balance[1], RightChild.balance[N_ASSETS])`. The balances are equal to the sum of the balances of the child nodes per each asset. -/// * The Root Node represents the committed state of the Tree and contains the sum of all the entries' balances per each asset. +/// * Each Middle Node contains a hash and #N_ASSETS balances. The hash is equal to `H(LeftChild.hash, LeftChild.balance[0], LeftChild.balance[1], LeftChild.balance[N_ASSETS], RightChild.hash, RightChild.balance[0], RightChild.balance[1], RightChild.balance[N_ASSETS])`. The balances are equal to the sum of the balances of the child nodes per each cryptocurrency. +/// * The Root Node represents the committed state of the Tree and contains the sum of all the entries' balances per each cryptocurrency. /// /// # Type Parameters /// -/// * `N_ASSETS`: The number of assets for each user account +/// * `N_ASSETS`: The number of cryptocurrencies for each user account /// * `N_BYTES`: Range in which each node balance should lie #[derive(Debug, Clone)] pub struct MerkleSumTree { @@ -22,6 +22,7 @@ pub struct MerkleSumTree { nodes: Vec>>, depth: usize, entries: Vec>, + cryptocurrencies: Vec, is_sorted: bool, } @@ -47,42 +48,54 @@ impl Tree fn get_entry(&self, index: usize) -> &Entry { &self.entries[index] } + + fn cryptocurrencies(&self) -> &[Cryptocurrency] { + &self.cryptocurrencies + } +} + +#[derive(Debug, Clone)] +pub struct Cryptocurrency { + pub name: String, + pub chain: String, } impl MerkleSumTree { /// Builds a Merkle Sum Tree from a CSV file stored at `path`. The CSV file must be formatted as follows: /// - /// `username;balances` + /// `username,balance__,balance__,...` /// - /// `dxGaEAii;11888,41163` + /// `dxGaEAii,11888,41163` pub fn new(path: &str) -> Result> where [usize; N_ASSETS + 1]: Sized, [usize; 2 * (1 + N_ASSETS)]: Sized, { - let entries = parse_csv_to_entries::<&str, N_ASSETS, N_BYTES>(path)?; - Self::from_entries(entries, false) + let (cryptocurrencies, entries) = parse_csv_to_entries::<&str, N_ASSETS, N_BYTES>(path)?; + Self::from_entries(entries, cryptocurrencies, false) } /// Builds a Merkle Sum Tree from a CSV file stored at `path`. The MST leaves are sorted by the username byte values. The CSV file must be formatted as follows: /// - /// `username;balances` + /// `username,balance__,balance__,...` /// - /// `dxGaEAii;11888,41163` + /// `dxGaEAii,11888,41163` pub fn new_sorted(path: &str) -> Result> where [usize; N_ASSETS + 1]: Sized, [usize; 2 * (1 + N_ASSETS)]: Sized, { - let mut entries = parse_csv_to_entries::<&str, N_ASSETS, N_BYTES>(path)?; + let (cryptocurrencies, mut entries) = + parse_csv_to_entries::<&str, N_ASSETS, N_BYTES>(path)?; entries.sort_by(|a, b| a.username().cmp(b.username())); - Self::from_entries(entries, true) + Self::from_entries(entries, cryptocurrencies, true) } pub fn from_entries( entries: Vec>, + cryptocurrencies: Vec, is_sorted: bool, ) -> Result, Box> where @@ -102,6 +115,7 @@ impl MerkleSumTree { @@ -16,6 +17,9 @@ pub trait Tree { /// Returns a slice of the nodes. fn nodes(&self) -> &[Vec>]; + /// Returns the cryptocurrencies whose balances are in the tree. The order of cryptocurrencies and balances is supposed to agree for all the entries. + fn cryptocurrencies(&self) -> &[Cryptocurrency]; + fn get_entry(&self, index: usize) -> &Entry; /// Generates a MerkleProof for the user with the given index. diff --git a/zk_prover/src/merkle_sum_tree/utils/csv_parser.rs b/zk_prover/src/merkle_sum_tree/utils/csv_parser.rs index 75bb39a6..bf77f0db 100644 --- a/zk_prover/src/merkle_sum_tree/utils/csv_parser.rs +++ b/zk_prover/src/merkle_sum_tree/utils/csv_parser.rs @@ -1,39 +1,55 @@ -use crate::merkle_sum_tree::Entry; +use crate::merkle_sum_tree::{Cryptocurrency, Entry}; use num_bigint::BigUint; -use serde::Deserialize; +use std::collections::HashMap; use std::error::Error; use std::fs::File; use std::path::Path; -#[derive(Debug, Deserialize)] -struct CsvEntry { - username: String, - balances: String, -} - -/// Parses a CSV file stored at path into a vector of Entries pub fn parse_csv_to_entries, const N_ASSETS: usize, const N_BYTES: usize>( path: P, -) -> Result>, Box> { - let mut entries = Vec::new(); +) -> Result<(Vec, Vec>), Box> { let file = File::open(path)?; - let mut rdr = csv::ReaderBuilder::new() - .delimiter(b';') // The fields are separated by a semicolon - .from_reader(file); + let mut rdr = csv::ReaderBuilder::new().from_reader(file); + let headers = rdr.headers()?.clone(); + let mut cryptocurrencies: Vec = Vec::with_capacity(N_ASSETS); + + // Extracting cryptocurrency names from column names + for header in headers.iter().skip(1) { + // Skipping 'username' column + let parts: Vec<&str> = header.split('_').collect(); + if parts.len() == 3 && parts[0] == "balance" { + cryptocurrencies.push(Cryptocurrency { + name: parts[1].to_owned(), + chain: parts[2].to_owned(), + }); + } else { + // Throw an error if the header is malformed + return Err(format!("Invalid header: {}", header).into()); + } + } + + let mut entries = Vec::new(); let mut balances_acc: Vec = vec![BigUint::from(0 as usize); N_ASSETS]; for result in rdr.deserialize() { - let record: CsvEntry = result?; - - // Split the balances string into separate balance strings - let balance_strs: Vec<&str> = record.balances.split(',').collect(); + let record: HashMap = result?; + let username = record.get("username").ok_or("Username not found")?.clone(); - // Parse each balance string as a BigUint - let balances_big_int: Vec = balance_strs - .into_iter() - .map(|balance_str| BigUint::parse_bytes(balance_str.as_bytes(), 10).unwrap()) - .collect(); + let mut balances_big_int = Vec::new(); + for cryptocurrency in &cryptocurrencies { + let balance_str = record + .get(format!("balance_{}_{}", cryptocurrency.name, cryptocurrency.chain).as_str()) + .ok_or(format!( + "Balance for {} on {} not found", + cryptocurrency.name, cryptocurrency.chain + ))?; + let balance = BigUint::parse_bytes(balance_str.as_bytes(), 10).ok_or(format!( + "Invalid balance for {} on {}", + cryptocurrency.name, cryptocurrency.chain + ))?; + balances_big_int.push(balance); + } balances_acc = balances_acc .iter() @@ -41,7 +57,7 @@ pub fn parse_csv_to_entries, const N_ASSETS: usize, const N_BYTES .map(|(x, y)| x + y) .collect(); - let entry = Entry::new(record.username, balances_big_int.try_into().unwrap())?; + let entry = Entry::new(username, balances_big_int.try_into().unwrap())?; entries.push(entry); } @@ -55,5 +71,5 @@ pub fn parse_csv_to_entries, const N_ASSETS: usize, const N_BYTES } } - Ok(entries) + Ok((cryptocurrencies, entries)) }