Files
pezkuwi-subxt/testing/integration-tests/src/full_client/frame/contracts.rs
T
Alexandru Vasile b31131d21d testing: Prepare light client testing with substrate binary and add subxt-test macro (#1507)
* testing: Add long running light client flag and cfg aliases

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Expose clients depending on feature flags

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* subxt: Use unstable backend for light client

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Disable flaky lightclient tests

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* ci: Add long runnnig step

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Revert "subxt: Use unstable backend for light client"

This reverts commit ea6f3cc58b.

* ci: Long running tests for 60 mins

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* ci: Use 16 cores for light-client testing

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* ci: Isolate light-client testing to save CI minutes

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Retry on Tx::Dropped for lightclinet only

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Wait for more blocks for the lightclient init

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* subxt: Use unstable backend for light client

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Disable legacy RPC tests

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Disable sudo and contracts tests

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Retry constructing lightclient on read-proof errors

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Disable tx dynamic test

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* proc-macro: Timeout for tests

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Add timeout 800 seconds

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* proc-macro/tests: Adjust subxt-test proc-macro

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* proc-macro: Rename crate to subxt-test-proc-macro

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Use default subxt-proc-macro timeout

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* light-client: Remove println

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* subxt: Remove tokio as dependency, use it only for testing

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Chagne default timeout to 6 seconds

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* proc-macro: Add env timeout variable

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* ci: Add subxt env var for controling test timeouts

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* tests/tx-retries: Retry on `Non node available` error

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Use unstable backend for testing lightclient

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Remove old lightclient object

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Adjust for the new interface

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* backend/rpc: Allow older version of the initialized event

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/tests: Check initialized decodes correctly

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* ci: Reset workflow

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Apply cargo fmt

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Remove unused dep

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Remove gitmerge old file

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Remove unused dep

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rename proc-macro to subxt-test-macro

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* tests: Remove txretries for lightclient

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* tests: Wait for 5 blocks for the lightclient full testing suite

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* tests: Group imports

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* macro: Rename const value

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

---------

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
2024-04-08 11:34:20 +03:00

255 lines
7.3 KiB
Rust

// Copyright 2019-2023 Parity Technologies (UK) Ltd.
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use crate::{
node_runtime::{
self,
contracts::events,
runtime_types::{pallet_contracts::wasm::Determinism, sp_weights::weight_v2::Weight},
system,
},
subxt_test, test_context, TestClient, TestConfig, TestContext,
};
use subxt::ext::futures::StreamExt;
use subxt::{tx::TxProgress, utils::MultiAddress, Config, Error};
use subxt_signer::sr25519::{self, dev};
struct ContractsTestContext {
cxt: TestContext,
signer: sr25519::Keypair,
}
type Hash = <TestConfig as Config>::Hash;
type AccountId = <TestConfig as Config>::AccountId;
/// A dummy contract which does nothing at all.
const CONTRACT: &str = r#"
(module
(import "env" "memory" (memory 1 1))
(func (export "deploy"))
(func (export "call"))
)
"#;
const PROOF_SIZE: u64 = u64::MAX / 2;
impl ContractsTestContext {
async fn init() -> Self {
let cxt = test_context().await;
let signer = dev::alice();
Self { cxt, signer }
}
fn client(&self) -> TestClient {
self.cxt.client()
}
async fn upload_code(&self) -> Result<Hash, Error> {
let code = wabt::wat2wasm(CONTRACT).expect("invalid wabt");
let upload_tx =
node_runtime::tx()
.contracts()
.upload_code(code, None, Determinism::Enforced);
let signed_extrinsic = self
.client()
.tx()
.create_signed(&upload_tx, &self.signer, Default::default())
.await?;
let events = signed_extrinsic
.submit_and_watch()
.await
.unwrap()
.wait_for_finalized_success()
.await?;
let code_stored = events
.find_first::<events::CodeStored>()?
.ok_or_else(|| Error::Other("Failed to find a CodeStored event".into()))?;
Ok(code_stored.code_hash)
}
async fn instantiate_with_code(&self) -> Result<(Hash, AccountId), Error> {
tracing::info!("instantiate_with_code:");
let code = wabt::wat2wasm(CONTRACT).expect("invalid wabt");
let instantiate_tx = node_runtime::tx().contracts().instantiate_with_code(
100_000_000_000_000_000, // endowment
Weight {
ref_time: 500_000_000_000,
proof_size: PROOF_SIZE,
}, // gas_limit
None, // storage_deposit_limit
code,
vec![], // data
vec![], // salt
);
let signed_extrinsic = self
.client()
.tx()
.create_signed(&instantiate_tx, &self.signer, Default::default())
.await?;
let events = signed_extrinsic
.submit_and_watch()
.await
.unwrap()
.wait_for_finalized_success()
.await?;
let code_stored = events
.find_first::<events::CodeStored>()?
.ok_or_else(|| Error::Other("Failed to find a CodeStored event".into()))?;
let instantiated = events
.find_first::<events::Instantiated>()?
.ok_or_else(|| Error::Other("Failed to find a Instantiated event".into()))?;
let _extrinsic_success = events
.find_first::<system::events::ExtrinsicSuccess>()?
.ok_or_else(|| Error::Other("Failed to find a ExtrinsicSuccess event".into()))?;
tracing::info!(" Code hash: {:?}", code_stored.code_hash);
tracing::info!(" Contract address: {:?}", instantiated.contract);
Ok((code_stored.code_hash, instantiated.contract))
}
async fn instantiate(
&self,
code_hash: Hash,
data: Vec<u8>,
salt: Vec<u8>,
) -> Result<AccountId, Error> {
// call instantiate extrinsic
let instantiate_tx = node_runtime::tx().contracts().instantiate(
100_000_000_000_000_000, // endowment
Weight {
ref_time: 500_000_000_000,
proof_size: PROOF_SIZE,
}, // gas_limit
None, // storage_deposit_limit
code_hash,
data,
salt,
);
let signed_extrinsic = self
.client()
.tx()
.create_signed(&instantiate_tx, &self.signer, Default::default())
.await?;
let result = signed_extrinsic
.submit_and_watch()
.await
.unwrap()
.wait_for_finalized_success()
.await?;
tracing::info!("Instantiate result: {:?}", result);
let instantiated = result
.find_first::<events::Instantiated>()?
.ok_or_else(|| Error::Other("Failed to find a Instantiated event".into()))?;
Ok(instantiated.contract)
}
async fn call(
&self,
contract: AccountId,
input_data: Vec<u8>,
) -> Result<TxProgress<TestConfig, TestClient>, Error> {
tracing::info!("call: {:?}", contract);
let call_tx = node_runtime::tx().contracts().call(
MultiAddress::Id(contract),
0, // value
Weight {
ref_time: 500_000_000,
proof_size: PROOF_SIZE,
}, // gas_limit
None, // storage_deposit_limit
input_data,
);
let result = self
.client()
.tx()
.sign_and_submit_then_watch_default(&call_tx, &self.signer)
.await?;
tracing::info!("Call result: {:?}", result);
Ok(result)
}
}
#[subxt_test]
async fn tx_instantiate_with_code() {
let ctx = ContractsTestContext::init().await;
let result = ctx.instantiate_with_code().await;
assert!(
result.is_ok(),
"Error calling instantiate_with_code and receiving CodeStored and Instantiated Events: {result:?}"
);
}
#[subxt_test]
async fn tx_instantiate() {
let ctx = ContractsTestContext::init().await;
let code_hash = ctx.upload_code().await.unwrap();
let instantiated = ctx.instantiate(code_hash, vec![], vec![]).await;
assert!(
instantiated.is_ok(),
"Error instantiating contract: {instantiated:?}"
);
}
#[subxt_test]
async fn tx_call() {
let cxt = ContractsTestContext::init().await;
let (_, contract) = cxt.instantiate_with_code().await.unwrap();
let info_addr = node_runtime::storage()
.contracts()
.contract_info_of(&contract);
let contract_info = cxt
.client()
.storage()
.at_latest()
.await
.unwrap()
.fetch(&info_addr)
.await;
assert!(
contract_info.is_ok(),
"Contract info is not ok, is: {contract_info:?}"
);
let info_addr_iter = node_runtime::storage().contracts().contract_info_of_iter();
let keys_and_values = cxt
.client()
.storage()
.at_latest()
.await
.unwrap()
.iter(info_addr_iter)
.await
.unwrap()
.collect::<Vec<_>>()
.await;
assert_eq!(keys_and_values.len(), 1);
println!("keys+values post: {keys_and_values:?}");
let executed = cxt.call(contract, vec![]).await;
assert!(executed.is_ok(), "Error calling contract: {executed:?}");
}