Skip to content

Commit

Permalink
Merge pull request #3357 from autonomys/add-test-for-custom-api
Browse files Browse the repository at this point in the history
Add test for the custom runtime api
  • Loading branch information
vedhavyas authored Jan 24, 2025
2 parents 3019471 + 35aacb5 commit 564c648
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 3 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

144 changes: 141 additions & 3 deletions domains/client/domain-operator/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ use crate::tests::TxPoolError::InvalidTransaction as TxPoolInvalidTransaction;
use crate::OperatorSlotInfo;
use codec::{Decode, Encode};
use cross_domain_message_gossip::get_channel_state;
use domain_block_builder::BlockBuilderApi;
use domain_runtime_primitives::opaque::Block as DomainBlock;
use domain_runtime_primitives::{AccountId20Converter, AccountIdConverter, Hash};
use domain_test_primitives::{OnchainStateApi, TimestampApi};
use domain_test_service::evm_domain_test_runtime::{Header, UncheckedExtrinsic};
use domain_test_service::EcdsaKeyring::{Alice, Bob, Charlie, Eve};
use domain_test_service::EcdsaKeyring::{Alice, Bob, Charlie, Dave, Eve};
use domain_test_service::Sr25519Keyring::{self, Alice as Sr25519Alice, Ferdie};
use domain_test_service::{construct_extrinsic_generic, AUTO_ID_DOMAIN_ID, EVM_DOMAIN_ID};
use futures::StreamExt;
Expand All @@ -22,7 +24,8 @@ use sc_transaction_pool::error::Error as PoolError;
use sc_transaction_pool_api::error::Error as TxPoolError;
use sc_transaction_pool_api::TransactionPool;
use sc_utils::mpsc::tracing_unbounded;
use sp_api::{ProvideRuntimeApi, StorageProof};
use sp_api::{ApiExt, Core, ProvideRuntimeApi, StorageProof};
use sp_blockchain::ApplyExtrinsicFailed;
use sp_consensus::SyncOracle;
use sp_core::storage::StateVersion;
use sp_core::traits::{FetchRuntimeCode, SpawnEssentialNamed};
Expand Down Expand Up @@ -50,7 +53,7 @@ use sp_runtime::traits::{
use sp_runtime::transaction_validity::{
InvalidTransaction, TransactionSource, TransactionValidityError,
};
use sp_runtime::OpaqueExtrinsic;
use sp_runtime::{Digest, OpaqueExtrinsic, TransactionOutcome};
use sp_state_machine::backend::AsTrieBackend;
use sp_subspace_mmr::ConsensusChainMmrLeafProof;
use sp_transaction_pool::runtime_api::TaggedTransactionQueue;
Expand Down Expand Up @@ -5805,3 +5808,138 @@ async fn test_stale_fork_xdm_true_invalid_fraud_proof() {
// We check for timeouts last, because they are the least useful test failure message.
assert!(!timed_out);
}

#[tokio::test(flavor = "multi_thread")]
async fn test_custom_api_storage_root_match_upstream_root() {
let directory = TempDir::new().expect("Must be able to create temporary directory");

let mut builder = sc_cli::LoggerBuilder::new("");
builder.with_colors(false);
let _ = builder.init();

let tokio_handle = tokio::runtime::Handle::current();

// Start Ferdie
let mut ferdie = MockConsensusNode::run(
tokio_handle.clone(),
Ferdie,
BasePath::new(directory.path().join("ferdie")),
);

// Run Alice (a evm domain authority node)
let mut alice = domain_test_service::DomainNodeBuilder::new(
tokio_handle.clone(),
BasePath::new(directory.path().join("alice")),
)
.build_evm_node(Role::Authority, Alice, &mut ferdie)
.await;

produce_blocks!(ferdie, alice, 3).await.unwrap();

let domain_parent_number = alice.client.info().best_number;
let domain_parent_hash = alice.client.info().best_hash;
let alice_account_nonce = alice.account_nonce();
let alice_total_balance = alice.free_balance(Alice.to_account_id());
// Success tx
let tx1 = alice.construct_extrinsic(
alice_account_nonce,
pallet_balances::Call::transfer_allow_death {
dest: Bob.to_account_id(),
value: 1234567890987654321,
},
);
// Tx fail during execution due to insufficient fund
let tx2 = alice.construct_extrinsic(
alice_account_nonce + 1,
pallet_balances::Call::transfer_allow_death {
dest: Charlie.to_account_id(),
value: alice_total_balance + 1,
},
);
// Tx transfer all of Alice's fund
let tx3 = alice.construct_extrinsic(
alice_account_nonce + 2,
pallet_balances::Call::transfer_all {
dest: Dave.to_account_id(),
keep_alive: false,
},
);
// Tx fail during pre-dispatch due to unable to pay tx fee
let tx4 = alice.construct_extrinsic(
alice_account_nonce + 3,
pallet_balances::Call::transfer_allow_death {
dest: Charlie.to_account_id(),
value: 1,
},
);
for tx in [tx1, tx2, tx3, tx4] {
alice
.send_extrinsic(tx)
.await
.expect("Failed to send extrinsic");
}

// Produce a domain block that contains the previously sent extrinsic
produce_blocks!(ferdie, alice, 1).await.unwrap();

// Get the receipt of that block, its execution trace is generated by the custom API instance
let (_, bundle) = ferdie.produce_slot_and_wait_for_bundle_submission().await;
let receipt = bundle.into_receipt();
assert_eq!(receipt.execution_trace.len(), 8);

let mut roots = vec![];
let runtime_api_instance = alice.client.runtime_api();

let init_header = <<DomainBlock as BlockT>::Header as HeaderT>::new(
domain_parent_number + 1u32,
Default::default(),
Default::default(),
domain_parent_hash,
Digest {
logs: vec![DigestItem::consensus_block_info(
receipt.consensus_block_hash,
)],
},
);
runtime_api_instance
.initialize_block(domain_parent_hash, &init_header)
.unwrap();
roots.push(
runtime_api_instance
.storage_root(domain_parent_hash)
.unwrap(),
);

let domain_block_body = {
let best_hash = alice.client.info().best_hash;
alice.client.block_body(best_hash).unwrap().unwrap()
};
for xt in domain_block_body {
let _ = runtime_api_instance.execute_in_transaction(|api| {
match api.apply_extrinsic(domain_parent_hash, xt) {
Ok(Ok(_)) => TransactionOutcome::Commit(Ok(())),
Ok(Err(tx_validity)) => TransactionOutcome::Rollback(Err(
ApplyExtrinsicFailed::Validity(tx_validity).into(),
)),
Err(e) => TransactionOutcome::Rollback(Err(sp_blockchain::Error::from(e))),
}
});
roots.push(
runtime_api_instance
.storage_root(domain_parent_hash)
.unwrap(),
);
}

let finalized_header = runtime_api_instance
.finalize_block(domain_parent_hash)
.unwrap();
roots.push((*finalized_header.state_root()).into());

let roots: Vec<<DomainBlock as BlockT>::Hash> = roots
.into_iter()
.map(|r| <DomainBlock as BlockT>::Hash::decode(&mut r.as_slice()).unwrap())
.collect();

assert_eq!(receipt.execution_trace, roots);
}
3 changes: 3 additions & 0 deletions domains/test/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@ sp_api::decl_runtime_apis! {

/// Api to get the current domain transaction byte fee
fn consensus_chain_byte_fee() -> Balance;

/// Get the storage root
fn storage_root() -> [u8; 32];
}
}
1 change: 1 addition & 0 deletions domains/test/runtime/auto-id/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ sp-messenger = { version = "0.1.0", default-features = false, path = "../../../p
sp-messenger-host-functions = { version = "0.1.0", default-features = false, path = "../../../primitives/messenger-host-functions" }
sp-mmr-primitives = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
sp-offchain = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
sp-io = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
sp-runtime = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
sp-session = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
sp-std = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
Expand Down
7 changes: 7 additions & 0 deletions domains/test/runtime/auto-id/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,13 @@ impl_runtime_apis! {
fn consensus_chain_byte_fee() -> Balance {
BlockFees::consensus_chain_byte_fee()
}

fn storage_root() -> [u8; 32] {
let version = <Runtime as frame_system::Config>::Version::get().state_version();
let root = sp_io::storage::root(version);
TryInto::<[u8; 32]>::try_into(root)
.expect("root is a SCALE encoded hash which uses H256; qed")
}
}

#[cfg(feature = "runtime-benchmarks")]
Expand Down
1 change: 1 addition & 0 deletions domains/test/runtime/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ sp-messenger = { version = "0.1.0", default-features = false, path = "../../../p
sp-messenger-host-functions = { version = "0.1.0", default-features = false, path = "../../../primitives/messenger-host-functions" }
sp-mmr-primitives = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
sp-offchain = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
sp-io = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
sp-runtime = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
sp-session = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
sp-std = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
Expand Down
7 changes: 7 additions & 0 deletions domains/test/runtime/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1524,6 +1524,13 @@ impl_runtime_apis! {
fn consensus_chain_byte_fee() -> Balance {
BlockFees::consensus_chain_byte_fee()
}

fn storage_root() -> [u8; 32] {
let version = <Runtime as frame_system::Config>::Version::get().state_version();
let root = sp_io::storage::root(version);
TryInto::<[u8; 32]>::try_into(root)
.expect("root is a SCALE encoded hash which uses H256; qed")
}
}

impl sp_domain_sudo::DomainSudoApi<Block> for Runtime {
Expand Down

0 comments on commit 564c648

Please sign in to comment.