diff --git a/contracts/anchor-handler/src/contract.rs b/contracts/anchor-handler/src/contract.rs index 85f880c..72f8c55 100644 --- a/contracts/anchor-handler/src/contract.rs +++ b/contracts/anchor-handler/src/contract.rs @@ -23,11 +23,6 @@ use protocol_cosmwasm::structs::{ const CONTRACT_NAME: &str = "crates.io:cosmwasm-anchor-handler"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); -// ChainType info -pub const COSMOS_CHAIN_TYPE: [u8; 2] = [4, 0]; // 0x0400 - -pub const MOCK_CHAIN_ID: u64 = 1; - #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( deps: DepsMut, diff --git a/contracts/anchor-handler/src/state.rs b/contracts/anchor-handler/src/state.rs index c0e4414..80dc923 100644 --- a/contracts/anchor-handler/src/state.rs +++ b/contracts/anchor-handler/src/state.rs @@ -21,13 +21,13 @@ pub struct State { pub const STATE: Item = Item::new("state"); /* ----- Handlers common ----- */ -// resourceID => token contract address +/// resourceID => token contract address pub const RESOURCEID2CONTRACTADDRESS: Map<&[u8], Addr> = Map::new("resourceIDToContractAddress"); -// Execution contract address => resourceID +/// Execution contract address => resourceID pub const CONTRACTADDRESS2RESOURCEID: Map = Map::new("contractAddressToResourceID"); -// Execution contract address => is whitelisted +/// Execution contract address => is whitelisted pub const CONTRACTWHITELIST: Map = Map::new("contract_whitelist"); pub fn set_resource( @@ -54,11 +54,11 @@ pub fn read_whitelist(store: &dyn Storage, contract_addr: Addr) -> StdResult height => Update Record -// (src_chain_id, height) -> UpdateRecord +/// sourceChainID => height => Update Record +/// (src_chain_id, height) -> UpdateRecord pub const UPDATE_RECORDS: Map<(String, String), UpdateRecord> = Map::new("update_records"); -// source chain ID => number of updates +/// source chain ID => number of updates pub const COUNTS: Map = Map::new("counts"); pub fn read_update_record( diff --git a/contracts/anchor/src/contract.rs b/contracts/anchor/src/contract.rs index ae4f1d4..779bbd6 100644 --- a/contracts/anchor/src/contract.rs +++ b/contracts/anchor/src/contract.rs @@ -30,7 +30,8 @@ use protocol_cosmwasm::token_wrapper::{ QueryMsg as TokenWrapperQueryMsg, }; use protocol_cosmwasm::utils::{ - compute_chain_id_type, element_encoder, parse_string_to_uint128, truncate_and_pad, + compute_chain_id, compute_chain_id_type, element_encoder, parse_string_to_uint128, + truncate_and_pad, }; use protocol_cosmwasm::zeroes::zeroes; @@ -84,7 +85,6 @@ pub fn instantiate( // Initialize the Anchor let deposit_size = msg.deposit_size; let anchor = Anchor { - chain_id: msg.chain_id, linkable_tree: linkable_merkle_tree, proposal_nonce: 0_u32, deposit_size, @@ -116,7 +116,7 @@ pub fn execute( ) -> Result { match msg { // Withdraw the cw20 token with proof - ExecuteMsg::Withdraw(msg) => withdraw(deps, info, msg), + ExecuteMsg::Withdraw(msg) => withdraw(deps, env, info, msg), // Unwrap the "TokenWrapper" token ExecuteMsg::UnwrapIntoToken { token_addr, amount } => { unwrap_into_token(deps, info.sender.to_string(), token_addr, amount) @@ -143,7 +143,7 @@ pub fn execute( ), // Withdraws the deposit & unwraps to valid token for `sender` - ExecuteMsg::WithdrawAndUnwrap(msg) => withdraw_and_unwrap(deps, info, msg), + ExecuteMsg::WithdrawAndUnwrap(msg) => withdraw_and_unwrap(deps, env, info, msg), // Sets a new handler for the contract ExecuteMsg::SetHandler { handler, nonce } => set_handler(deps, info, handler, nonce), @@ -297,6 +297,7 @@ fn unwrap_into_token( /// Withdraw a deposit from the contract pub fn withdraw( deps: DepsMut, + env: Env, info: MessageInfo, msg: WithdrawMsg, ) -> Result { @@ -329,8 +330,9 @@ pub fn withdraw( } // Format the public input bytes + let chain_id = compute_chain_id(&env.block.chain_id); let chain_id_type_bytes = - element_encoder(&compute_chain_id_type(anchor.chain_id, &COSMOS_CHAIN_TYPE).to_le_bytes()); + element_encoder(&compute_chain_id_type(chain_id.into(), &COSMOS_CHAIN_TYPE).to_le_bytes()); let recipient_bytes = truncate_and_pad(recipient.as_bytes()); let relayer_bytes = truncate_and_pad(relayer.as_bytes()); @@ -612,6 +614,7 @@ fn wrap_and_deposit_cw20( /// Withdraws the deposit & unwraps into valid token for `sender` fn withdraw_and_unwrap( deps: DepsMut, + env: Env, info: MessageInfo, msg: WithdrawMsg, ) -> Result { @@ -653,8 +656,9 @@ fn withdraw_and_unwrap( }; // Format the public input bytes + let chain_id = compute_chain_id(&env.block.chain_id); let chain_id_type_bytes = - element_encoder(&compute_chain_id_type(anchor.chain_id, &COSMOS_CHAIN_TYPE).to_le_bytes()); + element_encoder(&compute_chain_id_type(chain_id.into(), &COSMOS_CHAIN_TYPE).to_le_bytes()); let recipient_bytes = truncate_and_pad(recipient.as_bytes()); let relayer_bytes = truncate_and_pad(relayer.as_bytes()); @@ -857,7 +861,6 @@ pub fn get_config(deps: Deps) -> StdResult { Ok(ConfigResponse { handler: anchor.handler.to_string(), proposal_nonce: anchor.proposal_nonce, - chain_id: anchor.chain_id, tokenwrapper_addr: anchor.tokenwrapper_addr.to_string(), deposit_size: anchor.deposit_size.to_string(), }) @@ -926,7 +929,6 @@ pub fn validate_and_store_commitment( ANCHOR.save( deps.storage, &Anchor { - chain_id: anchor.chain_id, deposit_size: anchor.deposit_size, linkable_tree: anchor.linkable_tree, tokenwrapper_addr: anchor.tokenwrapper_addr, diff --git a/contracts/anchor/src/state.rs b/contracts/anchor/src/state.rs index b1b2534..5387c2d 100644 --- a/contracts/anchor/src/state.rs +++ b/contracts/anchor/src/state.rs @@ -20,23 +20,25 @@ pub const MERKLEROOTS: Map = Map::new("merkle_roots"); pub const FILLED_SUBTREES: Map = Map::new("filled_subtrees"); pub const NULLIFIERS: Map, bool> = Map::new("used_nullifers"); -// "Anchor" -// Connected instances that contains an on-chain merkle tree and -// tracks a set of connected _anchors_ across chains (through edges) -// in its local storage. - -// NOTE: The `chain_id` field is just for temporary development purpose. -// In the future, it should be removed & the contract should use the -// `chain_id`(blockchain-unique ID) obtained inside the contract. +/// "Anchor" +/// Connected instances that contains an on-chain merkle tree and +/// tracks a set of connected _anchors_ across chains (through edges) +/// in its local storage. +/// +/// "handler" Address of "anchor-handler", which add/updte the `edge` info +/// "proposal_nonce" Nonce value to track the proposals +/// "deposit_size" Minimum `deposit` amount for tx +/// "merkle_tree" Tree data structure to hold the `deposit` info +/// "linkable_tree" Tree data structure to hold the `edge` info +/// "tokenwrapper_addr" Cw20 token address used for wrapping native & any cw20 token #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct Anchor { - pub chain_id: u64, // ChainID of underlying blockchain(Temporary field) - pub handler: Addr, // Address of "anchor-handler", which add/updte the `edge` info - pub proposal_nonce: u32, // Proposal nonce - pub deposit_size: Uint128, // Minimum `deposit` amount for tx - pub merkle_tree: MerkleTree, // Tree data structure to hold the `deposit` info - pub linkable_tree: LinkableMerkleTree, // Tree data structure to hold the `edge` info - pub tokenwrapper_addr: Addr, // Cw20 token address used for wrapping native & any cw20 token + pub handler: Addr, + pub proposal_nonce: u32, + pub deposit_size: Uint128, + pub merkle_tree: MerkleTree, + pub linkable_tree: LinkableMerkleTree, + pub tokenwrapper_addr: Addr, } pub fn read_edge(store: &dyn Storage, k: ChainId) -> StdResult { @@ -77,7 +79,7 @@ pub fn save_neighbor_roots( NEIGHBOR_ROOTS.save(store, (id.to_string(), num.to_string()), &data) } -// LinkableMerkleTree +/// LinkableMerkleTree #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct LinkableMerkleTree { pub max_edges: u32, @@ -198,7 +200,7 @@ impl LinkableMerkleTree { } } -// MerkleTree +/// MerkleTree #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct MerkleTree { pub levels: u32, diff --git a/contracts/anchor/src/tests.rs b/contracts/anchor/src/tests.rs index 8f372c0..7ae7b6c 100644 --- a/contracts/anchor/src/tests.rs +++ b/contracts/anchor/src/tests.rs @@ -25,7 +25,7 @@ use crate::contract::{execute, instantiate}; use crate::test_util::Element; const MAX_EDGES: u32 = 2; -const CHAIN_ID: u64 = 1; +const CHAIN_ID: u64 = 2145598729; // chain_id: "cosmos-testnet-14002" const LEVELS: u32 = 30; const TOKENWRAPPER_ADDR: &str = "terra1340t6lqq6jxhm8d6gtz0hzz5jzcszvm27urkn2"; // Cw20 token const DEPOSIT_SIZE: u128 = 1_000_000; @@ -44,7 +44,6 @@ fn create_anchor() -> OwnedDeps Result { @@ -66,7 +66,7 @@ pub fn execute( ExecuteMsg::AdminSetResourceWithSig(msg) => { admin_set_resource_with_signature(deps, info, msg) } - ExecuteMsg::ExecProposalWithSig(msg) => exec_proposal_with_signature(deps, info, msg), + ExecuteMsg::ExecProposalWithSig(msg) => exec_proposal_with_signature(deps, env, msg), } } @@ -134,7 +134,7 @@ fn admin_set_resource_with_signature( fn exec_proposal_with_signature( mut deps: DepsMut, - _info: MessageInfo, + env: Env, msg: ExecProposalWithSigMsg, ) -> Result { let state = STATE.load(deps.storage)?; @@ -154,17 +154,10 @@ fn exec_proposal_with_signature( let execution_chain_id_type: u64 = get_chain_id_type(&resource_id_bytes[26..32]); // Verify current chain matches chain ID from resource ID - // - // NOTE: - // This part is prone to future changes since the current implementation - // is based on assumption that the `chain_id` is number. - // In fact, the `chain_id` of Cosmos SDK blockchains is string, not number. - // For example, the `chain_id` of Terra blockchain(mainnet) is `columbus-5`. - // Eventually, it should replace the `MOCK_CHAIN_ID` with `chain_id` obtained - // inside contract(here). - if compute_chain_id_type(MOCK_CHAIN_ID, &COSMOS_CHAIN_TYPE) != execution_chain_id_type { + let chain_id = compute_chain_id(&env.block.chain_id); + if compute_chain_id_type(chain_id.into(), &COSMOS_CHAIN_TYPE) != execution_chain_id_type { return Err(ContractError::Std(StdError::GenericErr { - msg: "executing on wrong chain".to_string(), + msg: "Executing on wrong chain".to_string(), })); } diff --git a/contracts/signature-bridge/src/state.rs b/contracts/signature-bridge/src/state.rs index da2deae..9a4e611 100644 --- a/contracts/signature-bridge/src/state.rs +++ b/contracts/signature-bridge/src/state.rs @@ -12,8 +12,8 @@ pub struct State { pub const STATE: Item = Item::new("state"); -// destinationChainID => number of deposits +/// destinationChainID => number of deposits pub const COUNTS: Map<&[u8], [u8; 32]> = Map::new("counts"); -// resourceID => handler address +/// resourceID => handler address pub const RESOURCEID2HANDLERADDR: Map<&[u8], Addr> = Map::new("resourceIDToHandlerAddress"); diff --git a/contracts/tokenwrapper-handler/src/state.rs b/contracts/tokenwrapper-handler/src/state.rs index f188452..10f1e5e 100644 --- a/contracts/tokenwrapper-handler/src/state.rs +++ b/contracts/tokenwrapper-handler/src/state.rs @@ -21,13 +21,13 @@ pub struct State { pub const STATE: Item = Item::new("state"); /* ----- Handlers common ----- */ -// resourceID => token contract address +/// resourceID => token contract address pub const RESOURCEID2CONTRACTADDRESS: Map<&[u8], Addr> = Map::new("resourceIDToContractAddress"); -// Execution contract address => resourceID +/// Execution contract address => resourceID pub const CONTRACTADDRESS2RESOURCEID: Map = Map::new("contractAddressToResourceID"); -// Execution contract address => is whitelisted +/// Execution contract address => is whitelisted pub const CONTRACTWHITELIST: Map = Map::new("contract_whitelist"); pub fn set_resource( @@ -54,11 +54,11 @@ pub fn read_whitelist(store: &dyn Storage, contract_addr: Addr) -> StdResult nonce => Update Record -// (src_chain_id, nonce) -> UpdateRecord +/// sourceChainID => nonce => Update Record +/// (src_chain_id, nonce) -> UpdateRecord pub const UPDATE_RECORDS: Map<(String, String), UpdateRecord> = Map::new("update_records"); -// source chain ID => number of updates +/// source chain ID => number of updates pub const COUNTS: Map = Map::new("counts"); pub fn read_update_record( diff --git a/contracts/tokenwrapper/src/state.rs b/contracts/tokenwrapper/src/state.rs index 2c98dda..3aba307 100644 --- a/contracts/tokenwrapper/src/state.rs +++ b/contracts/tokenwrapper/src/state.rs @@ -17,7 +17,6 @@ pub struct Config { pub proposal_nonce: u64, } -/// Governance - related pub const CONFIG: Item = Item::new("config"); pub const TOKENS: Map = Map::new("tokens"); diff --git a/contracts/vanchor/src/contract.rs b/contracts/vanchor/src/contract.rs index 7801d69..d60232c 100644 --- a/contracts/vanchor/src/contract.rs +++ b/contracts/vanchor/src/contract.rs @@ -20,7 +20,9 @@ use protocol_cosmwasm::token_wrapper::{ ExecuteMsg as TokenWrapperExecuteMsg, GetAmountToWrapResponse, QueryMsg as TokenWrapperQueryMsg, }; -use protocol_cosmwasm::utils::{compute_chain_id_type, element_encoder, parse_string_to_uint128}; +use protocol_cosmwasm::utils::{ + compute_chain_id, compute_chain_id_type, element_encoder, parse_string_to_uint128, +}; use protocol_cosmwasm::vanchor::{ ConfigResponse, Cw20HookMsg, ExecuteMsg, ExtData, InstantiateMsg, MigrateMsg, ProofData, QueryMsg, UpdateConfigMsg, @@ -91,7 +93,6 @@ pub fn instantiate( // Initialize the VAnchor let anchor = VAnchor { - chain_id: msg.chain_id, creator: deps.api.addr_validate(info.sender.as_str())?, max_deposit_amt: msg.max_deposit_amt, min_withdraw_amt: msg.min_withdraw_amt, @@ -139,7 +140,7 @@ pub fn execute( ExecuteMsg::TransactWithdraw { proof_data, ext_data, - } => transact_withdraw(deps, proof_data, ext_data), + } => transact_withdraw(deps, env, proof_data, ext_data), // Wraps the native token to "TokenWrapper" token // Send the tokens back to `tx sender` or deposit to `this` contract @@ -175,7 +176,7 @@ pub fn execute( ExecuteMsg::TransactDepositWrap { proof_data, ext_data, - } => transact_deposit_wrap_native(deps, info, proof_data, ext_data), + } => transact_deposit_wrap_native(deps, env, info, proof_data, ext_data), // Executes a withdrawal or combination join/split transaction // including wrapping or unwrapping @@ -185,7 +186,7 @@ pub fn execute( proof_data, ext_data, token_addr, - } => transact_withdraw_unwrap(deps, proof_data, ext_data, token_addr), + } => transact_withdraw_unwrap(deps, env, proof_data, ext_data, token_addr), // Sets a new handler for the contract ExecuteMsg::SetHandler { handler, nonce } => set_handler(deps, info, handler, nonce), @@ -293,7 +294,14 @@ fn receive_cw20( Ok(Cw20HookMsg::TransactDeposit { proof_data, ext_data, - }) => transact_deposit(deps, proof_data, ext_data, recv_token_addr, recv_token_amt), + }) => transact_deposit( + deps, + env, + proof_data, + ext_data, + recv_token_addr, + recv_token_amt, + ), Ok(Cw20HookMsg::WrapToken { is_deposit }) => { let recipient = if is_deposit { env.contract.address.to_string() @@ -305,9 +313,14 @@ fn receive_cw20( Ok(Cw20HookMsg::TransactDepositWrap { proof_data, ext_data, - }) => { - transact_deposit_wrap_cw20(deps, proof_data, ext_data, recv_token_addr, recv_token_amt) - } + }) => transact_deposit_wrap_cw20( + deps, + env, + proof_data, + ext_data, + recv_token_addr, + recv_token_amt, + ), Err(_) => Err(ContractError::InvalidCw20HookMsg), } } @@ -315,6 +328,7 @@ fn receive_cw20( // Executes a deposit or combination join/split transactions fn transact_deposit( mut deps: DepsMut, + env: Env, proof_data: ProofData, ext_data: ExtData, recv_token_addr: String, @@ -326,7 +340,7 @@ fn transact_deposit( return Err(ContractError::Unauthorized {}); } - validate_proof(deps.branch(), proof_data.clone(), ext_data.clone())?; + validate_proof(deps.branch(), env, proof_data.clone(), ext_data.clone())?; let ext_data_fee: u128 = ext_data.fee.u128(); let ext_amt: i128 = ext_data.ext_amount.parse().expect("Invalid ext_amount"); @@ -375,6 +389,7 @@ fn transact_deposit( // including wrapping fn transact_deposit_wrap_native( mut deps: DepsMut, + env: Env, info: MessageInfo, proof_data: ProofData, ext_data: ExtData, @@ -411,7 +426,7 @@ fn transact_deposit_wrap_native( } // Validate the "proof_data" & "ext_data" - validate_proof(deps.branch(), proof_data.clone(), ext_data.clone())?; + validate_proof(deps.branch(), env, proof_data.clone(), ext_data.clone())?; // Deposit let mut msgs: Vec = vec![]; @@ -459,6 +474,7 @@ fn transact_deposit_wrap_native( // including wrapping fn transact_deposit_wrap_cw20( mut deps: DepsMut, + env: Env, proof_data: ProofData, ext_data: ExtData, recv_token_addr: String, @@ -488,7 +504,7 @@ fn transact_deposit_wrap_cw20( } // Validate the "proof_data" & "ext_data" - validate_proof(deps.branch(), proof_data.clone(), ext_data.clone())?; + validate_proof(deps.branch(), env, proof_data.clone(), ext_data.clone())?; // Deposit let mut msgs: Vec = vec![]; @@ -538,10 +554,11 @@ fn transact_deposit_wrap_cw20( // Executes a deposit/withdrawal or combination join/split transaction fn transact_withdraw( mut deps: DepsMut, + env: Env, proof_data: ProofData, ext_data: ExtData, ) -> Result { - validate_proof(deps.branch(), proof_data.clone(), ext_data.clone())?; + validate_proof(deps.branch(), env, proof_data.clone(), ext_data.clone())?; let vanchor = VANCHOR.load(deps.storage)?; let ext_data_fee: u128 = ext_data.fee.u128(); @@ -593,11 +610,12 @@ fn transact_withdraw( // including unwrapping fn transact_withdraw_unwrap( mut deps: DepsMut, + env: Env, proof_data: ProofData, ext_data: ExtData, token_addr: Option, ) -> Result { - validate_proof(deps.branch(), proof_data.clone(), ext_data.clone())?; + validate_proof(deps.branch(), env, proof_data.clone(), ext_data.clone())?; let vanchor = VANCHOR.load(deps.storage)?; let ext_data_fee: u128 = ext_data.fee.u128(); @@ -650,6 +668,7 @@ fn transact_withdraw_unwrap( // Check whether if the zkSNARK proof is valid fn validate_proof( deps: DepsMut, + env: Env, proof_data: ProofData, ext_data: ExtData, ) -> Result<(), ContractError> { @@ -727,8 +746,9 @@ fn validate_proof( } // Construct public inputs + let chain_id = compute_chain_id(&env.block.chain_id); let chain_id_type_bytes = - element_encoder(&compute_chain_id_type(vanchor.chain_id, &COSMOS_CHAIN_TYPE).to_le_bytes()); + element_encoder(&compute_chain_id_type(chain_id.into(), &COSMOS_CHAIN_TYPE).to_le_bytes()); let mut bytes = Vec::new(); bytes.extend_from_slice(&proof_data.public_amount); @@ -782,7 +802,6 @@ fn execute_insertions(deps: DepsMut, proof_data: ProofData) -> Result<(), Contra deps.storage, &VAnchor { creator: vanchor.creator, - chain_id: vanchor.chain_id, merkle_tree, linkable_tree: vanchor.linkable_tree, tokenwrapper_addr: vanchor.tokenwrapper_addr, @@ -1062,7 +1081,6 @@ pub fn get_config(deps: Deps) -> StdResult { Ok(ConfigResponse { handler: vanchor.handler.to_string(), proposal_nonce: vanchor.proposal_nonce, - chain_id: vanchor.chain_id, tokenwrapper_addr: vanchor.tokenwrapper_addr.to_string(), max_deposit_amt: vanchor.max_deposit_amt.to_string(), min_withdraw_amt: vanchor.min_withdraw_amt.to_string(), diff --git a/contracts/vanchor/src/state.rs b/contracts/vanchor/src/state.rs index 9fdf7bb..1718872 100644 --- a/contracts/vanchor/src/state.rs +++ b/contracts/vanchor/src/state.rs @@ -9,7 +9,7 @@ use protocol_cosmwasm::structs::{ChainId, Edge, ROOT_HISTORY_SIZE}; use protocol_cosmwasm::vanchor_verifier::VAnchorVerifier; use protocol_cosmwasm::zeroes; -// Chain_ID -> Edge (String(u64) -> Edge) +/// Chain_ID -> Edge (String(u64) -> Edge) pub const EDGES: Map = Map::new("edges"); pub fn read_edge(store: &dyn Storage, k: ChainId) -> StdResult { @@ -24,7 +24,7 @@ pub fn has_edge(store: &dyn Storage, k: ChainId) -> bool { EDGES.has(store, k.to_string()) } -// Chain_ID -> root_idx (String(u64) -> u32) +/// Chain_ID -> root_idx (String(u64) -> u32) pub const CURR_NEIGHBOR_ROOT_INDEX: Map = Map::new("curr_neighbor_root_index"); pub fn read_curr_neighbor_root_index(store: &dyn Storage, k: ChainId) -> StdResult { @@ -55,7 +55,7 @@ pub fn save_neighbor_roots( NEIGHBOR_ROOTS.save(store, (id.to_string(), num.to_string()), &data) } -// LinkableMerkleTree +/// LinkableMerkleTree #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct LinkableMerkleTree { pub max_edges: u32, @@ -176,10 +176,23 @@ impl LinkableMerkleTree { } } -// VAnchor: (TODO: Add the description) +/// "VAnchor"(Variable Anchor) +/// The Variable Anchor is a variable-denominated shielded pool system +/// derived from Tornado Nova (tornado-pool). This system extends the shielded +/// pool system into a bridged system and allows for join/split transactions. +/// +/// "creator" Address of creating this "vanchor" contract +/// "merkle_tree" Tree data structure to hold the `transact` info +/// "linkable_tree" Tree data structure to hold the `edge` info +/// "tokenwrapper_addr" Cw20 token address used for wrapping native & any cw20 token +/// "max_deposit_amt" Maximum `transact(deposit)` amount in one transaction +/// "min_withdraw_amt" Minimum `transct(withdraw)` amount in one transcation +/// "max_ext_amt" Maximum `ext` amount in one transaction +/// "max_fee" Maximum `fee` amount in one transaction +/// "proposal_nonce" Nonce value to track the proposals +/// "handler" Address of `handler`(vanchor-handler), which updates the config of this contract(vanchor) #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct VAnchor { - pub chain_id: u64, pub creator: Addr, pub merkle_tree: MerkleTree, pub linkable_tree: LinkableMerkleTree, @@ -194,19 +207,19 @@ pub struct VAnchor { pub const VANCHOR: Item = Item::new("vanchor"); -// Struct to save the use of "nullifiers" +/// Struct to save the use of "nullifiers" pub const NULLIFIERS: Map, bool> = Map::new("used_nullifers"); -// "Poseidon hasher" +/// "Poseidon hasher" pub const HASHER: Item = Item::new("poseidon"); -// "VAnchorVerifier (2 * 2) +/// "VAnchorVerifier (2 * 2) pub const VERIFIER_2_2: Item = Item::new("vanchor_verifier_2_2"); -// "VAnchorVerifier" (16 * 2) +/// "VAnchorVerifier" (16 * 2) pub const VERIFIER_16_2: Item = Item::new("vanchor_verifier_16_2"); -// MerkleTree +/// MerkleTree #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct MerkleTree { pub levels: u32, @@ -214,7 +227,7 @@ pub struct MerkleTree { pub next_index: u32, } -// MerkleTree "filled_subtrees" +/// MerkleTree "filled_subtrees" pub const FILLED_SUBTREES: Map = Map::new("filled_subtrees"); pub fn save_subtree(store: &mut dyn Storage, k: u32, data: &[u8; 32]) -> StdResult<()> { @@ -225,7 +238,7 @@ pub fn read_subtree(store: &dyn Storage, k: u32) -> StdResult<[u8; 32]> { FILLED_SUBTREES.load(store, k.to_string()) } -// MerkleTree Roots +/// MerkleTree Roots pub const MERKLEROOTS: Map = Map::new("merkle_roots"); pub fn save_root(store: &mut dyn Storage, k: u32, data: &[u8; 32]) -> StdResult<()> { diff --git a/contracts/vanchor/src/tests.rs b/contracts/vanchor/src/tests.rs index 93cda50..a168db7 100644 --- a/contracts/vanchor/src/tests.rs +++ b/contracts/vanchor/src/tests.rs @@ -15,7 +15,7 @@ use protocol_cosmwasm::vanchor::{ use protocol_cosmwasm::zeroes::zeroes; const CHAIN_TYPE: [u8; 2] = [4, 0]; // 0x0400 -const TEST_CHAIN_ID: u64 = 1; +const CHAIN_ID: u64 = 2145598729; // chain_id: "cosmos-testnet-14002" const MAX_EDGES: u32 = 2; const LEVELS: u32 = 30; @@ -40,7 +40,6 @@ fn create_vanchor() -> OwnedDeps [u8; 32] { let mut output = [0u8; 32]; output.iter_mut().zip(v).for_each(|(b1, b2)| *b1 = *b2); output } -// Slice the length of bytes array into 4 bytes +/// Slice the length of bytes array into 4 bytes pub fn bytes4_encoder(v: &[u8]) -> [u8; 4] { let mut output = [0u8; 4]; output.iter_mut().zip(v).for_each(|(b1, b2)| *b1 = *b2); output } -// Computes the combination bytes of "chain_type" and "chain_id". -// Combination rule: 8 bytes array(00 * 2 bytes + [chain_type] 2 bytes + [chain_id] 4 bytes) -// Example: -// chain_type - 0x0401, chain_id - 0x00000001 (big endian) -// Result - [00, 00, 04, 01, 00, 00, 00, 01] +/// Computes the combination bytes of "chain_type" and "chain_id". +/// Combination rule: 8 bytes array(00 * 2 bytes + [chain_type] 2 bytes + [chain_id] 4 bytes) +/// Example: +/// chain_type - 0x0401, chain_id - 0x00000001 (big endian) +/// Result - [00, 00, 04, 01, 00, 00, 00, 01] pub fn compute_chain_id_type(chain_id: u64, chain_type: &[u8]) -> u64 { let chain_id_value: u32 = chain_id.try_into().unwrap_or_default(); let mut buf = [0u8; 8]; @@ -28,7 +29,24 @@ pub fn compute_chain_id_type(chain_id: u64, chain_type: &[u8]) -> u64 { u64::from_be_bytes(buf) } -// Truncate and pad 256 bit slice +/// Computes the numeric "chain_id" from string one. +/// This is only needed for Cosmos SDK blockchains since +/// their "chain_id"s are string(eg: "juno-1") +/// Rule: +/// 1. Hash the "chain_id" to get 32-length bytes array +/// eg: keccak256("juno-1") => 4c22bf61f15534242ee9dba16dceb4c976851b1788680fb5ee2a7b568a294d21 +/// 2. Slice the last 4 bytes & convert it to `u32` numeric value +/// eg: 8a294d21(hex) -> 2317962529(decimal) +pub fn compute_chain_id(chain_id_str: &str) -> u32 { + let hash_value = Keccak256::hash(chain_id_str.as_bytes()).expect("chain-id hashing error"); + let last_4_bytes = &hash_value[28..]; + + let mut buf = [0u8; 4]; + buf[0..4].copy_from_slice(last_4_bytes); + u32::from_be_bytes(buf) +} + +/// Truncate and pad 256 bit slice pub fn truncate_and_pad(t: &[u8]) -> Vec { let mut truncated_bytes = t[..20].to_vec(); truncated_bytes.extend_from_slice(&[0u8; 12]); @@ -43,7 +61,7 @@ pub fn parse_string_to_uint128(v: String) -> Result { Ok(res) } -// Get the `chain_id_type` from bytes array. +/// Get the `chain_id_type` from bytes array. pub fn get_chain_id_type(chain_id_type: &[u8]) -> u64 { let mut buf = [0u8; 8]; #[allow(clippy::needless_borrow)] diff --git a/packages/protocol_cosmwasm/src/vanchor.rs b/packages/protocol_cosmwasm/src/vanchor.rs index e3f39ab..c6ae6d6 100644 --- a/packages/protocol_cosmwasm/src/vanchor.rs +++ b/packages/protocol_cosmwasm/src/vanchor.rs @@ -5,7 +5,6 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct InstantiateMsg { - pub chain_id: u64, pub levels: u32, pub max_edges: u32, pub tokenwrapper_addr: String, @@ -179,7 +178,6 @@ pub struct ConfigResponse { pub handler: String, pub proposal_nonce: u32, pub tokenwrapper_addr: String, - pub chain_id: u64, pub max_deposit_amt: String, pub min_withdraw_amt: String, pub max_ext_amt: String, diff --git a/test-scripts/src/processes/setup/testnet.ts b/test-scripts/src/processes/setup/testnet.ts index ee31b74..3f537c6 100644 --- a/test-scripts/src/processes/setup/testnet.ts +++ b/test-scripts/src/processes/setup/testnet.ts @@ -255,7 +255,6 @@ async function setup( anchorCodeId, { "max_edges": localjuno.contractsConsts.maxEdges, - "chain_id": localjuno.contractsConsts.chainId, "levels": localjuno.contractsConsts.levels, "deposit_size": localjuno.contractsConsts.depositSize, "tokenwrapper_addr": tokenWrapper, @@ -276,7 +275,6 @@ async function setup( vanchorCodeId, { "max_edges": localjuno.contractsConsts.maxEdges, - "chain_id": localjuno.contractsConsts.chainId, "levels": localjuno.contractsConsts.levels, "max_deposit_amt": localjuno.contractsConsts.maxDepositAmt, "min_withdraw_amt": localjuno.contractsConsts.minWithdrawAmt, diff --git a/test-scripts/src/processes/tests/anchor.ts b/test-scripts/src/processes/tests/anchor.ts index 820d00d..7eb8241 100644 --- a/test-scripts/src/processes/tests/anchor.ts +++ b/test-scripts/src/processes/tests/anchor.ts @@ -28,7 +28,6 @@ export async function testAnchorInitialize( expect(result.handler == localjuno.contracts.anchorHandler); expect(result.proposal_nonce == 0); - expect(result.chain_id == localjuno.contractsConsts.chainId); expect(result.tokenwrapper_addr == localjuno.contracts.tokenWrapper); expect(result.deposit_size == localjuno.contractsConsts.depositSize); @@ -80,7 +79,7 @@ export async function testAnchorInitialize( // Succeed to "deposit" const result = await wallet3_client.execute(localjuno.addresses.wallet3, localjuno.contracts.anchor, { wrap_and_deposit: { - commitment: [235, 3, 87, 22, 66, 107, 162, 89, 147, 182, 207, 54, 195, 138, 136, 110, 150, 128, 213, 43, 44, 121, 177, 9, 17, 54, 9, 202, 11, 230, 158, 8], + commitment: [37, 182, 146, 58, 233, 152, 60, 235, 245, 80, 102, 165, 73, 117, 83, 34, 18, 215, 241, 142, 54, 189, 23, 80, 211, 122, 177, 140, 184, 200, 9, 47], amount: ucosm_amount, } }, "auto", undefined, [coin(ucosm_to_send, "ucosm")]) @@ -99,7 +98,7 @@ export async function testAnchorInitialize( await expect( wallet2_client.execute(localjuno.addresses.wallet2, anchor, { withdraw_and_unwrap: { - proof_bytes: [168, 60, 122, 239, 216, 49, 51, 19, 135, 224, 117, 57, 71, 178, 12, 149, 135, 132, 115, 166, 248, 175, 71, 160, 160, 92, 167, 35, 250, 197, 156, 13, 82, 106, 210, 191, 192, 174, 127, 23, 146, 114, 67, 179, 210, 230, 89, 73, 81, 109, 204, 170, 1, 80, 193, 229, 101, 58, 38, 204, 90, 111, 45, 20, 106, 206, 173, 139, 4, 104, 18, 116, 216, 41, 10, 147, 221, 99, 98, 42, 229, 213, 30, 251, 131, 33, 236, 31, 75, 76, 29, 155, 85, 244, 59, 162, 173, 48, 143, 49, 233, 38, 135, 62, 5, 125, 99, 61, 72, 168, 208, 187, 98, 141, 85, 129, 247, 145, 102, 19, 205, 100, 75, 200, 20, 205, 92, 168], + proof_bytes: [254, 221, 51, 90, 6, 117, 43, 109, 75, 64, 147, 126, 195, 246, 6, 35, 118, 181, 239, 213, 58, 121, 13, 49, 217, 124, 183, 146, 127, 73, 28, 172, 9, 222, 120, 126, 122, 54, 111, 247, 204, 235, 149, 87, 3, 254, 200, 51, 99, 26, 188, 44, 164, 205, 143, 195, 238, 12, 222, 155, 129, 89, 148, 28, 36, 197, 176, 99, 16, 173, 222, 27, 81, 136, 227, 125, 188, 250, 118, 148, 8, 193, 71, 34, 170, 133, 150, 164, 65, 242, 125, 70, 242, 142, 196, 157, 239, 202, 126, 206, 47, 103, 51, 70, 222, 69, 95, 16, 196, 47, 248, 128, 12, 162, 134, 172, 165, 178, 16, 1, 217, 35, 127, 73, 6, 92, 217, 46], roots: [], nullifier_hash: [183, 160, 141, 89, 98, 241, 220, 87, 120, 249, 242, 56, 92, 41, 28, 230, 247, 111, 155, 7, 94, 2, 142, 101, 0, 243, 39, 32, 59, 235, 198, 31], recipient: localjuno.addresses.wallet2, @@ -118,8 +117,8 @@ export async function testAnchorInitialize( const result1 = await wallet2_client.execute(localjuno.addresses.wallet2, anchor, { withdraw_and_unwrap: { - proof_bytes: [168, 60, 122, 239, 216, 49, 51, 19, 135, 224, 117, 57, 71, 178, 12, 149, 135, 132, 115, 166, 248, 175, 71, 160, 160, 92, 167, 35, 250, 197, 156, 13, 82, 106, 210, 191, 192, 174, 127, 23, 146, 114, 67, 179, 210, 230, 89, 73, 81, 109, 204, 170, 1, 80, 193, 229, 101, 58, 38, 204, 90, 111, 45, 20, 106, 206, 173, 139, 4, 104, 18, 116, 216, 41, 10, 147, 221, 99, 98, 42, 229, 213, 30, 251, 131, 33, 236, 31, 75, 76, 29, 155, 85, 244, 59, 162, 173, 48, 143, 49, 233, 38, 135, 62, 5, 125, 99, 61, 72, 168, 208, 187, 98, 141, 85, 129, 247, 145, 102, 19, 205, 100, 75, 200, 20, 205, 92, 168], - roots: [[95, 118, 152, 109, 95, 8, 90, 146, 31, 73, 193, 217, 18, 210, 109, 187, 210, 188, 213, 120, 236, 144, 71, 85, 80, 77, 197, 35, 135, 170, 135, 45], [95, 118, 152, 109, 95, 8, 90, 146, 31, 73, 193, 217, 18, 210, 109, 187, 210, 188, 213, 120, 236, 144, 71, 85, 80, 77, 197, 35, 135, 170, 135, 45]], + proof_bytes: [254, 221, 51, 90, 6, 117, 43, 109, 75, 64, 147, 126, 195, 246, 6, 35, 118, 181, 239, 213, 58, 121, 13, 49, 217, 124, 183, 146, 127, 73, 28, 172, 9, 222, 120, 126, 122, 54, 111, 247, 204, 235, 149, 87, 3, 254, 200, 51, 99, 26, 188, 44, 164, 205, 143, 195, 238, 12, 222, 155, 129, 89, 148, 28, 36, 197, 176, 99, 16, 173, 222, 27, 81, 136, 227, 125, 188, 250, 118, 148, 8, 193, 71, 34, 170, 133, 150, 164, 65, 242, 125, 70, 242, 142, 196, 157, 239, 202, 126, 206, 47, 103, 51, 70, 222, 69, 95, 16, 196, 47, 248, 128, 12, 162, 134, 172, 165, 178, 16, 1, 217, 35, 127, 73, 6, 92, 217, 46], + roots: [[175, 83, 6, 17, 157, 29, 197, 241, 102, 254, 25, 90, 172, 136, 69, 45, 105, 80, 35, 14, 135, 47, 253, 121, 150, 71, 5, 151, 124, 124, 61, 27], [175, 83, 6, 17, 157, 29, 197, 241, 102, 254, 25, 90, 172, 136, 69, 45, 105, 80, 35, 14, 135, 47, 253, 121, 150, 71, 5, 151, 124, 124, 61, 27]], nullifier_hash: [183, 160, 141, 89, 98, 241, 220, 87, 120, 249, 242, 56, 92, 41, 28, 230, 247, 111, 155, 7, 94, 2, 142, 101, 0, 243, 39, 32, 59, 235, 198, 31], recipient: localjuno.addresses.wallet2, relayer: localjuno.addresses.wallet3, diff --git a/test-scripts/src/processes/tests/vanchor.ts b/test-scripts/src/processes/tests/vanchor.ts index 4025130..d840b25 100644 --- a/test-scripts/src/processes/tests/vanchor.ts +++ b/test-scripts/src/processes/tests/vanchor.ts @@ -28,7 +28,6 @@ export async function testVAnchorInitialize( expect(result.handler == localjuno.contracts.anchorHandler); expect(result.proposal_nonce == 0); - expect(result.chain_id == localjuno.contractsConsts.chainId); expect(result.tokenwrapper_addr == localjuno.contracts.tokenWrapper); expect(result.max_deposit_amt == localjuno.contractsConsts.maxDepositAmt); expect(result.min_withdraw_amt == localjuno.contractsConsts.minWithdrawAmt); @@ -103,20 +102,20 @@ export async function testVAnchorInitialize( // Succeed to "deposit" let depositProofData = { - proof: [249, 63, 95, 77, 91, 215, 254, 58, 26, 170, 201, 237, 125, 157, 247, 143, 206, 218, 154, 56, 205, 12, 100, 134, 113, 235, 149, 53, 212, 99, 217, 142, 174, 68, 235, 82, 51, 193, 43, 178, 26, 128, 44, 121, 29, 218, 106, 107, 88, 143, 93, 26, 75, 200, 168, 173, 51, 169, 36, 67, 255, 105, 234, 25, 205, 146, 192, 16, 145, 11, 47, 4, 254, 134, 151, 174, 6, 178, 110, 86, 59, 190, 67, 5, 122, 177, 1, 189, 149, 238, 234, 135, 118, 239, 176, 149, 164, 68, 75, 163, 237, 7, 210, 183, 249, 185, 86, 82, 163, 54, 193, 236, 28, 196, 17, 23, 76, 142, 54, 154, 86, 36, 220, 121, 39, 11, 19, 31], + proof: [30, 112, 87, 195, 127, 201, 224, 192, 203, 17, 114, 63, 206, 53, 246, 44, 154, 53, 158, 151, 253, 88, 92, 134, 34, 231, 107, 190, 40, 1, 4, 143, 99, 243, 130, 31, 235, 198, 145, 24, 132, 255, 251, 85, 34, 75, 53, 120, 252, 221, 217, 25, 139, 104, 50, 252, 128, 74, 184, 42, 181, 230, 31, 1, 76, 34, 8, 226, 182, 246, 242, 123, 1, 180, 107, 59, 88, 235, 249, 127, 254, 161, 41, 2, 236, 186, 241, 152, 51, 126, 153, 77, 96, 45, 20, 130, 51, 19, 204, 125, 56, 81, 159, 251, 154, 252, 34, 146, 151, 60, 39, 216, 165, 26, 63, 208, 249, 193, 173, 154, 128, 253, 241, 209, 217, 55, 24, 146], public_amount: [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], roots: [[239, 89, 25, 14, 35, 42, 26, 61, 180, 140, 224, 106, 63, 122, 122, 78, 89, 65, 28, 26, 74, 63, 65, 52, 176, 152, 45, 245, 107, 212, 24, 9], [239, 89, 25, 14, 35, 42, 26, 61, 180, 140, 224, 106, 63, 122, 122, 78, 89, 65, 28, 26, 74, 63, 65, 52, 176, 152, 45, 245, 107, 212, 24, 9]], - input_nullifiers: [[83, 180, 139, 65, 56, 112, 24, 191, 212, 50, 135, 164, 184, 126, 193, 240, 161, 130, 245, 6, 63, 114, 230, 13, 221, 253, 248, 164, 249, 208, 50, 17], [211, 3, 245, 77, 123, 200, 59, 116, 120, 218, 244, 44, 163, 180, 233, 15, 17, 205, 20, 134, 149, 32, 203, 230, 174, 5, 41, 45, 2, 90, 51, 13]], - output_commitments: [[20, 75, 155, 185, 13, 156, 191, 68, 189, 39, 70, 163, 41, 46, 77, 108, 110, 192, 77, 226, 44, 203, 243, 44, 254, 89, 14, 136, 236, 79, 58, 29], [196, 160, 156, 49, 22, 132, 172, 188, 3, 250, 188, 30, 145, 3, 235, 15, 31, 179, 214, 170, 238, 161, 154, 42, 170, 39, 123, 249, 145, 138, 181, 29]], - ext_data_hash: [222, 216, 114, 136, 124, 143, 207, 214, 121, 161, 68, 249, 147, 71, 109, 45, 125, 223, 141, 196, 35, 109, 148, 196, 173, 32, 126, 248, 1, 226, 81, 39] + input_nullifiers: [[224, 165, 53, 18, 173, 250, 1, 6, 116, 81, 253, 141, 161, 15, 154, 235, 13, 168, 140, 246, 212, 77, 231, 208, 96, 80, 228, 184, 162, 53, 88, 32], [189, 77, 100, 41, 230, 177, 166, 236, 13, 175, 89, 198, 212, 179, 74, 166, 251, 129, 72, 74, 184, 110, 171, 89, 195, 255, 7, 222, 136, 120, 144, 43]], + output_commitments: [[51, 170, 43, 18, 241, 27, 148, 191, 180, 66, 129, 121, 76, 55, 72, 92, 154, 5, 174, 234, 119, 175, 22, 78, 12, 231, 3, 94, 147, 32, 125, 32], [118, 160, 222, 87, 203, 95, 19, 112, 183, 150, 179, 138, 42, 218, 199, 64, 60, 80, 99, 161, 160, 78, 146, 254, 116, 117, 190, 81, 39, 128, 55, 1]], + ext_data_hash: [185, 233, 54, 0, 212, 197, 132, 236, 29, 79, 18, 216, 69, 52, 78, 96, 245, 63, 47, 2, 227, 107, 23, 103, 100, 185, 119, 75, 189, 139, 220, 36] }; let depositExtData = { recipient: localjuno.addresses.wallet2, relayer: localjuno.addresses.wallet1, ext_amount: in_ext_amount, fee: in_fee, - encrypted_output1: [20, 75, 155, 185, 13, 156, 191, 68, 189, 39, 70, 163, 41, 46, 77, 108, 110, 192, 77, 226, 44, 203, 243, 44, 254, 89, 14, 136, 236, 79, 58, 29], - encrypted_output2: [196, 160, 156, 49, 22, 132, 172, 188, 3, 250, 188, 30, 145, 3, 235, 15, 31, 179, 214, 170, 238, 161, 154, 42, 170, 39, 123, 249, 145, 138, 181, 29], + encrypted_output1: [51, 170, 43, 18, 241, 27, 148, 191, 180, 66, 129, 121, 76, 55, 72, 92, 154, 5, 174, 234, 119, 175, 22, 78, 12, 231, 3, 94, 147, 32, 125, 32], + encrypted_output2: [118, 160, 222, 87, 203, 95, 19, 112, 183, 150, 179, 138, 42, 218, 199, 64, 60, 80, 99, 161, 160, 78, 146, 254, 116, 117, 190, 81, 39, 128, 55, 1], }; transactDepositWrapMsg = toEncodedBinary({ @@ -163,20 +162,20 @@ export async function testVAnchorInitialize( const beforeUcosm = beforeBalance.amount; let withdrawProofData = { - proof: [105, 7, 193, 151, 128, 163, 45, 175, 77, 115, 231, 108, 226, 228, 26, 193, 84, 92, 140, 202, 66, 187, 119, 209, 102, 35, 211, 66, 7, 153, 96, 20, 157, 71, 81, 253, 212, 37, 121, 176, 61, 226, 63, 24, 102, 224, 147, 94, 193, 171, 174, 249, 174, 113, 216, 248, 242, 118, 90, 18, 101, 229, 86, 15, 176, 58, 173, 137, 165, 35, 24, 71, 158, 128, 173, 103, 139, 45, 131, 247, 178, 115, 251, 148, 224, 223, 152, 4, 65, 49, 25, 41, 252, 78, 154, 22, 26, 142, 180, 44, 175, 144, 72, 243, 241, 179, 141, 190, 70, 49, 100, 67, 222, 207, 188, 189, 163, 198, 26, 222, 164, 47, 122, 144, 143, 210, 234, 162], + proof: [6, 15, 218, 177, 117, 235, 114, 126, 18, 191, 5, 117, 117, 130, 27, 242, 105, 237, 167, 173, 58, 16, 55, 33, 22, 202, 52, 118, 250, 128, 24, 141, 123, 25, 69, 125, 205, 228, 45, 63, 243, 107, 146, 122, 192, 81, 229, 170, 104, 109, 151, 55, 18, 54, 89, 25, 77, 139, 13, 112, 40, 148, 59, 2, 96, 138, 0, 106, 249, 75, 59, 151, 41, 52, 36, 36, 174, 97, 57, 236, 48, 33, 139, 240, 120, 57, 202, 196, 107, 99, 19, 72, 142, 17, 163, 34, 165, 23, 199, 90, 53, 243, 220, 183, 148, 172, 5, 171, 114, 255, 223, 40, 128, 55, 76, 74, 239, 212, 130, 143, 191, 153, 50, 226, 42, 18, 36, 150], public_amount: [250, 255, 255, 239, 147, 245, 225, 67, 145, 112, 185, 121, 72, 232, 51, 40, 93, 88, 129, 129, 182, 69, 80, 184, 41, 160, 49, 225, 114, 78, 100, 48], - roots: [[45, 21, 249, 142, 150, 215, 102, 179, 25, 192, 13, 7, 191, 101, 47, 62, 233, 117, 143, 207, 70, 159, 128, 227, 80, 80, 162, 50, 255, 166, 110, 41], [45, 21, 249, 142, 150, 215, 102, 179, 25, 192, 13, 7, 191, 101, 47, 62, 233, 117, 143, 207, 70, 159, 128, 227, 80, 80, 162, 50, 255, 166, 110, 41]], - input_nullifiers: [[0, 83, 230, 137, 230, 209, 253, 209, 28, 80, 92, 11, 41, 47, 175, 127, 209, 225, 57, 230, 1, 11, 4, 66, 92, 77, 120, 38, 129, 185, 66, 18], [232, 233, 88, 214, 173, 131, 231, 212, 227, 33, 2, 22, 236, 192, 180, 218, 27, 151, 77, 243, 134, 144, 86, 115, 1, 182, 148, 34, 17, 188, 106, 7]], - output_commitments: [[236, 125, 91, 108, 52, 47, 35, 195, 65, 197, 8, 183, 44, 160, 29, 149, 250, 218, 83, 10, 14, 80, 138, 83, 41, 72, 216, 79, 202, 91, 189, 31], [3, 48, 30, 43, 113, 185, 39, 226, 100, 156, 46, 26, 190, 67, 190, 116, 123, 17, 122, 116, 72, 225, 43, 137, 210, 142, 67, 211, 160, 4, 179, 15]], - ext_data_hash: [158, 9, 138, 113, 229, 26, 141, 207, 13, 240, 39, 98, 110, 41, 246, 100, 171, 99, 51, 92, 170, 131, 208, 76, 119, 5, 32, 149, 87, 129, 60, 11] + roots: [[217, 20, 52, 153, 71, 108, 157, 246, 118, 136, 162, 174, 179, 11, 230, 202, 111, 243, 7, 194, 127, 104, 188, 72, 177, 192, 208, 73, 30, 17, 193, 16], [217, 20, 52, 153, 71, 108, 157, 246, 118, 136, 162, 174, 179, 11, 230, 202, 111, 243, 7, 194, 127, 104, 188, 72, 177, 192, 208, 73, 30, 17, 193, 16]], + input_nullifiers: [[21, 220, 15, 156, 175, 19, 142, 182, 60, 133, 175, 250, 219, 252, 100, 173, 28, 42, 252, 248, 19, 57, 244, 112, 62, 113, 153, 19, 251, 16, 121, 40], [28, 89, 229, 192, 84, 147, 99, 165, 199, 33, 194, 56, 4, 74, 56, 163, 1, 25, 124, 188, 10, 70, 47, 147, 127, 165, 42, 197, 103, 113, 103, 7]], + output_commitments: [[125, 110, 224, 1, 48, 212, 222, 90, 24, 185, 247, 184, 195, 136, 3, 31, 194, 241, 204, 74, 166, 241, 108, 174, 60, 53, 231, 172, 185, 73, 238, 29], [187, 171, 58, 24, 2, 94, 165, 218, 55, 45, 129, 76, 99, 82, 221, 82, 249, 161, 176, 31, 55, 122, 23, 232, 184, 113, 110, 234, 202, 38, 36, 32]], + ext_data_hash: [20, 180, 8, 58, 78, 250, 172, 0, 115, 37, 109, 166, 113, 238, 248, 93, 84, 147, 18, 87, 48, 95, 194, 125, 85, 53, 110, 166, 201, 15, 24, 0] }; let withdrawExtData = { recipient: localjuno.addresses.wallet2, relayer: localjuno.addresses.wallet1, ext_amount: out_ext_amount, fee: out_fee, - encrypted_output1: [236, 125, 91, 108, 52, 47, 35, 195, 65, 197, 8, 183, 44, 160, 29, 149, 250, 218, 83, 10, 14, 80, 138, 83, 41, 72, 216, 79, 202, 91, 189, 31], - encrypted_output2: [3, 48, 30, 43, 113, 185, 39, 226, 100, 156, 46, 26, 190, 67, 190, 116, 123, 17, 122, 116, 72, 225, 43, 137, 210, 142, 67, 211, 160, 4, 179, 15] + encrypted_output1: [125, 110, 224, 1, 48, 212, 222, 90, 24, 185, 247, 184, 195, 136, 3, 31, 194, 241, 204, 74, 166, 241, 108, 174, 60, 53, 231, 172, 185, 73, 238, 29], + encrypted_output2: [187, 171, 58, 24, 2, 94, 165, 218, 55, 45, 129, 76, 99, 82, 221, 82, 249, 161, 176, 31, 55, 122, 23, 232, 184, 113, 110, 234, 202, 38, 36, 32] }; const result1 = await wallet2_client.execute(localjuno.addresses.wallet2, vanchor, { transact_withdraw_unwrap: {