Ditch the input buffer (#2911)

* Pass input data via the scratch buffer.

Remove calls to ext_input_*.

* Fix tests and docs

* Bump the version.

* Remove ext_input_* from COMPLEXITY.md

* Return back the length check and add more comments

* Update the documentation of the scratch buffer.

* Fix a silly mistake.
This commit is contained in:
Sergei Pepyakin
2019-06-20 17:06:12 +02:00
committed by GitHub
parent 32a14ba2b8
commit 83d3881542
6 changed files with 89 additions and 88 deletions
+1 -1
View File
@@ -134,7 +134,7 @@ impl<'a, T: Trait> crate::exec::Vm<T> for WasmVm<'a, T> {
let mut runtime = Runtime::new(
ext,
input_data,
input_data.to_vec(),
empty_output_buf,
&self.schedule,
memory,
+13 -38
View File
@@ -39,9 +39,8 @@ enum SpecialTrap {
}
/// Can only be used for one call.
pub(crate) struct Runtime<'a, 'data, E: Ext + 'a> {
pub(crate) struct Runtime<'a, E: Ext + 'a> {
ext: &'a mut E,
input_data: &'data [u8],
// A VM can return a result only once and only by value. So
// we wrap output buffer to make it possible to take the buffer out.
empty_output_buf: Option<EmptyOutputBuf>,
@@ -51,10 +50,10 @@ pub(crate) struct Runtime<'a, 'data, E: Ext + 'a> {
gas_meter: &'a mut GasMeter<E::T>,
special_trap: Option<SpecialTrap>,
}
impl<'a, 'data, E: Ext + 'a> Runtime<'a, 'data, E> {
impl<'a, E: Ext + 'a> Runtime<'a, E> {
pub(crate) fn new(
ext: &'a mut E,
input_data: &'data [u8],
input_data: Vec<u8>,
empty_output_buf: EmptyOutputBuf,
schedule: &'a Schedule<<E::T as Trait>::Gas>,
memory: sandbox::Memory,
@@ -62,9 +61,9 @@ impl<'a, 'data, E: Ext + 'a> Runtime<'a, 'data, E> {
) -> Self {
Runtime {
ext,
input_data,
empty_output_buf: Some(empty_output_buf),
scratch_buf: Vec::new(),
// Put the input data into the scratch buffer immediately.
scratch_buf: input_data,
schedule,
memory,
gas_meter,
@@ -443,6 +442,8 @@ define_env!(Env, <E: Ext>,
// Save a data buffer as a result of the execution, terminate the execution and return a
// successful result to the caller.
//
// This is the only way to return a data buffer to the caller.
ext_return(ctx, data_ptr: u32, data_len: u32) => {
match ctx
.gas_meter
@@ -573,45 +574,19 @@ define_env!(Env, <E: Ext>,
Ok(())
},
// Returns the size of the input buffer.
ext_input_size(ctx) -> u32 => {
Ok(ctx.input_data.len() as u32)
},
// Copy data from the input buffer starting from `offset` with length `len` into the contract memory.
// The region at which the data should be put is specified by `dest_ptr`.
ext_input_copy(ctx, dest_ptr: u32, offset: u32, len: u32) => {
let offset = offset as usize;
if offset > ctx.input_data.len() {
// Offset can't be larger than input buffer length.
return Err(sandbox::HostError);
}
// This can't panic since `offset <= ctx.input_data.len()`.
let src = &ctx.input_data[offset..];
if src.len() != len as usize {
return Err(sandbox::HostError);
}
// Finally, perform the write.
write_sandbox_memory(
ctx.schedule,
ctx.gas_meter,
&ctx.memory,
dest_ptr,
src,
)?;
Ok(())
},
// Returns the size of the scratch buffer.
//
// For more details on the scratch buffer see `ext_scratch_copy`.
ext_scratch_size(ctx) -> u32 => {
Ok(ctx.scratch_buf.len() as u32)
},
// Copy data from the scratch buffer starting from `offset` with length `len` into the contract memory.
// The region at which the data should be put is specified by `dest_ptr`.
//
// In order to get size of the scratch buffer use `ext_scratch_size`. At the start of contract
// execution, the scratch buffer is filled with the input data. Whenever a contract calls
// function that uses the scratch buffer the contents of the scratch buffer are overwritten.
ext_scratch_copy(ctx, dest_ptr: u32, offset: u32, len: u32) => {
let offset = offset as usize;
if offset > ctx.scratch_buf.len() {