Introduce ext_println to contract runtime (#2239)

* Implement `ext_println` in contract runtime

* Only allow contracts to import `ext_println` on dev chains

* Configure dev chain to allow contracts with `ext_println`

* Increment spec version

* Docs

* Rename config to the more specific enable_println
This commit is contained in:
Andrew Jones
2019-04-11 14:49:17 +01:00
committed by Sergei Pepyakin
parent 18df051947
commit 1e0c1d8850
5 changed files with 75 additions and 14 deletions
@@ -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_println && 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)
@@ -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 {
@@ -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_println = true;
let r = prepare_contract::<Test, TestEnv>(wasm.as_ref(), &schedule);
assert_matches!(r, Ok(_));
}
}
mod entrypoints {
@@ -628,4 +628,15 @@ define_env!(Env, <E: Ext>,
Ok(())
},
// Prints utf8 encoded string from the data buffer.
// Only available on `--dev` chains.
// This function may be removed at any time, superseded by a more general contract debugging feature.
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);
}
Ok(())
},
);