[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:
Sasha Gryaznov
2023-02-14 20:28:34 +02:00
committed by GitHub
parent df24729d74
commit 53b7778599
13 changed files with 1373 additions and 1065 deletions
+17 -34
View File
@@ -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);
});
}