Skip to content
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

test(pop-api): read_state chain extension test #22

Merged
merged 1 commit into from
Mar 7, 2024
Merged
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
6 changes: 3 additions & 3 deletions pop-api/primitives/src/storage_keys.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use scale::{Decode, Encode};
use scale::{Decode, Encode, MaxEncodedLen};

#[derive(Encode, Decode, Debug)]
#[derive(Encode, Decode, Debug, MaxEncodedLen)]
pub enum RuntimeStateKeys {
ParachainSystem(ParachainSystemKeys),
}

#[derive(Encode, Decode, Debug)]
#[derive(Encode, Decode, Debug, MaxEncodedLen)]
pub enum ParachainSystemKeys {
LastRelayChainBlockNumber,
}
97 changes: 81 additions & 16 deletions runtime/src/extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
dispatch::{GetDispatchInfo, PostDispatchInfo, RawOrigin},
pallet_prelude::*,
};
use log;

Check warning on line 6 in runtime/src/extensions.rs

View workflow job for this annotation

GitHub Actions / clippy

this import is redundant

warning: this import is redundant --> runtime/src/extensions.rs:6:1 | 6 | use log; | ^^^^^^^^ help: remove it entirely | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_component_path_imports = note: `#[warn(clippy::single_component_path_imports)]` on by default
use pallet_contracts::chain_extension::{
ChainExtension, Environment, Ext, InitState, RetVal, SysConfig,
};
Expand Down Expand Up @@ -77,7 +77,7 @@
}
}

pub(crate) fn dispatch<T, E>(env: Environment<E, InitState>) -> Result<(), DispatchError>
fn dispatch<T, E>(env: Environment<E, InitState>) -> Result<(), DispatchError>
where
T: pallet_contracts::Config + frame_system::Config,
<T as SysConfig>::AccountId: UncheckedFrom<<T as SysConfig>::Hash> + AsRef<[u8]>,
Expand Down Expand Up @@ -133,7 +133,7 @@
Ok(())
}

pub(crate) fn read_state<T, E>(env: Environment<E, InitState>) -> Result<(), DispatchError>
fn read_state<T, E>(env: Environment<E, InitState>) -> Result<(), DispatchError>
where
T: pallet_contracts::Config + frame_system::Config,
E: Ext<T = T>,
Expand All @@ -142,13 +142,14 @@

let mut env = env.buf_in_buf_out();

// TODO: Substitute len u32 with pop_api::src::impls::pop_network::StringLimit.
// Move StringLimit to pop_api_primitives first.
let len: u32 = env.in_len();
let key: ParachainSystemKeys = env.read_as_unbounded(len)?;
// TODO: replace with benchmark once available
env.charge_weight(T::DbWeight::get().reads(1_u64))?;

let key: ParachainSystemKeys = env.read_as()?;

let result = match key {
ParachainSystemKeys::LastRelayChainBlockNumber => {
env.charge_weight(T::DbWeight::get().reads(1_u64))?;
let relay_block_num: BlockNumber = crate::ParachainSystem::last_relay_block_number();
log::debug!(
target:LOG_TARGET,
Expand All @@ -157,7 +158,13 @@
relay_block_num
},
}
.encode()
// Double-encode result for extension return type of bytes
.encode();
log::trace!(
target:LOG_TARGET,
"read state result: {:?}.", result
);
env.write(&result, false, None).map_err(|e| {
log::trace!(target: LOG_TARGET, "{:?}", e);
DispatchError::Other("unable to write results to contract memory")
Expand All @@ -174,14 +181,14 @@
use parachains_common::CollectionId;
pub use sp_runtime::{traits::Hash, AccountId32};

pub const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug;
const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug;

pub const ALICE: AccountId32 = AccountId32::new([1_u8; 32]);
pub const BOB: AccountId32 = AccountId32::new([2_u8; 32]);
pub const INITIAL_AMOUNT: u128 = 100_000 * UNIT;
pub const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024);
const ALICE: AccountId32 = AccountId32::new([1_u8; 32]);
const BOB: AccountId32 = AccountId32::new([2_u8; 32]);
const INITIAL_AMOUNT: u128 = 100_000 * UNIT;
const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024);

pub fn new_test_ext() -> sp_io::TestExternalities {
fn new_test_ext() -> sp_io::TestExternalities {
let mut t = frame_system::GenesisConfig::<Runtime>::default()
.build_storage()
.expect("Frame system builds valid default genesis config");
Expand All @@ -197,9 +204,7 @@
ext
}

pub fn load_wasm_module<T>(
path: &str,
) -> std::io::Result<(Vec<u8>, <T::Hashing as Hash>::Output)>
fn load_wasm_module<T>(path: &str) -> std::io::Result<(Vec<u8>, <T::Hashing as Hash>::Output)>
where
T: frame_system::Config,
{
Expand All @@ -208,7 +213,7 @@
Ok((wasm_binary, code_hash))
}

pub fn function_selector(name: &str) -> Vec<u8> {
fn function_selector(name: &str) -> Vec<u8> {
evilrobot-01 marked this conversation as resolved.
Show resolved Hide resolved
let hash = sp_io::hashing::blake2_256(name.as_bytes());
[hash[0..4].to_vec()].concat()
}
Expand Down Expand Up @@ -439,4 +444,64 @@
assert!(result.did_revert());
});
}

#[test]
#[ignore]
fn reading_last_relay_chain_block_number_works() {
new_test_ext().execute_with(|| {
let _ = env_logger::try_init();

let (wasm_binary, _) = load_wasm_module::<Runtime>("../contracts/pop-api-examples/read-runtime-state/target/ink/pop_api_extension_demo.wasm").unwrap();

let init_value = 100;

let contract = Contracts::bare_instantiate(
ALICE,
init_value,
GAS_LIMIT,
None,
Code::Upload(wasm_binary),
function_selector("new"),
vec![],
DEBUG_OUTPUT,
pallet_contracts::CollectEvents::Skip,
)
.result
.unwrap();

assert!(
!contract.result.did_revert(),
"deploying contract reverted {:?}",
contract
);

let addr = contract.account_id;

let function = function_selector("read_relay_block_number");
let params = [function].concat();

let result = Contracts::bare_call(
ALICE,
addr.clone(),
0,
Weight::from_parts(100_000_000_000, 3 * 1024 * 1024),
None,
params,
DEBUG_OUTPUT,
pallet_contracts::CollectEvents::UnsafeCollect,
pallet_contracts::Determinism::Relaxed,
);

if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug {
evilrobot-01 marked this conversation as resolved.
Show resolved Hide resolved
log::debug!(
"Contract debug buffer - {:?}",
String::from_utf8(result.debug_message.clone())
);
log::debug!("result: {:?}", result);
}

// check for revert
assert!(!result.result.unwrap().did_revert(), "Contract reverted!");
});
}
}
Loading