Skip to content

chore(messaging): pop-api and integration tests #566

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: messaging-base
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,727 changes: 1,230 additions & 497 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ exclude = [
members = [
"node",
"pallets/*",
#"pop-api/integration-tests",
"pop-api/integration-tests",
"primitives",
"runtime/devnet",
"runtime/mainnet",
Expand Down
20 changes: 17 additions & 3 deletions pallets/api/src/messaging/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ mod messaging_benchmarks {
let id_data = (x, y, a, "ismp_get");
let encoded = id_data.encode();
let message_id = H256::from(blake2_256(&encoded));
let ismp_relayer_fee: BalanceOf<T> = u32::MAX.into();

let inner_keys: BoundedVec<u8, T::MaxKeyLen> =
vec![1u8].repeat(T::MaxKeyLen::get() as usize).try_into().unwrap();
Expand Down Expand Up @@ -362,7 +363,13 @@ mod messaging_benchmarks {
);

#[extrinsic_call]
Pallet::<T>::ismp_get(RawOrigin::Signed(origin.clone()), message_id.into(), get, callback);
Pallet::<T>::ismp_get(
RawOrigin::Signed(origin.clone()),
message_id.into(),
get,
ismp_relayer_fee,
callback,
);
}

/// Sends a `Post` request using ISMP with a variable-sized data payload.
Expand All @@ -380,6 +387,7 @@ mod messaging_benchmarks {
let id_data = (x, y, b"ismp_post");
let encoded = id_data.encode();
let message_id = H256::from(blake2_256(&encoded));
let ismp_relayer_fee: BalanceOf<T> = u32::MAX.into();

let data = vec![1u8].repeat(x as usize).try_into().unwrap();

Expand All @@ -402,7 +410,13 @@ mod messaging_benchmarks {
);

#[extrinsic_call]
Pallet::<T>::ismp_post(RawOrigin::Signed(origin.clone()), message_id.into(), get, callback);
Pallet::<T>::ismp_post(
RawOrigin::Signed(origin.clone()),
message_id.into(),
get,
ismp_relayer_fee,
callback,
);
}

/// Tops up callback weight for callback execution of pending messages.
Expand All @@ -416,7 +430,7 @@ mod messaging_benchmarks {

let message: Message<T> = Message::Ismp {
commitment: [10u8; 32].into(),
deposit: 100_000u32.into(),
message_deposit: 100_000u32.into(),
callback: Some(callback),
};

Expand Down
9 changes: 4 additions & 5 deletions pallets/api/src/messaging/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,6 @@ pub mod pallet {
/// payment.
type WeightToFee: WeightToFee<Balance = BalanceOf<Self>>;

/// The fee paid to the relayers account for relaying a message.
type IsmpRelayerFee: Get<BalanceOf<Self>>;

/// The implementation of Keccak used for commitment hashes.
type Keccak256: ::ismp::messaging::Keccak256;

Expand Down Expand Up @@ -383,6 +380,7 @@ pub mod pallet {
origin: OriginFor<T>,
id: MessageId,
message: ismp::Get<T>,
ismp_relayer_fee: BalanceOf<T>,
callback: Option<Callback>,
) -> DispatchResult {
let origin = ensure_signed(origin)?;
Expand All @@ -408,7 +406,7 @@ pub mod pallet {
// Process message by dispatching request via ISMP.
let commitment = match T::IsmpDispatcher::default().dispatch_request(
message.into(),
FeeMetadata { payer: origin.clone(), fee: T::IsmpRelayerFee::get() },
FeeMetadata { payer: origin.clone(), fee: ismp_relayer_fee },
) {
Ok(commitment) => Ok::<H256, DispatchError>(commitment),
Err(e) => {
Expand Down Expand Up @@ -454,6 +452,7 @@ pub mod pallet {
origin: OriginFor<T>,
id: MessageId,
message: ismp::Post<T>,
ismp_relayer_fee: BalanceOf<T>,
callback: Option<Callback>,
) -> DispatchResult {
let origin = ensure_signed(origin)?;
Expand All @@ -480,7 +479,7 @@ pub mod pallet {
let commitment = T::IsmpDispatcher::default()
.dispatch_request(
message.into(),
FeeMetadata { payer: origin.clone(), fee: T::IsmpRelayerFee::get() },
FeeMetadata { payer: origin.clone(), fee: ismp_relayer_fee },
)
.map_err(|_| Error::<T>::IsmpDispatchFailed)?;

Expand Down
78 changes: 69 additions & 9 deletions pallets/api/src/messaging/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,8 @@ mod xcm_hooks {
fn xcm_queries_expire_on_expiry_block() {
new_test_ext().execute_with(|| {
let message_id = [0; 32];
let timeout = System::block_number() + 10;
// timeout in 100 blocks time.
let timeout = 100;
assert_ok!(Messaging::xcm_new_query(
signed(ALICE),
message_id,
Expand All @@ -912,7 +913,22 @@ mod xcm_hooks {
None,
));

run_to(timeout + 1);
// assert that the block before is not timed out.

run_to(timeout + System::block_number() - 1);
let Some(Message::XcmQuery { .. }): Option<Message<Test>> =
Messages::get(ALICE, message_id)
else {
panic!("Message should be a query!")
};

let Some(Message::XcmQuery { .. }): Option<Message<Test>> =
Messages::get(ALICE, message_id_2)
else {
panic!("Message should be query!")
};

run_to(System::block_number() + 1);

let Some(Message::XcmTimeout { .. }): Option<Message<Test>> =
Messages::get(ALICE, message_id)
Expand Down Expand Up @@ -1178,10 +1194,17 @@ mod ismp_get {
keys: bounded_vec!(),
};
let callback = None;
let ismp_relayer_fee: Balance = u32::MAX.into();

assert_ok!(Messaging::ismp_get(signed(ALICE), message_id, message.clone(), callback));
assert_ok!(Messaging::ismp_get(
signed(ALICE),
message_id,
message.clone(),
ismp_relayer_fee,
callback
));
assert_noop!(
Messaging::ismp_get(signed(ALICE), message_id, message, callback),
Messaging::ismp_get(signed(ALICE), message_id, message, ismp_relayer_fee, callback),
Error::<Test>::MessageExists
);
})
Expand All @@ -1202,6 +1225,7 @@ mod ismp_get {
let callback = Callback { selector: [1; 4], weight, abi: Abi::Scale };

let callback_deposit = <Test as Config>::WeightToFee::weight_to_fee(&weight);
let ismp_relayer_fee: Balance = u32::MAX.into();

let expected_deposit = calculate_protocol_deposit::<
Test,
Expand All @@ -1215,7 +1239,13 @@ mod ismp_get {
assert_eq!(alice_hold_balance_pre_hold, 0);
assert!(expected_deposit != 0);

assert_ok!(Messaging::ismp_get(signed(ALICE), message_id, message, Some(callback)));
assert_ok!(Messaging::ismp_get(
signed(ALICE),
message_id,
message,
ismp_relayer_fee,
Some(callback)
));

let alice_hold_balance_post_hold = Balances::total_balance_on_hold(&ALICE);

Expand All @@ -1235,7 +1265,15 @@ mod ismp_get {
keys: bounded_vec!(),
};
let callback = None;
assert_ok!(Messaging::ismp_get(signed(ALICE), message_id, message, callback));
let ismp_relayer_fee: Balance = u32::MAX.into();

assert_ok!(Messaging::ismp_get(
signed(ALICE),
message_id,
message,
ismp_relayer_fee,
callback
));
let events = events();
let Some(Event::<Test>::IsmpGetDispatched { origin, id, commitment, callback }) =
events.first()
Expand All @@ -1262,10 +1300,23 @@ mod ismp_post {
let message_id = [0u8; 32];
let message = ismp::Post { dest: 2000, timeout: 100, data: bounded_vec![] };
let callback = None;
let ismp_relayer_fee: Balance = u32::MAX.into();

assert_ok!(Messaging::ismp_post(signed(ALICE), message_id, message.clone(), callback));
assert_ok!(Messaging::ismp_post(
signed(ALICE),
message_id,
message.clone(),
ismp_relayer_fee,
callback
));
assert_noop!(
Messaging::ismp_post(signed(ALICE), message_id, message, callback),
Messaging::ismp_post(
signed(ALICE),
message_id,
message,
ismp_relayer_fee,
callback
),
Error::<Test>::MessageExists
);
})
Expand All @@ -1277,6 +1328,7 @@ mod ismp_post {
let message_id = [0u8; 32];
let message = ismp::Post { dest: 2000, timeout: 100, data: bounded_vec![] };
let weight = Weight::from_parts(100_000_000, 100_000_000);
let ismp_relayer_fee: Balance = u32::MAX.into();
let callback = Callback { selector: [1; 4], weight, abi: Abi::Scale };
let callback_deposit = <Test as Config>::WeightToFee::weight_to_fee(&weight);
let expected_deposit = calculate_protocol_deposit::<
Expand All @@ -1297,6 +1349,7 @@ mod ismp_post {
signed(ALICE),
message_id,
message.clone(),
ismp_relayer_fee,
Some(callback)
));

Expand All @@ -1312,8 +1365,15 @@ mod ismp_post {
let message_id = [0u8; 32];
let message = ismp::Post { dest: 2000, timeout: 100, data: bounded_vec![] };
let callback = None;
let ismp_relayer_fee: Balance = u32::MAX.into();

assert_ok!(Messaging::ismp_post(signed(ALICE), message_id, message.clone(), callback));
assert_ok!(Messaging::ismp_post(
signed(ALICE),
message_id,
message.clone(),
ismp_relayer_fee,
callback
));

let events = events();
let Some(Event::<Test>::IsmpPostDispatched { origin, id, commitment, callback }) =
Expand Down
2 changes: 0 additions & 2 deletions pallets/api/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@ parameter_types! {
pub const OffChainByteFee: Balance = 5;
pub const MaxXcmQueryTimeoutsPerBlock: u32 = 10;
pub const FeeAccount: AccountId = FEE_ACCOUNT;
pub const IsmpRelayerFee: Balance = 100_000;
}

pub struct MockNotifyQuery<T>(T);
Expand Down Expand Up @@ -270,7 +269,6 @@ impl crate::messaging::Config for Test {
type FeeHandler = ResolveTo<FeeAccount, Balances>;
type Fungibles = Balances;
type IsmpDispatcher = pallet_ismp::Pallet<Test>;
type IsmpRelayerFee = IsmpRelayerFee;
type Keccak256 = Keccak;
type MaxContextLen = ConstU32<64>;
type MaxDataLen = ConstU32<1024>;
Expand Down
4 changes: 2 additions & 2 deletions pop-api/examples/messaging/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ mod messaging {
self.id,
Get::new(self.para, height, 0, Vec::default(), Vec::from([key.clone()])),
0,
Some(Callback::to(0x57ad942b, Weight::from_parts(800_000_000, 500_000))),
Some(Callback::new(0x57ad942b, Weight::from_parts(800_000_000, 500_000))),
)?;
self.env().emit_event(IsmpRequested { id: self.id, key, height });
Ok(())
Expand Down Expand Up @@ -95,7 +95,7 @@ mod messaging {
self.id,
dest.clone(),
self.env().block_number().saturating_add(100),
Some(Callback::to(0x641b0b03, Weight::from_parts(800_000_000, 500_000))),
Some(Callback::new(0x641b0b03, Weight::from_parts(800_000_000, 500_000), Abi::Scale)),
)?
.unwrap(); // TODO: handle error

Expand Down
4 changes: 4 additions & 0 deletions pop-api/integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pallet-assets = { workspace = true, default-features = false }
pallet-balances = { workspace = true, default-features = false }
pallet-contracts = { workspace = true, default-features = false }
pallet-ismp = { workspace = true, default-features = false }
pallet-revive = { workspace = true, default-features = false }
pallet-timestamp ={ workspace = true, default-features = false}
pallet-nfts = { workspace = true, default-features = false }
pallet-xcm = { workspace = true, default-features = false }
pop-api = { path = "../../pop-api", default-features = false, features = [
Expand All @@ -37,6 +39,7 @@ xcm-executor.workspace = true
[features]
default = [ "std" ]
devnet = [ "pop-runtime-devnet/default" ]

std = [
"codec/std",
"frame-support/std",
Expand All @@ -46,6 +49,7 @@ std = [
"pallet-balances/std",
"pallet-contracts/std",
"pallet-nfts/std",
"pallet-timestamp/std",
"pop-api/std",
"pop-primitives/std",
"pop-runtime-devnet/std",
Expand Down
21 changes: 14 additions & 7 deletions pop-api/integration-tests/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{
fs,
env, fs,
path::{Path, PathBuf},
process,
};
Expand All @@ -10,7 +10,10 @@ use contract_build::{
};

fn main() {
let contracts_dir = PathBuf::from("./contracts/");
println!("cargo:warning=🔨 build.rs is running");

let contracts_dir = PathBuf::from("contracts");

let contract_dirs = match get_subcontract_directories(&contracts_dir) {
Ok(dirs) => dirs,
Err(e) => {
Expand All @@ -19,15 +22,17 @@ fn main() {
},
};

for contract in contract_dirs {
if let Err(e) = build_contract(&contract) {
for contract in &contract_dirs {
if let Err(e) = build_contract(contract) {
eprintln!("Failed to build contract {}: {}", contract.display(), e);
process::exit(1);
}
}

println!("cargo:warning=✅ build.rs built {} contracts", contract_dirs.len());
}

// Function to retrieve all subdirectories in a given directory.
// Get subdirectories in the contracts/ folder
fn get_subcontract_directories(contracts_dir: &Path) -> Result<Vec<PathBuf>, String> {
fs::read_dir(contracts_dir)
.map_err(|e| format!("Could not read directory '{}': {}", contracts_dir.display(), e))?
Expand All @@ -39,8 +44,10 @@ fn get_subcontract_directories(contracts_dir: &Path) -> Result<Vec<PathBuf>, Str
.collect()
}

// Function to build a contract given its directory.
// Compile the contract using contract-build
fn build_contract(contract_dir: &Path) -> Result<BuildResult, String> {
println!("cargo:warning=📦 Building contract at {}", contract_dir.display());

let manifest_path = ManifestPath::new(contract_dir.join("Cargo.toml")).map_err(|e| {
format!("Could not retrieve manifest path for {}: {}", contract_dir.display(), e)
})?;
Expand All @@ -50,7 +57,7 @@ fn build_contract(contract_dir: &Path) -> Result<BuildResult, String> {
build_mode: BuildMode::Debug,
manifest_path,
output_type: OutputType::HumanReadable,
verbosity: Verbosity::Default,
verbosity: Verbosity::Verbose,
..Default::default()
};

Expand Down
Loading
Loading