Skip to content

Commit f2a7260

Browse files
authored
Merge pull request #4941 from namada-net/tiago/tx-wasm-panic-extract-from-guest
Pull panic info from tx wasm guest execution
2 parents 3a2d80c + 7f030a6 commit f2a7260

File tree

45 files changed

+229
-21
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+229
-21
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Pull panic info from tx wasm guest execution.
2+
([\#4941](https://github.com/namada-net/namada/pull/4941))

Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,12 @@ build-wasm-scripts:
335335
make opt-wasm
336336
make checksum-wasm
337337

338+
build-wasm-scripts-with-unwind:
339+
rm $(wasms)/*.wasm || true
340+
make -C $(wasms) release-unwind
341+
make opt-wasm
342+
make checksum-wasm
343+
338344
# Debug build the validity predicate and transactions wasm
339345
debug-wasm-scripts:
340346
rm wasm/*.wasm || true
@@ -348,6 +354,11 @@ build-wasm-tests-scripts:
348354
make -C $(wasms_for_tests)
349355
make opt-wasm-tests
350356

357+
build-wasm-tests-scripts-with-unwind:
358+
rm $(wasms_for_tests)/*.wasm || true
359+
make -C $(wasms_for_tests) release-unwind
360+
make opt-wasm-tests
361+
351362
# Debug build the validity predicate and transactions wasm for tests
352363
debug-wasm-tests-scripts:
353364
rm $(wasms_for_tests)/*.wasm || true

crates/macros/src/lib.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,51 @@ pub fn transaction(_attr: TokenStream, input: TokenStream) -> TokenStream {
5252
// to "fake" it.
5353
let mut ctx = unsafe { namada_tx_prelude::Ctx::new() };
5454

55+
// Add a custom panic hook, in order to receive detailed
56+
// information on the host of panicking transactions, to
57+
// improve debugging
58+
#[cfg(all(
59+
target_family = "wasm",
60+
feature = "debug-panic-hook"
61+
))]
62+
std::panic::set_hook(Box::new(|panic_info| {
63+
let mut ctx = unsafe { namada_tx_prelude::Ctx::new() };
64+
ctx.yield_value({
65+
use std::fmt::Write;
66+
67+
let mut buf = "Panic occurred".to_owned();
68+
69+
// Append panic location
70+
if let Some(loc) = panic_info.location() {
71+
_ = write!(
72+
&mut buf,
73+
" in file {:?} at line {}",
74+
loc.file(),
75+
loc.line()
76+
);
77+
}
78+
79+
// Append panic message
80+
if let Some(reason) = panic_info
81+
.payload()
82+
.downcast_ref::<&str>()
83+
.map(|&s| s)
84+
.or_else(|| {
85+
panic_info
86+
.payload()
87+
.downcast_ref::<String>()
88+
.map(String::as_str)
89+
})
90+
{
91+
_ = write!(&mut buf, ": {reason}");
92+
}
93+
94+
// TODO(namada#2980): pass some proper error from txs, instead of a string
95+
buf.serialize_to_vec()
96+
});
97+
core::arch::wasm32::unreachable()
98+
}));
99+
55100
match #ident(&mut ctx, tx_data) {
56101
Ok(()) => 1,
57102
Err(err) => {

crates/vm/src/wasm/run.rs

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -341,13 +341,7 @@ where
341341
let ok = result.map_err(|err| {
342342
tracing::debug!("Tx WASM failed with {}", err);
343343

344-
match *sentinel.borrow() {
345-
TxSentinel::None => Error::RuntimeError(err),
346-
TxSentinel::OutOfGas => Error::GasError(err.to_string()),
347-
TxSentinel::InvalidCommitment => {
348-
Error::MissingSection(err.to_string())
349-
}
350-
}
344+
extract_tx_error(&mut yielded_value, &sentinel, Some(err))
351345
})?;
352346

353347
// NB: early drop this data to avoid memory errors
@@ -359,20 +353,47 @@ where
359353
let _store = RefCell::into_inner(store);
360354
Ok(verifiers)
361355
} else {
362-
let err = yielded_value.take().map_or_else(
363-
|| Ok("Execution ended abruptly with an unknown error".to_owned()),
364-
|borsh_encoded_err| {
365-
let tx_err = TxError::try_from_slice(&borsh_encoded_err)
366-
.map_err(|e| Error::ConversionError(e.to_string()))?;
367-
Ok(tx_err)
368-
},
369-
)?;
356+
Err(extract_tx_error(&mut yielded_value, &sentinel, None))
357+
}
358+
}
370359

371-
Err(match *sentinel.borrow() {
372-
TxSentinel::None => Error::TxError(err),
373-
TxSentinel::OutOfGas => Error::GasError(err),
374-
TxSentinel::InvalidCommitment => Error::MissingSection(err),
375-
})
360+
fn extract_tx_error(
361+
yielded_value: &mut Option<Vec<u8>>,
362+
sentinel: &RefCell<TxSentinel>,
363+
runtime_err: Option<wasmer::RuntimeError>,
364+
) -> Error {
365+
#[inline]
366+
fn take(
367+
yielded_value: &mut Option<Vec<u8>>,
368+
runtime_err: Option<wasmer::RuntimeError>,
369+
) -> Error {
370+
const UNKNOWN: &str = "Runtime panic caused execution to end abruptly";
371+
372+
let yielded_err = yielded_value.take().map(|borsh_encoded_err| {
373+
TxError::try_from_slice(&borsh_encoded_err).map_err(|err| {
374+
Error::ConversionError(format!(
375+
"Failed to extract yielded tx error: {err}"
376+
))
377+
})
378+
});
379+
380+
if let Some(result) = yielded_err {
381+
result.map_or_else(|err| err, Error::TxError)
382+
} else if let Some(err) = runtime_err {
383+
Error::RuntimeError(err)
384+
} else {
385+
Error::TxError(UNKNOWN.to_owned())
386+
}
387+
}
388+
389+
match *sentinel.borrow() {
390+
TxSentinel::OutOfGas => {
391+
Error::GasError(take(yielded_value, runtime_err).to_string())
392+
}
393+
TxSentinel::InvalidCommitment => {
394+
Error::MissingSection(take(yielded_value, runtime_err).to_string())
395+
}
396+
TxSentinel::None => take(yielded_value, runtime_err),
376397
}
377398
}
378399

wasm/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,8 @@ panic = "abort"
5050
# tell llvm to optimize for size (https://rustwasm.github.io/book/reference/code-size.html#tell-llvm-to-optimize-for-size-instead-of-speed)
5151
opt-level = 'z'
5252
strip = "debuginfo"
53+
54+
[profile.release_unwind]
55+
inherits = "release"
56+
# unwind on panics, to extract debug information
57+
panic = "unwind"

wasm/Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ all:
88
RUSTFLAGS='-C link-arg=-s' $(cargo) build --release --target wasm32-unknown-unknown --target-dir 'target'
99
cp target/wasm32-unknown-unknown/release/*.wasm .
1010

11+
release-unwind:
12+
RUSTFLAGS='-C link-arg=-s' $(cargo) build --features debug-panic-hook --profile release_unwind --target wasm32-unknown-unknown --target-dir 'target'
13+
cp target/wasm32-unknown-unknown/release_unwind/*.wasm .
14+
1115
debug:
1216
RUSTFLAGS='-C link-arg=-s' $(cargo) build --target wasm32-unknown-unknown --target-dir 'target'
1317
cp target/wasm32-unknown-unknown/debug/*.wasm .
@@ -42,4 +46,4 @@ test-with-coverage:
4246
-- -Z unstable-options --report-time
4347

4448

45-
.PHONY: all debug check clippy clippy-fix fmt fmt-check test clean deps
49+
.PHONY: all debug check clippy clippy-fix fmt fmt-check test clean deps

wasm/tx_become_validator/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ version.workspace = true
88

99
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1010

11+
[features]
12+
debug-panic-hook = []
13+
1114
[dependencies]
1215
namada_tx_prelude.workspace = true
1316

wasm/tx_bond/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ version.workspace = true
88

99
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1010

11+
[features]
12+
debug-panic-hook = []
13+
1114
[dependencies]
1215
namada_tx_prelude.workspace = true
1316

wasm/tx_change_bridge_pool/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ version.workspace = true
88

99
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1010

11+
[features]
12+
debug-panic-hook = []
13+
1114
[dependencies]
1215
namada_tx_prelude.workspace = true
1316

wasm/tx_change_consensus_key/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ version.workspace = true
88

99
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1010

11+
[features]
12+
debug-panic-hook = []
13+
1114
[dependencies]
1215
namada_tx_prelude.workspace = true
1316

0 commit comments

Comments
 (0)