mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 16:31:07 +00:00
[contracts] make debug_message execution outcome invariant to node debug logging setting (#13197)
* update benchmark for seal_debug_message * add seal_debug_message_per_kb benchmark * un-fallable debug buffer: silently drops excessive and wrong utf-8 encoded messages * charge debug_message per byte of the message * improved benchmark * cap debug_message * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * Apply suggestions from code review Co-authored-by: Alexander Theißen <alex.theissen@me.com> * fix applied buggy suggestion * make sure i*1024 < MaxDebugBufferLen * fix schedule for our non-batched benchmark * Switch to a `wasmtime` fork with LTO linking failure workaround * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts --------- Co-authored-by: command-bot <> Co-authored-by: Alexander Theißen <alex.theissen@me.com> Co-authored-by: Jan Bujak <jan@parity.io>
This commit is contained in:
Generated
+19
-38
@@ -1186,8 +1186,7 @@ checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba"
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.92.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f3d54eab028f5805ae3b26fd60eca3f3a9cfb76b989d9bab173be3f61356cc3"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
@@ -1195,8 +1194,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.92.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2be1d5f2c3cca1efb691844bc1988b89c77291f13f778499a3f3c0cf49c0ed61"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"arrayvec 0.7.2",
|
||||
"bumpalo",
|
||||
@@ -1216,8 +1214,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.92.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9b1b1089750ce4005893af7ee00bb08a2cf1c9779999c0f7164cbc8ad2e0d2"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
]
|
||||
@@ -1225,14 +1222,12 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.92.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc5fbaec51de47297fd7304986fd53c8c0030abbe69728a60d72e1c63559318d"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.92.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dab984c94593f876090fae92e984bdcc74d9b1acf740ab5f79036001c65cba13"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -1240,8 +1235,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.92.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e0cb3102d21a2fe5f3210af608748ddd0cd09825ac12d42dc56ed5ed8725fe0"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
@@ -1252,14 +1246,12 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "cranelift-isle"
|
||||
version = "0.92.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72101dd1f441d629735143c41e00b3428f9267738176983ef588ff43382af0a0"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.92.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c22b0d9fcbe3fc5a1af9e7021b44ce42b930bcefac446ce22e02e8f9a0d67120"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"libc",
|
||||
@@ -1269,8 +1261,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "cranelift-wasm"
|
||||
version = "0.92.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bddebe32fb14fbfd9efa5f130ffb8f4665795de019928dcd7247b136c46f9249"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"cranelift-entity",
|
||||
@@ -11932,8 +11923,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "wasmtime"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e5b183a159484980138cc05231419c536d395a7b25c1802091310ea2f74276a"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
@@ -11960,8 +11950,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "wasmtime-asm-macros"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0aeb1cb256d76cf07b20264c808351c8b525ece56de1ef4d93f87a0aaf342db"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
@@ -11969,8 +11958,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "wasmtime-cache"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830570847f905b8f6d2ca635c33cf42ce701dd8e4abd7d1806c631f8f06e9e4b"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.13.1",
|
||||
@@ -11989,8 +11977,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "wasmtime-cranelift"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f7695d3814dcb508bf4d1c181a86ea6b97a209f6444478e95d86e2ffab8d1a3"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@@ -12010,8 +11997,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "wasmtime-environ"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5a2a5f0fb93aa837a727a48dd1076e8a9f882cc2fee20b433c04a18740ff63b"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-entity",
|
||||
@@ -12029,8 +12015,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "wasmtime-jit"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01c78f9fb2922dbb5a95f009539d4badb44866caeeb53d156bf2cf4d683c3afd"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"addr2line 0.17.0",
|
||||
"anyhow",
|
||||
@@ -12053,8 +12038,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "wasmtime-jit-debug"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67cacdb52a77b8c8e744e510beeabf0bd698b1c94c59eed33c52b3fbd19639b0"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"object 0.29.0",
|
||||
"once_cell",
|
||||
@@ -12064,8 +12048,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "wasmtime-jit-icache-coherence"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08fcba5ebd96da2a9f0747ab6337fe9788adfb3f63fa2c180520d665562d257e"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
@@ -12075,8 +12058,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "wasmtime-runtime"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0793210acf50d4c69182c916abaee1d423dc5d172cdfde6acfea2f9446725940"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cc",
|
||||
@@ -12099,8 +12081,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "wasmtime-types"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d015ba8b231248a811e323cf7a525cd3f982d4be0b9e62d27685102e5f12b1"
|
||||
source = "git+https://github.com/paritytech/wasmtime.git?branch=v5.0.0_lto_fix#8a02705ad378108e43abe23c538688adf73f3b71"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
"serde",
|
||||
|
||||
@@ -25,7 +25,7 @@ wasmtime = { version = "5.0.0", default-features = false, features = [
|
||||
"jitdump",
|
||||
"parallel-compilation",
|
||||
"pooling-allocator"
|
||||
] }
|
||||
], git = "https://github.com/paritytech/wasmtime.git", branch = "v5.0.0_lto_fix" }
|
||||
anyhow = "1.0.68"
|
||||
sc-allocator = { version = "4.1.0-dev", path = "../../allocator" }
|
||||
sc-executor-common = { version = "0.10.0-dev", path = "../common" }
|
||||
|
||||
@@ -1,18 +1,28 @@
|
||||
;; Emit a "Hello World!" debug message
|
||||
;; Emit a debug message with an invalid utf-8 code
|
||||
(module
|
||||
(import "seal0" "seal_debug_message" (func $seal_debug_message (param i32 i32) (result i32)))
|
||||
(import "env" "memory" (memory 1 1))
|
||||
|
||||
(data (i32.const 0) "\fc")
|
||||
|
||||
(func (export "call")
|
||||
(call $seal_debug_message
|
||||
(i32.const 0) ;; Pointer to the text buffer
|
||||
(i32.const 12) ;; The size of the buffer
|
||||
(func $assert_eq (param i32 i32)
|
||||
(block $ok
|
||||
(br_if $ok
|
||||
(i32.eq (get_local 0) (get_local 1))
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
;; the above call traps because we supplied invalid utf8
|
||||
unreachable
|
||||
)
|
||||
|
||||
(func (export "call")
|
||||
(call $assert_eq
|
||||
(call $seal_debug_message
|
||||
(i32.const 0) ;; Pointer to the text buffer
|
||||
(i32.const 12) ;; The size of the buffer
|
||||
)
|
||||
(i32.const 0) ;; Success return code
|
||||
)
|
||||
)
|
||||
|
||||
(func (export "deploy"))
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
(i32.const 0) ;; Pointer to the text buffer
|
||||
(i32.const 12) ;; The size of the buffer
|
||||
)
|
||||
(i32.const 9) ;; LoggingDisabled return code
|
||||
(i32.const 0) ;; Success return code
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -910,13 +910,12 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
// The size of the supplied message does not influence the weight because as it is never
|
||||
// processed during on-chain execution: It is only ever read during debugging which happens
|
||||
// when the contract is called as RPC where weights do not matter.
|
||||
// Benchmark debug_message call with zero input data.
|
||||
// Whereas this function is used in RPC mode only, it still should be secured
|
||||
// against an excessive use.
|
||||
#[pov_mode = Ignored]
|
||||
seal_debug_message {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let max_bytes = code::max_pages::<T>() * 64 * 1024;
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
memory: Some(ImportedMemory { min_pages: 1, max_pages: 1 }),
|
||||
imported_functions: vec![ImportedFunction {
|
||||
@@ -927,15 +926,75 @@ benchmarks! {
|
||||
}],
|
||||
call_body: Some(body::repeated(r * API_BENCHMARK_BATCH_SIZE, &[
|
||||
Instruction::I32Const(0), // value_ptr
|
||||
Instruction::I32Const(max_bytes as i32), // value_len
|
||||
Instruction::I32Const(0), // value_len
|
||||
Instruction::Call(0),
|
||||
Instruction::Drop,
|
||||
])),
|
||||
.. Default::default()
|
||||
});
|
||||
let instance = Contract::<T>::new(code, vec![])?;
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
}: {
|
||||
<Contracts<T>>::bare_call(
|
||||
instance.caller,
|
||||
instance.account_id,
|
||||
0u32.into(),
|
||||
Weight::MAX,
|
||||
None,
|
||||
vec![],
|
||||
true,
|
||||
Determinism::Deterministic,
|
||||
)
|
||||
.result?;
|
||||
}
|
||||
|
||||
seal_debug_message_per_kb {
|
||||
// Vary size of input in kilobytes up to maximum allowed contract memory
|
||||
// or maximum allowed debug buffer size, whichever is less.
|
||||
let i in 0 .. (T::Schedule::get().limits.memory_pages * 64).min(T::MaxDebugBufferLen::get() / 1024);
|
||||
// We benchmark versus messages containing printable ASCII codes.
|
||||
// About 1Kb goes to the instrumented contract code instructions,
|
||||
// whereas all the space left we use for the initialization of the debug messages data.
|
||||
let message = (0 .. T::MaxCodeLen::get() - 1024).zip((32..127).cycle()).map(|i| i.1).collect::<Vec<_>>();
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
memory: Some(ImportedMemory {
|
||||
min_pages: T::Schedule::get().limits.memory_pages,
|
||||
max_pages: T::Schedule::get().limits.memory_pages,
|
||||
}),
|
||||
imported_functions: vec![ImportedFunction {
|
||||
module: "seal0",
|
||||
name: "seal_debug_message",
|
||||
params: vec![ValueType::I32, ValueType::I32],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
data_segments: vec![
|
||||
DataSegment {
|
||||
offset: 0,
|
||||
value: message,
|
||||
},
|
||||
],
|
||||
call_body: Some(body::plain(vec![
|
||||
Instruction::I32Const(0), // value_ptr
|
||||
Instruction::I32Const((i * 1024) as i32), // value_len increments by i Kb
|
||||
Instruction::Call(0),
|
||||
Instruction::Drop,
|
||||
Instruction::End,
|
||||
])),
|
||||
..Default::default()
|
||||
});
|
||||
let instance = Contract::<T>::new(code, vec![])?;
|
||||
}: {
|
||||
<Contracts<T>>::bare_call(
|
||||
instance.caller,
|
||||
instance.account_id,
|
||||
0u32.into(),
|
||||
Weight::MAX,
|
||||
None,
|
||||
vec![],
|
||||
true,
|
||||
Determinism::Deterministic,
|
||||
)
|
||||
.result?;
|
||||
}
|
||||
|
||||
// Only the overhead of calling the function itself with minimal arguments.
|
||||
// The contract is a bit more complex because it needs to use different keys in order
|
||||
|
||||
@@ -1336,31 +1336,16 @@ where
|
||||
|
||||
fn append_debug_buffer(&mut self, msg: &str) -> bool {
|
||||
if let Some(buffer) = &mut self.debug_message {
|
||||
let err_msg = scale_info::prelude::format!(
|
||||
"Debug message too big (size={}) for debug buffer (bound={})",
|
||||
msg.len(),
|
||||
DebugBufferVec::<T>::bound(),
|
||||
);
|
||||
|
||||
let mut msg = if msg.len() > DebugBufferVec::<T>::bound() {
|
||||
err_msg.bytes()
|
||||
} else {
|
||||
msg.bytes()
|
||||
};
|
||||
|
||||
let num_drain = {
|
||||
let capacity = DebugBufferVec::<T>::bound().checked_sub(buffer.len()).expect(
|
||||
"
|
||||
`buffer` is of type `DebugBufferVec`,
|
||||
`DebugBufferVec` is a `BoundedVec`,
|
||||
`BoundedVec::len()` <= `BoundedVec::bound()`;
|
||||
qed
|
||||
",
|
||||
);
|
||||
msg.len().saturating_sub(capacity).min(buffer.len())
|
||||
};
|
||||
buffer.drain(0..num_drain);
|
||||
buffer.try_extend(&mut msg).ok();
|
||||
buffer
|
||||
.try_extend(&mut msg.bytes())
|
||||
.map_err(|_| {
|
||||
log::debug!(
|
||||
target: "runtime::contracts",
|
||||
"Debug buffer (of {} bytes) exhausted!",
|
||||
DebugBufferVec::<T>::bound(),
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -2603,9 +2588,11 @@ mod tests {
|
||||
exec_success()
|
||||
});
|
||||
|
||||
// Pre-fill the buffer up to its limit
|
||||
let mut debug_buffer =
|
||||
DebugBufferVec::<Test>::try_from(vec![0u8; DebugBufferVec::<Test>::bound()]).unwrap();
|
||||
// Pre-fill the buffer almost up to its limit, leaving not enough space to the message
|
||||
let debug_buf_before =
|
||||
DebugBufferVec::<Test>::try_from(vec![0u8; DebugBufferVec::<Test>::bound() - 5])
|
||||
.unwrap();
|
||||
let mut debug_buf_after = debug_buf_before.clone();
|
||||
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
let schedule: Schedule<Test> = <Test as Config>::Schedule::get();
|
||||
@@ -2622,15 +2609,11 @@ mod tests {
|
||||
&schedule,
|
||||
0,
|
||||
vec![],
|
||||
Some(&mut debug_buffer),
|
||||
Some(&mut debug_buf_after),
|
||||
Determinism::Deterministic,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
&String::from_utf8(debug_buffer[DebugBufferVec::<Test>::bound() - 17..].to_vec())
|
||||
.unwrap(),
|
||||
"overflowing bytes"
|
||||
);
|
||||
assert_eq!(debug_buf_before, debug_buf_after);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -912,8 +912,6 @@ pub mod pallet {
|
||||
///
|
||||
/// This can be triggered by a call to `seal_terminate`.
|
||||
TerminatedInConstructor,
|
||||
/// The debug message specified to `seal_debug_message` does contain invalid UTF-8.
|
||||
DebugMessageInvalidUTF8,
|
||||
/// A call tried to invoke a contract that is flagged as non-reentrant.
|
||||
ReentranceDenied,
|
||||
/// Origin doesn't have enough balance to pay the required storage deposits.
|
||||
|
||||
@@ -323,6 +323,9 @@ pub struct HostFnWeights<T: Config> {
|
||||
/// Weight of calling `seal_debug_message`.
|
||||
pub debug_message: Weight,
|
||||
|
||||
/// Weight of calling `seal_debug_message` per byte of the message.
|
||||
pub debug_message_per_byte: Weight,
|
||||
|
||||
/// Weight of calling `seal_set_storage`.
|
||||
pub set_storage: Weight,
|
||||
|
||||
@@ -644,6 +647,7 @@ impl<T: Config> Default for HostFnWeights<T> {
|
||||
1
|
||||
)),
|
||||
debug_message: to_weight!(cost_batched!(seal_debug_message)),
|
||||
debug_message_per_byte: to_weight!(cost_byte!(seal_debug_message_per_kb)),
|
||||
set_storage: to_weight!(cost_batched!(seal_set_storage), 1024u64),
|
||||
set_code_hash: to_weight!(cost_batched!(seal_set_code_hash)),
|
||||
set_storage_per_new_byte: to_weight!(cost_byte_batched!(seal_set_storage_per_new_kb)),
|
||||
|
||||
@@ -2714,7 +2714,8 @@ fn debug_message_invalid_utf8() {
|
||||
true,
|
||||
Determinism::Deterministic,
|
||||
);
|
||||
assert_err!(result.result, <Error<Test>>::DebugMessageInvalidUTF8);
|
||||
assert_ok!(result.result);
|
||||
assert!(result.debug_message.is_empty());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2363,13 +2363,8 @@ mod tests {
|
||||
"#;
|
||||
let mut ext = MockExt::default();
|
||||
let result = execute(CODE_DEBUG_MESSAGE_FAIL, vec![], &mut ext);
|
||||
assert_eq!(
|
||||
result,
|
||||
Err(ExecError {
|
||||
error: Error::<Test>::DebugMessageInvalidUTF8.into(),
|
||||
origin: ErrorOrigin::Caller,
|
||||
})
|
||||
);
|
||||
assert_ok!(result);
|
||||
assert!(ext.debug_buffer.is_empty());
|
||||
}
|
||||
|
||||
const CODE_CALL_RUNTIME: &str = r#"
|
||||
|
||||
@@ -21,7 +21,7 @@ use crate::{
|
||||
exec::{ExecError, ExecResult, Ext, FixSizedKey, TopicOf, VarSizedKey},
|
||||
gas::{ChargedAmount, Token},
|
||||
schedule::HostFnWeights,
|
||||
BalanceOf, CodeHash, Config, Error, SENTINEL,
|
||||
BalanceOf, CodeHash, Config, DebugBufferVec, Error, SENTINEL,
|
||||
};
|
||||
|
||||
use bitflags::bitflags;
|
||||
@@ -114,9 +114,6 @@ pub enum ReturnCode {
|
||||
CodeNotFound = 7,
|
||||
/// The contract that was called is no contract (a plain account).
|
||||
NotCallable = 8,
|
||||
/// The call to `seal_debug_message` had no effect because debug message
|
||||
/// recording was disabled.
|
||||
LoggingDisabled = 9,
|
||||
/// The call dispatched by `seal_call_runtime` was executed but returned an error.
|
||||
CallRuntimeReturnedError = 10,
|
||||
/// ECDSA pubkey recovery failed (most probably wrong recovery id or signature), or
|
||||
@@ -229,8 +226,8 @@ pub enum RuntimeCosts {
|
||||
Random,
|
||||
/// Weight of calling `seal_deposit_event` with the given number of topics and event size.
|
||||
DepositEvent { num_topic: u32, len: u32 },
|
||||
/// Weight of calling `seal_debug_message`.
|
||||
DebugMessage,
|
||||
/// Weight of calling `seal_debug_message` per byte of passed message.
|
||||
DebugMessage(u32),
|
||||
/// Weight of calling `seal_set_storage` for the given storage item sizes.
|
||||
SetStorage { old_bytes: u32, new_bytes: u32 },
|
||||
/// Weight of calling `seal_clear_storage` per cleared byte.
|
||||
@@ -309,7 +306,9 @@ impl RuntimeCosts {
|
||||
.deposit_event
|
||||
.saturating_add(s.deposit_event_per_topic.saturating_mul(num_topic.into()))
|
||||
.saturating_add(s.deposit_event_per_byte.saturating_mul(len.into())),
|
||||
DebugMessage => s.debug_message,
|
||||
DebugMessage(len) => s
|
||||
.debug_message
|
||||
.saturating_add(s.deposit_event_per_byte.saturating_mul(len.into())),
|
||||
SetStorage { new_bytes, old_bytes } => s
|
||||
.set_storage
|
||||
.saturating_add(s.set_storage_per_new_byte.saturating_mul(new_bytes.into()))
|
||||
@@ -2054,7 +2053,7 @@ pub mod env {
|
||||
_delta_ptr: u32,
|
||||
_delta_count: u32,
|
||||
) -> Result<(), TrapReason> {
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage)?;
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage(0))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -2076,7 +2075,7 @@ pub mod env {
|
||||
_delta_ptr: u32,
|
||||
_delta_count: u32,
|
||||
) -> Result<(), TrapReason> {
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage)?;
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage(0))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -2094,7 +2093,7 @@ pub mod env {
|
||||
_value_ptr: u32,
|
||||
_value_len: u32,
|
||||
) -> Result<(), TrapReason> {
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage)?;
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage(0))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -2108,7 +2107,7 @@ pub mod env {
|
||||
#[prefixed_alias]
|
||||
#[deprecated]
|
||||
fn set_rent_allowance(ctx: _, _memory: _, _value_ptr: u32) -> Result<(), TrapReason> {
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage)?;
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage(0))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -2362,7 +2361,7 @@ pub mod env {
|
||||
/// Emit a custom debug message.
|
||||
///
|
||||
/// No newlines are added to the supplied message.
|
||||
/// Specifying invalid UTF-8 triggers a trap.
|
||||
/// Specifying invalid UTF-8 just drops the message with no trap.
|
||||
///
|
||||
/// This is a no-op if debug message recording is disabled which is always the case
|
||||
/// when the code is executing on-chain. The message is interpreted as UTF-8 and
|
||||
@@ -2383,15 +2382,15 @@ pub mod env {
|
||||
str_ptr: u32,
|
||||
str_len: u32,
|
||||
) -> Result<ReturnCode, TrapReason> {
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage)?;
|
||||
let str_len = str_len.min(DebugBufferVec::<E::T>::bound() as u32);
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage(str_len))?;
|
||||
if ctx.ext.append_debug_buffer("") {
|
||||
let data = ctx.read_sandbox_memory(memory, str_ptr, str_len)?;
|
||||
let msg =
|
||||
core::str::from_utf8(&data).map_err(|_| <Error<E::T>>::DebugMessageInvalidUTF8)?;
|
||||
ctx.ext.append_debug_buffer(msg);
|
||||
return Ok(ReturnCode::Success)
|
||||
if let Some(msg) = core::str::from_utf8(&data).ok() {
|
||||
ctx.ext.append_debug_buffer(msg);
|
||||
}
|
||||
}
|
||||
Ok(ReturnCode::LoggingDisabled)
|
||||
Ok(ReturnCode::Success)
|
||||
}
|
||||
|
||||
/// Call some dispatchable of the runtime.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "3.2.2", default-features =
|
||||
impl-trait-for-tuples = "0.2.2"
|
||||
log = { version = "0.4.17", optional = true }
|
||||
wasmi = { version = "0.13", optional = true }
|
||||
wasmtime = { version = "5.0.0", default-features = false, optional = true }
|
||||
wasmtime = { version = "5.0.0", default-features = false, optional = true, git = "https://github.com/paritytech/wasmtime.git", branch = "v5.0.0_lto_fix" }
|
||||
anyhow = { version = "1.0.68", optional = true }
|
||||
sp-std = { version = "5.0.0", default-features = false, path = "../std" }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user