Skip to content

Commit 56d135e

Browse files
authored
Merge pull request #3359 from autonomys/private-evm-prep
Fix custom transaction error code clash, and make ethereum tests easier to write
2 parents f11c5f9 + 18cdf19 commit 56d135e

File tree

17 files changed

+200
-171
lines changed

17 files changed

+200
-171
lines changed

Cargo.lock

+6-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/sp-domains-fraud-proof/Cargo.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,16 @@ domain-test-service = { version = "0.1.0", path = "../../domains/test/service" }
4747
ethereum = "0.15.0"
4848
fp-rpc = { version = "3.0.0-dev", git = "https://github.com/autonomys/frontier", rev = "f80f9e2bad338f3bf3854b256b3c4edea23e5968", features = ['default'] }
4949
fp-self-contained = { version = "1.0.0-dev", git = "https://github.com/autonomys/frontier", rev = "f80f9e2bad338f3bf3854b256b3c4edea23e5968", features = ['default'] }
50-
frame-support = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
5150
frame-system = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
5251
futures = "0.3.31"
5352
libsecp256k1 = { version = "0.7.1", features = ["static-context", "hmac"] }
5453
pallet-balances = { git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
5554
pallet-ethereum = { git = "https://github.com/autonomys/frontier", rev = "f80f9e2bad338f3bf3854b256b3c4edea23e5968", features = ['default'] }
56-
pallet-evm = { version = "6.0.0-dev", git = "https://github.com/autonomys/frontier", rev = "f80f9e2bad338f3bf3854b256b3c4edea23e5968", default-features = false }
5755
rand = { version = "0.8.5", features = ["min_const_gen"] }
5856
rlp = "0.5.2"
5957
sp-core = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305" }
6058
sc-cli = { git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305", default-features = false }
59+
sp-domains = { version = "0.1.0", default-features = false, features = ["test-ethereum"], path = "../sp-domains" }
6160
sc-service = { git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305", default-features = false }
6261
subspace-test-service = { version = "0.1.0", path = "../../test/subspace-test-service" }
6362
subspace-runtime-primitives = { version = "0.1.0", path = "../../crates/subspace-runtime-primitives" }

crates/sp-domains-fraud-proof/src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ mod host_functions;
1515
mod runtime_interface;
1616
pub mod storage_proof;
1717
#[cfg(test)]
18-
pub mod test_ethereum_tx;
19-
#[cfg(test)]
2018
mod tests;
2119
pub mod verification;
2220

@@ -47,6 +45,9 @@ use subspace_core_primitives::U256;
4745
use subspace_runtime_primitives::{Balance, Moment};
4846

4947
/// Custom invalid validity code for the extrinsics in pallet-domains.
48+
// When updating these error codes, check for clashes between:
49+
// <https://github.com/autonomys/subspace/blob/main/domains/primitives/runtime/src/lib.rs#L85-L88>
50+
// <https://github.com/autonomys/subspace/blob/main/domains/pallets/messenger/src/lib.rs#L49-L53>
5051
#[repr(u8)]
5152
pub enum InvalidTransactionCode {
5253
TransactionProof = 101,

crates/sp-domains-fraud-proof/src/tests.rs

+14-115
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
use crate::test_ethereum_tx::{
2-
EIP1559UnsignedTransaction, EIP2930UnsignedTransaction, LegacyUnsignedTransaction,
3-
};
41
use codec::Encode;
52
use domain_runtime_primitives::{Balance, CheckExtrinsicsValidityError};
63
use domain_test_service::evm_domain_test_runtime::{
@@ -11,125 +8,27 @@ use domain_test_service::Sr25519Keyring::Ferdie;
118
use domain_test_service::{construct_extrinsic_raw_payload, EvmDomainNode};
129
use ethereum::TransactionV2 as Transaction;
1310
use fp_rpc::EthereumRuntimeRPCApi;
14-
use frame_support::pallet_prelude::DispatchClass;
1511
use pallet_ethereum::Call;
16-
use pallet_evm::GasWeightMapping;
1712
use rand::distributions::{Distribution, Uniform};
1813
use sc_client_api::{HeaderBackend, StorageProof};
1914
use sc_service::{BasePath, Role};
2015
use sp_api::{ApiExt, ProvideRuntimeApi, TransactionOutcome};
2116
use sp_core::ecdsa::Pair;
22-
use sp_core::{keccak_256, Pair as _, H160, H256, U256};
17+
use sp_core::{keccak_256, Pair as _, U256};
2318
use sp_domains::core_api::DomainCoreApi;
19+
use sp_domains::test_ethereum::{
20+
address_build, generate_eip1559_tx, generate_eip2930_tx, generate_legacy_tx, AccountInfo,
21+
};
2422
use sp_runtime::traits::{Extrinsic, Zero};
2523
use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidityError};
2624
use sp_runtime::OpaqueExtrinsic;
2725
use subspace_test_service::{produce_block_with, produce_blocks, MockConsensusNode};
2826
use tempfile::TempDir;
2927

30-
#[derive(Clone)]
31-
pub struct AccountInfo {
32-
pub address: H160,
33-
pub private_key: H256,
34-
}
35-
36-
fn address_build(seed_number: u128) -> AccountInfo {
37-
let mut seed = [0u8; 32];
38-
seed[0..16].copy_from_slice(&seed_number.to_be_bytes());
39-
let private_key = H256::from_slice(&seed);
40-
let secret_key = libsecp256k1::SecretKey::parse_slice(&private_key[..]).unwrap();
41-
let public_key = &libsecp256k1::PublicKey::from_secret_key(&secret_key).serialize()[1..65];
42-
let address = H160::from(H256::from(keccak_256(public_key)));
43-
44-
let mut data = [0u8; 32];
45-
data[0..20].copy_from_slice(&address[..]);
46-
47-
AccountInfo {
48-
private_key,
49-
address,
50-
}
51-
}
52-
53-
fn generate_legacy_tx(
54-
account_info: AccountInfo,
55-
nonce: U256,
56-
action: ethereum::TransactionAction,
57-
input: Vec<u8>,
58-
gas_price: U256,
59-
) -> Transaction {
60-
let limits: frame_system::limits::BlockWeights =
61-
<TestRuntime as frame_system::Config>::BlockWeights::get();
62-
// `limits.get(DispatchClass::Normal).max_extrinsic` is too large to use as `gas_limit`
63-
// thus use `base_extrinsic`
64-
let max_extrinsic = limits.get(DispatchClass::Normal).base_extrinsic * 1000;
65-
let max_extrinsic_gas =
66-
<TestRuntime as pallet_evm::Config>::GasWeightMapping::weight_to_gas(max_extrinsic);
67-
68-
LegacyUnsignedTransaction {
69-
nonce,
70-
gas_price,
71-
gas_limit: U256::from(max_extrinsic_gas),
72-
action,
73-
value: U256::zero(),
74-
input,
75-
}
76-
.sign(&account_info.private_key)
77-
}
78-
79-
fn generate_eip2930_tx(
80-
account_info: AccountInfo,
81-
nonce: U256,
82-
action: ethereum::TransactionAction,
83-
input: Vec<u8>,
84-
gas_price: U256,
85-
) -> Transaction {
86-
let limits: frame_system::limits::BlockWeights =
87-
<TestRuntime as frame_system::Config>::BlockWeights::get();
88-
// `limits.get(DispatchClass::Normal).max_extrinsic` is too large to use as `gas_limit`
89-
// thus use `base_extrinsic`
90-
let max_extrinsic = limits.get(DispatchClass::Normal).base_extrinsic * 100;
91-
let max_extrinsic_gas =
92-
<TestRuntime as pallet_evm::Config>::GasWeightMapping::weight_to_gas(max_extrinsic);
93-
94-
EIP2930UnsignedTransaction {
95-
nonce,
96-
gas_price,
97-
gas_limit: U256::from(max_extrinsic_gas),
98-
action,
99-
value: U256::one(),
100-
input,
101-
}
102-
.sign(&account_info.private_key, None)
103-
}
104-
105-
fn generate_eip1559_tx(
106-
account_info: AccountInfo,
107-
nonce: U256,
108-
action: ethereum::TransactionAction,
109-
input: Vec<u8>,
110-
gas_price: U256,
111-
) -> Transaction {
112-
let limits: frame_system::limits::BlockWeights =
113-
<TestRuntime as frame_system::Config>::BlockWeights::get();
114-
// `limits.get(DispatchClass::Normal).max_extrinsic` is too large to use as `gas_limit`
115-
// thus use `base_extrinsic`
116-
let max_extrinsic = limits.get(DispatchClass::Normal).base_extrinsic * 1000;
117-
let max_extrinsic_gas =
118-
<TestRuntime as pallet_evm::Config>::GasWeightMapping::weight_to_gas(max_extrinsic);
119-
120-
EIP1559UnsignedTransaction {
121-
nonce,
122-
max_priority_fee_per_gas: U256::from(1),
123-
max_fee_per_gas: gas_price,
124-
gas_limit: U256::from(max_extrinsic_gas),
125-
action,
126-
value: U256::zero(),
127-
input,
128-
}
129-
.sign(&account_info.private_key, None)
130-
}
131-
132-
fn generate_evm_domain_extrinsic(tx: Transaction) -> RuntimeUncheckedExtrinsic {
28+
/// Generate a self-contained EVM domain extrinsic.
29+
// This function depends on the macro-constructed `TestRuntime::RuntimeCall` enum, so it can't be
30+
// shared via `sp_domains::test_ethereum`.
31+
pub fn generate_evm_domain_extrinsic(tx: Transaction) -> RuntimeUncheckedExtrinsic {
13332
let call = Call::<TestRuntime>::transact { transaction: tx };
13433
fp_self_contained::UncheckedExtrinsic::new(RuntimeCall::Ethereum(call), None).unwrap()
13534
}
@@ -191,7 +90,7 @@ async fn benchmark_bundle_with_evm_tx(
19190
);
19291
let extrinsic = match tx_type_to_use {
19392
0 => {
194-
let evm_tx = generate_eip1559_tx(
93+
let evm_tx = generate_eip1559_tx::<TestRuntime>(
19594
account_info.clone(),
19695
U256::zero(),
19796
ethereum::TransactionAction::Create,
@@ -201,7 +100,7 @@ async fn benchmark_bundle_with_evm_tx(
201100
generate_evm_domain_extrinsic(evm_tx)
202101
}
203102
1 => {
204-
let evm_tx = generate_eip2930_tx(
103+
let evm_tx = generate_eip2930_tx::<TestRuntime>(
205104
account_info.clone(),
206105
U256::zero(),
207106
ethereum::TransactionAction::Create,
@@ -211,7 +110,7 @@ async fn benchmark_bundle_with_evm_tx(
211110
generate_evm_domain_extrinsic(evm_tx)
212111
}
213112
2 => {
214-
let evm_tx = generate_legacy_tx(
113+
let evm_tx = generate_legacy_tx::<TestRuntime>(
215114
account_info.clone(),
216115
U256::zero(),
217116
ethereum::TransactionAction::Create,
@@ -727,9 +626,9 @@ async fn test_evm_domain_block_fee() {
727626
let tx_generators: Vec<
728627
Box<dyn Fn(AccountInfo, U256, ethereum::TransactionAction, Vec<u8>, U256) -> Transaction>,
729628
> = vec![
730-
Box::new(generate_eip2930_tx),
731-
Box::new(generate_eip1559_tx),
732-
Box::new(generate_legacy_tx),
629+
Box::new(generate_eip2930_tx::<TestRuntime>),
630+
Box::new(generate_eip1559_tx::<TestRuntime>),
631+
Box::new(generate_legacy_tx::<TestRuntime>),
733632
];
734633
for (i, (acc, tx_generator)) in account_infos
735634
.iter()

crates/sp-domains/Cargo.toml

+16
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ subspace-core-primitives = { version = "0.1.0", default-features = false, path =
3838
subspace-runtime-primitives = { version = "0.1.0", default-features = false, path = "../subspace-runtime-primitives" }
3939
trie-db = { version = "0.29.1", default-features = false }
4040

41+
# test-ethereum dependencies
42+
ethereum = { version = "0.15.0", optional = true }
43+
fp-self-contained = { version = "1.0.0-dev", git = "https://github.com/autonomys/frontier", rev = "f80f9e2bad338f3bf3854b256b3c4edea23e5968", features = ['default'], optional = true }
44+
frame-system = { default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "94a1a8143a89bbe9f938c1939ff68abc1519a305", optional = true }
45+
libsecp256k1 = { version = "0.7.1", features = ["static-context", "hmac"], optional = true }
46+
pallet-evm = { version = "6.0.0-dev", git = "https://github.com/autonomys/frontier", rev = "f80f9e2bad338f3bf3854b256b3c4edea23e5968", default-features = false, optional = true }
47+
rlp = { version = "0.5.2", optional = true }
48+
4149
[dev-dependencies]
4250
num-traits = "0.2.18"
4351
rand = { version = "0.8.5", features = ["min_const_gen"] }
@@ -70,3 +78,11 @@ std = [
7078
"trie-db/std",
7179
]
7280
runtime-benchmarks = []
81+
test-ethereum = [
82+
"ethereum",
83+
"fp-self-contained",
84+
"frame-system",
85+
"libsecp256k1",
86+
"pallet-evm",
87+
"rlp",
88+
]

crates/sp-domains/src/lib.rs

+15-11
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ pub mod extrinsics;
88
pub mod merkle_tree;
99
pub mod proof_provider_and_verifier;
1010
pub mod storage;
11+
#[cfg(any(test, feature = "test-ethereum"))]
12+
pub mod test_ethereum;
13+
#[cfg(any(test, feature = "test-ethereum"))]
14+
pub mod test_ethereum_tx;
1115
#[cfg(test)]
1216
mod tests;
1317
pub mod valued_trie;
@@ -968,17 +972,17 @@ impl DomainsDigestItem for DigestItem {
968972

969973
/// EVM chain Id storage key.
970974
///
971-
/// This and next function should ideally use Host function to fetch the storage key
975+
/// This function should ideally use a Host function to fetch the storage key
972976
/// from the domain runtime. But since the Host function is not available at Genesis, we have to
973977
/// assume the storage keys.
974978
/// TODO: once the chain is launched in mainnet, we should use the Host function for all domain instances.
975979
pub(crate) fn evm_chain_id_storage_key() -> StorageKey {
976980
StorageKey(
977981
storage_prefix(
978-
// This is the name used for the `pallet_evm_chain_id` in the `construct_runtime` macro
982+
// This is the name used for `pallet_evm_chain_id` in the `construct_runtime` macro
979983
// i.e. `EVMChainId: pallet_evm_chain_id = 82,`
980984
"EVMChainId".as_bytes(),
981-
// This is the storage item name used inside the `pallet_evm_chain_id`
985+
// This is the storage item name used inside `pallet_evm_chain_id`
982986
"ChainId".as_bytes(),
983987
)
984988
.to_vec(),
@@ -994,9 +998,9 @@ pub(crate) fn evm_chain_id_storage_key() -> StorageKey {
994998
pub fn domain_total_issuance_storage_key() -> StorageKey {
995999
StorageKey(
9961000
storage_prefix(
997-
// This is the name used for the `pallet_balances` in the `construct_runtime` macro
1001+
// This is the name used for `pallet_balances` in the `construct_runtime` macro
9981002
"Balances".as_bytes(),
999-
// This is the storage item name used inside the `pallet_balances`
1003+
// This is the storage item name used inside `pallet_balances`
10001004
"TotalIssuance".as_bytes(),
10011005
)
10021006
.to_vec(),
@@ -1005,7 +1009,7 @@ pub fn domain_total_issuance_storage_key() -> StorageKey {
10051009

10061010
/// Account info on frame_system on Domains
10071011
///
1008-
/// This function should ideally use Host function to fetch the storage key
1012+
/// This function should ideally use a Host function to fetch the storage key
10091013
/// from the domain runtime. But since the Host function is not available at Genesis, we have to
10101014
/// assume the storage keys.
10111015
/// TODO: once the chain is launched in mainnet, we should use the Host function for all domain instances.
@@ -1021,17 +1025,17 @@ pub fn domain_account_storage_key<AccountId: Encode>(who: AccountId) -> StorageK
10211025
StorageKey(final_key)
10221026
}
10231027

1024-
/// The storage key of the `SelfDomainId` storage item in the `pallet-domain-id`
1028+
/// The storage key of the `SelfDomainId` storage item in `pallet-domain-id`
10251029
///
1026-
/// Any change to the storage item name or the `pallet-domain-id` name used in the `construct_runtime`
1030+
/// Any change to the storage item name or `pallet-domain-id` name used in the `construct_runtime`
10271031
/// macro must be reflected here.
10281032
pub fn self_domain_id_storage_key() -> StorageKey {
10291033
StorageKey(
10301034
frame_support::storage::storage_prefix(
1031-
// This is the name used for the `pallet-domain-id` in the `construct_runtime` macro
1035+
// This is the name used for `pallet-domain-id` in the `construct_runtime` macro
10321036
// i.e. `SelfDomainId: pallet_domain_id = 90`
10331037
"SelfDomainId".as_bytes(),
1034-
// This is the storage item name used inside the `pallet-domain-id`
1038+
// This is the storage item name used inside `pallet-domain-id`
10351039
"SelfDomainId".as_bytes(),
10361040
)
10371041
.to_vec(),
@@ -1552,7 +1556,7 @@ sp_api::decl_runtime_apis! {
15521556

15531557
/// Returns the last confirmed domain block execution receipt.
15541558
fn last_confirmed_domain_block_receipt(domain_id: DomainId) ->Option<ExecutionReceiptFor<DomainHeader, Block, Balance>>;
1555-
}
1559+
}
15561560

15571561
pub trait BundleProducerElectionApi<Balance: Encode + Decode> {
15581562
fn bundle_producer_election_params(domain_id: DomainId) -> Option<BundleProducerElectionParams<Balance>>;

0 commit comments

Comments
 (0)