Skip to content

Commit 0e22238

Browse files
authored
Union test phase 2 (#4926)
2 parents 1c5e8e2 + 90f4dd7 commit 0e22238

File tree

13 files changed

+2773
-115
lines changed

13 files changed

+2773
-115
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/all-tests.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
# ensure-blocks = import ./ensure-blocks/ensure-blocks.nix { inherit e2e networks pkgs nixpkgs crane; };
3737
#
3838
# Tests from ./full-e2e.nix
39-
# inherit (full-e2e) voyager-queue-works;
39+
# inherit (full-e2e) all-works;
4040

4141
# Tests from ./epoch-staking.nix
4242
inherit (epoch-staking) epoch-completes;

e2e/e2e.nix

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@
132132
virtualisation = {
133133
diskSize = 16 * 1024;
134134
memorySize = 32 * 1024;
135+
# TODO(aeryz): remove this
136+
cores = 32;
135137
arion = {
136138
backend = "docker";
137139
projects.galois.settings = galois-arion-project;
@@ -218,17 +220,14 @@
218220
219221
galois.wait_for_console_text('${galoisNode.wait_for_console_text}')
220222
221-
devnetVoyager.succeed('${voyagerBin} init-fetch union-devnet-1 --config-file-path ${voyagerNode.voyagerConfig}/voyager-config.jsonc');
222-
devnetVoyager.succeed('${voyagerBin} init-fetch 32382 --config-file-path ${voyagerNode.voyagerConfig}/voyager-config.jsonc');
223-
224223
devnetUnion.wait_until_succeeds('[[ $(curl "http://localhost:26660/block" --fail --silent | ${pkgs.lib.meta.getExe pkgs.jq} ".result.block.header.height | tonumber > 200000") == "true" ]]')
225224
'';
226225

227226
nodes =
228227
(pkgs.lib.throwIf (builtins.hasAttr "devnetUnion" nodes) "union node already exists; use a different name")
229228
(pkgs.lib.throwIf (builtins.hasAttr "devnetEth" nodes) "devnetEth node already exists; use a different name")
230229
(pkgs.lib.throwIf (builtins.hasAttr "voyager" nodes) "voyager node already exists; use a different name")
231-
# (pkgs.lib.throwIf (builtins.hasAttr "galois" nodes) "galois node already exists; use a different name")
230+
(pkgs.lib.throwIf (builtins.hasAttr "galois" nodes) "galois node already exists; use a different name")
232231
(
233232
{
234233
devnetUnion = unionNode.node;

e2e/full-e2e.nix

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@
44
...
55
}:
66
{
7-
voyager-queue-works = e2e.mkE2eTestEthUnion {
8-
name = "voyager-queue-works";
7+
all-works = e2e.mkE2eTestEthUnion {
8+
name = "all-works";
99

1010
testScript = '''';
1111

1212
nodes = {
13-
# empty node used to communicate with the other nodes
14-
client = _: { };
1513
};
1614
};
1715
}

galoisd/galoisd.nix

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99
mkCi,
1010
...
1111
}:
12+
let
13+
galoisKeys = pkgs.runCommand "galois-keys" { } ''
14+
mkdir $out
15+
cp ${../vk.bin} $out/vk.bin
16+
cp ${../pk.bin} $out/pk.bin
17+
cp ${../r1cs.bin} $out/r1cs.bin
18+
'';
19+
in
1220
{
1321
# TODO(aeryz): This builds the keys for now bc of my shitty internet. Otherwise, it takes me forever to try
1422
# In the real CI version, this will just use `galois-testnet-standalone` and download the keys.
@@ -22,6 +30,7 @@
2230
pkgs.coreutils-full
2331
pkgs.cacert
2432
self'.packages.galoisd
33+
galoisKeys
2534
];
2635
};
2736

@@ -37,7 +46,7 @@
3746
"sh"
3847
"-c"
3948
''
40-
${pkgs.lib.getExe self'.packages.galoisd} serve 0.0.0.0:9999 --cs-path=/tmp/r1cs.bin --pk-path=/tmp/pk.bin --vk-path=/tmp/vk.bin --max-conn 3
49+
${pkgs.lib.getExe self'.packages.galoisd} serve 0.0.0.0:9999 --cs-path=${galoisKeys}/r1cs.bin --pk-path=${galoisKeys}/pk.bin --vk-path=${galoisKeys}/vk.bin --max-conn 3
4150
''
4251
];
4352
};

tools/union-test/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ ibc-union-spec = { workspace = true }
2525
jsonrpsee = { workspace = true, features = ["tracing", "ws-client", "http-client"] }
2626
protos = { workspace = true }
2727
rand = { version = "0.9.0" }
28+
regex = "1"
2829
serde = { workspace = true }
2930
serde-utils = { workspace = true }
3031
thiserror = { workspace = true }

tools/union-test/config.jsonc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@
232232
}
233233
]
234234
},
235+
"max_tx_size": 500000,
235236
"gas_config": {
236237
"type": "feemarket",
237238
"config": {

tools/union-test/src/cosmos.rs

Lines changed: 190 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@ use cosmos_client::{
1414
use cosmos_sdk_event::CosmosSdkEvent;
1515
use ibc_union_spec::{ChannelId, ClientId, ConnectionId, Timestamp};
1616
use protos::{
17-
cosmos::base::v1beta1::Coin,
17+
cosmos::{
18+
bank::v1beta1::{QueryBalanceRequest, QueryBalanceResponse},
19+
base::v1beta1::Coin,
20+
},
1821
cosmwasm::wasm::v1::{QuerySmartContractStateRequest, QuerySmartContractStateResponse},
1922
};
2023
use serde::{Deserialize, Serialize};
2124
use ucs03_zkgm::msg::{PredictWrappedTokenResponse, QueryMsg};
2225
use unionlabs::{
2326
self,
2427
google::protobuf::any::mk_any,
28+
ibc::core::client::height::Height,
2529
primitives::{encoding::HexUnprefixed, Bech32, Bytes, H160, H256},
2630
};
2731
use voyager_sdk::{
@@ -38,6 +42,7 @@ pub struct Config {
3842
pub chain_id: ChainId,
3943
pub ibc_host_contract_address: Bech32<H256>,
4044
pub keyring: KeyringConfig,
45+
pub privileged_acc_keyring: KeyringConfig,
4146
pub rpc_url: String,
4247
pub gas_config: GasFillerConfig,
4348
#[serde(default)]
@@ -64,6 +69,7 @@ pub struct Module {
6469
pub chain_id: ChainId,
6570
pub ibc_host_contract_address: Bech32<H256>,
6671
pub keyring: ConcurrentKeyring<Bech32<H160>, LocalSigner>,
72+
pub privileged_acc_keyring: ConcurrentKeyring<Bech32<H160>, LocalSigner>,
6773
pub rpc: Rpc,
6874
pub gas_config: any::GasFiller,
6975
pub bech32_prefix: String,
@@ -128,6 +134,18 @@ impl Module {
128134
}
129135
}),
130136
),
137+
privileged_acc_keyring: ConcurrentKeyring::new(
138+
config.privileged_acc_keyring.name,
139+
config.privileged_acc_keyring.keys.into_iter().map(|entry| {
140+
let signer =
141+
LocalSigner::new(entry.value().try_into().unwrap(), bech32_prefix.clone());
142+
143+
KeyringEntry {
144+
address: signer.address(),
145+
signer,
146+
}
147+
}),
148+
),
131149
rpc,
132150
chain_id: ChainId::new(chain_id),
133151
gas_config: config
@@ -345,6 +363,65 @@ impl Module {
345363
.unwrap())
346364
}
347365

366+
pub async fn wait_for_update_client(
367+
&self,
368+
expected_revision_height: u64,
369+
max_wait: Duration,
370+
) -> anyhow::Result<helpers::UpdateClient> {
371+
Ok(self
372+
.wait_for_event(
373+
move |evt| {
374+
if let ModuleEvent::UpdateClient {
375+
consensus_heights, ..
376+
} = evt
377+
{
378+
if let Some(first) = consensus_heights.first() {
379+
if first.height() >= expected_revision_height {
380+
return Some(helpers::UpdateClient {
381+
height: first.height(),
382+
});
383+
}
384+
}
385+
}
386+
None
387+
},
388+
max_wait,
389+
1,
390+
)
391+
.await?
392+
.pop()
393+
.unwrap())
394+
}
395+
396+
pub async fn wait_for_packet_timeout(
397+
&self,
398+
packet_hash_param: H256,
399+
max_wait: Duration,
400+
) -> anyhow::Result<helpers::PacketTimeout> {
401+
println!("Waiting for packet timeout event with hash: {packet_hash_param:?}");
402+
Ok(self
403+
.wait_for_event(
404+
move |evt| {
405+
if let ModuleEvent::WasmPacketTimeout { packet_hash, .. } = evt {
406+
println!("Packet timeout event came with hash: {packet_hash:?}");
407+
if packet_hash.as_ref() == packet_hash_param.as_ref() {
408+
return Some(helpers::PacketTimeout {
409+
packet_hash: *packet_hash,
410+
});
411+
}
412+
None
413+
} else {
414+
None
415+
}
416+
},
417+
max_wait,
418+
1,
419+
)
420+
.await?
421+
.pop()
422+
.unwrap())
423+
}
424+
348425
pub async fn wait_for_packet_ack(
349426
&self,
350427
packet_hash_param: H256,
@@ -354,10 +431,22 @@ impl Module {
354431
Ok(self
355432
.wait_for_event(
356433
move |evt| {
357-
if let ModuleEvent::WasmPacketAck { packet_hash, .. } = evt {
434+
if let ModuleEvent::WasmPacketAck {
435+
packet_hash,
436+
acknowledgement,
437+
..
438+
} = evt
439+
{
358440
if packet_hash.as_ref() == packet_hash_param.as_ref() {
441+
let ack_bytes: &[u8] = acknowledgement.as_ref();
442+
443+
// Grab the first 32 bytes — this is the uint256 in ABI encoding
444+
let mut tag_be = [0u8; 32];
445+
tag_be.copy_from_slice(&ack_bytes[..32]);
446+
let tag_u128 = u128::from_be_bytes(tag_be[16..].try_into().ok()?);
359447
return Some(helpers::PacketAck {
360448
packet_hash: *packet_hash,
449+
tag: tag_u128,
361450
});
362451
}
363452
None
@@ -480,6 +569,52 @@ impl Module {
480569
}
481570
}
482571

572+
pub async fn get_minter(&self, contract: Bech32<H256>) -> anyhow::Result<String> {
573+
let req = QuerySmartContractStateRequest {
574+
address: contract.to_string(),
575+
query_data: serde_json::to_vec(&QueryMsg::GetMinter {})?,
576+
};
577+
578+
let raw = self
579+
.rpc
580+
.client()
581+
.grpc_abci_query::<_, QuerySmartContractStateResponse>(
582+
"/cosmwasm.wasm.v1.Query/SmartContractState",
583+
&req,
584+
None,
585+
false,
586+
)
587+
.await?
588+
.into_result()?
589+
.unwrap()
590+
.data;
591+
592+
// 3) Deserialize the JSON `{ "minter": "union1..." }` into our struct
593+
let resp = serde_json::from_slice(&raw).context("deserializing GetMinterResponse")?;
594+
595+
Ok(resp)
596+
}
597+
598+
pub async fn get_balance(
599+
&self,
600+
address: impl Into<String>,
601+
denom: &str,
602+
) -> anyhow::Result<protos::cosmos::base::v1beta1::Coin> {
603+
let req = QueryBalanceRequest {
604+
address: address.into(),
605+
denom: denom.to_string(),
606+
};
607+
let resp: QueryBalanceResponse = self
608+
.rpc
609+
.client()
610+
.grpc_abci_query("/cosmos.bank.v1beta1.Query/Balance", &req, None, false)
611+
.await?
612+
.into_result()?
613+
.unwrap();
614+
resp.balance
615+
.ok_or_else(|| anyhow::anyhow!("no balance for denom {}", denom))
616+
}
617+
483618
pub async fn send_transaction_with_retry(
484619
&self,
485620
contract: Bech32<H256>,
@@ -561,10 +696,12 @@ impl Module {
561696
contract: Bech32<H256>,
562697
msg: (Vec<u8>, Vec<Coin>),
563698
signer: &LocalSigner,
564-
) -> anyhow::Result<H256> {
699+
) -> anyhow::Result<(H256, u64)> {
565700
let result = self.send_transaction(contract, msg, signer).await;
566-
567701
let tx_result = result.ok_or_else(|| anyhow!("failed to send transaction"))??;
702+
let height = tx_result
703+
.height
704+
.ok_or_else(|| anyhow!("transaction height not found"))?;
568705

569706
let send_event = tx_result
570707
.tx_result
@@ -580,7 +717,7 @@ impl Module {
580717
.ok_or_else(|| anyhow!("wasm-packet_send event not found"))?;
581718

582719
Ok(match send_event {
583-
ModuleEvent::WasmPacketSend { packet_hash, .. } => packet_hash,
720+
ModuleEvent::WasmPacketSend { packet_hash, .. } => (packet_hash, height.get()),
584721
_ => bail!("unexpected event variant"),
585722
})
586723
}
@@ -610,6 +747,12 @@ pub enum ModuleEvent {
610747
channel_id: ChannelId,
611748
packet_hash: H256,
612749
},
750+
#[serde(rename = "wasm-packet_timeout")]
751+
WasmPacketTimeout {
752+
#[serde(with = "serde_utils::string")]
753+
channel_id: ChannelId,
754+
packet_hash: H256,
755+
},
613756

614757
#[serde(rename = "wasm-create_client")]
615758
WasmCreateClient {
@@ -658,4 +801,46 @@ pub enum ModuleEvent {
658801
packet_hash: H256,
659802
acknowledgement: Bytes<HexUnprefixed>,
660803
},
804+
805+
#[serde(rename = "update_client")]
806+
UpdateClient {
807+
client_id: unionlabs::id::ClientId,
808+
client_type: String,
809+
#[serde(with = "height_list_comma_separated")]
810+
consensus_heights: Vec<Height>,
811+
},
812+
}
813+
814+
// TODO: Check if human readable
815+
pub mod height_list_comma_separated {
816+
use std::string::String;
817+
818+
use serde::{
819+
de::{self, Deserialize},
820+
Deserializer, Serialize, Serializer,
821+
};
822+
use unionlabs::ibc::core::client::height::Height;
823+
824+
#[allow(clippy::ptr_arg)] // required by serde
825+
pub fn serialize<S>(data: &Vec<Height>, serializer: S) -> Result<S::Ok, S::Error>
826+
where
827+
S: Serializer,
828+
{
829+
data.iter()
830+
.map(|height| format!("{height:#}"))
831+
.collect::<Vec<_>>()
832+
.join(",")
833+
.serialize(serializer)
834+
}
835+
836+
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Height>, D::Error>
837+
where
838+
D: Deserializer<'de>,
839+
{
840+
String::deserialize(deserializer)?
841+
.split(',')
842+
.map(Height::from_str_allow_zero_revision)
843+
.collect::<Result<_, _>>()
844+
.map_err(de::Error::custom)
845+
}
661846
}

0 commit comments

Comments
 (0)