Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Introduce ext_println to contract runtime #2239

Merged
merged 6 commits into from
Apr 11, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 20 additions & 13 deletions node/cli/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ pub fn testnet_genesis(
initial_authorities: Vec<(AccountId, AccountId, AuthorityId)>,
root_key: AccountId,
endowed_accounts: Option<Vec<AccountId>>,
enable_contract_debug: bool,
ascjones marked this conversation as resolved.
Show resolved Hide resolved
) -> GenesisConfig {
let endowed_accounts: Vec<AccountId> = endowed_accounts.unwrap_or_else(|| {
vec![
Expand All @@ -237,6 +238,22 @@ pub fn testnet_genesis(
const STASH: u128 = 1 << 20;
const ENDOWMENT: u128 = 1 << 20;

let mut contract_config = ContractConfig {
transaction_base_fee: 1,
transaction_byte_fee: 0,
transfer_fee: 0,
creation_fee: 0,
contract_fee: 21,
call_base_fee: 135,
create_base_fee: 175,
gas_price: 1,
max_depth: 1024,
block_gas_limit: 10_000_000,
current_schedule: Default::default(),
};
// this should only be enabled on development chains
contract_config.current_schedule.enable_debug = enable_contract_debug;

GenesisConfig {
consensus: Some(ConsensusConfig {
code: include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm").to_vec(),
Expand Down Expand Up @@ -308,19 +325,7 @@ pub fn testnet_genesis(
spend_period: 12 * 60 * 24,
burn: Permill::from_percent(50),
}),
contract: Some(ContractConfig {
transaction_base_fee: 1,
transaction_byte_fee: 0,
transfer_fee: 0,
creation_fee: 0,
contract_fee: 21,
call_base_fee: 135,
create_base_fee: 175,
gas_price: 1,
max_depth: 1024,
block_gas_limit: 10_000_000,
current_schedule: Default::default(),
}),
contract: Some(contract_config),
sudo: Some(SudoConfig {
key: root_key,
}),
Expand All @@ -337,6 +342,7 @@ fn development_config_genesis() -> GenesisConfig {
],
get_account_id_from_seed("Alice"),
None,
true,
)
}

Expand All @@ -353,6 +359,7 @@ fn local_testnet_genesis() -> GenesisConfig {
],
get_account_id_from_seed("Alice"),
None,
false,
)
}

Expand Down
2 changes: 1 addition & 1 deletion node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("node"),
impl_name: create_runtime_str!("substrate-node"),
authoring_version: 10,
spec_version: 58,
spec_version: 59,
impl_version: 59,
apis: RUNTIME_API_VERSIONS,
};
Expand Down
5 changes: 5 additions & 0 deletions srml/contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,10 @@ pub struct Schedule<Gas> {
/// What is the maximal memory pages amount is allowed to have for
/// a contract.
pub max_memory_pages: u32,

/// Whether debug features are enabled for contracts.
/// MUST only be enabled for `dev` chains, NOT for production chains
pub enable_debug: bool,
}

impl<Gas: As<u64>> Default for Schedule<Gas> {
Expand All @@ -543,6 +547,7 @@ impl<Gas: As<u64>> Default for Schedule<Gas> {
sandbox_data_write_cost: Gas::sa(1),
max_stack_height: 64 * 1024,
max_memory_pages: 16,
enable_debug: false,
}
}
}
38 changes: 38 additions & 0 deletions srml/contract/src/wasm/prepare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,12 @@ impl<'a, Gas: 'a + As<u32> + Clone> ContractModule<'a, Gas> {
.get(*type_idx as usize)
.ok_or_else(|| "validation: import entry points to a non-existent type")?;

// We disallow importing `ext_println` unless debug features are enabled,
// which should only be allowed on a dev chain
if !self.schedule.enable_debug && import.field().as_bytes() == b"ext_println" {
return Err("module imports `ext_println` but debug features disabled");
}

// We disallow importing `gas` function here since it is treated as implementation detail.
if import.field().as_bytes() == b"gas"
|| !C::can_satisfy(import.field().as_bytes(), func_ty)
Expand Down Expand Up @@ -347,6 +353,8 @@ mod tests {
gas(_ctx, _amount: u32) => { unreachable!(); },

nop(_ctx, _unused: u64) => { unreachable!(); },

ext_println(_ctx, _ptr: u32, _len: u32) => { unreachable!(); },
);

macro_rules! prepare_test {
Expand Down Expand Up @@ -572,6 +580,36 @@ mod tests {
"#,
Err("module imports a non-existent function")
);

prepare_test!(ext_println_debug_disabled,
r#"
(module
(import "env" "ext_println" (func $ext_println (param i32 i32)))

(func (export "call"))
(func (export "deploy"))
)
"#,
Err("module imports `ext_println` but debug features disabled")
);

#[test]
fn ext_println_debug_enabled() {
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();
let mut schedule = Schedule::<u64>::default();
schedule.enable_debug = true;
let r = prepare_contract::<Test, TestEnv>(wasm.as_ref(), &schedule);
assert_matches!(r, Ok(_));
}
}

mod entrypoints {
Expand Down
12 changes: 12 additions & 0 deletions srml/contract/src/wasm/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -628,4 +628,16 @@ define_env!(Env, <E: Ext>,

Ok(())
},

// Prints utf8 encoded string from the data buffer.
// MUST only be called from contracts deployed to `--dev` chains, NOT for use in production chains.
// This function may be removed in the future and superseded by "Diagnostic Runtimes":
ascjones marked this conversation as resolved.
Show resolved Hide resolved
// https://github.com/paritytech/substrate/issues/2082
ext_println(ctx, str_ptr: u32, str_len: u32) => {
let data = read_sandbox_memory(ctx, str_ptr, str_len)?;
if let Ok(utf8) = core::str::from_utf8(&data) {
runtime_io::print(utf8);
bkchr marked this conversation as resolved.
Show resolved Hide resolved
}
Ok(())
},
);