mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 08:11:03 +00:00
One node two runtimes (#191)
* One node two runtimes This enables the rococo-collator to run the normal and the contracts runtime. * Fix tests
This commit is contained in:
Generated
+16
@@ -976,6 +976,7 @@ dependencies = [
|
||||
"parachain-info",
|
||||
"parity-scale-codec",
|
||||
"polkadot-parachain",
|
||||
"rococo-parachain-primitives",
|
||||
"serde",
|
||||
"sp-api",
|
||||
"sp-block-builder",
|
||||
@@ -1213,6 +1214,7 @@ dependencies = [
|
||||
"parachain-info",
|
||||
"parity-scale-codec",
|
||||
"polkadot-parachain",
|
||||
"rococo-parachain-primitives",
|
||||
"serde",
|
||||
"sp-api",
|
||||
"sp-block-builder",
|
||||
@@ -5831,6 +5833,7 @@ dependencies = [
|
||||
"polkadot-test-runtime-client",
|
||||
"polkadot-test-service",
|
||||
"rand 0.7.3",
|
||||
"rococo-parachain-primitives",
|
||||
"sc-basic-authorship",
|
||||
"sc-chain-spec",
|
||||
"sc-cli",
|
||||
@@ -5840,15 +5843,20 @@ dependencies = [
|
||||
"sc-finality-grandpa",
|
||||
"sc-informant",
|
||||
"sc-network",
|
||||
"sc-rpc",
|
||||
"sc-service",
|
||||
"sc-transaction-pool",
|
||||
"serde",
|
||||
"sp-api",
|
||||
"sp-block-builder",
|
||||
"sp-blockchain",
|
||||
"sp-consensus",
|
||||
"sp-core",
|
||||
"sp-inherents",
|
||||
"sp-io",
|
||||
"sp-offchain",
|
||||
"sp-runtime",
|
||||
"sp-session",
|
||||
"sp-timestamp",
|
||||
"sp-transaction-pool",
|
||||
"sp-trie",
|
||||
@@ -5860,6 +5868,14 @@ dependencies = [
|
||||
"trie-root 0.15.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rococo-parachain-primitives"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"sp-core",
|
||||
"sp-runtime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rococo-runtime"
|
||||
version = "0.8.22"
|
||||
|
||||
@@ -9,6 +9,7 @@ members = [
|
||||
"rococo-parachains/contracts-runtime",
|
||||
"rococo-parachains/pallets/parachain-info",
|
||||
"rococo-parachains/pallets/token-dealer",
|
||||
"rococo-parachains/primitives",
|
||||
"rococo-parachains/runtime",
|
||||
"runtime",
|
||||
"service",
|
||||
|
||||
+11
-12
@@ -518,18 +518,17 @@ where
|
||||
Box::new(self.polkadot_network.clone()),
|
||||
)));
|
||||
|
||||
let follow =
|
||||
match cumulus_consensus::follow_polkadot(
|
||||
self.para_id,
|
||||
self.client,
|
||||
polkadot_client,
|
||||
self.announce_block.clone(),
|
||||
) {
|
||||
Ok(follow) => follow,
|
||||
Err(e) => {
|
||||
return Err(error!("Could not start following polkadot: {:?}", e));
|
||||
}
|
||||
};
|
||||
let follow = match cumulus_consensus::follow_polkadot(
|
||||
self.para_id,
|
||||
self.client,
|
||||
polkadot_client,
|
||||
self.announce_block.clone(),
|
||||
) {
|
||||
Ok(follow) => follow,
|
||||
Err(e) => {
|
||||
return Err(error!("Could not start following polkadot: {:?}", e));
|
||||
}
|
||||
};
|
||||
|
||||
self.spawner
|
||||
.spawn("cumulus-follow-polkadot", follow.map(|_| ()).boxed());
|
||||
|
||||
@@ -23,7 +23,10 @@ mod tests;
|
||||
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use sp_blockchain::{Error as ClientError, HeaderBackend};
|
||||
use sp_consensus::{block_validation::{BlockAnnounceValidator, Validation}, SyncOracle};
|
||||
use sp_consensus::{
|
||||
block_validation::{BlockAnnounceValidator, Validation},
|
||||
SyncOracle,
|
||||
};
|
||||
use sp_core::traits::SpawnNamed;
|
||||
use sp_runtime::{
|
||||
generic::BlockId,
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
use super::*;
|
||||
use cumulus_test_runtime::{Block, Header};
|
||||
use polkadot_primitives::v0::{
|
||||
AbridgedCandidateReceipt, Chain, CollatorId, DutyRoster, GlobalValidationData,
|
||||
Id as ParaId, LocalValidationData, ParachainHost, Retriable, SigningContext,
|
||||
ValidationCode, ValidatorId, Block as PBlock, Hash as PHash, Header as PHeader,
|
||||
AbridgedCandidateReceipt, Block as PBlock, Chain, CollatorId, DutyRoster, GlobalValidationData,
|
||||
Hash as PHash, Header as PHeader, Id as ParaId, LocalValidationData, ParachainHost, Retriable,
|
||||
SigningContext, ValidationCode, ValidatorId,
|
||||
};
|
||||
use polkadot_test_runtime_client::{
|
||||
DefaultTestClientBuilderExt, TestClient, TestClientBuilder, TestClientBuilderExt,
|
||||
|
||||
@@ -25,6 +25,7 @@ hex-literal = "0.2.1"
|
||||
# Parachain dependencies
|
||||
parachain-runtime = { package = "cumulus-test-parachain-runtime", path = "runtime" }
|
||||
parachain-contracts-runtime = { package = "cumulus-contracts-parachain-runtime", path = "contracts-runtime" }
|
||||
rococo-parachain-primitives = { path = "primitives" }
|
||||
|
||||
# Substrate dependencies
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
|
||||
@@ -32,6 +33,7 @@ sp-io = { git = "https://github.com/paritytech/substrate", branch = "rococo-bran
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sp-session = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
@@ -42,11 +44,15 @@ sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch
|
||||
sc-network = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch", version = "0.8.0-rc5" }
|
||||
sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sc-informant = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
|
||||
|
||||
# RPC related dependencies
|
||||
cumulus-pallet-contracts-rpc = { path = "./pallets/contracts/rpc" }
|
||||
|
||||
@@ -10,6 +10,7 @@ codec = { package = "parity-scale-codec", version = "1.3.0", default-features =
|
||||
|
||||
cumulus-token-dealer = { path = "../pallets/token-dealer", default-features = false}
|
||||
parachain-info = { path = "../pallets/parachain-info", default-features = false}
|
||||
rococo-parachain-primitives = { path = "../primitives", default-features = false}
|
||||
|
||||
# Substrate dependencies
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
|
||||
@@ -79,6 +80,7 @@ std = [
|
||||
"pallet-sudo/std",
|
||||
"pallet-transaction-payment/std",
|
||||
"parachain-info/std",
|
||||
"rococo-parachain-primitives/std",
|
||||
"cumulus-runtime/std",
|
||||
"cumulus-parachain-upgrade/std",
|
||||
"cumulus-message-broker/std",
|
||||
|
||||
@@ -23,13 +23,14 @@
|
||||
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
|
||||
|
||||
use cumulus_pallet_contracts_rpc_runtime_api::ContractExecResult;
|
||||
use rococo_parachain_primitives::*;
|
||||
use sp_api::impl_runtime_apis;
|
||||
use sp_core::OpaqueMetadata;
|
||||
use sp_runtime::{
|
||||
create_runtime_str, generic, impl_opaque_keys,
|
||||
traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, IdentityLookup, Saturating, Verify},
|
||||
traits::{BlakeTwo256, Block as BlockT, IdentityLookup, Saturating},
|
||||
transaction_validity::{TransactionSource, TransactionValidity},
|
||||
ApplyExtrinsicResult, MultiSignature,
|
||||
ApplyExtrinsicResult,
|
||||
};
|
||||
use sp_std::prelude::*;
|
||||
#[cfg(feature = "std")]
|
||||
@@ -49,53 +50,10 @@ pub use pallet_timestamp::Call as TimestampCall;
|
||||
pub use sp_runtime::BuildStorage;
|
||||
pub use sp_runtime::{Perbill, Permill};
|
||||
|
||||
/// An index to a block.
|
||||
pub type BlockNumber = u32;
|
||||
pub type SessionHandlers = ();
|
||||
|
||||
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
|
||||
pub type Signature = MultiSignature;
|
||||
|
||||
/// Some way of identifying an account on the chain. We intentionally make it equivalent
|
||||
/// to the public key of our transaction signing scheme.
|
||||
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
|
||||
|
||||
/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
|
||||
/// never know...
|
||||
pub type AccountIndex = u32;
|
||||
|
||||
/// Balance of an account.
|
||||
pub type Balance = u128;
|
||||
|
||||
/// Index of a transaction in the chain.
|
||||
pub type Index = u32;
|
||||
|
||||
/// A hash of some data used by the chain.
|
||||
pub type Hash = sp_core::H256;
|
||||
|
||||
/// Digest item type.
|
||||
pub type DigestItem = generic::DigestItem<Hash>;
|
||||
|
||||
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
|
||||
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
|
||||
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
|
||||
/// to even the core datastructures.
|
||||
pub mod opaque {
|
||||
use super::*;
|
||||
|
||||
pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
|
||||
|
||||
/// Opaque block header type.
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
/// Opaque block type.
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
/// Opaque block identifier type.
|
||||
pub type BlockId = generic::BlockId<Block>;
|
||||
|
||||
pub type SessionHandlers = ();
|
||||
|
||||
impl_opaque_keys! {
|
||||
pub struct SessionKeys {}
|
||||
}
|
||||
impl_opaque_keys! {
|
||||
pub struct SessionKeys {}
|
||||
}
|
||||
|
||||
/// This runtime version.
|
||||
@@ -103,7 +61,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
spec_name: create_runtime_str!("cumulus-contracts-parachain"),
|
||||
impl_name: create_runtime_str!("cumulus-contracts-parachain"),
|
||||
authoring_version: 1,
|
||||
spec_version: 1,
|
||||
spec_version: 2,
|
||||
impl_version: 1,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
transaction_version: 1,
|
||||
@@ -292,7 +250,7 @@ impl cumulus_pallet_contracts::Trait for Runtime {
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = opaque::Block,
|
||||
NodeBlock = rococo_parachain_primitives::Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: frame_system::{Module, Call, Storage, Config, Event<T>},
|
||||
@@ -405,11 +363,11 @@ impl_runtime_apis! {
|
||||
fn decode_session_keys(
|
||||
encoded: Vec<u8>,
|
||||
) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
|
||||
opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
|
||||
SessionKeys::decode_into_raw_public_keys(&encoded)
|
||||
}
|
||||
|
||||
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
|
||||
opaque::SessionKeys::generate(seed)
|
||||
SessionKeys::generate(seed)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use codec::Codec;
|
||||
use cumulus_pallet_contracts_primitives::RentProjection;
|
||||
use jsonrpc_core::{Error, ErrorCode, Result};
|
||||
use jsonrpc_derive::rpc;
|
||||
use cumulus_pallet_contracts_primitives::RentProjection;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use sp_blockchain::HeaderBackend;
|
||||
@@ -106,7 +106,11 @@ pub enum RpcContractExecResult {
|
||||
impl From<ContractExecResult> for RpcContractExecResult {
|
||||
fn from(r: ContractExecResult) -> Self {
|
||||
match r {
|
||||
ContractExecResult::Success { flags, data, gas_consumed } => RpcContractExecResult::Success {
|
||||
ContractExecResult::Success {
|
||||
flags,
|
||||
data,
|
||||
gas_consumed,
|
||||
} => RpcContractExecResult::Success {
|
||||
flags,
|
||||
data: data.into(),
|
||||
gas_consumed,
|
||||
@@ -293,7 +297,8 @@ mod tests {
|
||||
#[test]
|
||||
fn call_request_should_serialize_deserialize_properly() {
|
||||
type Req = CallRequest<String, u128>;
|
||||
let req: Req = serde_json::from_str(r#"
|
||||
let req: Req = serde_json::from_str(
|
||||
r#"
|
||||
{
|
||||
"origin": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL",
|
||||
"dest": "5DRakbLVnjVrW6niwLfHGW24EeCEvDAFGEXrtaYS5M4ynoom",
|
||||
@@ -301,7 +306,9 @@ mod tests {
|
||||
"gasLimit": 1000000000000,
|
||||
"inputData": "0x8c97db39"
|
||||
}
|
||||
"#).unwrap();
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(req.gas_limit.into_u256(), U256::from(0xe8d4a51000u64));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,14 +21,19 @@ use super::{
|
||||
TrieIdGenerator,
|
||||
};
|
||||
use crate::exec::StorageKey;
|
||||
use sp_std::cell::RefCell;
|
||||
use sp_std::collections::btree_map::{BTreeMap, Entry};
|
||||
use sp_std::prelude::*;
|
||||
use frame_support::{
|
||||
storage::unhashed as storage,
|
||||
traits::{Currency, Imbalance, SignedImbalance},
|
||||
StorageMap,
|
||||
};
|
||||
use frame_system;
|
||||
use sp_io::hashing::blake2_256;
|
||||
use sp_runtime::traits::{Bounded, Zero};
|
||||
use frame_support::traits::{Currency, Imbalance, SignedImbalance};
|
||||
use frame_support::{storage::unhashed as storage, StorageMap};
|
||||
use frame_system;
|
||||
use sp_std::{
|
||||
cell::RefCell,
|
||||
collections::btree_map::{BTreeMap, Entry},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
// Note: we don't provide Option<Contract> because we can't create
|
||||
// the trie_id in the overlay, thus we provide an overlay on the fields
|
||||
@@ -133,8 +138,7 @@ impl<T: Trait> AccountDb<T> for DirectAccountDb {
|
||||
trie_id: Option<&TrieId>,
|
||||
location: &StorageKey,
|
||||
) -> Option<Vec<u8>> {
|
||||
trie_id
|
||||
.and_then(|id| storage::get_raw(&crate::prefixed_key(id, &blake2_256(location))))
|
||||
trie_id.and_then(|id| storage::get_raw(&crate::prefixed_key(id, &blake2_256(location))))
|
||||
}
|
||||
fn get_code_hash(&self, account: &T::AccountId) -> Option<CodeHash<T>> {
|
||||
<ContractInfoOf<T>>::get(account).and_then(|i| i.as_alive().map(|i| i.code_hash))
|
||||
@@ -241,13 +245,13 @@ impl<T: Trait> AccountDb<T> for DirectAccountDb {
|
||||
if prev_value.is_empty() {
|
||||
new_info.empty_pair_count -= 1;
|
||||
}
|
||||
},
|
||||
}
|
||||
(None, Some(new_value)) => {
|
||||
new_info.total_pair_count += 1;
|
||||
if new_value.is_empty() {
|
||||
new_info.empty_pair_count += 1;
|
||||
}
|
||||
},
|
||||
}
|
||||
(Some(prev_value), Some(new_value)) => {
|
||||
if prev_value.is_empty() {
|
||||
new_info.empty_pair_count -= 1;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,11 +15,11 @@
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::Trait;
|
||||
use sp_std::marker::PhantomData;
|
||||
use sp_runtime::traits::Zero;
|
||||
use frame_support::dispatch::{
|
||||
DispatchError, DispatchResultWithPostInfo, PostDispatchInfo, DispatchErrorWithPostInfo,
|
||||
DispatchError, DispatchErrorWithPostInfo, DispatchResultWithPostInfo, PostDispatchInfo,
|
||||
};
|
||||
use sp_runtime::traits::Zero;
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
#[cfg(test)]
|
||||
use std::{any::Any, fmt::Debug};
|
||||
@@ -189,7 +189,8 @@ impl<T: Trait> GasMeter<T> {
|
||||
}
|
||||
|
||||
/// Turn this GasMeter into a DispatchResult that contains the actually used gas.
|
||||
pub fn into_dispatch_result<R, E>(self, result: Result<R, E>) -> DispatchResultWithPostInfo where
|
||||
pub fn into_dispatch_result<R, E>(self, result: Result<R, E>) -> DispatchResultWithPostInfo
|
||||
where
|
||||
E: Into<DispatchError>,
|
||||
{
|
||||
let post_info = PostDispatchInfo {
|
||||
@@ -199,7 +200,10 @@ impl<T: Trait> GasMeter<T> {
|
||||
|
||||
result
|
||||
.map(|_| post_info)
|
||||
.map_err(|e| DispatchErrorWithPostInfo { post_info, error: e.into() })
|
||||
.map_err(|e| DispatchErrorWithPostInfo {
|
||||
post_info,
|
||||
error: e.into(),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -256,7 +260,9 @@ mod tests {
|
||||
struct SimpleToken(u64);
|
||||
impl Token<Test> for SimpleToken {
|
||||
type Metadata = ();
|
||||
fn calculate_amount(&self, _metadata: &()) -> u64 { self.0 }
|
||||
fn calculate_amount(&self, _metadata: &()) -> u64 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
struct MultiplierTokenMetadata {
|
||||
@@ -285,8 +291,10 @@ mod tests {
|
||||
fn simple() {
|
||||
let mut gas_meter = GasMeter::<Test>::new(50000);
|
||||
|
||||
let result = gas_meter
|
||||
.charge(&MultiplierTokenMetadata { multiplier: 3 }, MultiplierToken(10));
|
||||
let result = gas_meter.charge(
|
||||
&MultiplierTokenMetadata { multiplier: 3 },
|
||||
MultiplierToken(10),
|
||||
);
|
||||
assert!(!result.is_out_of_gas());
|
||||
|
||||
assert_eq!(gas_meter.gas_left(), 49_970);
|
||||
@@ -297,7 +305,10 @@ mod tests {
|
||||
let mut gas_meter = GasMeter::<Test>::new(50000);
|
||||
assert!(!gas_meter.charge(&(), SimpleToken(1)).is_out_of_gas());
|
||||
assert!(!gas_meter
|
||||
.charge(&MultiplierTokenMetadata { multiplier: 3 }, MultiplierToken(10))
|
||||
.charge(
|
||||
&MultiplierTokenMetadata { multiplier: 3 },
|
||||
MultiplierToken(10)
|
||||
)
|
||||
.is_out_of_gas());
|
||||
|
||||
let mut tokens = gas_meter.tokens()[0..2].iter();
|
||||
@@ -327,7 +338,6 @@ mod tests {
|
||||
assert!(gas_meter.charge(&(), SimpleToken(1)).is_out_of_gas());
|
||||
}
|
||||
|
||||
|
||||
// Charging the exact amount that the user paid for should be
|
||||
// possible.
|
||||
#[test]
|
||||
|
||||
@@ -84,42 +84,42 @@ mod gas;
|
||||
|
||||
mod account_db;
|
||||
mod exec;
|
||||
mod wasm;
|
||||
mod rent;
|
||||
mod wasm;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::exec::ExecutionContext;
|
||||
use crate::account_db::{AccountDb, DirectAccountDb};
|
||||
use crate::wasm::{WasmLoader, WasmVm};
|
||||
use crate::{
|
||||
account_db::{AccountDb, DirectAccountDb},
|
||||
exec::ExecutionContext,
|
||||
wasm::{WasmLoader, WasmVm},
|
||||
};
|
||||
|
||||
pub use crate::gas::{Gas, GasMeter};
|
||||
pub use crate::exec::{ExecResult, ExecReturnValue, ExecError, StatusCode};
|
||||
pub use crate::{
|
||||
exec::{ExecError, ExecResult, ExecReturnValue, StatusCode},
|
||||
gas::{Gas, GasMeter},
|
||||
};
|
||||
|
||||
use codec::{Codec, Decode, Encode};
|
||||
use cumulus_pallet_contracts_primitives::{ContractAccessError, RentProjection};
|
||||
use frame_support::{
|
||||
decl_error, decl_event, decl_module, decl_storage,
|
||||
dispatch::{DispatchResult, DispatchResultWithPostInfo, Dispatchable, PostDispatchInfo},
|
||||
parameter_types,
|
||||
traits::{Currency, Get, OnUnbalanced, Randomness, Time},
|
||||
weights::{GetDispatchInfo, Weight},
|
||||
Parameter,
|
||||
};
|
||||
use frame_system::{ensure_root, ensure_signed, RawOrigin};
|
||||
#[cfg(feature = "std")]
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sp_core::crypto::UncheckedFrom;
|
||||
use sp_std::{prelude::*, marker::PhantomData, fmt::Debug};
|
||||
use codec::{Codec, Encode, Decode};
|
||||
use sp_runtime::{
|
||||
traits::{
|
||||
Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member, Convert,
|
||||
},
|
||||
traits::{Convert, Hash, MaybeSerializeDeserialize, Member, StaticLookup, Zero},
|
||||
RuntimeDebug,
|
||||
};
|
||||
use frame_support::dispatch::{
|
||||
PostDispatchInfo, DispatchResult, Dispatchable, DispatchResultWithPostInfo
|
||||
};
|
||||
use frame_support::{
|
||||
Parameter, decl_module, decl_event, decl_storage, decl_error,
|
||||
parameter_types,
|
||||
};
|
||||
use frame_support::traits::{OnUnbalanced, Currency, Get, Time, Randomness};
|
||||
use frame_support::weights::GetDispatchInfo;
|
||||
use frame_system::{ensure_signed, RawOrigin, ensure_root};
|
||||
use cumulus_pallet_contracts_primitives::{RentProjection, ContractAccessError};
|
||||
use frame_support::weights::Weight;
|
||||
use sp_std::{fmt::Debug, marker::PhantomData, prelude::*};
|
||||
|
||||
pub type CodeHash<T> = <T as frame_system::Trait>::Hash;
|
||||
pub type TrieId = Vec<u8>;
|
||||
@@ -240,10 +240,16 @@ pub struct RawTombstoneContractInfo<H, Hasher>(H, PhantomData<Hasher>);
|
||||
|
||||
impl<H, Hasher> RawTombstoneContractInfo<H, Hasher>
|
||||
where
|
||||
H: Member + MaybeSerializeDeserialize+ Debug
|
||||
+ AsRef<[u8]> + AsMut<[u8]> + Copy + Default
|
||||
+ sp_std::hash::Hash + Codec,
|
||||
Hasher: Hash<Output=H>,
|
||||
H: Member
|
||||
+ MaybeSerializeDeserialize
|
||||
+ Debug
|
||||
+ AsRef<[u8]>
|
||||
+ AsMut<[u8]>
|
||||
+ Copy
|
||||
+ Default
|
||||
+ sp_std::hash::Hash
|
||||
+ Codec,
|
||||
Hasher: Hash<Output = H>,
|
||||
{
|
||||
fn new(storage_root: &[u8], code_hash: H) -> Self {
|
||||
let mut buf = Vec::new();
|
||||
@@ -272,7 +278,7 @@ pub struct TrieIdFromParentCounter<T: Trait>(PhantomData<T>);
|
||||
/// accountid_counter`.
|
||||
impl<T: Trait> TrieIdGenerator<T::AccountId> for TrieIdFromParentCounter<T>
|
||||
where
|
||||
T::AccountId: AsRef<[u8]>
|
||||
T::AccountId: AsRef<[u8]>,
|
||||
{
|
||||
fn trie_id(account_id: &T::AccountId) -> TrieId {
|
||||
// Note that skipping a value due to error is not an issue here.
|
||||
@@ -321,10 +327,9 @@ pub trait Trait: frame_system::Trait {
|
||||
type Currency: Currency<Self::AccountId>;
|
||||
|
||||
/// The outer call dispatch type.
|
||||
type Call:
|
||||
Parameter +
|
||||
Dispatchable<PostInfo=PostDispatchInfo, Origin=<Self as frame_system::Trait>::Origin> +
|
||||
GetDispatchInfo;
|
||||
type Call: Parameter
|
||||
+ Dispatchable<PostInfo = PostDispatchInfo, Origin = <Self as frame_system::Trait>::Origin>
|
||||
+ GetDispatchInfo;
|
||||
|
||||
/// The overarching event type.
|
||||
type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
|
||||
@@ -390,9 +395,13 @@ pub trait Trait: frame_system::Trait {
|
||||
pub struct SimpleAddressDeterminer<T: Trait>(PhantomData<T>);
|
||||
impl<T: Trait> ContractAddressFor<CodeHash<T>, T::AccountId> for SimpleAddressDeterminer<T>
|
||||
where
|
||||
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
|
||||
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
|
||||
{
|
||||
fn contract_address_for(code_hash: &CodeHash<T>, data: &[u8], origin: &T::AccountId) -> T::AccountId {
|
||||
fn contract_address_for(
|
||||
code_hash: &CodeHash<T>,
|
||||
data: &[u8],
|
||||
origin: &T::AccountId,
|
||||
) -> T::AccountId {
|
||||
let data_hash = T::Hashing::hash(data);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
@@ -641,13 +650,15 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
impl<T: Trait> Module<T> {
|
||||
fn calc_code_put_costs(code: &Vec<u8>) -> Gas {
|
||||
<Module<T>>::current_schedule().put_code_per_byte_cost.saturating_mul(code.len() as Gas)
|
||||
<Module<T>>::current_schedule()
|
||||
.put_code_per_byte_cost
|
||||
.saturating_mul(code.len() as Gas)
|
||||
}
|
||||
|
||||
fn execute_wasm(
|
||||
origin: T::AccountId,
|
||||
gas_meter: &mut GasMeter<T>,
|
||||
func: impl FnOnce(&mut ExecutionContext<T, WasmVm, WasmLoader>, &mut GasMeter<T>) -> ExecResult
|
||||
func: impl FnOnce(&mut ExecutionContext<T, WasmVm, WasmLoader>, &mut GasMeter<T>) -> ExecResult,
|
||||
) -> ExecResult {
|
||||
let cfg = Config::preload();
|
||||
let vm = WasmVm::new(&cfg.schedule);
|
||||
@@ -656,7 +667,11 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
let result = func(&mut ctx, gas_meter);
|
||||
|
||||
if result.as_ref().map(|output| output.is_success()).unwrap_or(false) {
|
||||
if result
|
||||
.as_ref()
|
||||
.map(|output| output.is_success())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
// Commit all changes that made it thus far into the persistent storage.
|
||||
DirectAccountDb.commit(ctx.overlay.into_change_set());
|
||||
}
|
||||
@@ -665,17 +680,11 @@ impl<T: Trait> Module<T> {
|
||||
ctx.deferred.into_iter().for_each(|deferred| {
|
||||
use self::exec::DeferredAction::*;
|
||||
match deferred {
|
||||
DepositEvent {
|
||||
topics,
|
||||
event,
|
||||
} => <frame_system::Module<T>>::deposit_event_indexed(
|
||||
DepositEvent { topics, event } => <frame_system::Module<T>>::deposit_event_indexed(
|
||||
&*topics,
|
||||
<T as Trait>::Event::from(event).into(),
|
||||
),
|
||||
DispatchRuntimeCall {
|
||||
origin: who,
|
||||
call,
|
||||
} => {
|
||||
DispatchRuntimeCall { origin: who, call } => {
|
||||
let info = call.get_dispatch_info();
|
||||
let result = call.dispatch(RawOrigin::Signed(who.clone()).into());
|
||||
let post_info = match result {
|
||||
@@ -693,11 +702,19 @@ impl<T: Trait> Module<T> {
|
||||
delta,
|
||||
} => {
|
||||
let result = Self::restore_to(
|
||||
donor.clone(), dest.clone(), code_hash.clone(), rent_allowance.clone(), delta
|
||||
);
|
||||
Self::deposit_event(
|
||||
RawEvent::Restored(donor, dest, code_hash, rent_allowance, result.is_ok())
|
||||
donor.clone(),
|
||||
dest.clone(),
|
||||
code_hash.clone(),
|
||||
rent_allowance.clone(),
|
||||
delta,
|
||||
);
|
||||
Self::deposit_event(RawEvent::Restored(
|
||||
donor,
|
||||
dest,
|
||||
code_hash,
|
||||
rent_allowance,
|
||||
result.is_ok(),
|
||||
));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -20,10 +20,14 @@ use crate::{
|
||||
AliveContractInfo, BalanceOf, ContractInfo, ContractInfoOf, Module, RawEvent,
|
||||
TombstoneContractInfo, Trait,
|
||||
};
|
||||
use frame_support::storage::unhashed as storage;
|
||||
use frame_support::traits::{Currency, ExistenceRequirement, Get, OnUnbalanced, WithdrawReason};
|
||||
use frame_support::StorageMap;
|
||||
use cumulus_pallet_contracts_primitives::{ContractAccessError, RentProjection, RentProjectionResult};
|
||||
use cumulus_pallet_contracts_primitives::{
|
||||
ContractAccessError, RentProjection, RentProjectionResult,
|
||||
};
|
||||
use frame_support::{
|
||||
storage::unhashed as storage,
|
||||
traits::{Currency, ExistenceRequirement, Get, OnUnbalanced, WithdrawReason},
|
||||
StorageMap,
|
||||
};
|
||||
use sp_runtime::traits::{Bounded, CheckedDiv, CheckedMul, SaturatedConversion, Saturating, Zero};
|
||||
|
||||
/// The amount to charge.
|
||||
@@ -238,10 +242,8 @@ fn enact_verdict<T: Trait>(
|
||||
|
||||
// Use a dummy storage root because restoration is currentlyy unsupported
|
||||
// for parachains anyways.
|
||||
let tombstone = <TombstoneContractInfo<T>>::new(
|
||||
&[0u8; 32],
|
||||
alive_contract_info.code_hash,
|
||||
);
|
||||
let tombstone =
|
||||
<TombstoneContractInfo<T>>::new(&[0u8; 32], alive_contract_info.code_hash);
|
||||
let tombstone_info = ContractInfo::Tombstone(tombstone);
|
||||
<ContractInfoOf<T>>::insert(account, &tombstone_info);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,11 +26,13 @@
|
||||
//! this guarantees that every instrumented contract code in cache cannot have the version equal to the current one.
|
||||
//! Thus, before executing a contract it should be reinstrument with new schedule.
|
||||
|
||||
use crate::wasm::{prepare, runtime::Env, PrefabWasmModule};
|
||||
use crate::{CodeHash, CodeStorage, PristineCode, Schedule, Trait};
|
||||
use sp_std::prelude::*;
|
||||
use sp_runtime::traits::Hash;
|
||||
use crate::{
|
||||
wasm::{prepare, runtime::Env, PrefabWasmModule},
|
||||
CodeHash, CodeStorage, PristineCode, Schedule, Trait,
|
||||
};
|
||||
use frame_support::StorageMap;
|
||||
use sp_runtime::traits::Hash;
|
||||
use sp_std::prelude::*;
|
||||
|
||||
/// Put code in the storage. The hash of code is used as a key and is returned
|
||||
/// as a result of this function.
|
||||
@@ -58,8 +60,7 @@ pub fn load<T: Trait>(
|
||||
code_hash: &CodeHash<T>,
|
||||
schedule: &Schedule,
|
||||
) -> Result<PrefabWasmModule, &'static str> {
|
||||
let mut prefab_module =
|
||||
<CodeStorage<T>>::get(code_hash).ok_or_else(|| "code is not found")?;
|
||||
let mut prefab_module = <CodeStorage<T>>::get(code_hash).ok_or_else(|| "code is not found")?;
|
||||
|
||||
if prefab_module.schedule_version < schedule.version {
|
||||
// The current schedule version is greater than the version of the one cached
|
||||
|
||||
@@ -193,14 +193,14 @@ macro_rules! define_env {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use parity_wasm::elements::FunctionType;
|
||||
use parity_wasm::elements::ValueType;
|
||||
use crate::{
|
||||
exec::Ext,
|
||||
gas::Gas,
|
||||
wasm::{tests::MockExt, Runtime},
|
||||
};
|
||||
use parity_wasm::elements::{FunctionType, ValueType};
|
||||
use sp_runtime::traits::Zero;
|
||||
use sp_sandbox::{ReturnValue, Value};
|
||||
use crate::wasm::tests::MockExt;
|
||||
use crate::wasm::Runtime;
|
||||
use crate::exec::Ext;
|
||||
use crate::gas::Gas;
|
||||
|
||||
#[test]
|
||||
fn macro_unmarshall_then_body_then_marshall_value_or_trap() {
|
||||
@@ -263,8 +263,10 @@ mod tests {
|
||||
Err(sp_sandbox::HostError)
|
||||
}
|
||||
});
|
||||
let _f: fn(&mut Runtime<MockExt>, &[sp_sandbox::Value])
|
||||
-> Result<sp_sandbox::ReturnValue, sp_sandbox::HostError> = ext_gas::<MockExt>;
|
||||
let _f: fn(
|
||||
&mut Runtime<MockExt>,
|
||||
&[sp_sandbox::Value],
|
||||
) -> Result<sp_sandbox::ReturnValue, sp_sandbox::HostError> = ext_gas::<MockExt>;
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -317,7 +319,13 @@ mod tests {
|
||||
},
|
||||
);
|
||||
|
||||
assert!(Env::can_satisfy(b"ext_gas", &FunctionType::new(vec![ValueType::I32], None)));
|
||||
assert!(!Env::can_satisfy(b"not_exists", &FunctionType::new(vec![], None)));
|
||||
assert!(Env::can_satisfy(
|
||||
b"ext_gas",
|
||||
&FunctionType::new(vec![ValueType::I32], None)
|
||||
));
|
||||
assert!(!Env::can_satisfy(
|
||||
b"not_exists",
|
||||
&FunctionType::new(vec![], None)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
use super::Runtime;
|
||||
use crate::exec::Ext;
|
||||
|
||||
use sp_sandbox::Value;
|
||||
use parity_wasm::elements::{FunctionType, ValueType};
|
||||
use sp_sandbox::Value;
|
||||
|
||||
#[macro_use]
|
||||
pub(crate) mod macros;
|
||||
@@ -66,11 +66,10 @@ impl ConvertibleToWasm for u64 {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type HostFunc<E> =
|
||||
fn(
|
||||
&mut Runtime<E>,
|
||||
&[sp_sandbox::Value]
|
||||
) -> Result<sp_sandbox::ReturnValue, sp_sandbox::HostError>;
|
||||
pub(crate) type HostFunc<E> = fn(
|
||||
&mut Runtime<E>,
|
||||
&[sp_sandbox::Value],
|
||||
) -> Result<sp_sandbox::ReturnValue, sp_sandbox::HostError>;
|
||||
|
||||
pub(crate) trait FunctionImplProvider<E: Ext> {
|
||||
fn impls<F: FnMut(&[u8], HostFunc<E>)>(f: &mut F);
|
||||
|
||||
@@ -17,14 +17,16 @@
|
||||
//! This module provides a means for executing contracts
|
||||
//! represented in wasm.
|
||||
|
||||
use crate::{CodeHash, Schedule, Trait};
|
||||
use crate::wasm::env_def::FunctionImplProvider;
|
||||
use crate::exec::{Ext, ExecResult};
|
||||
use crate::gas::GasMeter;
|
||||
use crate::{
|
||||
exec::{ExecResult, Ext},
|
||||
gas::GasMeter,
|
||||
wasm::env_def::FunctionImplProvider,
|
||||
CodeHash, Schedule, Trait,
|
||||
};
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use codec::{Encode, Decode};
|
||||
use codec::{Decode, Encode};
|
||||
use sp_sandbox;
|
||||
use sp_std::prelude::*;
|
||||
|
||||
#[macro_use]
|
||||
mod env_def;
|
||||
@@ -32,8 +34,10 @@ mod code_cache;
|
||||
mod prepare;
|
||||
mod runtime;
|
||||
|
||||
use self::runtime::{to_execution_result, Runtime};
|
||||
use self::code_cache::load as load_code;
|
||||
use self::{
|
||||
code_cache::load as load_code,
|
||||
runtime::{to_execution_result, Runtime},
|
||||
};
|
||||
|
||||
pub use self::code_cache::save as save_code;
|
||||
|
||||
@@ -116,8 +120,8 @@ impl<'a, T: Trait> crate::exec::Vm<T> for WasmVm<'a> {
|
||||
let memory =
|
||||
sp_sandbox::Memory::new(exec.prefab_module.initial, Some(exec.prefab_module.maximum))
|
||||
.unwrap_or_else(|_| {
|
||||
// unlike `.expect`, explicit panic preserves the source location.
|
||||
// Needed as we can't use `RUST_BACKTRACE` in here.
|
||||
// unlike `.expect`, explicit panic preserves the source location.
|
||||
// Needed as we can't use `RUST_BACKTRACE` in here.
|
||||
panic!(
|
||||
"exec.prefab_module.initial can't be greater than exec.prefab_module.maximum;
|
||||
thus Memory::new must not fail;
|
||||
@@ -131,13 +135,7 @@ impl<'a, T: Trait> crate::exec::Vm<T> for WasmVm<'a> {
|
||||
imports.add_host_func("env", name, func_ptr);
|
||||
});
|
||||
|
||||
let mut runtime = Runtime::new(
|
||||
&mut ext,
|
||||
input_data,
|
||||
&self.schedule,
|
||||
memory,
|
||||
gas_meter,
|
||||
);
|
||||
let mut runtime = Runtime::new(&mut ext, input_data, &self.schedule, memory, gas_meter);
|
||||
|
||||
// Instantiate the instance from the instrumented module code and invoke the contract
|
||||
// entrypoint.
|
||||
@@ -150,19 +148,20 @@ impl<'a, T: Trait> crate::exec::Vm<T> for WasmVm<'a> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::collections::HashMap;
|
||||
use std::cell::RefCell;
|
||||
use sp_core::H256;
|
||||
use crate::exec::{Ext, StorageKey, ExecError, ExecReturnValue, STATUS_SUCCESS};
|
||||
use crate::gas::{Gas, GasMeter};
|
||||
use crate::tests::{Test, Call};
|
||||
use crate::wasm::prepare::prepare_contract;
|
||||
use crate::{CodeHash, BalanceOf};
|
||||
use wabt;
|
||||
use hex_literal::hex;
|
||||
use crate::{
|
||||
exec::{ExecError, ExecReturnValue, Ext, StorageKey, STATUS_SUCCESS},
|
||||
gas::{Gas, GasMeter},
|
||||
tests::{Call, Test},
|
||||
wasm::prepare::prepare_contract,
|
||||
BalanceOf, CodeHash,
|
||||
};
|
||||
use assert_matches::assert_matches;
|
||||
use sp_runtime::DispatchError;
|
||||
use frame_support::weights::Weight;
|
||||
use hex_literal::hex;
|
||||
use sp_core::H256;
|
||||
use sp_runtime::DispatchError;
|
||||
use std::{cell::RefCell, collections::HashMap};
|
||||
use wabt;
|
||||
|
||||
const GAS_LIMIT: Gas = 10_000_000_000;
|
||||
|
||||
@@ -230,9 +229,11 @@ mod tests {
|
||||
fn get_storage(&self, key: &StorageKey) -> Option<Vec<u8>> {
|
||||
self.storage.get(key).cloned()
|
||||
}
|
||||
fn set_storage(&mut self, key: StorageKey, value: Option<Vec<u8>>)
|
||||
-> Result<(), &'static str>
|
||||
{
|
||||
fn set_storage(
|
||||
&mut self,
|
||||
key: StorageKey,
|
||||
value: Option<Vec<u8>>,
|
||||
) -> Result<(), &'static str> {
|
||||
*self.storage.entry(key).or_insert(Vec::new()) = value.unwrap_or(Vec::new());
|
||||
Ok(())
|
||||
}
|
||||
@@ -289,7 +290,10 @@ mod tests {
|
||||
});
|
||||
// Assume for now that it was just a plain transfer.
|
||||
// TODO: Add tests for different call outcomes.
|
||||
Ok(ExecReturnValue { status: STATUS_SUCCESS, data: Vec::new() })
|
||||
Ok(ExecReturnValue {
|
||||
status: STATUS_SUCCESS,
|
||||
data: Vec::new(),
|
||||
})
|
||||
}
|
||||
fn terminate(
|
||||
&mut self,
|
||||
@@ -360,21 +364,22 @@ mod tests {
|
||||
self.rent_allowance
|
||||
}
|
||||
|
||||
fn block_number(&self) -> u64 { 121 }
|
||||
fn block_number(&self) -> u64 {
|
||||
121
|
||||
}
|
||||
|
||||
fn max_value_size(&self) -> u32 { 16_384 }
|
||||
fn max_value_size(&self) -> u32 {
|
||||
16_384
|
||||
}
|
||||
|
||||
fn get_runtime_storage(&self, key: &[u8]) -> Option<Vec<u8>> {
|
||||
let opt_value = self.runtime_storage_keys
|
||||
.borrow_mut()
|
||||
.remove(key);
|
||||
opt_value.unwrap_or_else(||
|
||||
let opt_value = self.runtime_storage_keys.borrow_mut().remove(key);
|
||||
opt_value.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"{:?} doesn't exist. values that do exist {:?}",
|
||||
key,
|
||||
self.runtime_storage_keys
|
||||
key, self.runtime_storage_keys
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
fn get_weight_price(&self, weight: Weight) -> BalanceOf<Self::T> {
|
||||
BalanceOf::<Self::T>::from(1312_u32).saturating_mul(weight.into())
|
||||
@@ -387,9 +392,11 @@ mod tests {
|
||||
fn get_storage(&self, key: &[u8; 32]) -> Option<Vec<u8>> {
|
||||
(**self).get_storage(key)
|
||||
}
|
||||
fn set_storage(&mut self, key: [u8; 32], value: Option<Vec<u8>>)
|
||||
-> Result<(), &'static str>
|
||||
{
|
||||
fn set_storage(
|
||||
&mut self,
|
||||
key: [u8; 32],
|
||||
value: Option<Vec<u8>>,
|
||||
) -> Result<(), &'static str> {
|
||||
(**self).set_storage(key, value)
|
||||
}
|
||||
fn instantiate(
|
||||
@@ -435,12 +442,7 @@ mod tests {
|
||||
rent_allowance: u64,
|
||||
delta: Vec<StorageKey>,
|
||||
) {
|
||||
(**self).note_restore_to(
|
||||
dest,
|
||||
code_hash,
|
||||
rent_allowance,
|
||||
delta,
|
||||
)
|
||||
(**self).note_restore_to(dest, code_hash, rent_allowance, delta)
|
||||
}
|
||||
fn caller(&self) -> &u64 {
|
||||
(**self).caller()
|
||||
@@ -499,8 +501,7 @@ mod tests {
|
||||
|
||||
let wasm = wabt::wat2wasm(wat).unwrap();
|
||||
let schedule = crate::Schedule::default();
|
||||
let prefab_module =
|
||||
prepare_contract::<super::runtime::Env>(&wasm, &schedule).unwrap();
|
||||
let prefab_module = prepare_contract::<super::runtime::Env>(&wasm, &schedule).unwrap();
|
||||
|
||||
let exec = WasmExecutable {
|
||||
// Use a "call" convention.
|
||||
@@ -554,7 +555,8 @@ mod tests {
|
||||
vec![],
|
||||
&mut mock_ext,
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&mock_ext.transfers,
|
||||
@@ -614,7 +616,8 @@ mod tests {
|
||||
vec![],
|
||||
&mut mock_ext,
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&mock_ext.transfers,
|
||||
@@ -676,7 +679,8 @@ mod tests {
|
||||
vec![],
|
||||
&mut mock_ext,
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&mock_ext.instantiates,
|
||||
@@ -719,7 +723,8 @@ mod tests {
|
||||
vec![],
|
||||
&mut mock_ext,
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&mock_ext.terminations,
|
||||
@@ -777,7 +782,8 @@ mod tests {
|
||||
vec![],
|
||||
&mut mock_ext,
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&mock_ext.transfers,
|
||||
@@ -861,18 +867,23 @@ mod tests {
|
||||
#[test]
|
||||
fn get_storage_puts_data_into_scratch_buf() {
|
||||
let mut mock_ext = MockExt::default();
|
||||
mock_ext
|
||||
.storage
|
||||
.insert([0x11; 32], [0x22; 32].to_vec());
|
||||
mock_ext.storage.insert([0x11; 32], [0x22; 32].to_vec());
|
||||
|
||||
let output = execute(
|
||||
CODE_GET_STORAGE,
|
||||
vec![],
|
||||
mock_ext,
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(output, ExecReturnValue { status: STATUS_SUCCESS, data: [0x22; 32].to_vec() });
|
||||
assert_eq!(
|
||||
output,
|
||||
ExecReturnValue {
|
||||
status: STATUS_SUCCESS,
|
||||
data: [0x22; 32].to_vec()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// calls `ext_caller`, loads the address from the scratch buffer and
|
||||
@@ -934,7 +945,8 @@ mod tests {
|
||||
vec![],
|
||||
MockExt::default(),
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// calls `ext_address`, loads the address from the scratch buffer and
|
||||
@@ -996,7 +1008,8 @@ mod tests {
|
||||
vec![],
|
||||
MockExt::default(),
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
const CODE_BALANCE: &str = r#"
|
||||
@@ -1051,12 +1064,7 @@ mod tests {
|
||||
#[test]
|
||||
fn balance() {
|
||||
let mut gas_meter = GasMeter::new(GAS_LIMIT);
|
||||
let _ = execute(
|
||||
CODE_BALANCE,
|
||||
vec![],
|
||||
MockExt::default(),
|
||||
&mut gas_meter,
|
||||
).unwrap();
|
||||
let _ = execute(CODE_BALANCE, vec![], MockExt::default(), &mut gas_meter).unwrap();
|
||||
}
|
||||
|
||||
const CODE_GAS_PRICE: &str = r#"
|
||||
@@ -1111,12 +1119,7 @@ mod tests {
|
||||
#[test]
|
||||
fn gas_price() {
|
||||
let mut gas_meter = GasMeter::new(GAS_LIMIT);
|
||||
let _ = execute(
|
||||
CODE_GAS_PRICE,
|
||||
vec![],
|
||||
MockExt::default(),
|
||||
&mut gas_meter,
|
||||
).unwrap();
|
||||
let _ = execute(CODE_GAS_PRICE, vec![], MockExt::default(), &mut gas_meter).unwrap();
|
||||
}
|
||||
|
||||
const CODE_GAS_LEFT: &str = r#"
|
||||
@@ -1170,16 +1173,14 @@ mod tests {
|
||||
fn gas_left() {
|
||||
let mut gas_meter = GasMeter::new(GAS_LIMIT);
|
||||
|
||||
let output = execute(
|
||||
CODE_GAS_LEFT,
|
||||
vec![],
|
||||
MockExt::default(),
|
||||
&mut gas_meter,
|
||||
).unwrap();
|
||||
let output = execute(CODE_GAS_LEFT, vec![], MockExt::default(), &mut gas_meter).unwrap();
|
||||
|
||||
let gas_left = Gas::decode(&mut output.data.as_slice()).unwrap();
|
||||
assert!(gas_left < GAS_LIMIT, "gas_left must be less than initial");
|
||||
assert!(gas_left > gas_meter.gas_left(), "gas_left must be greater than final");
|
||||
assert!(
|
||||
gas_left > gas_meter.gas_left(),
|
||||
"gas_left must be greater than final"
|
||||
);
|
||||
}
|
||||
|
||||
const CODE_VALUE_TRANSFERRED: &str = r#"
|
||||
@@ -1239,7 +1240,8 @@ mod tests {
|
||||
vec![],
|
||||
MockExt::default(),
|
||||
&mut gas_meter,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
const CODE_DISPATCH_CALL: &str = r#"
|
||||
@@ -1270,13 +1272,14 @@ mod tests {
|
||||
vec![],
|
||||
&mut mock_ext,
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&mock_ext.dispatches,
|
||||
&[DispatchEntry(
|
||||
Call::Balances(pallet_balances::Call::set_balance(42, 1337, 0)),
|
||||
)]
|
||||
&[DispatchEntry(Call::Balances(
|
||||
pallet_balances::Call::set_balance(42, 1337, 0)
|
||||
),)]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1310,9 +1313,16 @@ mod tests {
|
||||
vec![],
|
||||
MockExt::default(),
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(output, ExecReturnValue { status: STATUS_SUCCESS, data: vec![1, 2, 3, 4] });
|
||||
assert_eq!(
|
||||
output,
|
||||
ExecReturnValue {
|
||||
status: STATUS_SUCCESS,
|
||||
data: vec![1, 2, 3, 4]
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const CODE_TIMESTAMP_NOW: &str = r#"
|
||||
@@ -1372,7 +1382,8 @@ mod tests {
|
||||
vec![],
|
||||
MockExt::default(),
|
||||
&mut gas_meter,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
const CODE_MINIMUM_BALANCE: &str = r#"
|
||||
@@ -1431,7 +1442,8 @@ mod tests {
|
||||
vec![],
|
||||
MockExt::default(),
|
||||
&mut gas_meter,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
const CODE_TOMBSTONE_DEPOSIT: &str = r#"
|
||||
@@ -1490,7 +1502,8 @@ mod tests {
|
||||
vec![],
|
||||
MockExt::default(),
|
||||
&mut gas_meter,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
const CODE_RANDOM: &str = r#"
|
||||
@@ -1554,19 +1567,15 @@ mod tests {
|
||||
fn random() {
|
||||
let mut gas_meter = GasMeter::new(GAS_LIMIT);
|
||||
|
||||
let output = execute(
|
||||
CODE_RANDOM,
|
||||
vec![],
|
||||
MockExt::default(),
|
||||
&mut gas_meter,
|
||||
).unwrap();
|
||||
let output = execute(CODE_RANDOM, vec![], MockExt::default(), &mut gas_meter).unwrap();
|
||||
|
||||
// The mock ext just returns the same data that was passed as the subject.
|
||||
assert_eq!(
|
||||
output,
|
||||
ExecReturnValue {
|
||||
status: STATUS_SUCCESS,
|
||||
data: hex!("000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F").to_vec(),
|
||||
data: hex!("000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F")
|
||||
.to_vec(),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -1598,17 +1607,15 @@ mod tests {
|
||||
fn deposit_event() {
|
||||
let mut mock_ext = MockExt::default();
|
||||
let mut gas_meter = GasMeter::new(GAS_LIMIT);
|
||||
let _ = execute(
|
||||
CODE_DEPOSIT_EVENT,
|
||||
vec![],
|
||||
&mut mock_ext,
|
||||
&mut gas_meter
|
||||
).unwrap();
|
||||
let _ = execute(CODE_DEPOSIT_EVENT, vec![], &mut mock_ext, &mut gas_meter).unwrap();
|
||||
|
||||
assert_eq!(mock_ext.events, vec![
|
||||
(vec![H256::repeat_byte(0x33)],
|
||||
vec![0x00, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00])
|
||||
]);
|
||||
assert_eq!(
|
||||
mock_ext.events,
|
||||
vec![(
|
||||
vec![H256::repeat_byte(0x33)],
|
||||
vec![0x00, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00]
|
||||
)]
|
||||
);
|
||||
|
||||
assert_eq!(gas_meter.gas_left(), 9967000000);
|
||||
}
|
||||
@@ -1653,7 +1660,8 @@ mod tests {
|
||||
&mut gas_meter
|
||||
),
|
||||
Err(ExecError {
|
||||
reason: DispatchError::Other("contract trapped during execution"), buffer: _
|
||||
reason: DispatchError::Other("contract trapped during execution"),
|
||||
buffer: _,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -1696,7 +1704,10 @@ mod tests {
|
||||
MockExt::default(),
|
||||
&mut gas_meter
|
||||
),
|
||||
Err(ExecError { reason: DispatchError::Other("contract trapped during execution"), buffer: _ })
|
||||
Err(ExecError {
|
||||
reason: DispatchError::Other("contract trapped during execution"),
|
||||
buffer: _,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1759,7 +1770,8 @@ mod tests {
|
||||
vec![],
|
||||
MockExt::default(),
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// asserts that the size of the input data is 4.
|
||||
@@ -1799,7 +1811,8 @@ mod tests {
|
||||
input_data,
|
||||
MockExt::default(),
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(output.data.len(), 0);
|
||||
assert_eq!(output.data.capacity(), 1_234);
|
||||
@@ -1815,7 +1828,9 @@ mod tests {
|
||||
input_data,
|
||||
MockExt::default(),
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).err().unwrap();
|
||||
)
|
||||
.err()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(error.buffer.capacity(), 1_234);
|
||||
}
|
||||
@@ -1869,9 +1884,16 @@ mod tests {
|
||||
hex!("00112233445566778899").to_vec(),
|
||||
MockExt::default(),
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(output, ExecReturnValue { status: 0, data: hex!("445566778899").to_vec() });
|
||||
assert_eq!(
|
||||
output,
|
||||
ExecReturnValue {
|
||||
status: 0,
|
||||
data: hex!("445566778899").to_vec()
|
||||
}
|
||||
);
|
||||
assert!(output.is_success());
|
||||
}
|
||||
|
||||
@@ -1882,9 +1904,16 @@ mod tests {
|
||||
hex!("112233445566778899").to_vec(),
|
||||
MockExt::default(),
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(output, ExecReturnValue { status: 17, data: hex!("5566778899").to_vec() });
|
||||
assert_eq!(
|
||||
output,
|
||||
ExecReturnValue {
|
||||
status: 17,
|
||||
data: hex!("5566778899").to_vec()
|
||||
}
|
||||
);
|
||||
assert!(!output.is_success());
|
||||
}
|
||||
|
||||
@@ -1973,17 +2002,15 @@ mod tests {
|
||||
// "\01\02\03\04" - Some(0x14144020)
|
||||
// "\02\03\04\05" - None
|
||||
*mock_ext.runtime_storage_keys.borrow_mut() = [
|
||||
([1, 2, 3, 4].to_vec(), Some(0x14144020u32.to_le_bytes().to_vec())),
|
||||
(
|
||||
[1, 2, 3, 4].to_vec(),
|
||||
Some(0x14144020u32.to_le_bytes().to_vec()),
|
||||
),
|
||||
([2, 3, 4, 5].to_vec().to_vec(), None),
|
||||
]
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect();
|
||||
let _ = execute(
|
||||
CODE_GET_RUNTIME_STORAGE,
|
||||
vec![],
|
||||
mock_ext,
|
||||
&mut gas_meter,
|
||||
).unwrap();
|
||||
let _ = execute(CODE_GET_RUNTIME_STORAGE, vec![], mock_ext, &mut gas_meter).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,15 +18,15 @@
|
||||
//! wasm module before execution. It also extracts some essential information
|
||||
//! from a module.
|
||||
|
||||
use crate::wasm::env_def::ImportSatisfyCheck;
|
||||
use crate::wasm::PrefabWasmModule;
|
||||
use crate::Schedule;
|
||||
use crate::{
|
||||
wasm::{env_def::ImportSatisfyCheck, PrefabWasmModule},
|
||||
Schedule,
|
||||
};
|
||||
|
||||
use parity_wasm::elements::{self, Internal, External, MemoryType, Type, ValueType};
|
||||
use pwasm_utils;
|
||||
use pwasm_utils::rules;
|
||||
use parity_wasm::elements::{self, External, Internal, MemoryType, Type, ValueType};
|
||||
use pwasm_utils::{self, rules};
|
||||
use sp_runtime::traits::SaturatedConversion;
|
||||
use sp_std::prelude::*;
|
||||
use sp_runtime::traits::{SaturatedConversion};
|
||||
|
||||
struct ContractModule<'a> {
|
||||
/// A deserialized module. The module is valid (this is Guaranteed by `new` method).
|
||||
@@ -39,10 +39,7 @@ impl<'a> ContractModule<'a> {
|
||||
///
|
||||
/// Returns `Err` if the `original_code` couldn't be decoded or
|
||||
/// if it contains an invalid module.
|
||||
fn new(
|
||||
original_code: &[u8],
|
||||
schedule: &'a Schedule,
|
||||
) -> Result<Self, &'static str> {
|
||||
fn new(original_code: &[u8], schedule: &'a Schedule) -> Result<Self, &'static str> {
|
||||
use wasmi_validation::{validate_module, PlainValidator};
|
||||
|
||||
let module =
|
||||
@@ -53,10 +50,7 @@ impl<'a> ContractModule<'a> {
|
||||
|
||||
// Return a `ContractModule` instance with
|
||||
// __valid__ module.
|
||||
Ok(ContractModule {
|
||||
module,
|
||||
schedule,
|
||||
})
|
||||
Ok(ContractModule { module, schedule })
|
||||
}
|
||||
|
||||
/// Ensures that module doesn't declare internal memories.
|
||||
@@ -65,7 +59,8 @@ impl<'a> ContractModule<'a> {
|
||||
/// Memory section contains declarations of internal linear memories, so if we find one
|
||||
/// we reject such a module.
|
||||
fn ensure_no_internal_memory(&self) -> Result<(), &'static str> {
|
||||
if self.module
|
||||
if self
|
||||
.module
|
||||
.memory_section()
|
||||
.map_or(false, |ms| ms.entries().len() > 0)
|
||||
{
|
||||
@@ -86,7 +81,7 @@ impl<'a> ContractModule<'a> {
|
||||
// Check the table's initial size as there is no instruction or environment function
|
||||
// capable of growing the table.
|
||||
if table_type.limits().initial() > limit {
|
||||
return Err("table exceeds maximum size allowed")
|
||||
return Err("table exceeds maximum size allowed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,8 +93,9 @@ impl<'a> ContractModule<'a> {
|
||||
if let Some(global_section) = self.module.global_section() {
|
||||
for global in global_section.entries() {
|
||||
match global.global_type().content_type() {
|
||||
ValueType::F32 | ValueType::F64 =>
|
||||
return Err("use of floating point type in globals is forbidden"),
|
||||
ValueType::F32 | ValueType::F64 => {
|
||||
return Err("use of floating point type in globals is forbidden")
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -109,8 +105,9 @@ impl<'a> ContractModule<'a> {
|
||||
for func_body in code_section.bodies() {
|
||||
for local in func_body.locals() {
|
||||
match local.value_type() {
|
||||
ValueType::F32 | ValueType::F64 =>
|
||||
return Err("use of floating point type in locals is forbidden"),
|
||||
ValueType::F32 | ValueType::F64 => {
|
||||
return Err("use of floating point type in locals is forbidden")
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -124,8 +121,11 @@ impl<'a> ContractModule<'a> {
|
||||
let return_type = func_type.return_type();
|
||||
for value_type in func_type.params().iter().chain(return_type.iter()) {
|
||||
match value_type {
|
||||
ValueType::F32 | ValueType::F64 =>
|
||||
return Err("use of floating point type in function types is forbidden"),
|
||||
ValueType::F32 | ValueType::F64 => {
|
||||
return Err(
|
||||
"use of floating point type in function types is forbidden",
|
||||
)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -138,13 +138,12 @@ impl<'a> ContractModule<'a> {
|
||||
}
|
||||
|
||||
fn inject_gas_metering(self) -> Result<Self, &'static str> {
|
||||
let gas_rules =
|
||||
rules::Set::new(
|
||||
self.schedule.regular_op_cost.clone().saturated_into(),
|
||||
Default::default(),
|
||||
)
|
||||
.with_grow_cost(self.schedule.grow_mem_cost.clone().saturated_into())
|
||||
.with_forbidden_floats();
|
||||
let gas_rules = rules::Set::new(
|
||||
self.schedule.regular_op_cost.clone().saturated_into(),
|
||||
Default::default(),
|
||||
)
|
||||
.with_grow_cost(self.schedule.grow_mem_cost.clone().saturated_into())
|
||||
.with_forbidden_floats();
|
||||
|
||||
let contract_module = pwasm_utils::inject_gas_counter(self.module, &gas_rules)
|
||||
.map_err(|_| "gas instrumentation failed")?;
|
||||
@@ -195,11 +194,9 @@ impl<'a> ContractModule<'a> {
|
||||
.map(|is| is.entries())
|
||||
.unwrap_or(&[])
|
||||
.iter()
|
||||
.filter(|entry| {
|
||||
match *entry.external() {
|
||||
External::Function(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
.filter(|entry| match *entry.external() {
|
||||
External::Function(_) => true,
|
||||
_ => false,
|
||||
})
|
||||
.count();
|
||||
|
||||
@@ -232,15 +229,17 @@ impl<'a> ContractModule<'a> {
|
||||
// The [] -> [] signature predates the [] -> [i32] signature and is supported for
|
||||
// backwards compatibility. This will likely be removed once ink! is updated to
|
||||
// generate modules with the new function signatures.
|
||||
let func_ty_idx = func_entries.get(fn_idx as usize)
|
||||
let func_ty_idx = func_entries
|
||||
.get(fn_idx as usize)
|
||||
.ok_or_else(|| "export refers to non-existent function")?
|
||||
.type_ref();
|
||||
let Type::Function(ref func_ty) = types
|
||||
.get(func_ty_idx as usize)
|
||||
.ok_or_else(|| "function has a non-existent type")?;
|
||||
if !func_ty.params().is_empty() ||
|
||||
!(func_ty.return_type().is_none() ||
|
||||
func_ty.return_type() == Some(ValueType::I32)) {
|
||||
if !func_ty.params().is_empty()
|
||||
|| !(func_ty.return_type().is_none()
|
||||
|| func_ty.return_type() == Some(ValueType::I32))
|
||||
{
|
||||
return Err("entry point has wrong signature");
|
||||
}
|
||||
}
|
||||
@@ -286,10 +285,10 @@ impl<'a> ContractModule<'a> {
|
||||
&External::Function(ref type_idx) => type_idx,
|
||||
&External::Memory(ref memory_type) => {
|
||||
if import.field() != "memory" {
|
||||
return Err("Memory import must have the field name 'memory'")
|
||||
return Err("Memory import must have the field name 'memory'");
|
||||
}
|
||||
if imported_mem_type.is_some() {
|
||||
return Err("Multiple memory imports defined")
|
||||
return Err("Multiple memory imports defined");
|
||||
}
|
||||
imported_mem_type = Some(memory_type);
|
||||
continue;
|
||||
@@ -317,8 +316,7 @@ impl<'a> ContractModule<'a> {
|
||||
}
|
||||
|
||||
fn into_wasm_code(self) -> Result<Vec<u8>, &'static str> {
|
||||
elements::serialize(self.module)
|
||||
.map_err(|_| "error serializing instrumented module")
|
||||
elements::serialize(self.module).map_err(|_| "error serializing instrumented module")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,9 +392,9 @@ pub fn prepare_contract<C: ImportSatisfyCheck>(
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::exec::Ext;
|
||||
use assert_matches::assert_matches;
|
||||
use std::fmt;
|
||||
use wabt;
|
||||
use assert_matches::assert_matches;
|
||||
|
||||
impl fmt::Debug for PrefabWasmModule {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
@@ -429,7 +427,8 @@ mod tests {
|
||||
};
|
||||
}
|
||||
|
||||
prepare_test!(no_floats,
|
||||
prepare_test!(
|
||||
no_floats,
|
||||
r#"
|
||||
(module
|
||||
(func (export "call")
|
||||
@@ -454,7 +453,8 @@ mod tests {
|
||||
assert_eq!(Schedule::default().max_memory_pages, 16);
|
||||
}
|
||||
|
||||
prepare_test!(memory_with_one_page,
|
||||
prepare_test!(
|
||||
memory_with_one_page,
|
||||
r#"
|
||||
(module
|
||||
(import "env" "memory" (memory 1 1))
|
||||
@@ -466,7 +466,8 @@ mod tests {
|
||||
Ok(_)
|
||||
);
|
||||
|
||||
prepare_test!(internal_memory_declaration,
|
||||
prepare_test!(
|
||||
internal_memory_declaration,
|
||||
r#"
|
||||
(module
|
||||
(memory 1 1)
|
||||
@@ -478,7 +479,8 @@ mod tests {
|
||||
Err("module declares internal memory")
|
||||
);
|
||||
|
||||
prepare_test!(no_memory_import,
|
||||
prepare_test!(
|
||||
no_memory_import,
|
||||
r#"
|
||||
(module
|
||||
;; no memory imported
|
||||
@@ -489,7 +491,8 @@ mod tests {
|
||||
Ok(_)
|
||||
);
|
||||
|
||||
prepare_test!(initial_exceeds_maximum,
|
||||
prepare_test!(
|
||||
initial_exceeds_maximum,
|
||||
r#"
|
||||
(module
|
||||
(import "env" "memory" (memory 16 1))
|
||||
@@ -501,7 +504,8 @@ mod tests {
|
||||
Err("Module is not valid")
|
||||
);
|
||||
|
||||
prepare_test!(no_maximum,
|
||||
prepare_test!(
|
||||
no_maximum,
|
||||
r#"
|
||||
(module
|
||||
(import "env" "memory" (memory 1))
|
||||
@@ -513,7 +517,8 @@ mod tests {
|
||||
Err("Maximum number of pages should be always declared.")
|
||||
);
|
||||
|
||||
prepare_test!(requested_maximum_exceeds_configured_maximum,
|
||||
prepare_test!(
|
||||
requested_maximum_exceeds_configured_maximum,
|
||||
r#"
|
||||
(module
|
||||
(import "env" "memory" (memory 1 17))
|
||||
@@ -525,7 +530,8 @@ mod tests {
|
||||
Err("Maximum number of pages should not exceed the configured maximum.")
|
||||
);
|
||||
|
||||
prepare_test!(field_name_not_memory,
|
||||
prepare_test!(
|
||||
field_name_not_memory,
|
||||
r#"
|
||||
(module
|
||||
(import "env" "forgetit" (memory 1 1))
|
||||
@@ -537,7 +543,8 @@ mod tests {
|
||||
Err("Memory import must have the field name 'memory'")
|
||||
);
|
||||
|
||||
prepare_test!(multiple_memory_imports,
|
||||
prepare_test!(
|
||||
multiple_memory_imports,
|
||||
r#"
|
||||
(module
|
||||
(import "env" "memory" (memory 1 1))
|
||||
@@ -550,7 +557,8 @@ mod tests {
|
||||
Err("Module is not valid")
|
||||
);
|
||||
|
||||
prepare_test!(table_import,
|
||||
prepare_test!(
|
||||
table_import,
|
||||
r#"
|
||||
(module
|
||||
(import "env" "table" (table 1 anyfunc))
|
||||
@@ -562,7 +570,8 @@ mod tests {
|
||||
Err("Cannot import tables")
|
||||
);
|
||||
|
||||
prepare_test!(global_import,
|
||||
prepare_test!(
|
||||
global_import,
|
||||
r#"
|
||||
(module
|
||||
(global $g (import "env" "global") i32)
|
||||
@@ -583,7 +592,8 @@ mod tests {
|
||||
assert_eq!(Schedule::default().max_table_size, 16384);
|
||||
}
|
||||
|
||||
prepare_test!(no_tables,
|
||||
prepare_test!(
|
||||
no_tables,
|
||||
r#"
|
||||
(module
|
||||
(func (export "call"))
|
||||
@@ -593,7 +603,8 @@ mod tests {
|
||||
Ok(_)
|
||||
);
|
||||
|
||||
prepare_test!(table_valid_size,
|
||||
prepare_test!(
|
||||
table_valid_size,
|
||||
r#"
|
||||
(module
|
||||
(table 10000 funcref)
|
||||
@@ -605,7 +616,8 @@ mod tests {
|
||||
Ok(_)
|
||||
);
|
||||
|
||||
prepare_test!(table_too_big,
|
||||
prepare_test!(
|
||||
table_too_big,
|
||||
r#"
|
||||
(module
|
||||
(table 20000 funcref)
|
||||
@@ -620,7 +632,8 @@ mod tests {
|
||||
mod imports {
|
||||
use super::*;
|
||||
|
||||
prepare_test!(can_import_legit_function,
|
||||
prepare_test!(
|
||||
can_import_legit_function,
|
||||
r#"
|
||||
(module
|
||||
(import "env" "nop" (func (param i64)))
|
||||
@@ -634,7 +647,8 @@ mod tests {
|
||||
|
||||
// even though gas is defined the contract can't import it since
|
||||
// it is an implementation defined.
|
||||
prepare_test!(can_not_import_gas_function,
|
||||
prepare_test!(
|
||||
can_not_import_gas_function,
|
||||
r#"
|
||||
(module
|
||||
(import "env" "gas" (func (param i32)))
|
||||
@@ -647,7 +661,8 @@ mod tests {
|
||||
);
|
||||
|
||||
// nothing can be imported from non-"env" module for now.
|
||||
prepare_test!(non_env_import,
|
||||
prepare_test!(
|
||||
non_env_import,
|
||||
r#"
|
||||
(module
|
||||
(import "another_module" "memory" (memory 1 1))
|
||||
@@ -660,7 +675,8 @@ mod tests {
|
||||
);
|
||||
|
||||
// wrong signature
|
||||
prepare_test!(wrong_signature,
|
||||
prepare_test!(
|
||||
wrong_signature,
|
||||
r#"
|
||||
(module
|
||||
(import "env" "gas" (func (param i64)))
|
||||
@@ -672,7 +688,8 @@ mod tests {
|
||||
Err("module imports a non-existent function")
|
||||
);
|
||||
|
||||
prepare_test!(unknown_func_name,
|
||||
prepare_test!(
|
||||
unknown_func_name,
|
||||
r#"
|
||||
(module
|
||||
(import "env" "unknown_func" (func))
|
||||
@@ -684,7 +701,8 @@ mod tests {
|
||||
Err("module imports a non-existent function")
|
||||
);
|
||||
|
||||
prepare_test!(ext_println_debug_disabled,
|
||||
prepare_test!(
|
||||
ext_println_debug_disabled,
|
||||
r#"
|
||||
(module
|
||||
(import "env" "ext_println" (func $ext_println (param i32 i32)))
|
||||
@@ -698,16 +716,19 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn ext_println_debug_enabled() {
|
||||
let wasm = wabt::Wat2Wasm::new().validate(false).convert(
|
||||
r#"
|
||||
let wasm = wabt::Wat2Wasm::new()
|
||||
.validate(false)
|
||||
.convert(
|
||||
r#"
|
||||
(module
|
||||
(import "env" "ext_println" (func $ext_println (param i32 i32)))
|
||||
|
||||
(func (export "call"))
|
||||
(func (export "deploy"))
|
||||
)
|
||||
"#
|
||||
).unwrap();
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
let mut schedule = Schedule::default();
|
||||
schedule.enable_println = true;
|
||||
let r = prepare_contract::<TestEnv>(wasm.as_ref(), &schedule);
|
||||
@@ -718,7 +739,8 @@ mod tests {
|
||||
mod entrypoints {
|
||||
use super::*;
|
||||
|
||||
prepare_test!(it_works,
|
||||
prepare_test!(
|
||||
it_works,
|
||||
r#"
|
||||
(module
|
||||
(func (export "call"))
|
||||
@@ -728,7 +750,8 @@ mod tests {
|
||||
Ok(_)
|
||||
);
|
||||
|
||||
prepare_test!(omit_deploy,
|
||||
prepare_test!(
|
||||
omit_deploy,
|
||||
r#"
|
||||
(module
|
||||
(func (export "call"))
|
||||
@@ -737,7 +760,8 @@ mod tests {
|
||||
Err("deploy function isn't exported")
|
||||
);
|
||||
|
||||
prepare_test!(omit_call,
|
||||
prepare_test!(
|
||||
omit_call,
|
||||
r#"
|
||||
(module
|
||||
(func (export "deploy"))
|
||||
@@ -747,7 +771,8 @@ mod tests {
|
||||
);
|
||||
|
||||
// Try to use imported function as an entry point.
|
||||
prepare_test!(try_sneak_export_as_entrypoint,
|
||||
prepare_test!(
|
||||
try_sneak_export_as_entrypoint,
|
||||
r#"
|
||||
(module
|
||||
(import "env" "panic" (func))
|
||||
@@ -761,7 +786,8 @@ mod tests {
|
||||
);
|
||||
|
||||
// Try to use imported function as an entry point.
|
||||
prepare_test!(try_sneak_export_as_global,
|
||||
prepare_test!(
|
||||
try_sneak_export_as_global,
|
||||
r#"
|
||||
(module
|
||||
(func (export "deploy"))
|
||||
@@ -771,7 +797,8 @@ mod tests {
|
||||
Err("expected a function")
|
||||
);
|
||||
|
||||
prepare_test!(wrong_signature,
|
||||
prepare_test!(
|
||||
wrong_signature,
|
||||
r#"
|
||||
(module
|
||||
(func (export "deploy"))
|
||||
@@ -781,7 +808,8 @@ mod tests {
|
||||
Err("entry point has wrong signature")
|
||||
);
|
||||
|
||||
prepare_test!(unknown_exports,
|
||||
prepare_test!(
|
||||
unknown_exports,
|
||||
r#"
|
||||
(module
|
||||
(func (export "call"))
|
||||
@@ -792,7 +820,8 @@ mod tests {
|
||||
Err("unknown export: expecting only deploy and call functions")
|
||||
);
|
||||
|
||||
prepare_test!(global_float,
|
||||
prepare_test!(
|
||||
global_float,
|
||||
r#"
|
||||
(module
|
||||
(global $x f32 (f32.const 0))
|
||||
@@ -803,7 +832,8 @@ mod tests {
|
||||
Err("use of floating point type in globals is forbidden")
|
||||
);
|
||||
|
||||
prepare_test!(local_float,
|
||||
prepare_test!(
|
||||
local_float,
|
||||
r#"
|
||||
(module
|
||||
(func $foo (local f32))
|
||||
@@ -814,7 +844,8 @@ mod tests {
|
||||
Err("use of floating point type in locals is forbidden")
|
||||
);
|
||||
|
||||
prepare_test!(param_float,
|
||||
prepare_test!(
|
||||
param_float,
|
||||
r#"
|
||||
(module
|
||||
(func $foo (param f32))
|
||||
@@ -825,7 +856,8 @@ mod tests {
|
||||
Err("use of floating point type in function types is forbidden")
|
||||
);
|
||||
|
||||
prepare_test!(result_float,
|
||||
prepare_test!(
|
||||
result_float,
|
||||
r#"
|
||||
(module
|
||||
(func $foo (result f32) (f32.const 0))
|
||||
|
||||
@@ -16,23 +16,18 @@
|
||||
|
||||
//! Environment definition of the wasm smart-contract runtime.
|
||||
|
||||
use crate::{Schedule, Trait, CodeHash, BalanceOf};
|
||||
use crate::exec::{
|
||||
Ext, ExecResult, ExecError, ExecReturnValue, StorageKey, TopicOf, STATUS_SUCCESS,
|
||||
use crate::{
|
||||
exec::{ExecError, ExecResult, ExecReturnValue, Ext, StorageKey, TopicOf, STATUS_SUCCESS},
|
||||
gas::{Gas, GasMeter, GasMeterResult, Token},
|
||||
BalanceOf, CodeHash, Schedule, Trait,
|
||||
};
|
||||
use crate::gas::{Gas, GasMeter, Token, GasMeterResult};
|
||||
use sp_sandbox;
|
||||
use frame_system;
|
||||
use sp_std::{prelude::*, mem, convert::TryInto};
|
||||
use codec::{Decode, Encode};
|
||||
use sp_runtime::traits::{Bounded, SaturatedConversion};
|
||||
use sp_io::hashing::{
|
||||
keccak_256,
|
||||
blake2_256,
|
||||
blake2_128,
|
||||
sha2_256,
|
||||
};
|
||||
use frame_support::weights::GetDispatchInfo;
|
||||
use frame_system;
|
||||
use sp_io::hashing::{blake2_128, blake2_256, keccak_256, sha2_256};
|
||||
use sp_runtime::traits::{Bounded, SaturatedConversion};
|
||||
use sp_sandbox;
|
||||
use sp_std::{convert::TryInto, mem, prelude::*};
|
||||
|
||||
/// The value returned from ext_call and ext_instantiate contract external functions if the call or
|
||||
/// instantiation traps. This value is chosen as if the execution does not trap, the return value
|
||||
@@ -93,19 +88,19 @@ pub(crate) fn to_execution_result<E: Ext>(
|
||||
status: STATUS_SUCCESS,
|
||||
data,
|
||||
})
|
||||
},
|
||||
}
|
||||
Some(SpecialTrap::Termination) => {
|
||||
return Ok(ExecReturnValue {
|
||||
status: STATUS_SUCCESS,
|
||||
data: Vec::new(),
|
||||
})
|
||||
},
|
||||
}
|
||||
Some(SpecialTrap::OutOfGas) => {
|
||||
return Err(ExecError {
|
||||
reason: "ran out of gas during contract execution".into(),
|
||||
buffer: runtime.scratch_buf,
|
||||
})
|
||||
},
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
|
||||
@@ -115,29 +110,43 @@ pub(crate) fn to_execution_result<E: Ext>(
|
||||
Ok(sp_sandbox::ReturnValue::Unit) => {
|
||||
let mut buffer = runtime.scratch_buf;
|
||||
buffer.clear();
|
||||
Ok(ExecReturnValue { status: STATUS_SUCCESS, data: buffer })
|
||||
Ok(ExecReturnValue {
|
||||
status: STATUS_SUCCESS,
|
||||
data: buffer,
|
||||
})
|
||||
}
|
||||
Ok(sp_sandbox::ReturnValue::Value(sp_sandbox::Value::I32(exit_code))) => {
|
||||
let status = (exit_code & 0xFF).try_into()
|
||||
let status = (exit_code & 0xFF)
|
||||
.try_into()
|
||||
.expect("exit_code is masked into the range of a u8; qed");
|
||||
Ok(ExecReturnValue { status, data: runtime.scratch_buf })
|
||||
Ok(ExecReturnValue {
|
||||
status,
|
||||
data: runtime.scratch_buf,
|
||||
})
|
||||
}
|
||||
// This should never happen as the return type of exported functions should have been
|
||||
// validated by the code preparation process. However, because panics are really
|
||||
// undesirable in the runtime code, we treat this as a trap for now. Eventually, we might
|
||||
// want to revisit this.
|
||||
Ok(_) => Err(ExecError { reason: "return type error".into(), buffer: runtime.scratch_buf }),
|
||||
Ok(_) => Err(ExecError {
|
||||
reason: "return type error".into(),
|
||||
buffer: runtime.scratch_buf,
|
||||
}),
|
||||
// `Error::Module` is returned only if instantiation or linking failed (i.e.
|
||||
// wasm binary tried to import a function that is not provided by the host).
|
||||
// This shouldn't happen because validation process ought to reject such binaries.
|
||||
//
|
||||
// Because panics are really undesirable in the runtime code, we treat this as
|
||||
// a trap for now. Eventually, we might want to revisit this.
|
||||
Err(sp_sandbox::Error::Module) =>
|
||||
Err(ExecError { reason: "validation error".into(), buffer: runtime.scratch_buf }),
|
||||
Err(sp_sandbox::Error::Module) => Err(ExecError {
|
||||
reason: "validation error".into(),
|
||||
buffer: runtime.scratch_buf,
|
||||
}),
|
||||
// Any other kind of a trap should result in a failure.
|
||||
Err(sp_sandbox::Error::Execution) | Err(sp_sandbox::Error::OutOfBounds) =>
|
||||
Err(ExecError { reason: "contract trapped during execution".into(), buffer: runtime.scratch_buf }),
|
||||
Err(sp_sandbox::Error::Execution) | Err(sp_sandbox::Error::OutOfBounds) => Err(ExecError {
|
||||
reason: "contract trapped during execution".into(),
|
||||
buffer: runtime.scratch_buf,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,14 +197,12 @@ impl<T: Trait> Token<T> for RuntimeToken {
|
||||
|
||||
data_cost
|
||||
.and_then(|data_cost| {
|
||||
topics_cost.and_then(|topics_cost| {
|
||||
data_cost.checked_add(topics_cost)
|
||||
})
|
||||
topics_cost.and_then(|topics_cost| data_cost.checked_add(topics_cost))
|
||||
})
|
||||
.and_then(|data_and_topics_cost|
|
||||
.and_then(|data_and_topics_cost| {
|
||||
data_and_topics_cost.checked_add(metadata.event_base_cost)
|
||||
)
|
||||
},
|
||||
})
|
||||
}
|
||||
DispatchWithWeight(gas) => gas.checked_add(metadata.dispatch_base_cost),
|
||||
};
|
||||
|
||||
@@ -214,10 +221,10 @@ fn charge_gas<T: Trait, Tok: Token<T>>(
|
||||
) -> Result<(), sp_sandbox::HostError> {
|
||||
match gas_meter.charge(metadata, token) {
|
||||
GasMeterResult::Proceed => Ok(()),
|
||||
GasMeterResult::OutOfGas => {
|
||||
GasMeterResult::OutOfGas => {
|
||||
*special_trap = Some(SpecialTrap::OutOfGas);
|
||||
Err(sp_sandbox::HostError)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,7 +249,9 @@ fn read_sandbox_memory<E: Ext>(
|
||||
)?;
|
||||
|
||||
let mut buf = vec![0u8; len as usize];
|
||||
ctx.memory.get(ptr, buf.as_mut_slice()).map_err(|_| sp_sandbox::HostError)?;
|
||||
ctx.memory
|
||||
.get(ptr, buf.as_mut_slice())
|
||||
.map_err(|_| sp_sandbox::HostError)?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
@@ -267,7 +276,9 @@ fn read_sandbox_memory_into_scratch<E: Ext>(
|
||||
)?;
|
||||
|
||||
ctx.scratch_buf.resize(len as usize, 0);
|
||||
ctx.memory.get(ptr, ctx.scratch_buf.as_mut_slice()).map_err(|_| sp_sandbox::HostError)?;
|
||||
ctx.memory
|
||||
.get(ptr, ctx.scratch_buf.as_mut_slice())
|
||||
.map_err(|_| sp_sandbox::HostError)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1165,14 +1176,10 @@ where
|
||||
/// the order of items is not preserved.
|
||||
fn has_duplicates<T: PartialEq + AsRef<[u8]>>(items: &mut Vec<T>) -> bool {
|
||||
// Sort the vector
|
||||
items.sort_unstable_by(|a, b| {
|
||||
Ord::cmp(a.as_ref(), b.as_ref())
|
||||
});
|
||||
items.sort_unstable_by(|a, b| Ord::cmp(a.as_ref(), b.as_ref()));
|
||||
// And then find any two consecutive equal elements.
|
||||
items.windows(2).any(|w| {
|
||||
match w {
|
||||
&[ref a, ref b] => a == b,
|
||||
_ => false,
|
||||
}
|
||||
items.windows(2).any(|w| match w {
|
||||
&[ref a, ref b] => a == b,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ use cumulus_primitives::ParaId;
|
||||
/// Configuration trait of this pallet.
|
||||
pub trait Trait: frame_system::Trait {}
|
||||
|
||||
impl <T: Trait> Get<ParaId> for Module<T> {
|
||||
impl<T: Trait> Get<ParaId> for Module<T> {
|
||||
fn get() -> ParaId {
|
||||
Self::parachain_id()
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use frame_support::{
|
||||
decl_event, decl_module, dispatch::DispatchResult,
|
||||
decl_event, decl_module,
|
||||
dispatch::DispatchResult,
|
||||
traits::{Currency, ExistenceRequirement, WithdrawReason},
|
||||
};
|
||||
use frame_system::ensure_signed;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "rococo-parachain-primitives"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
# Substrate dependencies
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
|
||||
|
||||
[features]
|
||||
default = [ "std" ]
|
||||
std = [
|
||||
"sp-runtime/std",
|
||||
"sp-core/std"
|
||||
]
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Cumulus.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Primitives used by the Parachains Tick, Trick and Track.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use sp_runtime::{
|
||||
generic,
|
||||
traits::{BlakeTwo256, IdentifyAccount, Verify},
|
||||
MultiSignature,
|
||||
};
|
||||
|
||||
pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
|
||||
|
||||
/// Opaque block header type.
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
/// Opaque block type.
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
/// Opaque block identifier type.
|
||||
pub type BlockId = generic::BlockId<Block>;
|
||||
/// An index to a block.
|
||||
pub type BlockNumber = u32;
|
||||
|
||||
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
|
||||
pub type Signature = MultiSignature;
|
||||
|
||||
/// Some way of identifying an account on the chain. We intentionally make it equivalent
|
||||
/// to the public key of our transaction signing scheme.
|
||||
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
|
||||
|
||||
/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
|
||||
/// never know...
|
||||
pub type AccountIndex = u32;
|
||||
|
||||
/// Balance of an account.
|
||||
pub type Balance = u128;
|
||||
|
||||
/// Index of a transaction in the chain.
|
||||
pub type Index = u32;
|
||||
|
||||
/// A hash of some data used by the chain.
|
||||
pub type Hash = sp_core::H256;
|
||||
|
||||
/// Digest item type.
|
||||
pub type DigestItem = generic::DigestItem<Hash>;
|
||||
@@ -8,8 +8,9 @@ edition = '2018'
|
||||
serde = { version = "1.0.101", optional = true, features = ["derive"] }
|
||||
codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] }
|
||||
|
||||
cumulus-token-dealer = { path = "../pallets/token-dealer", default-features = false}
|
||||
parachain-info = { path = "../pallets/parachain-info", default-features = false}
|
||||
cumulus-token-dealer = { path = "../pallets/token-dealer", default-features = false }
|
||||
parachain-info = { path = "../pallets/parachain-info", default-features = false }
|
||||
rococo-parachain-primitives = { path = "../primitives", default-features = false }
|
||||
|
||||
# Substrate dependencies
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
|
||||
@@ -71,6 +72,7 @@ std = [
|
||||
"pallet-sudo/std",
|
||||
"pallet-transaction-payment/std",
|
||||
"parachain-info/std",
|
||||
"rococo-parachain-primitives/std",
|
||||
"cumulus-runtime/std",
|
||||
"cumulus-parachain-upgrade/std",
|
||||
"cumulus-message-broker/std",
|
||||
|
||||
@@ -22,13 +22,14 @@
|
||||
#[cfg(feature = "std")]
|
||||
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
|
||||
|
||||
use rococo_parachain_primitives::*;
|
||||
use sp_api::impl_runtime_apis;
|
||||
use sp_core::OpaqueMetadata;
|
||||
use sp_runtime::{
|
||||
create_runtime_str, generic, impl_opaque_keys,
|
||||
traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, IdentityLookup, Saturating, Verify},
|
||||
traits::{BlakeTwo256, Block as BlockT, IdentityLookup, Saturating},
|
||||
transaction_validity::{TransactionSource, TransactionValidity},
|
||||
ApplyExtrinsicResult, MultiSignature,
|
||||
ApplyExtrinsicResult,
|
||||
};
|
||||
use sp_std::prelude::*;
|
||||
#[cfg(feature = "std")]
|
||||
@@ -51,53 +52,10 @@ pub use pallet_timestamp::Call as TimestampCall;
|
||||
pub use sp_runtime::BuildStorage;
|
||||
pub use sp_runtime::{Perbill, Permill};
|
||||
|
||||
/// An index to a block.
|
||||
pub type BlockNumber = u32;
|
||||
pub type SessionHandlers = ();
|
||||
|
||||
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
|
||||
pub type Signature = MultiSignature;
|
||||
|
||||
/// Some way of identifying an account on the chain. We intentionally make it equivalent
|
||||
/// to the public key of our transaction signing scheme.
|
||||
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
|
||||
|
||||
/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
|
||||
/// never know...
|
||||
pub type AccountIndex = u32;
|
||||
|
||||
/// Balance of an account.
|
||||
pub type Balance = u128;
|
||||
|
||||
/// Index of a transaction in the chain.
|
||||
pub type Index = u32;
|
||||
|
||||
/// A hash of some data used by the chain.
|
||||
pub type Hash = sp_core::H256;
|
||||
|
||||
/// Digest item type.
|
||||
pub type DigestItem = generic::DigestItem<Hash>;
|
||||
|
||||
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
|
||||
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
|
||||
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
|
||||
/// to even the core datastructures.
|
||||
pub mod opaque {
|
||||
use super::*;
|
||||
|
||||
pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
|
||||
|
||||
/// Opaque block header type.
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
/// Opaque block type.
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
/// Opaque block identifier type.
|
||||
pub type BlockId = generic::BlockId<Block>;
|
||||
|
||||
pub type SessionHandlers = ();
|
||||
|
||||
impl_opaque_keys! {
|
||||
pub struct SessionKeys {}
|
||||
}
|
||||
impl_opaque_keys! {
|
||||
pub struct SessionKeys {}
|
||||
}
|
||||
|
||||
/// This runtime version.
|
||||
@@ -105,7 +63,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
spec_name: create_runtime_str!("cumulus-test-parachain"),
|
||||
impl_name: create_runtime_str!("cumulus-test-parachain"),
|
||||
authoring_version: 1,
|
||||
spec_version: 1,
|
||||
spec_version: 2,
|
||||
impl_version: 1,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
transaction_version: 1,
|
||||
@@ -266,8 +224,8 @@ impl parachain_info::Trait for Runtime {}
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = opaque::Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
NodeBlock = rococo_parachain_primitives::Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic,
|
||||
{
|
||||
System: frame_system::{Module, Call, Storage, Config, Event<T>},
|
||||
Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},
|
||||
@@ -378,11 +336,11 @@ impl_runtime_apis! {
|
||||
fn decode_session_keys(
|
||||
encoded: Vec<u8>,
|
||||
) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
|
||||
opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
|
||||
SessionKeys::decode_into_raw_public_keys(&encoded)
|
||||
}
|
||||
|
||||
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
|
||||
opaque::SessionKeys::generate(seed)
|
||||
SessionKeys::generate(seed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,19 +15,20 @@
|
||||
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use cumulus_primitives::ParaId;
|
||||
use parachain_runtime::{
|
||||
AccountId, BalancesConfig, GenesisConfig, Signature, SudoConfig, SystemConfig,
|
||||
ParachainInfoConfig, WASM_BINARY,
|
||||
};
|
||||
use hex_literal::hex;
|
||||
use rococo_parachain_primitives::{AccountId, Signature};
|
||||
use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};
|
||||
use sc_service::ChainType;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sp_core::{sr25519, Pair, Public};
|
||||
use sp_runtime::traits::{IdentifyAccount, Verify};
|
||||
use hex_literal::hex;
|
||||
|
||||
/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
|
||||
pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig, Extensions>;
|
||||
/// Specialized `ChainSpec` for the normal parachain runtime.
|
||||
pub type ChainSpec = sc_service::GenericChainSpec<parachain_runtime::GenesisConfig, Extensions>;
|
||||
|
||||
/// Specialized `ChainSpec` for the contracts parachain runtime.
|
||||
pub type ContractsChainSpec =
|
||||
sc_service::GenericChainSpec<parachain_contracts_runtime::GenesisConfig, Extensions>;
|
||||
|
||||
/// Helper function to generate a crypto pair from seed
|
||||
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
|
||||
@@ -99,6 +100,42 @@ pub fn get_chain_spec(id: ParaId) -> ChainSpec {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_contracts_chain_spec(id: ParaId) -> ContractsChainSpec {
|
||||
ContractsChainSpec::from_genesis(
|
||||
"Contracts Local Testnet",
|
||||
"contracts_local_testnet",
|
||||
ChainType::Local,
|
||||
move || {
|
||||
contracts_testnet_genesis(
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
||||
vec![
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Bob"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Charlie"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Dave"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Eve"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
|
||||
],
|
||||
id,
|
||||
)
|
||||
},
|
||||
vec![],
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Extensions {
|
||||
relay_chain: "westend-dev".into(),
|
||||
para_id: id.into(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn staging_test_net(id: ParaId) -> ChainSpec {
|
||||
ChainSpec::from_genesis(
|
||||
"Staging Testnet",
|
||||
@@ -107,7 +144,9 @@ pub fn staging_test_net(id: ParaId) -> ChainSpec {
|
||||
move || {
|
||||
testnet_genesis(
|
||||
hex!["9ed7705e3c7da027ba0583a22a3212042f7e715d3c168ba14f1424e2bc111d00"].into(),
|
||||
vec![hex!["9ed7705e3c7da027ba0583a22a3212042f7e715d3c168ba14f1424e2bc111d00"].into()],
|
||||
vec![
|
||||
hex!["9ed7705e3c7da027ba0583a22a3212042f7e715d3c168ba14f1424e2bc111d00"].into(),
|
||||
],
|
||||
id,
|
||||
)
|
||||
},
|
||||
@@ -126,22 +165,47 @@ fn testnet_genesis(
|
||||
root_key: AccountId,
|
||||
endowed_accounts: Vec<AccountId>,
|
||||
id: ParaId,
|
||||
) -> GenesisConfig {
|
||||
GenesisConfig {
|
||||
frame_system: Some(SystemConfig {
|
||||
code: WASM_BINARY.expect("WASM binary was not build, please build it!").to_vec(),
|
||||
) -> parachain_runtime::GenesisConfig {
|
||||
parachain_runtime::GenesisConfig {
|
||||
frame_system: Some(parachain_runtime::SystemConfig {
|
||||
code: parachain_runtime::WASM_BINARY
|
||||
.expect("WASM binary was not build, please build it!")
|
||||
.to_vec(),
|
||||
changes_trie_config: Default::default(),
|
||||
}),
|
||||
pallet_balances: Some(BalancesConfig {
|
||||
pallet_balances: Some(parachain_runtime::BalancesConfig {
|
||||
balances: endowed_accounts
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|k| (k, 1 << 60))
|
||||
.collect(),
|
||||
}),
|
||||
pallet_sudo: Some(SudoConfig { key: root_key }),
|
||||
parachain_info: Some(ParachainInfoConfig { parachain_id: id }),
|
||||
// TODO: add contracts genesis for the contracts runtime
|
||||
// pallet_contracts: Some(parachain_runtime::ContractsConfig { current_schedule: Default::default() }),
|
||||
pallet_sudo: Some(parachain_runtime::SudoConfig { key: root_key }),
|
||||
parachain_info: Some(parachain_runtime::ParachainInfoConfig { parachain_id: id }),
|
||||
}
|
||||
}
|
||||
|
||||
fn contracts_testnet_genesis(
|
||||
root_key: AccountId,
|
||||
endowed_accounts: Vec<AccountId>,
|
||||
id: ParaId,
|
||||
) -> parachain_contracts_runtime::GenesisConfig {
|
||||
parachain_contracts_runtime::GenesisConfig {
|
||||
frame_system: Some(parachain_contracts_runtime::SystemConfig {
|
||||
code: parachain_contracts_runtime::WASM_BINARY
|
||||
.expect("WASM binary was not build, please build it!")
|
||||
.to_vec(),
|
||||
changes_trie_config: Default::default(),
|
||||
}),
|
||||
pallet_balances: Some(parachain_contracts_runtime::BalancesConfig {
|
||||
balances: endowed_accounts
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|k| (k, 1 << 60))
|
||||
.collect(),
|
||||
}),
|
||||
pallet_sudo: Some(parachain_contracts_runtime::SudoConfig { key: root_key }),
|
||||
parachain_info: Some(parachain_contracts_runtime::ParachainInfoConfig { parachain_id: id }),
|
||||
cumulus_pallet_contracts: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ use log::info;
|
||||
use parachain_runtime::Block;
|
||||
use polkadot_parachain::primitives::AccountIdConversion;
|
||||
use sc_cli::{
|
||||
ChainSpec, CliConfiguration, ImportParams, KeystoreParams, NetworkParams, Result,
|
||||
RuntimeVersion, SharedParams, SubstrateCli, DefaultConfigurationValues,
|
||||
ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams,
|
||||
NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli,
|
||||
};
|
||||
use sc_service::config::{BasePath, PrometheusConfig};
|
||||
use sp_core::hexdisplay::HexDisplay;
|
||||
@@ -77,6 +77,9 @@ impl SubstrateCli for Cli {
|
||||
"track" => Ok(Box::new(chain_spec::ChainSpec::from_json_bytes(
|
||||
&include_bytes!("../res/track.json")[..],
|
||||
)?)),
|
||||
"contracts" => Ok(Box::new(chain_spec::get_contracts_chain_spec(
|
||||
self.run.parachain_id.unwrap_or(100).into(),
|
||||
))),
|
||||
"" => Ok(Box::new(chain_spec::get_chain_spec(
|
||||
self.run.parachain_id.unwrap_or(100).into(),
|
||||
))),
|
||||
@@ -167,6 +170,10 @@ fn extract_genesis_wasm(chain_spec: &Box<dyn sc_service::ChainSpec>) -> Result<V
|
||||
.ok_or_else(|| "Could not find wasm file in genesis state!".into())
|
||||
}
|
||||
|
||||
fn use_contracts_runtime(chain_spec: &Box<dyn ChainSpec>) -> bool {
|
||||
chain_spec.id().starts_with("trick") || chain_spec.id().starts_with("contracts")
|
||||
}
|
||||
|
||||
/// Parse command line arguments into service configuration.
|
||||
pub fn run() -> Result<()> {
|
||||
let cli = Cli::from_args();
|
||||
@@ -175,16 +182,35 @@ pub fn run() -> Result<()> {
|
||||
Some(Subcommand::Base(subcommand)) => {
|
||||
let runner = cli.create_runner(subcommand)?;
|
||||
|
||||
runner.run_subcommand(subcommand, |mut config| {
|
||||
let params = crate::service::new_partial(&mut config)?;
|
||||
if use_contracts_runtime(&runner.config().chain_spec) {
|
||||
runner.run_subcommand(subcommand, |mut config| {
|
||||
let params = crate::service::new_partial::<
|
||||
parachain_contracts_runtime::RuntimeApi,
|
||||
crate::service::ContractsRuntimeExecutor,
|
||||
>(&mut config)?;
|
||||
|
||||
Ok((
|
||||
params.client,
|
||||
params.backend,
|
||||
params.import_queue,
|
||||
params.task_manager,
|
||||
))
|
||||
})
|
||||
Ok((
|
||||
params.client,
|
||||
params.backend,
|
||||
params.import_queue,
|
||||
params.task_manager,
|
||||
))
|
||||
})
|
||||
} else {
|
||||
runner.run_subcommand(subcommand, |mut config| {
|
||||
let params = crate::service::new_partial::<
|
||||
parachain_runtime::RuntimeApi,
|
||||
crate::service::RuntimeExecutor,
|
||||
>(&mut config)?;
|
||||
|
||||
Ok((
|
||||
params.client,
|
||||
params.backend,
|
||||
params.import_queue,
|
||||
params.task_manager,
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
Some(Subcommand::ExportGenesisState(params)) => {
|
||||
sc_cli::init_logger("");
|
||||
@@ -256,14 +282,23 @@ pub fn run() -> Result<()> {
|
||||
if cli.run.base.validator { "yes" } else { "no" }
|
||||
);
|
||||
|
||||
crate::service::run_node(
|
||||
config,
|
||||
key,
|
||||
polkadot_config,
|
||||
id,
|
||||
cli.run.base.validator,
|
||||
)
|
||||
.map(|(x, _)| x)
|
||||
if use_contracts_runtime(&config.chain_spec) {
|
||||
crate::service::start_contracts_node(
|
||||
config,
|
||||
key,
|
||||
polkadot_config,
|
||||
id,
|
||||
cli.run.base.validator,
|
||||
)
|
||||
} else {
|
||||
crate::service::start_node(
|
||||
config,
|
||||
key,
|
||||
polkadot_config,
|
||||
id,
|
||||
cli.run.base.validator,
|
||||
).map(|r| r.0)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,8 @@ async fn integration_test() {
|
||||
INTEGRATION_TEST_ALLOWED_TIME
|
||||
.and_then(|x| x.parse().ok())
|
||||
.unwrap_or(600),
|
||||
)).fuse();
|
||||
))
|
||||
.fuse();
|
||||
|
||||
let t2 = async {
|
||||
let para_id = ParaId::from(100);
|
||||
@@ -105,7 +106,7 @@ async fn integration_test() {
|
||||
let parachain_config =
|
||||
parachain_config(task_executor.clone(), Charlie, vec![], para_id).unwrap();
|
||||
let (_service, charlie_client) =
|
||||
crate::service::run_node(parachain_config, key, polkadot_config, para_id, true)
|
||||
crate::service::start_node(parachain_config, key, polkadot_config, para_id, true)
|
||||
.unwrap();
|
||||
sleep(Duration::from_secs(3)).await;
|
||||
charlie_client.wait_for_blocks(4).await;
|
||||
|
||||
@@ -20,67 +20,74 @@ use cumulus_service::{
|
||||
prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams,
|
||||
};
|
||||
use polkadot_primitives::v0::CollatorPair;
|
||||
use rococo_parachain_primitives::Block;
|
||||
use sc_executor::native_executor_instance;
|
||||
pub use sc_executor::NativeExecutor;
|
||||
use sc_informant::OutputFormat;
|
||||
use sc_service::{Configuration, PartialComponents, Role, TFullBackend, TFullClient, TaskManager};
|
||||
use sp_api::ConstructRuntimeApi;
|
||||
use sp_runtime::traits::BlakeTwo256;
|
||||
use sp_trie::PrefixedMemoryDB;
|
||||
use std::sync::Arc;
|
||||
|
||||
// Our native executor instance.
|
||||
// Native executor instance.
|
||||
native_executor_instance!(
|
||||
pub Executor,
|
||||
pub RuntimeExecutor,
|
||||
parachain_runtime::api::dispatch,
|
||||
parachain_runtime::native_version,
|
||||
);
|
||||
|
||||
// Native executor instance for the contracts runtime.
|
||||
native_executor_instance!(
|
||||
pub ContractsRuntimeExecutor,
|
||||
parachain_contracts_runtime::api::dispatch,
|
||||
parachain_contracts_runtime::native_version,
|
||||
);
|
||||
|
||||
/// Starts a `ServiceBuilder` for a full service.
|
||||
///
|
||||
/// Use this macro if you don't actually need the full service, but just the builder in order to
|
||||
/// be able to perform chain operations.
|
||||
pub fn new_partial(
|
||||
pub fn new_partial<RuntimeApi, Executor>(
|
||||
config: &mut Configuration,
|
||||
) -> Result<
|
||||
PartialComponents<
|
||||
TFullClient<
|
||||
parachain_runtime::opaque::Block,
|
||||
parachain_runtime::RuntimeApi,
|
||||
crate::service::Executor,
|
||||
>,
|
||||
TFullBackend<parachain_runtime::opaque::Block>,
|
||||
TFullClient<Block, RuntimeApi, Executor>,
|
||||
TFullBackend<Block>,
|
||||
(),
|
||||
sp_consensus::import_queue::BasicQueue<
|
||||
parachain_runtime::opaque::Block,
|
||||
PrefixedMemoryDB<BlakeTwo256>,
|
||||
>,
|
||||
sc_transaction_pool::FullPool<
|
||||
parachain_runtime::opaque::Block,
|
||||
TFullClient<
|
||||
parachain_runtime::opaque::Block,
|
||||
parachain_runtime::RuntimeApi,
|
||||
crate::service::Executor,
|
||||
>,
|
||||
>,
|
||||
sp_consensus::import_queue::BasicQueue<Block, PrefixedMemoryDB<BlakeTwo256>>,
|
||||
sc_transaction_pool::FullPool<Block, TFullClient<Block, RuntimeApi, Executor>>,
|
||||
(),
|
||||
>,
|
||||
sc_service::Error,
|
||||
> {
|
||||
>
|
||||
where
|
||||
RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, Executor>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
|
||||
+ sp_api::Metadata<Block>
|
||||
+ sp_session::SessionKeys<Block>
|
||||
+ sp_api::ApiExt<
|
||||
Block,
|
||||
Error = sp_blockchain::Error,
|
||||
StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>,
|
||||
> + sp_offchain::OffchainWorkerApi<Block>
|
||||
+ sp_block_builder::BlockBuilder<Block>,
|
||||
sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,
|
||||
Executor: sc_executor::NativeExecutionDispatch + 'static,
|
||||
{
|
||||
let inherent_data_providers = sp_inherents::InherentDataProviders::new();
|
||||
|
||||
let (client, backend, keystore, task_manager) = sc_service::new_full_parts::<
|
||||
parachain_runtime::opaque::Block,
|
||||
parachain_runtime::RuntimeApi,
|
||||
crate::service::Executor,
|
||||
>(&config)?;
|
||||
let (client, backend, keystore, task_manager) =
|
||||
sc_service::new_full_parts::<Block, RuntimeApi, Executor>(&config)?;
|
||||
let client = Arc::new(client);
|
||||
//let select_chain = sc_consensus::LongestChain::new(backend.clone());
|
||||
|
||||
let registry = config.prometheus_registry();
|
||||
|
||||
let transaction_pool = sc_transaction_pool::BasicPool::new_full(
|
||||
config.transaction_pool.clone(),
|
||||
//std::sync::Arc::new(pool_api),
|
||||
config.prometheus_registry(),
|
||||
task_manager.spawn_handle(),
|
||||
client.clone(),
|
||||
@@ -109,25 +116,39 @@ pub fn new_partial(
|
||||
Ok(params)
|
||||
}
|
||||
|
||||
/// Run a node with the given parachain `Configuration` and relay chain `Configuration`
|
||||
/// Start a node with the given parachain `Configuration` and relay chain `Configuration`.
|
||||
///
|
||||
/// This function blocks until done.
|
||||
pub fn run_node(
|
||||
/// This is the actual implementation that is abstract over the executor and the runtime api.
|
||||
fn start_node_impl<RuntimeApi, Executor, RB>(
|
||||
parachain_config: Configuration,
|
||||
collator_key: Arc<CollatorPair>,
|
||||
mut polkadot_config: polkadot_collator::Configuration,
|
||||
id: polkadot_primitives::v0::Id,
|
||||
validator: bool,
|
||||
) -> sc_service::error::Result<(
|
||||
TaskManager,
|
||||
Arc<
|
||||
TFullClient<
|
||||
parachain_runtime::opaque::Block,
|
||||
parachain_runtime::RuntimeApi,
|
||||
crate::service::Executor,
|
||||
>,
|
||||
>,
|
||||
)> {
|
||||
rpc_ext_builder: RB,
|
||||
) -> sc_service::error::Result<(TaskManager, Arc<TFullClient<Block, RuntimeApi, Executor>>)>
|
||||
where
|
||||
RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, Executor>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
|
||||
+ sp_api::Metadata<Block>
|
||||
+ sp_session::SessionKeys<Block>
|
||||
+ sp_api::ApiExt<
|
||||
Block,
|
||||
Error = sp_blockchain::Error,
|
||||
StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>,
|
||||
> + sp_offchain::OffchainWorkerApi<Block>
|
||||
+ sp_block_builder::BlockBuilder<Block>,
|
||||
sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,
|
||||
Executor: sc_executor::NativeExecutionDispatch + 'static,
|
||||
RB: Fn(
|
||||
Arc<TFullClient<Block, RuntimeApi, Executor>>,
|
||||
) -> jsonrpc_core::IoHandler<sc_rpc::Metadata>
|
||||
+ Send
|
||||
+ 'static,
|
||||
{
|
||||
if matches!(parachain_config.role, Role::Light) {
|
||||
return Err("Light client not supported!".into());
|
||||
}
|
||||
@@ -143,7 +164,7 @@ pub fn run_node(
|
||||
prefix: format!("[{}] ", Color::Blue.bold().paint("Relaychain")),
|
||||
};
|
||||
|
||||
let params = new_partial(&mut parachain_config)?;
|
||||
let params = new_partial::<RuntimeApi, Executor>(&mut parachain_config)?;
|
||||
params
|
||||
.inherent_data_providers
|
||||
.register_provider(sp_timestamp::InherentDataProvider)
|
||||
@@ -163,32 +184,21 @@ pub fn run_node(
|
||||
let import_queue = params.import_queue;
|
||||
let (network, network_status_sinks, system_rpc_tx, start_network) =
|
||||
sc_service::build_network(sc_service::BuildNetworkParams {
|
||||
config: ¶chain_config,
|
||||
client: client.clone(),
|
||||
transaction_pool: transaction_pool.clone(),
|
||||
spawn_handle: task_manager.spawn_handle(),
|
||||
import_queue,
|
||||
on_demand: None,
|
||||
block_announce_validator_builder: Some(Box::new(block_announce_validator_builder)),
|
||||
finality_proof_request_builder: None,
|
||||
finality_proof_provider: None,
|
||||
config: ¶chain_config,
|
||||
client: client.clone(),
|
||||
transaction_pool: transaction_pool.clone(),
|
||||
spawn_handle: task_manager.spawn_handle(),
|
||||
import_queue,
|
||||
on_demand: None,
|
||||
block_announce_validator_builder: Some(Box::new(block_announce_validator_builder)),
|
||||
finality_proof_request_builder: None,
|
||||
finality_proof_provider: None,
|
||||
})?;
|
||||
|
||||
let rpc_extensions_builder = {
|
||||
let _client = client.clone();
|
||||
let client = client.clone();
|
||||
|
||||
Box::new(move |_deny_unsafe| {
|
||||
let io = jsonrpc_core::IoHandler::default();
|
||||
|
||||
// TODO: add this rpc when running the contracts runtime
|
||||
/*
|
||||
use pallet_contracts_rpc::{Contracts, ContractsApi};
|
||||
io.extend_with(
|
||||
ContractsApi::to_delegate(Contracts::new(client.clone()))
|
||||
);
|
||||
*/
|
||||
io
|
||||
})
|
||||
Box::new(move |_deny_unsafe| rpc_ext_builder(client.clone()))
|
||||
};
|
||||
|
||||
sc_service::spawn_tasks(sc_service::SpawnTasksParams {
|
||||
@@ -249,3 +259,49 @@ pub fn run_node(
|
||||
|
||||
Ok((task_manager, client))
|
||||
}
|
||||
|
||||
/// Start a normal parachain node.
|
||||
pub fn start_node(
|
||||
parachain_config: Configuration,
|
||||
collator_key: Arc<CollatorPair>,
|
||||
polkadot_config: polkadot_collator::Configuration,
|
||||
id: polkadot_primitives::v0::Id,
|
||||
validator: bool,
|
||||
) -> sc_service::error::Result<(
|
||||
TaskManager,
|
||||
Arc<TFullClient<Block, parachain_runtime::RuntimeApi, RuntimeExecutor>>,
|
||||
)> {
|
||||
start_node_impl::<parachain_runtime::RuntimeApi, RuntimeExecutor, _>(
|
||||
parachain_config,
|
||||
collator_key,
|
||||
polkadot_config,
|
||||
id,
|
||||
validator,
|
||||
|_| Default::default(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Start a contracts parachain node.
|
||||
pub fn start_contracts_node(
|
||||
parachain_config: Configuration,
|
||||
collator_key: Arc<CollatorPair>,
|
||||
polkadot_config: polkadot_collator::Configuration,
|
||||
id: polkadot_primitives::v0::Id,
|
||||
validator: bool,
|
||||
) -> sc_service::error::Result<TaskManager> {
|
||||
start_node_impl::<parachain_contracts_runtime::RuntimeApi, ContractsRuntimeExecutor, _>(
|
||||
parachain_config,
|
||||
collator_key,
|
||||
polkadot_config,
|
||||
id,
|
||||
validator,
|
||||
|client| {
|
||||
let mut io = jsonrpc_core::IoHandler::default();
|
||||
|
||||
use cumulus_pallet_contracts_rpc::{Contracts, ContractsApi};
|
||||
io.extend_with(ContractsApi::to_delegate(Contracts::new(client)));
|
||||
io
|
||||
},
|
||||
)
|
||||
.map(|r| r.0)
|
||||
}
|
||||
|
||||
@@ -51,7 +51,9 @@ static mut STORAGE: Option<Box<dyn Storage>> = None;
|
||||
/// Panics if the [`STORAGE`] is not initialized.
|
||||
fn with_storage<R>(call: impl FnOnce(&mut dyn Storage) -> R) -> R {
|
||||
let mut storage = unsafe {
|
||||
STORAGE.take().expect("`STORAGE` needs to be set before calling this function.")
|
||||
STORAGE
|
||||
.take()
|
||||
.expect("`STORAGE` needs to be set before calling this function.")
|
||||
};
|
||||
|
||||
let res = call(&mut *storage);
|
||||
@@ -142,7 +144,8 @@ pub fn validate_block<B: BlockT, E: ExecuteBlock<B>>(params: ValidationParams) -
|
||||
|
||||
// If in the course of block execution new validation code was set, insert
|
||||
// its scheduled upgrade so we can validate that block number later.
|
||||
let new_validation_code = with_storage(|storage| storage.get(NEW_VALIDATION_CODE)).map(ValidationCode);
|
||||
let new_validation_code =
|
||||
with_storage(|storage| storage.get(NEW_VALIDATION_CODE)).map(ValidationCode);
|
||||
if new_validation_code.is_some() && validation_function_params.code_upgrade_allowed.is_none() {
|
||||
panic!("Attempt to upgrade validation function when not permitted!");
|
||||
}
|
||||
@@ -154,9 +157,10 @@ pub fn validate_block<B: BlockT, E: ExecuteBlock<B>>(params: ValidationParams) -
|
||||
None => Vec::new(),
|
||||
};
|
||||
|
||||
let processed_downward_messages = with_storage(|storage| storage.get(PROCESSED_DOWNWARD_MESSAGES))
|
||||
.and_then(|v| Decode::decode(&mut &v[..]).ok())
|
||||
.unwrap_or_default();
|
||||
let processed_downward_messages =
|
||||
with_storage(|storage| storage.get(PROCESSED_DOWNWARD_MESSAGES))
|
||||
.and_then(|v| Decode::decode(&mut &v[..]).ok())
|
||||
.unwrap_or_default();
|
||||
|
||||
ValidationResult {
|
||||
head_data,
|
||||
@@ -266,13 +270,11 @@ impl<B: BlockT> Storage for WitnessStorage<B> {
|
||||
let witness_data = &self.witness_data;
|
||||
let storage_root = &self.storage_root;
|
||||
|
||||
let current_value = overlay.entry(key.to_vec()).or_insert_with(||
|
||||
read_trie_value::<Layout<HashFor<B>>, _>(
|
||||
witness_data,
|
||||
storage_root,
|
||||
key,
|
||||
).ok().flatten()
|
||||
);
|
||||
let current_value = overlay.entry(key.to_vec()).or_insert_with(|| {
|
||||
read_trie_value::<Layout<HashFor<B>>, _>(witness_data, storage_root, key)
|
||||
.ok()
|
||||
.flatten()
|
||||
});
|
||||
|
||||
let item = current_value.take().unwrap_or_default();
|
||||
*current_value = Some(
|
||||
|
||||
@@ -130,7 +130,7 @@ fn build_block_with_proof(
|
||||
built_block.block,
|
||||
built_block
|
||||
.proof
|
||||
.expect("We enabled proof recording before.")
|
||||
.expect("We enabled proof recording before."),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user