seal_delegate_call api function (support for library contracts) (#10617)

* seal_call_code implementation

- tests
- benchmark

* Addressing @xgreenx's comments

* Fix test-linux-stable-int

* Rename seal_call_code to seal_delegate_call

* Pass value unchanged into lib contract

* Address @athei's comments

- whitespace .wat issues
- wrong/missing .wat comments
- redundant .wat calls/declarations

- change order of functions (seal_delegate_call right after seal_call)
  in decls, tests, benchmark
- fix comments, move doc comments to enum variants
- remove unnecessary empty lines

- rename runtime cost DelegateCall to DelegateCallBase
- do not set CallFlags::ALLOW_REENTRY for delegate_call

* Do not pass CallFlags::ALLOWS_REENTRY for delegate_call

* Update comment for seal_delegate_call and CallFlags

* Addressing @athei's comments (minor)

* Allow reentry for a new frame after delegate_call (revert)

* Same seal_caller and seal_value_transferred for lib contract

- test
- refactor frame args due to review
- logic for seal_caller (please review)

* Put caller on frame for delegate_call, minor fixes

* Update comment for delegate_call

* Addressing @athei's comments

* Update weights generated by benchmark

* Improve comments

* Address @HCastano's comments

* Update weights, thanks @joao-paulo-parity

* Improve InvalidCallFlags error comment
This commit is contained in:
Yarik Bratashchuk
2022-02-08 13:43:32 +02:00
committed by GitHub
parent 1d62516fad
commit d14e1c641e
10 changed files with 574 additions and 49 deletions
@@ -1474,6 +1474,58 @@ benchmarks! {
let origin = RawOrigin::Signed(instance.caller.clone());
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
seal_delegate_call {
let r in 0 .. API_BENCHMARK_BATCHES;
let hashes = (0..r * API_BENCHMARK_BATCH_SIZE)
.map(|i| {
let code = WasmModule::<T>::dummy_with_bytes(i);
Contracts::<T>::store_code_raw(code.code, whitelisted_caller())?;
Ok(code.hash)
})
.collect::<Result<Vec<_>, &'static str>>()?;
let hash_len = hashes.get(0).map(|x| x.encode().len()).unwrap_or(0);
let hashes_bytes = hashes.iter().flat_map(|x| x.encode()).collect::<Vec<_>>();
let hashes_len = hashes_bytes.len();
let hashes_offset = 0;
let code = WasmModule::<T>::from(ModuleDefinition {
memory: Some(ImportedMemory::max::<T>()),
imported_functions: vec![ImportedFunction {
module: "__unstable__",
name: "seal_delegate_call",
params: vec![
ValueType::I32,
ValueType::I32,
ValueType::I32,
ValueType::I32,
ValueType::I32,
ValueType::I32,
],
return_type: Some(ValueType::I32),
}],
data_segments: vec![
DataSegment {
offset: hashes_offset as u32,
value: hashes_bytes,
},
],
call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![
Regular(Instruction::I32Const(0)), // flags
Counter(hashes_offset as u32, hash_len as u32), // code_hash_ptr
Regular(Instruction::I32Const(0)), // input_data_ptr
Regular(Instruction::I32Const(0)), // input_data_len
Regular(Instruction::I32Const(u32::max_value() as i32)), // output_ptr
Regular(Instruction::I32Const(0)), // output_len_ptr
Regular(Instruction::Call(0)),
Regular(Instruction::Drop),
])),
.. Default::default()
});
let instance = Contract::<T>::new(code, vec![])?;
let callee = instance.addr.clone();
let origin = RawOrigin::Signed(instance.caller.clone());
}: call(origin, callee, 0u32.into(), Weight::MAX, None, vec![])
seal_call_per_transfer_input_output_kb {
let t in 0 .. 1;
let i in 0 .. code::max_pages::<T>() * 64;