diff --git a/bridge/pkg/processor/processor.go b/bridge/pkg/processor/processor.go index 353953fc4d..67d1feaae1 100644 --- a/bridge/pkg/processor/processor.go +++ b/bridge/pkg/processor/processor.go @@ -14,6 +14,7 @@ import ( "github.com/certusone/wormhole/bridge/pkg/devnet" gossipv1 "github.com/certusone/wormhole/bridge/pkg/proto/gossip/v1" "github.com/certusone/wormhole/bridge/pkg/supervisor" + "github.com/certusone/wormhole/bridge/pkg/terra" "github.com/certusone/wormhole/bridge/pkg/vaa" ) @@ -167,6 +168,15 @@ func (p *Processor) checkDevModeGuardianSetUpdate(ctx context.Context) error { p.logger.Info("devnet guardian set change submitted to Ethereum", zap.Any("trx", trx), zap.Any("vaa", v)) + if p.terraChaidID != "" { + // Submit to Terra + trxResponse, err := terra.SubmitVAA(timeout, p.terraLCD, p.terraChaidID, p.terraContract, p.terraFeePayer, v) + if err != nil { + return fmt.Errorf("failed to submit devnet guardian set change: %v", err) + } + p.logger.Info("devnet guardian set change submitted to Terra", zap.Any("trxResponse", trxResponse), zap.Any("vaa", v)) + } + // Submit VAA to Solana as well. This is asynchronous and can fail, leading to inconsistent devnet state. p.vaaC <- v } diff --git a/bridge/pkg/terra/sender.go b/bridge/pkg/terra/sender.go index 3002c863e4..d5a3dbe8c8 100644 --- a/bridge/pkg/terra/sender.go +++ b/bridge/pkg/terra/sender.go @@ -3,8 +3,6 @@ package terra import ( "context" "encoding/json" - "fmt" - "strings" "time" "github.com/certusone/wormhole/bridge/pkg/vaa" @@ -14,24 +12,12 @@ import ( "github.com/terra-project/terra.go/tx" ) -type JSONArraySlice []uint8 - -func (u JSONArraySlice) MarshalJSON() ([]uint8, error) { - var result string - if u == nil { - result = "null" - } else { - result = strings.Join(strings.Fields(fmt.Sprintf("%d", u)), ",") - } - return []byte(result), nil -} - type SubmitVAAMsg struct { Params SubmitVAAParams `json:"submit_v_a_a"` } type SubmitVAAParams struct { - VAA JSONArraySlice `json:"vaa"` + VAA []byte `json:"vaa"` } // SubmitVAA prepares transaction with signed VAA and sends it to the Terra blockchain diff --git a/devnet/terra-configmaps.yaml b/devnet/terra-configmaps.yaml index 54a94a9e28..4393c2af49 100644 --- a/devnet/terra-configmaps.yaml +++ b/devnet/terra-configmaps.yaml @@ -242,7 +242,7 @@ data: flush_throttle_timeout = "100ms" # Maximum size of a message packet payload, in bytes - max_packet_msg_payload_size = 1024 + max_packet_msg_payload_size = 4096 # Rate at which packets can be sent, in bytes/second send_rate = 5120000 @@ -776,7 +776,7 @@ data: "params": { "max_contract_size": "512000", "max_contract_gas": "100000000", - "max_contract_msg_size": "1024" + "max_contract_msg_size": "4096" }, "last_code_id": "0", "last_instance_id": "0", @@ -1279,7 +1279,7 @@ data: flush_throttle_timeout = "100ms" # Maximum size of a message packet payload, in bytes - max_packet_msg_payload_size = 1024 + max_packet_msg_payload_size = 4096 # Rate at which packets can be sent, in bytes/second send_rate = 5120000 @@ -1813,7 +1813,7 @@ data: "params": { "max_contract_size": "512000", "max_contract_gas": "100000000", - "max_contract_msg_size": "1024" + "max_contract_msg_size": "4096" }, "last_code_id": "0", "last_instance_id": "0", diff --git a/terra/contracts/cw20-wrapped/src/contract.rs b/terra/contracts/cw20-wrapped/src/contract.rs index 6edfb06f31..587f241c16 100644 --- a/terra/contracts/cw20-wrapped/src/contract.rs +++ b/terra/contracts/cw20-wrapped/src/contract.rs @@ -168,7 +168,7 @@ mod tests { fn do_init(deps: &mut Extern, creator: &HumanAddr) { let init_msg = InitMsg { asset_chain: 1, - asset_address: vec![1; 32], + asset_address: vec![1; 32].into(), decimals: 10, mint: None, init_hook: None, @@ -191,7 +191,7 @@ mod tests { query_wrapped_asset_info(&deps).unwrap(), WrappedAssetInfoResponse { asset_chain: 1, - asset_address: vec![1; 32], + asset_address: vec![1; 32].into(), bridge: creator.clone(), } ); diff --git a/terra/contracts/cw20-wrapped/src/msg.rs b/terra/contracts/cw20-wrapped/src/msg.rs index cf043c57c1..75da562c97 100644 --- a/terra/contracts/cw20-wrapped/src/msg.rs +++ b/terra/contracts/cw20-wrapped/src/msg.rs @@ -7,7 +7,7 @@ use cw20::Expiration; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct InitMsg { pub asset_chain: u8, - pub asset_address: Vec, + pub asset_address: Binary, pub decimals: u8, pub mint: Option, pub init_hook: Option, @@ -105,6 +105,6 @@ pub enum QueryMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct WrappedAssetInfoResponse { pub asset_chain: u8, // Asset chain id - pub asset_address: Vec, // Asset smart contract address in the original chain + pub asset_address: Binary, // Asset smart contract address in the original chain pub bridge: HumanAddr, // Bridge address, authorized to mint and burn wrapped tokens } diff --git a/terra/contracts/cw20-wrapped/src/state.rs b/terra/contracts/cw20-wrapped/src/state.rs index 22be1c551a..30c8f1e970 100644 --- a/terra/contracts/cw20-wrapped/src/state.rs +++ b/terra/contracts/cw20-wrapped/src/state.rs @@ -1,7 +1,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use cosmwasm_std::{CanonicalAddr, ReadonlyStorage, Storage}; +use cosmwasm_std::{CanonicalAddr, ReadonlyStorage, Storage, Binary}; use cosmwasm_storage::{singleton, singleton_read, ReadonlySingleton, Singleton}; pub const KEY_WRAPPED_ASSET: &[u8] = b"wrappedAsset"; @@ -10,7 +10,7 @@ pub const KEY_WRAPPED_ASSET: &[u8] = b"wrappedAsset"; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct WrappedAssetInfo { pub asset_chain: u8, // Asset chain id - pub asset_address: Vec, // Asset smart contract address on the original chain + pub asset_address: Binary, // Asset smart contract address on the original chain pub bridge: CanonicalAddr, // Bridge address, authorized to mint and burn wrapped tokens } diff --git a/terra/contracts/cw20-wrapped/tests/integration.rs b/terra/contracts/cw20-wrapped/tests/integration.rs index 34a584e1d7..f0d0763300 100644 --- a/terra/contracts/cw20-wrapped/tests/integration.rs +++ b/terra/contracts/cw20-wrapped/tests/integration.rs @@ -2,7 +2,7 @@ static WASM: &[u8] = include_bytes!("../../../target/wasm32-unknown-unknown/release/cw20_wrapped.wasm"); use cosmwasm_std::{ - from_slice, Env, HandleResponse, HandleResult, HumanAddr, InitResponse, Uint128, + from_slice, Env, HandleResponse, HandleResult, HumanAddr, InitResponse, Uint128, Binary, }; use cosmwasm_storage::to_length_prefixed; use cosmwasm_vm::testing::{ @@ -51,7 +51,7 @@ fn do_init(height: u64) -> Instance { let mut deps = mock_instance(WASM, &[]); let init_msg = InitMsg { asset_chain: 1, - asset_address: vec![1; 32], + asset_address: vec![1; 32].into(), decimals: 10, mint: None, init_hook: None, @@ -67,7 +67,7 @@ fn do_init(height: u64) -> Instance { get_wrapped_asset_info(storage), WrappedAssetInfo { asset_chain: 1, - asset_address: vec![1; 32], + asset_address: vec![1; 32].into(), bridge: api.canonical_address(&TestAddress::INITIALIZER.value()).0?, } ); @@ -141,18 +141,6 @@ fn check_token_details(deps: &mut Instance, s ); } -fn format_array(data: &Vec) -> String { - let mut result = String::new(); - - for num in &data[0..data.len() - 1] { - result.push_str(&num.to_string()); - result.push_str(","); - } - result.push_str(&data[data.len() - 1].to_string()); - - result -} - #[test] fn init_works() { let mut deps = do_init(111); @@ -168,9 +156,9 @@ fn query_works() { query_response.as_slice(), format!( "{{\"asset_chain\":1,\ - \"asset_address\":[{}],\ + \"asset_address\":\"{}\",\ \"bridge\":\"{}\"}}", - format_array(&vec![1; 32]), + Binary::from(vec![1; 32]).to_base64(), TestAddress::INITIALIZER.value().as_str() ) .as_bytes() diff --git a/terra/contracts/wormhole/src/contract.rs b/terra/contracts/wormhole/src/contract.rs index bd3908a5cc..700e4faf53 100644 --- a/terra/contracts/wormhole/src/contract.rs +++ b/terra/contracts/wormhole/src/contract.rs @@ -68,15 +68,15 @@ pub fn handle( msg: HandleMsg, ) -> StdResult { match msg { - HandleMsg::SubmitVAA { vaa } => handle_submit_vaa(deps, env, &vaa), - HandleMsg::RegisterAssetHook { asset_id } => handle_register_asset(deps, env, &asset_id), + HandleMsg::SubmitVAA { vaa } => handle_submit_vaa(deps, env, &vaa.as_slice()), + HandleMsg::RegisterAssetHook { asset_id } => handle_register_asset(deps, env, &asset_id.as_slice()), HandleMsg::LockAssets { asset, recipient, amount, target_chain, nonce, - } => handle_lock_assets(deps, env, asset, amount, recipient, target_chain, nonce), + } => handle_lock_assets(deps, env, asset, amount, recipient.as_slice(), target_chain, nonce), HandleMsg::SetActive { is_active } => handle_set_active(deps, env, is_active), } } @@ -249,7 +249,7 @@ fn vaa_update_guardian_set( let mut pos = 5; for _ in 0..len { new_guardian_set.addresses.push(GuardianAddress { - bytes: data[pos..pos + 20].to_vec(), + bytes: data[pos..pos + 20].to_vec().into(), }); pos += 20; } @@ -351,7 +351,7 @@ fn vaa_transfer( code_id: state.wrapped_asset_code_id, msg: to_binary(&WrappedInit { asset_chain: token_chain, - asset_address: asset_address.to_vec(), + asset_address: asset_address.to_vec().into(), decimals: data.get_u8(103), mint: Some(InitMint { recipient: deps.api.human_address(&target_address)?, @@ -360,7 +360,7 @@ fn vaa_transfer( init_hook: Some(InitHook { contract_addr: env.contract.address, msg: to_binary(&HandleMsg::RegisterAssetHook { - asset_id: asset_id.to_vec(), + asset_id: asset_id.to_vec().into(), })?, }), })?, @@ -398,7 +398,7 @@ fn handle_lock_assets( env: Env, asset: HumanAddr, amount: Uint128, - recipient: Vec, + recipient: &[u8], target_chain: u8, nonce: u32, ) -> StdResult { @@ -449,7 +449,7 @@ fn handle_lock_assets( let wrapped_token_info: WrappedAssetInfoResponse = deps.querier.custom_query(&request)?; asset_chain = wrapped_token_info.asset_chain; - asset_address = wrapped_token_info.asset_address; + asset_address = wrapped_token_info.asset_address.as_slice().to_vec(); } Err(_) => { // This is a regular asset, transfer its balance @@ -544,7 +544,7 @@ fn keys_equal(a: &VerifyKey, b: &GuardianAddress) -> bool { if a.len() != b.len() { return false; } - for (ai, bi) in a.iter().zip(b.iter()) { + for (ai, bi) in a.iter().zip(b.as_slice().iter()) { if ai != bi { return false; } @@ -594,7 +594,7 @@ mod tests { vaa: &str, ) -> StdResult { let msg = HandleMsg::SubmitVAA { - vaa: hex::decode(vaa).expect("Decoding failed"), + vaa: hex::decode(vaa).expect("Decoding failed").into(), }; let env = mock_env(&HumanAddr::from("creator"), &[]); diff --git a/terra/contracts/wormhole/src/msg.rs b/terra/contracts/wormhole/src/msg.rs index 823060b018..fef6b96c0a 100644 --- a/terra/contracts/wormhole/src/msg.rs +++ b/terra/contracts/wormhole/src/msg.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{HumanAddr, Uint128}; +use cosmwasm_std::{HumanAddr, Uint128, Binary}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -15,15 +15,15 @@ pub struct InitMsg { #[serde(rename_all = "snake_case")] pub enum HandleMsg { SubmitVAA { - vaa: Vec, + vaa: Binary, }, RegisterAssetHook { - asset_id: Vec, + asset_id: Binary, }, LockAssets { asset: HumanAddr, amount: Uint128, - recipient: Vec, + recipient: Binary, target_chain: u8, nonce: u32, }, diff --git a/terra/contracts/wormhole/src/state.rs b/terra/contracts/wormhole/src/state.rs index 5b928813e5..6a096b61d7 100644 --- a/terra/contracts/wormhole/src/state.rs +++ b/terra/contracts/wormhole/src/state.rs @@ -1,7 +1,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use cosmwasm_std::{CanonicalAddr, HumanAddr, StdResult, Storage}; +use cosmwasm_std::{CanonicalAddr, HumanAddr, StdResult, Storage, Binary}; use cosmwasm_storage::{ bucket, bucket_read, singleton, singleton_read, Bucket, ReadonlyBucket, ReadonlySingleton, Singleton, @@ -34,7 +34,7 @@ pub struct ConfigInfo { // Guardian address #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct GuardianAddress { - pub bytes: Vec, // 20-byte addresses + pub bytes: Binary, // 20-byte addresses } #[cfg(test)] @@ -43,7 +43,7 @@ use hex; impl GuardianAddress { pub fn from(string: &str) -> GuardianAddress { GuardianAddress { - bytes: hex::decode(string).expect("Decoding failed"), + bytes: hex::decode(string).expect("Decoding failed").into(), } } } diff --git a/terra/contracts/wormhole/tests/integration.rs b/terra/contracts/wormhole/tests/integration.rs index 29fff62437..f2dc0df0c3 100644 --- a/terra/contracts/wormhole/tests/integration.rs +++ b/terra/contracts/wormhole/tests/integration.rs @@ -78,7 +78,7 @@ fn do_init( #[test] fn init_works() { let guardians = vec![GuardianAddress::from(GuardianAddress { - bytes: hex::decode("beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe").expect("Decoding failed"), + bytes: hex::decode("beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe").expect("Decoding failed").into(), })]; let _deps = do_init(111, &guardians); } diff --git a/terra/tools/lock-token.ts b/terra/tools/lock-token.ts index a5151e43f8..266f69c2a3 100644 --- a/terra/tools/lock-token.ts +++ b/terra/tools/lock-token.ts @@ -14,7 +14,7 @@ async function script() { let lockResult = await execute_contract(wormhole_contract, {lock_assets: { asset: token_contract, amount, - recipient: [...Buffer.from('00000000000000000000000019a4437E2BA06bF1FA42C56Fb269Ca0d30f60716', 'hex')], + recipient: Buffer.from('00000000000000000000000019a4437E2BA06bF1FA42C56Fb269Ca0d30f60716', 'hex').toString('base64'), target_chain: 2, // Ethereum nonce: Date.now() % 1000000 }}); diff --git a/terra/tools/prepare-wormhole.ts b/terra/tools/prepare-wormhole.ts index e3cc9c77de..fbc01340f4 100644 --- a/terra/tools/prepare-wormhole.ts +++ b/terra/tools/prepare-wormhole.ts @@ -13,7 +13,7 @@ async function script() { let contract_address = await instantiate_contract(wormhole_code_id, { initial_guardian_set: { addresses: [ - { bytes: [0xbe, 0xfa, 0x42, 0x9d, 0x57, 0xcd, 0x18, 0xb7, 0xf8, 0xa4, 0xd9, 0x1a, 0x2d, 0xa9, 0xab, 0x4a, 0xf0, 0x5d, 0x0f, 0xbe] } + { bytes: Buffer.from('beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe', 'hex').toString('base64') } ], expiration_time: 1000 * 60 * 60 }, diff --git a/terra/tools/submit-vaa.ts b/terra/tools/submit-vaa.ts index 0311016e59..518a61d563 100644 --- a/terra/tools/submit-vaa.ts +++ b/terra/tools/submit-vaa.ts @@ -8,7 +8,7 @@ async function script() { // Test VAA built using bridge/cmd/vaa-test let vaaResult = await execute_contract(wormhole_contract, {submit_v_a_a: { - vaa: [...Buffer.from('010000000001005468beb21caff68710b2af2d60a986245bf85099509b6babe990a6c32456b44b3e2e9493e3056b7d5892957e14beab24be02dab77ed6c8915000e4a1267f78f400000007d01000000038018002010400000000000000000000000000000000000000000000000000000000000101010101010101010101010101010101010101000000000000000000000000010000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988080000000000000000000000000000000000000000000000000de0b6b3a7640000', 'hex')] + vaa: Buffer.from('010000000001001063f503dd308134e0f158537f54c5799719f4fa2687dd276c72ef60ae0c82c47d4fb560545afaabdf60c15918e221763fd1892c75f2098c0ffd5db4af254a4501000007d01000000038010302010400000000000000000000000000000000000000000000000000000000000101010101010101010101010101010101010101000000000000000000000000010000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988080000000000000000000000000000000000000000000000000de0b6b3a7640000', 'hex').toString('base64') }}); if (vaaResult == null) return; console.log('Vaa submitted');