From 2951aceb63dde2af9e4fccb569882722a6171561 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Sat, 18 May 2024 18:09:04 +0100 Subject: [PATCH 01/70] Track the origin of emitted events --- crates/events/Cargo.toml | 1 + crates/events/src/lib.rs | 2 + crates/events/src/tracer.rs | 271 ++++++++++++++++++++++++++++++++++++ 3 files changed, 274 insertions(+) create mode 100644 crates/events/src/tracer.rs diff --git a/crates/events/Cargo.toml b/crates/events/Cargo.toml index 961b40f7ef..a52ad249ea 100644 --- a/crates/events/Cargo.toml +++ b/crates/events/Cargo.toml @@ -14,6 +14,7 @@ version.workspace = true [features] default = [] +debug = [] mainnet = [] migrations = [ "namada_migrations", diff --git a/crates/events/src/lib.rs b/crates/events/src/lib.rs index 3c8db7d82b..acbe9d64d6 100644 --- a/crates/events/src/lib.rs +++ b/crates/events/src/lib.rs @@ -20,6 +20,8 @@ pub mod extend; #[cfg(any(test, feature = "testing"))] pub mod testing; +#[cfg(any(test, feature = "debug"))] +pub mod tracer; use std::borrow::Cow; use std::collections::BTreeMap; diff --git a/crates/events/src/tracer.rs b/crates/events/src/tracer.rs new file mode 100644 index 0000000000..4d3e4ee767 --- /dev/null +++ b/crates/events/src/tracer.rs @@ -0,0 +1,271 @@ +//! Trace the origin of emitted events. +//! +//! ## Example +//! +//! ``` +//! #[track_caller] +//! fn emit_event(event: crate::Event, events: &mut impl EmitEvents) { +//! let mut tracer = EventTracer::trace(events); +//! tracer.emit(event); +//! } +//! ``` + +use std::borrow::Cow; +use std::fmt; +use std::mem::{self, MaybeUninit}; +use std::ops::DerefMut; +use std::panic::Location; +use std::str::FromStr; + +use namada_core::booleans::BoolResultUnitExt; + +use super::{EmitEvents, EventToEmit}; +use crate::extend::{ComposeEvent, EventAttributeEntry}; + +/// The origin of an event in source code. +#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct EventTrace<'a> { + pkg_name: Cow<'a, str>, + pkg_version: Cow<'a, str>, + file: Cow<'a, str>, + line: u32, + column: u32, +} + +impl<'a> FromStr for EventTrace<'a> { + type Err = String; + + fn from_str(s: &str) -> Result { + let bindings = s.split(',').map(|binding| { + binding.split_once('=').ok_or_else(|| { + format!("Invalid event trace binding: {binding}") + }) + }); + + mod bits { + pub const DONE: i32 = PKG_NAME | PKG_VERSION | FILE | LINE | COLUMN; + + pub const PKG_NAME: i32 = 0b1; + pub const PKG_VERSION: i32 = 0b10; + pub const FILE: i32 = 0b100; + pub const LINE: i32 = 0b1000; + pub const COLUMN: i32 = 0b10000; + } + + macro_rules! init_trace_field { + ($trace:expr => $field:ident : $type:ty = $value:expr) => { + $trace + .as_mut_ptr() + .cast::() + .wrapping_add(mem::offset_of!(Self, $field)) + .cast::<$type>() + .write($value); + }; + } + + let mut init_state = 0i32; + let mut trace: MaybeUninit> = MaybeUninit::uninit(); + + for maybe_binding in bindings { + let (field, value) = maybe_binding?; + + match field { + "pkg_name" => { + unsafe { + init_trace_field!(trace => pkg_name: Cow<'static, str> = Cow::Owned(value.to_owned())); + } + + init_state |= bits::PKG_NAME; + } + "pkg_version" => { + unsafe { + init_trace_field!(trace => pkg_version: Cow<'static, str> = Cow::Owned(value.to_owned())); + } + + init_state |= bits::PKG_VERSION; + } + "file" => { + unsafe { + init_trace_field!(trace => file: Cow<'static, str> = Cow::Owned(value.to_owned())); + } + + init_state |= bits::FILE; + } + "line" => { + let line = value.parse().map_err(|err| { + format!( + "Failed to parse event trace file line: {value}: \ + {err}" + ) + })?; + unsafe { + init_trace_field!(trace => line: u32 = line); + } + + init_state |= bits::LINE; + } + "column" => { + let column = value.parse().map_err(|err| { + format!( + "Failed to parse event trace file column: \ + {value}: {err}" + ) + })?; + unsafe { + init_trace_field!(trace => column: u32 = column); + } + + init_state |= bits::COLUMN; + } + _ => return Err(format!("Unknown event trace field: {field}")), + } + } + + (init_state == bits::DONE).ok_or_else(|| { + "Some fields were not initialized in the event trace".to_owned() + })?; + + Ok(unsafe { trace.assume_init() }) + } +} + +impl fmt::Display for EventTrace<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { + pkg_name, + pkg_version, + file, + line, + column, + } = self; + write!( + f, + "pkg_name={pkg_name},pkg_version={pkg_version},file={file},\ + line={line},column={column}" + ) + } +} + +/// Tracer of emitted events. +pub struct EventTracer { + wrapped: W, + pkg_name: &'static str, + pkg_version: &'static str, +} + +impl EventTracer { + /// Build a new [`EventTracer`]. + pub const fn trace(wrapped: W) -> Self { + Self { + wrapped, + pkg_name: env!("CARGO_PKG_NAME"), + pkg_version: env!("CARGO_PKG_VERSION"), + } + } +} + +impl EmitEvents for EventTracer +where + EE: EmitEvents, + W: DerefMut, +{ + #[track_caller] + fn emit(&mut self, event: E) + where + E: EventToEmit, + { + let caller = Location::caller(); + + self.wrapped.emit(event.with(EventOrigin(EventTrace { + pkg_name: Cow::Borrowed(self.pkg_name), + pkg_version: Cow::Borrowed(self.pkg_version), + file: Cow::Borrowed(caller.file()), + line: caller.line(), + column: caller.column(), + }))); + } + + #[track_caller] + fn emit_many(&mut self, event_batch: B) + where + B: IntoIterator, + E: EventToEmit, + { + let caller = Location::caller(); + + self.wrapped.emit_many(event_batch.into_iter().map(|event| { + event.with(EventOrigin(EventTrace { + pkg_name: Cow::Borrowed(self.pkg_name), + pkg_version: Cow::Borrowed(self.pkg_version), + file: Cow::Borrowed(caller.file()), + line: caller.line(), + column: caller.column(), + })) + })); + } +} + +/// Extend an [`Event`](super::Event) with data pertaining to its origin in +/// source code. +pub struct EventOrigin<'a>(pub EventTrace<'a>); + +impl<'a> EventAttributeEntry<'a> for EventOrigin<'a> { + type Value = EventTrace<'a>; + type ValueOwned = EventTrace<'static>; + + const KEY: &'static str = "event-origin"; + + fn into_value(self) -> Self::Value { + self.0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const fn dummy_trace() -> EventTrace<'static> { + EventTrace { + pkg_name: Cow::Borrowed("pkg"), + pkg_version: Cow::Borrowed("ver"), + file: Cow::Borrowed("src/file.rs"), + line: 1, + column: 2, + } + } + + #[test] + fn test_event_trace_roundtrip() { + let serialized = dummy_trace().to_string(); + let deserialized: EventTrace<'static> = serialized.parse().unwrap(); + + assert_eq!(deserialized, dummy_trace()); + } + + #[test] + fn test_event_trace_fields_missing() { + let serialized = "pkg_name=pkg,pkg_version=ver"; + let result: Result, _> = serialized.parse(); + + assert_eq!( + result, + Err("Some fields were not initialized in the event trace" + .to_owned()) + ); + } + + #[test] + fn test_event_trace_invalid_line() { + let serialized = "pkg_name=pkg,line=bruv"; + let result: Result, _> = serialized.parse(); + + assert_eq!( + result, + Err( + "Failed to parse event trace file line: bruv: invalid digit \ + found in string" + .to_owned() + ) + ); + } +} From 210879f032164f00ffc98cca6916276f77710252 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 20 May 2024 09:06:01 +0100 Subject: [PATCH 02/70] Test event emission origin --- crates/events/src/tracer.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/events/src/tracer.rs b/crates/events/src/tracer.rs index 4d3e4ee767..91ca8d147b 100644 --- a/crates/events/src/tracer.rs +++ b/crates/events/src/tracer.rs @@ -223,6 +223,7 @@ impl<'a> EventAttributeEntry<'a> for EventOrigin<'a> { #[cfg(test)] mod tests { use super::*; + use crate::{Event, EventLevel, EventTypeBuilder}; const fn dummy_trace() -> EventTrace<'static> { EventTrace { @@ -234,6 +235,30 @@ mod tests { } } + #[test] + fn test_event_trace_emit_event() { + let (event, start_line, end_line) = { + let ev = Event::new( + EventTypeBuilder::new_with_type("test").build(), + EventLevel::Tx, + ); + let mut events = Vec::with_capacity(1); + + const START_LINE: u32 = line!(); + emit_event(ev, &mut events); + const END_LINE: u32 = line!(); + + (events.pop().unwrap(), START_LINE, END_LINE) + }; + + let trace = event.read_attribute::>().unwrap(); + + assert!(trace.line > start_line && trace.line < end_line); + assert_eq!(trace.file, file!()); + assert_eq!(trace.pkg_name, env!("CARGO_PKG_NAME")); + assert_eq!(trace.pkg_version, env!("CARGO_PKG_VERSION")); + } + #[test] fn test_event_trace_roundtrip() { let serialized = dummy_trace().to_string(); @@ -268,4 +293,10 @@ mod tests { ) ); } + + #[track_caller] + fn emit_event(event: Event, events: &mut impl EmitEvents) { + let mut tracer = EventTracer::trace(events); + tracer.emit(event); + } } From 89bd08be01db1ca494ec25e2bbf5878b71b8b515 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 20 May 2024 12:33:09 +0100 Subject: [PATCH 03/70] Activate `debug` feat when `testing` is active --- crates/events/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/events/Cargo.toml b/crates/events/Cargo.toml index a52ad249ea..573b82e25f 100644 --- a/crates/events/Cargo.toml +++ b/crates/events/Cargo.toml @@ -20,7 +20,7 @@ migrations = [ "namada_migrations", "linkme", ] -testing = [] +testing = ["debug"] [dependencies] namada_core = {path = "../core"} From df4b4f76841d0ce31e3f31bad7fe21bbffefe5f0 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 20 May 2024 11:13:27 +0100 Subject: [PATCH 04/70] Changelog for #3268 --- .changelog/unreleased/improvements/3268-track-caller-events.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/unreleased/improvements/3268-track-caller-events.md diff --git a/.changelog/unreleased/improvements/3268-track-caller-events.md b/.changelog/unreleased/improvements/3268-track-caller-events.md new file mode 100644 index 0000000000..a195bc6cf8 --- /dev/null +++ b/.changelog/unreleased/improvements/3268-track-caller-events.md @@ -0,0 +1,3 @@ +- Add a new event attribute facility to track events to their origin + in Namada's source code. This is useful for debugging purposes. + ([\#3268](https://github.com/anoma/namada/pull/3268)) \ No newline at end of file From 4daf77b471824641b30216a38eaee81abc0503e8 Mon Sep 17 00:00:00 2001 From: brentstone Date: Mon, 13 May 2024 12:00:09 -0600 Subject: [PATCH 05/70] improve `ValidatorState` documentation --- crates/proof_of_stake/src/types/mod.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/crates/proof_of_stake/src/types/mod.rs b/crates/proof_of_stake/src/types/mod.rs index 936c17507a..6be5b78fdb 100644 --- a/crates/proof_of_stake/src/types/mod.rs +++ b/crates/proof_of_stake/src/types/mod.rs @@ -534,7 +534,8 @@ impl Position { } } -/// Validator's state. +/// Validator's state. May correspond to the validator set within which the +/// validator belongs. #[derive( Debug, Clone, @@ -547,19 +548,22 @@ impl Position { Eq, )] pub enum ValidatorState { - /// A validator who may participate in the consensus + /// A validator who may participate in the consensus and is one of the top + /// `max_validator_slots` validators with stake above + /// `validator_stake_threshold` Consensus, - /// A validator who does not have enough stake to be considered in the - /// `Consensus` validator set but still may have active bonds and unbonds + /// A validator who has stake greater than the `validator_stake_threshold` + /// but is not one of the top `max_validator_slots` validators who have + /// such stake BelowCapacity, /// A validator who has stake less than the `validator_stake_threshold` /// parameter BelowThreshold, /// A validator who is deactivated via a tx when a validator no longer - /// wants to be one (not implemented yet) + /// wants to be considered for consensus Inactive, - /// A `Jailed` validator has been prohibited from participating in - /// consensus due to a misbehavior + /// A validator who is prohibited from participating in + /// consensus due to a misbehavior or downtime Jailed, } From 0400685b32fb2863e21b5e320812d7e5dd5b5ee0 Mon Sep 17 00:00:00 2001 From: brentstone Date: Wed, 22 May 2024 15:21:04 -0700 Subject: [PATCH 06/70] remove unused deps --- Cargo.lock | 52 ------- crates/apps/Cargo.toml | 3 - crates/ethereum_bridge/Cargo.toml | 5 - crates/ibc/Cargo.toml | 2 - crates/namada/Cargo.toml | 23 --- crates/parameters/Cargo.toml | 1 - crates/proof_of_stake/Cargo.toml | 2 - crates/sdk/Cargo.toml | 1 - crates/shielded_token/Cargo.toml | 1 - crates/state/Cargo.toml | 4 - crates/storage/Cargo.toml | 1 - crates/tests/Cargo.toml | 10 +- crates/tx_prelude/Cargo.toml | 2 - crates/vp_env/Cargo.toml | 1 - crates/vp_prelude/Cargo.toml | 1 - examples/Cargo.toml | 3 - wasm/Cargo.lock | 95 ------------ wasm_for_tests/Cargo.lock | 146 ------------------ wasm_for_tests/tx_fail/Cargo.toml | 2 - .../tx_infinite_guest_gas/Cargo.toml | 2 - .../tx_infinite_host_gas/Cargo.toml | 2 - wasm_for_tests/tx_invalid_data/Cargo.toml | 2 - wasm_for_tests/tx_memory_limit/Cargo.toml | 2 - wasm_for_tests/tx_no_op/Cargo.toml | 2 - wasm_for_tests/tx_proposal_code/Cargo.toml | 2 - .../Cargo.toml | 2 - .../tx_proposal_masp_reward/Cargo.toml | 2 - wasm_for_tests/tx_read_storage_key/Cargo.toml | 2 - wasm_for_tests/tx_write/Cargo.toml | 1 - wasm_for_tests/vp_always_false/Cargo.toml | 2 - wasm_for_tests/vp_always_true/Cargo.toml | 2 - wasm_for_tests/vp_eval/Cargo.toml | 1 - .../vp_infinite_guest_gas/Cargo.toml | 2 - .../vp_infinite_host_gas/Cargo.toml | 1 - wasm_for_tests/vp_memory_limit/Cargo.toml | 2 - wasm_for_tests/vp_read_storage_key/Cargo.toml | 2 - 36 files changed, 2 insertions(+), 384 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a9d914fe1..c3b4a86b51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4365,23 +4365,15 @@ dependencies = [ "assert_matches", "async-trait", "base58", - "bimap", "borsh 1.2.1", "borsh-ext", "byte-unit", - "circular-queue", "clru", - "data-encoding", - "derivation-path", - "derivative", - "ethbridge-bridge-contract", "ethers", "eyre", - "futures", "ibc-testkit", "itertools 0.12.1", "k256", - "konst", "linkme", "loupe", "masp_primitives", @@ -4393,7 +4385,6 @@ dependencies = [ "namada_gas", "namada_governance", "namada_ibc", - "namada_macros", "namada_migrations", "namada_parameters", "namada_proof_of_stake", @@ -4406,33 +4397,22 @@ dependencies = [ "namada_tx_env", "namada_vote_ext", "namada_vp_env", - "num-traits 0.2.17", - "num256", - "orion", - "owo-colors", "parity-wasm", - "paste", "pretty_assertions", "proptest", "prost 0.12.3", "rand 0.8.5", - "rand_core 0.6.4", "rayon", - "regex", "ripemd", - "serde 1.0.193", "serde_json", "sha2 0.9.9", - "slip10_ed25519", "smooth-operator", "tempfile", "tendermint-rpc", "test-log", "thiserror", "tiny-bip39", - "tiny-hderive", "tokio", - "toml 0.5.11", "tracing", "tracing-subscriber", "uint", @@ -4445,8 +4425,6 @@ dependencies = [ "wasmer-vm", "wasmparser 0.107.0", "wasmtimer", - "wat", - "zeroize", ] [[package]] @@ -4469,7 +4447,6 @@ version = "0.37.0" dependencies = [ "assert_matches", "bit-set", - "bytes", "color-eyre", "eyre", "git2", @@ -4484,9 +4461,7 @@ dependencies = [ "toml 0.5.11", "tracing", "tracing-subscriber", - "warp", "winapi", - "zeroize", ] [[package]] @@ -4668,11 +4643,7 @@ dependencies = [ "namada_trans_token", "namada_tx", "namada_vote_ext", - "rand 0.8.5", "serde 1.0.193", - "serde_json", - "tendermint 0.36.0", - "tendermint-proto 0.36.0", "thiserror", "toml 0.5.11", "tracing", @@ -4708,7 +4679,6 @@ dependencies = [ "namada_shielded_token", "namada_trans_token", "proptest", - "regex", "serde_json", "tokio", ] @@ -4766,7 +4736,6 @@ dependencies = [ "masp_primitives", "namada_core", "namada_events", - "namada_gas", "namada_governance", "namada_macros", "namada_migrations", @@ -4774,7 +4743,6 @@ dependencies = [ "namada_state", "namada_storage", "namada_token", - "namada_tx", "primitive-types", "proptest", "prost 0.12.3", @@ -4904,7 +4872,6 @@ dependencies = [ name = "namada_parameters" version = "0.37.0" dependencies = [ - "borsh 1.2.1", "namada_core", "namada_macros", "namada_storage", @@ -4917,7 +4884,6 @@ version = "0.37.0" dependencies = [ "assert_matches", "borsh 1.2.1", - "data-encoding", "derivative", "itertools 0.12.1", "konst", @@ -4933,7 +4899,6 @@ dependencies = [ "namada_state", "namada_storage", "namada_trans_token", - "num-traits 0.2.17", "once_cell", "pretty_assertions", "proptest", @@ -5015,7 +4980,6 @@ dependencies = [ "slip10_ed25519", "smooth-operator", "tempfile", - "tendermint-config", "tendermint-rpc", "thiserror", "tiny-bip39", @@ -5038,7 +5002,6 @@ dependencies = [ "namada_parameters", "namada_storage", "namada_trans_token", - "namada_tx", "proptest", "rayon", "serde 1.0.193", @@ -5054,7 +5017,6 @@ dependencies = [ "assert_matches", "borsh 1.2.1", "chrono", - "ics23", "itertools 0.12.1", "linkme", "namada_core", @@ -5070,12 +5032,9 @@ dependencies = [ "patricia_tree", "pretty_assertions", "proptest", - "sha2 0.9.9", "smooth-operator", - "sparse-merkle-tree", "test-log", "thiserror", - "tiny-keccak", "tracing", ] @@ -5092,7 +5051,6 @@ dependencies = [ "namada_migrations", "namada_replay_protection", "regex", - "serde 1.0.193", "smooth-operator", "thiserror", "tracing", @@ -5113,10 +5071,8 @@ version = "0.37.0" dependencies = [ "assert_cmd", "assert_matches", - "async-trait", "borsh 1.2.1", "borsh-ext", - "chrono", "color-eyre", "concat-idents", "data-encoding", @@ -5130,7 +5086,6 @@ dependencies = [ "ibc-testkit", "ics23", "itertools 0.12.1", - "lazy_static", "namada", "namada_apps_lib", "namada_core", @@ -5140,7 +5095,6 @@ dependencies = [ "namada_tx_prelude", "namada_vm_env", "namada_vp_prelude", - "num-traits 0.2.17", "once_cell", "pretty_assertions", "proptest", @@ -5157,8 +5111,6 @@ dependencies = [ "test-log", "tokio", "toml 0.5.11", - "tracing", - "tracing-subscriber", ] [[package]] @@ -5241,8 +5193,6 @@ dependencies = [ "namada_tx", "namada_tx_env", "namada_vm_env", - "sha2 0.9.9", - "thiserror", ] [[package]] @@ -5280,7 +5230,6 @@ dependencies = [ "namada_storage", "namada_tx", "smooth-operator", - "thiserror", ] [[package]] @@ -5302,7 +5251,6 @@ dependencies = [ "namada_vm_env", "namada_vp_env", "sha2 0.9.9", - "thiserror", ] [[package]] diff --git a/crates/apps/Cargo.toml b/crates/apps/Cargo.toml index 9faffd9963..d53b817861 100644 --- a/crates/apps/Cargo.toml +++ b/crates/apps/Cargo.toml @@ -61,9 +61,6 @@ tokio = {workspace = true, features = ["full"]} toml.workspace = true tracing-subscriber = { workspace = true, features = ["std", "json", "ansi", "tracing-log"]} tracing.workspace = true -zeroize.workspace = true -warp = "0.3.2" -bytes = "1.1.0" [target.'cfg(windows)'.dependencies] winapi.workspace = true diff --git a/crates/ethereum_bridge/Cargo.toml b/crates/ethereum_bridge/Cargo.toml index 89c558ecd9..0250028605 100644 --- a/crates/ethereum_bridge/Cargo.toml +++ b/crates/ethereum_bridge/Cargo.toml @@ -40,17 +40,12 @@ namada_tx = {path = "../tx"} namada_vote_ext = {path = "../vote_ext"} borsh.workspace = true -ethabi.workspace = true ethers.workspace = true eyre.workspace = true itertools.workspace = true konst.workspace = true linkme = {workspace = true, optional = true} serde.workspace = true -serde_json.workspace = true -rand.workspace = true -tendermint = {workspace = true} -tendermint-proto = {workspace = true} thiserror.workspace = true tracing = "0.1.30" diff --git a/crates/ibc/Cargo.toml b/crates/ibc/Cargo.toml index d523b9f793..6822e0b40f 100644 --- a/crates/ibc/Cargo.toml +++ b/crates/ibc/Cargo.toml @@ -23,7 +23,6 @@ testing = ["namada_core/testing", "ibc-testkit", "proptest"] [dependencies] namada_core = { path = "../core" } namada_events = { path = "../events", default-features = false } -namada_gas = { path = "../gas" } namada_governance = { path = "../governance" } namada_macros = {path = "../macros"} namada_migrations = {path = "../migrations", optional = true} @@ -31,7 +30,6 @@ namada_parameters = { path = "../parameters" } namada_state = { path = "../state" } namada_storage = { path = "../storage" } namada_token = { path = "../token" } -namada_tx = { path = "../tx"} borsh.workspace = true konst.workspace = true diff --git a/crates/namada/Cargo.toml b/crates/namada/Cargo.toml index 3f500eb42c..9099bf663e 100644 --- a/crates/namada/Cargo.toml +++ b/crates/namada/Cargo.toml @@ -92,7 +92,6 @@ namada_ethereum_bridge = { path = "../ethereum_bridge", default-features = false namada_gas = { path = "../gas" } namada_governance = { path = "../governance" } namada_ibc = { path = "../ibc" } -namada_macros = { path = "../macros" } namada_migrations = { path = "../migrations", optional = true } namada_parameters = { path = "../parameters" } namada_proof_of_stake = { path = "../proof_of_stake" } @@ -106,48 +105,29 @@ namada_vote_ext = { path = "../vote_ext" } namada_vp_env = { path = "../vp_env" } async-trait = { version = "0.1.51", optional = true } -bimap.workspace = true borsh.workspace = true borsh-ext.workspace = true -circular-queue.workspace = true clru.workspace = true -data-encoding.workspace = true -derivation-path.workspace = true -derivative.workspace = true -ethbridge-bridge-contract.workspace = true ethers.workspace = true eyre.workspace = true -futures.workspace = true itertools.workspace = true -konst.workspace = true linkme = {workspace = true, optional = true} loupe = { version = "0.1.3", optional = true } masp_primitives.workspace = true masp_proofs.workspace = true -num256.workspace = true -num-traits.workspace = true -orion.workspace = true -owo-colors = "3.5.0" parity-wasm = { version = "0.45.0", features = ["sign_ext"], optional = true } -paste.workspace = true proptest = { workspace = true, optional = true } prost.workspace = true rand.workspace = true -rand_core.workspace = true rayon = { version = "=1.5.3", optional = true } -regex.workspace = true ripemd.workspace = true -serde.workspace = true serde_json.workspace = true sha2.workspace = true -slip10_ed25519.workspace = true smooth-operator.workspace = true tempfile = { version = "3.2.0", optional = true } tendermint-rpc = { workspace = true, optional = true } thiserror.workspace = true tiny-bip39.workspace = true -tiny-hderive.workspace = true -toml.workspace = true tracing.workspace = true uint = "0.9.5" wasm-instrument = { workspace = true, optional = true } @@ -157,10 +137,7 @@ wasmer-compiler-singlepass = { workspace = true, optional = true } wasmer-engine-dylib = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b", optional = true } wasmer-engine-universal = { workspace = true, optional = true } wasmer-vm = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b", optional = true } -# Greater versions break in `test_tx_stack_limiter` and `test_vp_stack_limiter` -wat = "=1.0.71" wasmparser.workspace = true -zeroize.workspace = true [target.'cfg(not(target_family = "wasm"))'.dependencies] tokio = { workspace = true, features = ["full"] } diff --git a/crates/parameters/Cargo.toml b/crates/parameters/Cargo.toml index 6be22eda9c..131f49118c 100644 --- a/crates/parameters/Cargo.toml +++ b/crates/parameters/Cargo.toml @@ -24,5 +24,4 @@ namada_core = { path = "../core" } namada_macros = { path = "../macros" } namada_storage = { path = "../storage" } -borsh.workspace = true thiserror.workspace = true diff --git a/crates/proof_of_stake/Cargo.toml b/crates/proof_of_stake/Cargo.toml index 578ed50d18..0bcb8a5c4d 100644 --- a/crates/proof_of_stake/Cargo.toml +++ b/crates/proof_of_stake/Cargo.toml @@ -34,10 +34,8 @@ namada_parameters = { path = "../parameters" } namada_trans_token = { path = "../trans_token" } borsh.workspace = true -data-encoding.workspace = true konst.workspace = true linkme = {workspace = true, optional = true} -num-traits.workspace = true once_cell.workspace = true proptest = { workspace = true, optional = true } serde.workspace = true diff --git a/crates/sdk/Cargo.toml b/crates/sdk/Cargo.toml index d681124f8e..c408e74085 100644 --- a/crates/sdk/Cargo.toml +++ b/crates/sdk/Cargo.toml @@ -126,7 +126,6 @@ serde_json.workspace = true sha2.workspace = true slip10_ed25519.workspace = true smooth-operator.workspace = true -tendermint-config.workspace = true tendermint-rpc = { workspace = true, optional = true } thiserror.workspace = true tiny-bip39.workspace = true diff --git a/crates/shielded_token/Cargo.toml b/crates/shielded_token/Cargo.toml index 567ec8a239..c9d7618ab9 100644 --- a/crates/shielded_token/Cargo.toml +++ b/crates/shielded_token/Cargo.toml @@ -23,7 +23,6 @@ namada_core = { path = "../core" } namada_parameters = { path = "../parameters" } namada_storage = { path = "../storage" } namada_trans_token = { path = "../trans_token" } -namada_tx = { path = "../tx" } borsh.workspace = true masp_primitives.workspace = true diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index 69c34303af..56a80b261a 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -39,15 +39,11 @@ namada_replay_protection = { path = "../replay_protection" } namada_storage = { path = "../storage" } namada_tx = { path = "../tx" } -arse-merkle-tree.workspace = true borsh.workspace = true -ics23.workspace = true itertools.workspace = true linkme = {workspace = true, optional = true} -sha2.workspace = true smooth-operator.workspace = true thiserror.workspace = true -tiny-keccak.workspace = true tracing.workspace = true patricia_tree.workspace = true proptest = { workspace = true, optional = true } diff --git a/crates/storage/Cargo.toml b/crates/storage/Cargo.toml index 470c72caf8..6612b42dbb 100644 --- a/crates/storage/Cargo.toml +++ b/crates/storage/Cargo.toml @@ -33,7 +33,6 @@ borsh.workspace = true itertools.workspace = true linkme = {workspace = true, optional = true} regex.workspace = true -serde.workspace = true smooth-operator.workspace = true thiserror.workspace = true tracing.workspace = true diff --git a/crates/tests/Cargo.toml b/crates/tests/Cargo.toml index 75a2fbc0c9..6c76c5d816 100644 --- a/crates/tests/Cargo.toml +++ b/crates/tests/Cargo.toml @@ -37,29 +37,21 @@ namada_sdk = {path = "../sdk", default-features = false, features = ["tendermint namada_test_utils = {path = "../test_utils"} namada_tx_prelude = {path = "../tx_prelude"} namada_vp_prelude = {path = "../vp_prelude"} -async-trait.workspace = true -chrono.workspace = true concat-idents.workspace = true derivative.workspace = true -flate2.workspace = true hyper = {version = "0.14.20", features = ["full"]} ibc-testkit.workspace = true ics23.workspace = true itertools.workspace = true -lazy_static.workspace = true -num-traits.workspace = true proptest.workspace = true prost.workspace = true regex.workspace = true serde.workspace = true serde_json.workspace = true sha2.workspace = true -tar.workspace = true tempfile.workspace = true test-log.workspace = true tokio = {workspace = true, features = ["full"]} -tracing-subscriber.workspace = true -tracing.workspace = true [dev-dependencies] namada_apps_lib = {path = "../apps_lib", features = ["testing"]} @@ -75,11 +67,13 @@ data-encoding.workspace = true escargot = {workspace = true} # , features = ["print"]} expectrl.workspace = true eyre.workspace = true +flate2.workspace = true fs_extra.workspace = true once_cell.workspace = true pretty_assertions.workspace = true proptest-state-machine.workspace = true rand.workspace = true +tar.workspace = true tendermint-light-client.workspace = true test-log.workspace = true toml.workspace = true diff --git a/crates/tx_prelude/Cargo.toml b/crates/tx_prelude/Cargo.toml index 58c57ba5bf..83f5423f69 100644 --- a/crates/tx_prelude/Cargo.toml +++ b/crates/tx_prelude/Cargo.toml @@ -33,8 +33,6 @@ namada_vm_env = { path = "../vm_env" } borsh.workspace = true masp_primitives.workspace = true -sha2.workspace = true -thiserror.workspace = true [dev-dependencies] namada_token = { path = "../token", features = ["testing"] } diff --git a/crates/vp_env/Cargo.toml b/crates/vp_env/Cargo.toml index 29045213aa..e21b44ab11 100644 --- a/crates/vp_env/Cargo.toml +++ b/crates/vp_env/Cargo.toml @@ -22,4 +22,3 @@ namada_ibc = { path = "../ibc" } derivative.workspace = true masp_primitives.workspace = true smooth-operator.workspace = true -thiserror.workspace = true diff --git a/crates/vp_prelude/Cargo.toml b/crates/vp_prelude/Cargo.toml index a06c529d6a..e1275442c7 100644 --- a/crates/vp_prelude/Cargo.toml +++ b/crates/vp_prelude/Cargo.toml @@ -32,4 +32,3 @@ namada_vp_env = { path = "../vp_env" } borsh.workspace = true sha2.workspace = true -thiserror.workspace = true diff --git a/examples/Cargo.toml b/examples/Cargo.toml index a95700f17a..031e04248c 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -42,6 +42,3 @@ data-encoding.workspace = true proptest.workspace = true serde_json.workspace = true tokio = {workspace = true, default-features = false} - -[dependencies] -regex.workspace = true diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 2a00208e8a..479e40076d 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -1893,18 +1893,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "filetime" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall", - "windows-sys 0.52.0", -] - [[package]] name = "fixed-hash" version = "0.8.0" @@ -1923,16 +1911,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" -[[package]] -name = "flate2" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - [[package]] name = "flex-error" version = "0.4.4" @@ -3569,20 +3547,12 @@ name = "namada" version = "0.37.0" dependencies = [ "async-trait", - "bimap", "borsh 1.4.0", "borsh-ext", - "circular-queue", "clru", - "data-encoding", - "derivation-path", - "derivative", - "ethbridge-bridge-contract", "ethers", "eyre", - "futures", "itertools 0.12.1", - "konst", "linkme", "loupe", "masp_primitives", @@ -3594,7 +3564,6 @@ dependencies = [ "namada_gas", "namada_governance", "namada_ibc", - "namada_macros", "namada_migrations", "namada_parameters", "namada_proof_of_stake", @@ -3606,30 +3575,19 @@ dependencies = [ "namada_tx_env", "namada_vote_ext", "namada_vp_env", - "num-traits 0.2.17", - "num256", - "orion", - "owo-colors", "parity-wasm", - "paste", "proptest", "prost", "rand 0.8.5", - "rand_core 0.6.4", "rayon", - "regex", "ripemd", - "serde", "serde_json", "sha2 0.9.9", - "slip10_ed25519", "smooth-operator", "tempfile", "thiserror", "tiny-bip39", - "tiny-hderive", "tokio", - "toml 0.5.11", "tracing", "uint", "wasm-instrument", @@ -3641,8 +3599,6 @@ dependencies = [ "wasmer-vm", "wasmparser 0.107.0", "wasmtimer", - "wat", - "zeroize", ] [[package]] @@ -3720,7 +3676,6 @@ name = "namada_ethereum_bridge" version = "0.37.0" dependencies = [ "borsh 1.4.0", - "ethabi", "ethers", "eyre", "itertools 0.12.1", @@ -3738,11 +3693,7 @@ dependencies = [ "namada_trans_token", "namada_tx", "namada_vote_ext", - "rand 0.8.5", "serde", - "serde_json", - "tendermint 0.36.0", - "tendermint-proto 0.36.0", "thiserror", "tracing", ] @@ -3812,14 +3763,12 @@ dependencies = [ "masp_primitives", "namada_core", "namada_events", - "namada_gas", "namada_governance", "namada_macros", "namada_parameters", "namada_state", "namada_storage", "namada_token", - "namada_tx", "primitive-types", "proptest", "prost", @@ -3868,7 +3817,6 @@ dependencies = [ name = "namada_parameters" version = "0.37.0" dependencies = [ - "borsh 1.4.0", "namada_core", "namada_macros", "namada_storage", @@ -3880,7 +3828,6 @@ name = "namada_proof_of_stake" version = "0.37.0" dependencies = [ "borsh 1.4.0", - "data-encoding", "konst", "linkme", "namada_account", @@ -3893,7 +3840,6 @@ dependencies = [ "namada_parameters", "namada_storage", "namada_trans_token", - "num-traits 0.2.17", "once_cell", "proptest", "serde", @@ -3966,7 +3912,6 @@ dependencies = [ "sha2 0.9.9", "slip10_ed25519", "smooth-operator", - "tendermint-config", "tendermint-rpc", "thiserror", "tiny-bip39", @@ -3989,7 +3934,6 @@ dependencies = [ "namada_parameters", "namada_storage", "namada_trans_token", - "namada_tx", "serde", "smooth-operator", "tracing", @@ -4000,7 +3944,6 @@ name = "namada_state" version = "0.37.0" dependencies = [ "borsh 1.4.0", - "ics23", "itertools 0.12.1", "linkme", "namada_core", @@ -4015,11 +3958,8 @@ dependencies = [ "namada_tx", "patricia_tree", "proptest", - "sha2 0.9.9", "smooth-operator", - "sparse-merkle-tree", "thiserror", - "tiny-keccak", "tracing", ] @@ -4036,7 +3976,6 @@ dependencies = [ "namada_migrations", "namada_replay_protection", "regex", - "serde", "smooth-operator", "thiserror", "tracing", @@ -4055,35 +3994,27 @@ dependencies = [ name = "namada_tests" version = "0.37.0" dependencies = [ - "async-trait", - "chrono", "concat-idents", "derivative", - "flate2", "hyper", "ibc-testkit", "ics23", "itertools 0.12.1", - "lazy_static", "namada", "namada_core", "namada_sdk", "namada_test_utils", "namada_tx_prelude", "namada_vp_prelude", - "num-traits 0.2.17", "proptest", "prost", "regex", "serde", "serde_json", "sha2 0.9.9", - "tar", "tempfile", "test-log", "tokio", - "tracing", - "tracing-subscriber", ] [[package]] @@ -4163,8 +4094,6 @@ dependencies = [ "namada_tx", "namada_tx_env", "namada_vm_env", - "sha2 0.9.9", - "thiserror", ] [[package]] @@ -4201,7 +4130,6 @@ dependencies = [ "namada_storage", "namada_tx", "smooth-operator", - "thiserror", ] [[package]] @@ -4223,7 +4151,6 @@ dependencies = [ "namada_vm_env", "namada_vp_env", "sha2 0.9.9", - "thiserror", ] [[package]] @@ -5997,17 +5924,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "tar" -version = "0.4.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" -dependencies = [ - "filetime", - "libc", - "xattr", -] - [[package]] name = "target-lexicon" version = "0.12.12" @@ -7750,17 +7666,6 @@ dependencies = [ "tap", ] -[[package]] -name = "xattr" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" -dependencies = [ - "libc", - "linux-raw-sys", - "rustix", -] - [[package]] name = "zcash_encoding" version = "0.2.0" diff --git a/wasm_for_tests/Cargo.lock b/wasm_for_tests/Cargo.lock index 59aa30e730..f79ae53126 100644 --- a/wasm_for_tests/Cargo.lock +++ b/wasm_for_tests/Cargo.lock @@ -1893,18 +1893,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "filetime" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall", - "windows-sys 0.52.0", -] - [[package]] name = "fixed-hash" version = "0.8.0" @@ -1923,16 +1911,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" -[[package]] -name = "flate2" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - [[package]] name = "flex-error" version = "0.4.4" @@ -3549,20 +3527,12 @@ name = "namada" version = "0.37.0" dependencies = [ "async-trait", - "bimap", "borsh 1.2.1", "borsh-ext", - "circular-queue", "clru", - "data-encoding", - "derivation-path", - "derivative", - "ethbridge-bridge-contract", "ethers", "eyre", - "futures", "itertools 0.12.1", - "konst", "loupe", "masp_primitives", "masp_proofs", @@ -3573,7 +3543,6 @@ dependencies = [ "namada_gas", "namada_governance", "namada_ibc", - "namada_macros", "namada_parameters", "namada_proof_of_stake", "namada_replay_protection", @@ -3584,30 +3553,19 @@ dependencies = [ "namada_tx_env", "namada_vote_ext", "namada_vp_env", - "num-traits 0.2.17", - "num256", - "orion", - "owo-colors", "parity-wasm", - "paste", "proptest", "prost", "rand 0.8.5", - "rand_core 0.6.4", "rayon", - "regex", "ripemd", - "serde", "serde_json", "sha2 0.9.9", - "slip10_ed25519", "smooth-operator", "tempfile", "thiserror", "tiny-bip39", - "tiny-hderive", "tokio", - "toml 0.5.11", "tracing", "uint", "wasm-instrument", @@ -3619,8 +3577,6 @@ dependencies = [ "wasmer-vm", "wasmparser 0.107.0", "wasmtimer", - "wat", - "zeroize", ] [[package]] @@ -3694,7 +3650,6 @@ name = "namada_ethereum_bridge" version = "0.37.0" dependencies = [ "borsh 1.2.1", - "ethabi", "ethers", "eyre", "itertools 0.12.1", @@ -3710,11 +3665,7 @@ dependencies = [ "namada_trans_token", "namada_tx", "namada_vote_ext", - "rand 0.8.5", "serde", - "serde_json", - "tendermint 0.36.0", - "tendermint-proto 0.36.0", "thiserror", "tracing", ] @@ -3778,14 +3729,12 @@ dependencies = [ "masp_primitives", "namada_core", "namada_events", - "namada_gas", "namada_governance", "namada_macros", "namada_parameters", "namada_state", "namada_storage", "namada_token", - "namada_tx", "primitive-types", "proptest", "prost", @@ -3825,7 +3774,6 @@ dependencies = [ name = "namada_parameters" version = "0.37.0" dependencies = [ - "borsh 1.2.1", "namada_core", "namada_macros", "namada_storage", @@ -3837,7 +3785,6 @@ name = "namada_proof_of_stake" version = "0.37.0" dependencies = [ "borsh 1.2.1", - "data-encoding", "konst", "namada_account", "namada_controller", @@ -3848,7 +3795,6 @@ dependencies = [ "namada_parameters", "namada_storage", "namada_trans_token", - "num-traits 0.2.17", "once_cell", "proptest", "serde", @@ -3919,7 +3865,6 @@ dependencies = [ "sha2 0.9.9", "slip10_ed25519", "smooth-operator", - "tendermint-config", "tendermint-rpc", "thiserror", "tiny-bip39", @@ -3942,7 +3887,6 @@ dependencies = [ "namada_parameters", "namada_storage", "namada_trans_token", - "namada_tx", "serde", "smooth-operator", "tracing", @@ -3953,7 +3897,6 @@ name = "namada_state" version = "0.37.0" dependencies = [ "borsh 1.2.1", - "ics23", "itertools 0.12.1", "namada_core", "namada_events", @@ -3966,11 +3909,8 @@ dependencies = [ "namada_tx", "patricia_tree", "proptest", - "sha2 0.9.9", "smooth-operator", - "sparse-merkle-tree", "thiserror", - "tiny-keccak", "tracing", ] @@ -3985,7 +3925,6 @@ dependencies = [ "namada_merkle_tree", "namada_replay_protection", "regex", - "serde", "smooth-operator", "thiserror", "tracing", @@ -4004,35 +3943,27 @@ dependencies = [ name = "namada_tests" version = "0.37.0" dependencies = [ - "async-trait", - "chrono", "concat-idents", "derivative", - "flate2", "hyper", "ibc-testkit", "ics23", "itertools 0.12.1", - "lazy_static", "namada", "namada_core", "namada_sdk", "namada_test_utils", "namada_tx_prelude", "namada_vp_prelude", - "num-traits 0.2.17", "proptest", "prost", "regex", "serde", "serde_json", "sha2 0.9.9", - "tar", "tempfile", "test-log", "tokio", - "tracing", - "tracing-subscriber", ] [[package]] @@ -4110,8 +4041,6 @@ dependencies = [ "namada_tx", "namada_tx_env", "namada_vm_env", - "sha2 0.9.9", - "thiserror", ] [[package]] @@ -4146,7 +4075,6 @@ dependencies = [ "namada_storage", "namada_tx", "smooth-operator", - "thiserror", ] [[package]] @@ -4168,7 +4096,6 @@ dependencies = [ "namada_vm_env", "namada_vp_env", "sha2 0.9.9", - "thiserror", ] [[package]] @@ -5934,17 +5861,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "tar" -version = "0.4.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" -dependencies = [ - "filetime", - "libc", - "xattr", -] - [[package]] name = "target-lexicon" version = "0.12.12" @@ -6520,11 +6436,8 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" name = "tx_fail" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", "namada_tx_prelude", - "namada_vp_prelude", "proptest", "test-log", "tracing", @@ -6536,11 +6449,8 @@ dependencies = [ name = "tx_infinite_guest_gas" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", "namada_tx_prelude", - "namada_vp_prelude", "proptest", "test-log", "tracing", @@ -6552,11 +6462,8 @@ dependencies = [ name = "tx_infinite_host_gas" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", "namada_tx_prelude", - "namada_vp_prelude", "proptest", "test-log", "tracing", @@ -6568,11 +6475,8 @@ dependencies = [ name = "tx_invalid_data" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", "namada_tx_prelude", - "namada_vp_prelude", "proptest", "test-log", "tracing", @@ -6584,11 +6488,8 @@ dependencies = [ name = "tx_memory_limit" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", "namada_tx_prelude", - "namada_vp_prelude", "proptest", "test-log", "tracing", @@ -6600,11 +6501,8 @@ dependencies = [ name = "tx_no_op" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", "namada_tx_prelude", - "namada_vp_prelude", "proptest", "test-log", "tracing", @@ -6616,11 +6514,8 @@ dependencies = [ name = "tx_proposal_code" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", "namada_tx_prelude", - "namada_vp_prelude", "proptest", "test-log", "tracing", @@ -6632,11 +6527,8 @@ dependencies = [ name = "tx_proposal_ibc_token_inflation" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", "namada_tx_prelude", - "namada_vp_prelude", "proptest", "test-log", "tracing", @@ -6648,11 +6540,8 @@ dependencies = [ name = "tx_proposal_masp_reward" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", "namada_tx_prelude", - "namada_vp_prelude", "proptest", "test-log", "tracing", @@ -6664,11 +6553,8 @@ dependencies = [ name = "tx_read_storage_key" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", "namada_tx_prelude", - "namada_vp_prelude", "proptest", "test-log", "tracing", @@ -6680,11 +6566,9 @@ dependencies = [ name = "tx_write" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", "namada_test_utils", "namada_tests", "namada_tx_prelude", - "namada_vp_prelude", "proptest", "test-log", "tracing", @@ -6849,10 +6733,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" name = "vp_always_false" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", - "namada_tx_prelude", "namada_vp_prelude", "proptest", "test-log", @@ -6865,10 +6746,7 @@ dependencies = [ name = "vp_always_true" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", - "namada_tx_prelude", "namada_vp_prelude", "proptest", "test-log", @@ -6881,8 +6759,6 @@ dependencies = [ name = "vp_eval" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", "namada_tx_prelude", "namada_vp_prelude", @@ -6897,10 +6773,7 @@ dependencies = [ name = "vp_infinite_guest_gas" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", - "namada_tx_prelude", "namada_vp_prelude", "proptest", "test-log", @@ -6913,8 +6786,6 @@ dependencies = [ name = "vp_infinite_host_gas" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", "namada_tx_prelude", "namada_vp_prelude", @@ -6929,10 +6800,7 @@ dependencies = [ name = "vp_memory_limit" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", - "namada_tx_prelude", "namada_vp_prelude", "proptest", "test-log", @@ -6945,10 +6813,7 @@ dependencies = [ name = "vp_read_storage_key" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", - "namada_test_utils", "namada_tests", - "namada_tx_prelude", "namada_vp_prelude", "proptest", "test-log", @@ -7692,17 +7557,6 @@ dependencies = [ "tap", ] -[[package]] -name = "xattr" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" -dependencies = [ - "libc", - "linux-raw-sys", - "rustix", -] - [[package]] name = "zcash_encoding" version = "0.2.0" diff --git a/wasm_for_tests/tx_fail/Cargo.toml b/wasm_for_tests/tx_fail/Cargo.toml index 1662428c00..2ae4e5cd52 100644 --- a/wasm_for_tests/tx_fail/Cargo.toml +++ b/wasm_for_tests/tx_fail/Cargo.toml @@ -9,9 +9,7 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true namada_tx_prelude.workspace = true -namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/tx_infinite_guest_gas/Cargo.toml b/wasm_for_tests/tx_infinite_guest_gas/Cargo.toml index 18bc81e956..1137483628 100644 --- a/wasm_for_tests/tx_infinite_guest_gas/Cargo.toml +++ b/wasm_for_tests/tx_infinite_guest_gas/Cargo.toml @@ -9,9 +9,7 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true namada_tx_prelude.workspace = true -namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/tx_infinite_host_gas/Cargo.toml b/wasm_for_tests/tx_infinite_host_gas/Cargo.toml index dd78ce23f2..d276e9f168 100644 --- a/wasm_for_tests/tx_infinite_host_gas/Cargo.toml +++ b/wasm_for_tests/tx_infinite_host_gas/Cargo.toml @@ -9,9 +9,7 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true namada_tx_prelude.workspace = true -namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/tx_invalid_data/Cargo.toml b/wasm_for_tests/tx_invalid_data/Cargo.toml index a228c741be..7c4eefed9b 100644 --- a/wasm_for_tests/tx_invalid_data/Cargo.toml +++ b/wasm_for_tests/tx_invalid_data/Cargo.toml @@ -9,9 +9,7 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true namada_tx_prelude.workspace = true -namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/tx_memory_limit/Cargo.toml b/wasm_for_tests/tx_memory_limit/Cargo.toml index 9e7206bdaf..8e15579717 100644 --- a/wasm_for_tests/tx_memory_limit/Cargo.toml +++ b/wasm_for_tests/tx_memory_limit/Cargo.toml @@ -9,9 +9,7 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true namada_tx_prelude.workspace = true -namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/tx_no_op/Cargo.toml b/wasm_for_tests/tx_no_op/Cargo.toml index 1edd8f9513..3860bf7b6f 100644 --- a/wasm_for_tests/tx_no_op/Cargo.toml +++ b/wasm_for_tests/tx_no_op/Cargo.toml @@ -9,9 +9,7 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true namada_tx_prelude.workspace = true -namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/tx_proposal_code/Cargo.toml b/wasm_for_tests/tx_proposal_code/Cargo.toml index 9fb447f057..22ff69bea5 100644 --- a/wasm_for_tests/tx_proposal_code/Cargo.toml +++ b/wasm_for_tests/tx_proposal_code/Cargo.toml @@ -9,9 +9,7 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true namada_tx_prelude.workspace = true -namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/tx_proposal_ibc_token_inflation/Cargo.toml b/wasm_for_tests/tx_proposal_ibc_token_inflation/Cargo.toml index 8116c055d6..79f197680b 100644 --- a/wasm_for_tests/tx_proposal_ibc_token_inflation/Cargo.toml +++ b/wasm_for_tests/tx_proposal_ibc_token_inflation/Cargo.toml @@ -9,9 +9,7 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true namada_tx_prelude.workspace = true -namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/tx_proposal_masp_reward/Cargo.toml b/wasm_for_tests/tx_proposal_masp_reward/Cargo.toml index ba52a8b614..ae7a78f254 100644 --- a/wasm_for_tests/tx_proposal_masp_reward/Cargo.toml +++ b/wasm_for_tests/tx_proposal_masp_reward/Cargo.toml @@ -9,9 +9,7 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true namada_tx_prelude.workspace = true -namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/tx_read_storage_key/Cargo.toml b/wasm_for_tests/tx_read_storage_key/Cargo.toml index 195c76f3e8..56c019aed4 100644 --- a/wasm_for_tests/tx_read_storage_key/Cargo.toml +++ b/wasm_for_tests/tx_read_storage_key/Cargo.toml @@ -9,9 +9,7 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true namada_tx_prelude.workspace = true -namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/tx_write/Cargo.toml b/wasm_for_tests/tx_write/Cargo.toml index d26ec28930..d75c02a681 100644 --- a/wasm_for_tests/tx_write/Cargo.toml +++ b/wasm_for_tests/tx_write/Cargo.toml @@ -11,7 +11,6 @@ version.workspace = true [dependencies] namada_test_utils.workspace = true namada_tx_prelude.workspace = true -namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/vp_always_false/Cargo.toml b/wasm_for_tests/vp_always_false/Cargo.toml index 65b36fb190..7c8a540bc8 100644 --- a/wasm_for_tests/vp_always_false/Cargo.toml +++ b/wasm_for_tests/vp_always_false/Cargo.toml @@ -9,8 +9,6 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true -namada_tx_prelude.workspace = true namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/vp_always_true/Cargo.toml b/wasm_for_tests/vp_always_true/Cargo.toml index 6ba4a1a14c..a02dc408d9 100644 --- a/wasm_for_tests/vp_always_true/Cargo.toml +++ b/wasm_for_tests/vp_always_true/Cargo.toml @@ -9,8 +9,6 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true -namada_tx_prelude.workspace = true namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/vp_eval/Cargo.toml b/wasm_for_tests/vp_eval/Cargo.toml index 77d5ae8f66..ad75f9b460 100644 --- a/wasm_for_tests/vp_eval/Cargo.toml +++ b/wasm_for_tests/vp_eval/Cargo.toml @@ -9,7 +9,6 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true namada_tx_prelude.workspace = true namada_vp_prelude.workspace = true wee_alloc.workspace = true diff --git a/wasm_for_tests/vp_infinite_guest_gas/Cargo.toml b/wasm_for_tests/vp_infinite_guest_gas/Cargo.toml index 674646e6c0..94d2ce5285 100644 --- a/wasm_for_tests/vp_infinite_guest_gas/Cargo.toml +++ b/wasm_for_tests/vp_infinite_guest_gas/Cargo.toml @@ -9,8 +9,6 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true -namada_tx_prelude.workspace = true namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/vp_infinite_host_gas/Cargo.toml b/wasm_for_tests/vp_infinite_host_gas/Cargo.toml index bec1ef23ee..0f918678d6 100644 --- a/wasm_for_tests/vp_infinite_host_gas/Cargo.toml +++ b/wasm_for_tests/vp_infinite_host_gas/Cargo.toml @@ -9,7 +9,6 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true namada_tx_prelude.workspace = true namada_vp_prelude.workspace = true wee_alloc.workspace = true diff --git a/wasm_for_tests/vp_memory_limit/Cargo.toml b/wasm_for_tests/vp_memory_limit/Cargo.toml index ed9c0894b9..8f208251a0 100644 --- a/wasm_for_tests/vp_memory_limit/Cargo.toml +++ b/wasm_for_tests/vp_memory_limit/Cargo.toml @@ -9,8 +9,6 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true -namada_tx_prelude.workspace = true namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true diff --git a/wasm_for_tests/vp_read_storage_key/Cargo.toml b/wasm_for_tests/vp_read_storage_key/Cargo.toml index 6ba5fc315e..5261f3e598 100644 --- a/wasm_for_tests/vp_read_storage_key/Cargo.toml +++ b/wasm_for_tests/vp_read_storage_key/Cargo.toml @@ -9,8 +9,6 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -namada_test_utils.workspace = true -namada_tx_prelude.workspace = true namada_vp_prelude.workspace = true wee_alloc.workspace = true getrandom.workspace = true From cd71146130eb93436f1d0c02d84bd18a4e829d16 Mon Sep 17 00:00:00 2001 From: brentstone Date: Wed, 22 May 2024 18:50:53 -0700 Subject: [PATCH 07/70] remove folder --- wasm_for_tests/wasm_source/Cargo.toml | 48 --------------------------- 1 file changed, 48 deletions(-) delete mode 100644 wasm_for_tests/wasm_source/Cargo.toml diff --git a/wasm_for_tests/wasm_source/Cargo.toml b/wasm_for_tests/wasm_source/Cargo.toml deleted file mode 100644 index 85bc53973d..0000000000 --- a/wasm_for_tests/wasm_source/Cargo.toml +++ /dev/null @@ -1,48 +0,0 @@ -[package] -authors = ["Heliax AG "] -edition = "2021" -license = "GPL-3.0" -name = "namada_wasm_for_tests" -resolver = "2" -version = "0.32.1" - -[lib] -crate-type = ["cdylib"] - -# The features should be used individually to build the selected wasm. -# Newly added wasms should also be added into the Makefile `$(wasms)` list. -[features] -tx_fail = [] -tx_infinite_guest_gas = [] -tx_infinite_host_gas = [] -tx_invalid_data = [] -tx_memory_limit = [] -tx_no_op = [] -tx_proposal_code = [] -tx_proposal_ibc_token_inflation = [] -tx_proposal_masp_reward = [] -tx_read_storage_key = [] -tx_write = [] -vp_always_false = [] -vp_always_true = [] -vp_eval = [] -vp_infinite_guest_gas = [] -vp_infinite_host_gas = [] -vp_memory_limit = [] -vp_read_storage_key = [] - -[dependencies] -namada_test_utils = {path = "../../crates/test_utils"} -namada_tx_prelude = {path = "../../crates/tx_prelude"} -namada_vp_prelude = {path = "../../crates/vp_prelude"} -wee_alloc = "0.4.5" -getrandom = { version = "0.2", features = ["custom"] } - -[dev-dependencies] -namada_tests = {path = "../../crates/tests", default-features = false, features = ["wasm-runtime"]} - -[profile.release] -# smaller and faster wasm https://rustwasm.github.io/book/reference/code-size.html#compiling-with-link-time-optimizations-lto -lto = true -# simply terminate on panics, no unwinding -panic = "abort" From c8eb3261747c3e92cb3ed5524b94ecf70edba786 Mon Sep 17 00:00:00 2001 From: brentstone Date: Thu, 23 May 2024 13:25:05 -0700 Subject: [PATCH 08/70] WIPPP --- wasm_for_tests/Cargo.lock | 18 ++++++++++++++++++ .../tx_proposal_ibc_token_inflation.wasm | Bin 310755 -> 310755 bytes wasm_for_tests/tx_proposal_masp_reward.wasm | Bin 284133 -> 284133 bytes wasm_for_tests/tx_read_storage_key.wasm | Bin 287549 -> 287549 bytes wasm_for_tests/tx_write.wasm | Bin 290608 -> 290608 bytes wasm_for_tests/vp_always_false.wasm | Bin 261291 -> 261291 bytes wasm_for_tests/vp_infinite_guest_gas.wasm | Bin 260526 -> 260526 bytes wasm_for_tests/vp_memory_limit.wasm | Bin 294950 -> 294950 bytes 8 files changed, 18 insertions(+) diff --git a/wasm_for_tests/Cargo.lock b/wasm_for_tests/Cargo.lock index f79ae53126..85a3a3db7f 100644 --- a/wasm_for_tests/Cargo.lock +++ b/wasm_for_tests/Cargo.lock @@ -6436,6 +6436,7 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" name = "tx_fail" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_tx_prelude", "proptest", @@ -6449,6 +6450,7 @@ dependencies = [ name = "tx_infinite_guest_gas" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_tx_prelude", "proptest", @@ -6462,6 +6464,7 @@ dependencies = [ name = "tx_infinite_host_gas" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_tx_prelude", "proptest", @@ -6475,6 +6478,7 @@ dependencies = [ name = "tx_invalid_data" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_tx_prelude", "proptest", @@ -6488,6 +6492,7 @@ dependencies = [ name = "tx_memory_limit" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_tx_prelude", "proptest", @@ -6501,6 +6506,7 @@ dependencies = [ name = "tx_no_op" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_tx_prelude", "proptest", @@ -6514,6 +6520,7 @@ dependencies = [ name = "tx_proposal_code" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_tx_prelude", "proptest", @@ -6527,6 +6534,7 @@ dependencies = [ name = "tx_proposal_ibc_token_inflation" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_tx_prelude", "proptest", @@ -6540,6 +6548,7 @@ dependencies = [ name = "tx_proposal_masp_reward" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_tx_prelude", "proptest", @@ -6553,6 +6562,7 @@ dependencies = [ name = "tx_read_storage_key" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_tx_prelude", "proptest", @@ -6566,6 +6576,7 @@ dependencies = [ name = "tx_write" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6733,6 +6744,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" name = "vp_always_false" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_vp_prelude", "proptest", @@ -6746,6 +6758,7 @@ dependencies = [ name = "vp_always_true" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_vp_prelude", "proptest", @@ -6759,6 +6772,7 @@ dependencies = [ name = "vp_eval" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_tx_prelude", "namada_vp_prelude", @@ -6773,6 +6787,7 @@ dependencies = [ name = "vp_infinite_guest_gas" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_vp_prelude", "proptest", @@ -6786,6 +6801,7 @@ dependencies = [ name = "vp_infinite_host_gas" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_tx_prelude", "namada_vp_prelude", @@ -6800,6 +6816,7 @@ dependencies = [ name = "vp_memory_limit" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_vp_prelude", "proptest", @@ -6813,6 +6830,7 @@ dependencies = [ name = "vp_read_storage_key" version = "0.37.0" dependencies = [ + "getrandom 0.2.11", "namada_tests", "namada_vp_prelude", "proptest", diff --git a/wasm_for_tests/tx_proposal_ibc_token_inflation.wasm b/wasm_for_tests/tx_proposal_ibc_token_inflation.wasm index ef853e4f30ac5e483810f8d79aeff3c4a797f8d8..9e73e3244ee3e15f9ac9873dd2924809133600cb 100755 GIT binary patch delta 14735 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 delta 14468 zcmbt*33yIN+ka*zPZrruWRt{l9wcH9Y8M=87i+0~E&9e@wN*=0kkoF-2r02g#nuOh z(19Gxt9CoLqld^7_k?I}a0{ zLn0_+{2r-IoNQ%jZ^EarW{i3|@pQI<_jjH_{P`8<%0bqDjU1IgmN@^wQk`|@r{o!l zCqJ<>yo@Ed(swML9=B|vGcB_$3+Zl4zU7$ZXZo0Vdt_S{krFPyGFN32J^8f@vMkTpAM6?Xg}r8fvX?B@`LOd`%MG&Hvc{5PS!c0X z4qBer>bQJJLL!}LbJkoXt-Ofp6hWO-C(StqwUS_~?dCzqeBRW(FIm7>x-UXmrNnTu z#I~eF1o4fJjg19#1a&j!DV!hk=tq|GN}jz*BA@9wi3tAOa}Zgsh08?ut0 z@oGs{@j&lo=-=ucqOOowJXGfh8tW>{I9DaXKFim(~D>8#%%xM*}MPC z+0o|W!kF$`JU#QjoNmreb!?p%1O_#9P)Snsz;B?avduv^X9p#>+j}4pqa$u4ih@h8=>L#_~Ykn}O0kQGlf~t@Nu9gZX zyLp>ZlFl!LMvw#ib!ZbT-K4Zi4)Xq`dy#MW-qH>IG8{|1 zHIOb$VJN?F`+q69v+%si6GUzXWP4)e6K{h=`>%2jmFk~5t=lx$wVoE3e&%SGTI zpO>qEa#Oi3D4&&!@X3)-<;%44a?)anlEZ7L)krSytM(#C_-?fc%ExL?lx?kHg|F7J|S8J%1J4@(*mN~(klcHOHCQ4|s@Bx^f;l7&6pj<5 zoaDEwRcUNY@O1L<(2`TJMXi#SBWop3LOXeA=ZxN9?a|x4s=Mj}_C;48O4jgQ)%^m$ zlh7WTQ+201S(qK7Icsi8A-`C?R-hrz8nIe5YNejkLk&;^Vau&G8W2cLpPH+JPRPmS zsV2>V+?=x}?aMjt89AO5@#&GR$qAktxwPd);{c(W5(9a~*-FWxv~tSmb~d}+wfQ7Q zxny*e*49Fo4Nygb`YQ!|Wvzvz$X2=bH-uc~x9U`Ly(~dJUHJVv;poxcsZOr&vG2^r z@88~8PtNnCy5-0PzQ1ni@GB-HNU~WHs;)NwZIWoQ8ztHD`OCU33=}hw80*+1<9H z`Y1mcuq9Pr<)-ao)44S0d;5VwL=~3SbVJHjK1FK@G9T2sm{O~{Zc~Z!xd9AE3W+b@ zqA>slv=~K>^W!a~ak}54O|g>a+m*a!%Qk*jXGuO$?V2l=&{iOHNEd^%slP~>L;ZM8 z%eJt`Uhg)AJ?{8!Z@WFF5mZ%CR8(D{;SPJ8`EJV~(;m~x?3%09LxQYuG4>PEDvV_D z=B+xC{d_^IqcF+ux0WV3wskdsL-9OI09-DwT2yD{AkS<)1opW?8;5;1QK3wh3O%+> z0|Z8?ZHAM0?$fpk%0_J`1SG_nM*$Wsz&w(Y!L!=dL|FAp+d&Acy0;sKm}q~yf#eGw z+Z$Je$m58~vsZ-jX5b^CD;@o^ojfLz+)GqR8?9mB{XUa#Z#m47zKRLV{wv*q`1 zEt7bQc~o>XX3mS&U>8qBHxF=FaHe|VY&bzCL&#UY(>uWYey0j#8K2gvBX*M4DHms2 z*m>uFI7jy`lgU$lyvt04iqTyc`6a$NEtoH4i=XZi$SvJQz;})A7K&3Rbo-6`#%FYI zTg+w|FWK45FLr+yqvhUfLZ8m!i#nI#pS(9O;HF(397L4*lEFiIBqQ$Bd+hn!c#bhX zvu6}Z=7)M#E|Dyy(9;E8(e_JEA3|2xXs`Ctf=2fq>+29USVpRqlA`wLJ`EIy?m^U^ z_HIH7d7VCALO4$MIRaX&=xasbTWe4NKh?J?-{04ZyY`!BuRr3x{ex*@EMGe&n78WR z1}t09e;D@gYyaI~aq57j2zwh3EDgKgYhVYI8wL(TSz=H)NwL)$RDuAs$>0$V3>kwZ z2A3h@K)T68-ox*dF#-ICA=N-~@1ZI7Q!_2rS&A0Z@?iKgc=pg1yh{H-9{NEaJAnbg zVlWOkC7s8AFq^F9-ouLi!~8#nwLsY2Z1^ZU%irL?jo>_kXAUn9W?vtE6~dW4VljmC zy$@CFZQ_R$$$EbG!w9m$=KrsnBxs}LK5b5$tNySv1{xTVjl54x%~p2}hMIjoFw#cb zLuJ*S_A>iUHyNUYo|M1z$aAQc&A@arCfs|o1j9_@bc;D1*%7&AN`Gy5@QCxFlCijqG`)p zsPUVv?#9kD2K)2WskMRY($sWgsjZ(>le)Nej6c8s$>3s{iZ3B$>b4tX$~Jh~hopD_ zT^M+ddrvyQ{Am_6XU%8hE9^GT#k6=t;1xAhakL?{b~JlSX)?SnG zhUDzTB76C7)Bja0vY4g$W1bwz;1g#2OxD;2#C9fRAKyOnNu+5n-bijr34j?#WtDM# zwpt)CxT8X_;Qg4gpP%_W(%&Z6^iVCTYn;{D175@%SJA*(<>4I~&Z-%ZE{DsPgU^&Q zjTjAqb2|TQR!xMm+h(1B-!gJdqxSQw6D`D6sNwuinjr6k5mRjIr2up7o~ zBT`;0Lp@E^=5In>94X(EEiFP@Cc{G|k2hZw5cD6SXxpeoOBpQX>!ssSj^~3&vh55% zD$RNF@`W(hRTINec1z48$3=(bB-BL;w2JFvMg>Q@g?(gl=gH3ia7C#fS<*`28&!PFM4*K<{{yNiy?B6mIMO)dfQ5 z$1dMVD%d)uJz;=qxpM$XlEG{M*LU70>9&o#<`Tpe)ot^N2n^W9?O8=YB~QI?u>HJ&xF)^1X@Y5m zJXSvmn9lpU;SRoTUu)dH@9c|1IcEP1X!V2rT`<}#{o|5$g{(x#3|PP?RM{i8c{`Wk zKc)``+`9*Ap`2utsRwqDJX^1Wdx>clP=;lULU6e>qk2il6`mkB2?ODxEaIm#4hNWb zT_-E^B)Cw=Zjpu{-?sTsUqWWv*x^V*F7kJ>)N1CHm1=M^Ziw{XTv}z1b#NBrk~>$)Ic6V-k+88JRo->xHK=fCM4)UZZlBrWo}n; zgGV3fh;rqT;pCi+e0z(Ko3=Z7+bFUQ;`qYg>jp=emI;f261->HHSqo{Z<=2l7tZnd zfyh$C=f6j8@+)erN+Uk0dO?t*Jo`col)qf4PiFEe-<_{>%y2fCPz@6z zjS0scT@BFH#OTU5yR;nWKrXLcSgm=c11MIedE%%6W`2ap?jRTw-h$I;u*>^*7U*1b3LVQ3}%5eMXl zCgdsE#=XQa+!Y~?(h_T#+YQk-rPHAZ{L`W;AkOBZe31O!#a4X(#oETN4@jY{>!mn% za@cm^2J|hPFSywOa#3`%21eX&xuVOa+>W%MrQN@6L95EI+lhbi6;QkDqUD{+gti^F z-Fwpe?U4g;Hs%QL{d6Rd=01(Y0#BdTL(Z}Kv(vb?ync30>iD_e@4!4}ytq!52=5$P z!8Jc#Vq9X&f7yv)$($D0wD~z_o zyqtuKwuvOj0rX%e@zJj*lL;=xTeoQ6Ssa|xW7d&y$C4#_>-uyEMZKjV%|$K7 zHleAgN=4B&_Pu=^MFZg;^?6OHKLvMFn$rLX^V`8^{O<_K5SZ?iwUQ@(Y)-2KQqd^9 zooHcH`o|g_f%*F7mNb;Mbi}QhC*{=I+7nq9N4jyROoVB&F79Th`&i@EaC#QW&CQ3(=nqHG4=MRp^opU| zp(m~*X&;g!hK!`MNT#?sl1@i8Y!uxOAuBhUu2&ArHDycyD_IeSUYr?CJ3wj6j-heX z-89xt=-xVxmLs|1_&D0t?}VIVb&)qU`42LALev~jmy(lu)_D3QK|N>!#pUL(7&DRn z2y9&^(NCla$e&C#a!Pnlp`A#9=syJ_Qy^TX(hQ8{PNh2_EfYVX5z-c{o<<))Y8QM; zzsFujeMaY!)8ffzbQ#W@Fr9Wsb!9qjh|ZuHv_ICEID_UolT&)*IBF$if#^RQYnc(Z zC0iYs!(!KXiMora!D^(N^yv5@r8d!}rasp>$94C=0e?^u2$XLgi;bqJaxk=RLZ~I9z z;l$k}TJ>*(2knE^SJEnf8_c&4j#>E+GcVf*cVe*2U-x#;95nXkX70^<)j#a*4?B`~ zR?#Y;!N66pFIU7wvz3CDogx;KBJTe)MbaL>p@_3Nqs0F_R zktn~49Xsd|*y>3;>2iwnnRtAX28oI`I;;4WSLh`L|29%n>3X`27P-(zv&62$G*sW2 zPM;BSRZl%g$1#6L@;lGnyzwE)kfB%0go`WAd&?nzAdB~sV>=Ji{?gwe4yz1Hpa1fG zu_%X51nn%jlw%+%mxiOt%%!hob;M}hGAr+IjaJ=nX?MDd@xy-xibr|)_GO7^e^mNS zarHPJeV+d+C2@(^f7F1!W>&7p42aIhjLu2NXsTz5WV4gUNlMrZ(d;<#>g&IyH6ROT zzNK|lgKS_gsHT|N2_FxWgy?aGOjOFFL%SGI|2`nG{@;2$-W;mCSbUtim?zU*bDo+< z!ucd|a5A;H59fQ+z$xEA`^PAU^Z`H76NEe$)o#J%#fmYv==<<5hnlbosD8dh7m)kPDFGmShIjqk&kCX4m=X_J43Tx5LZ zt2qCHIu;)%R7m2dGD<$&;eOefH!IB7Zj#Hz<& zTatMC7{Zb)I{$*>tQ7h$AZC*I{TGmLrI`CGtws)t-M`ZIVDRf-X?65#b5(v(eIr{6V`A%PJ`@ zBE`Z=iBo?XP;Fj;<~zjLS9A;cNe_MvuR&G`FUHC)PhpeE6A|gc0!0nNyn!oH7|jD?7O79hVZ=TrpV z9xedCt)Fy};6>uLE1LyQjdEi#sG7Mmt9b6ltT<lgI#2a z(LSuO+%FQ$46M!I8gF#|&{&OVu~ZS_1BHD;e$lTgj1x?4;?LA#)aFyKiF#8>19dY$ z1NBfpR`^%w__sDP*58133oxLo1+bUou80U^jVyQNengExR$e3ovI4|eeS&Z{p?@93 zey4tyj8oN8W=l!I$2%%w*NhMr1%N+7*mL53*#M}m%ocx^Ho6;^VGF2xk@oiQx+NjEkM^@%y z{x0K;{HM{2U#@W84a>8k6l%6BjNuEAbJ8cJh?5P_cz)Jw$PuB20fPx8I=%Vr`uw{$ zK(4pnG^*QyE99Adrd!r>;@(a*oikf{<#0BG!1!;e#5hA8Rh9ihNT!Ia&IUlX7gcBP zl1%+vbrvdj`lu$8*b8dQJ=!;HG~&;jdjUWt*A?~#b{`=MBAEqKQW~%b7kfW`S8~m> zH)_{1P!1}tD!Ha!Fp;4TaQ23=OyOG%(X6&X7jrXjPl>nF!Wdccrr{ur>+?cm0lius zFdx~c^tw!!$1^sTY7WYVoB)2+-}D5NTS%) zoQ;GSmC-PDxfrLhI@r_(js1&k72Ykd#duMv1+3X_vA+eIPhLo05-9q$WSiU#zax!~ zAg!3cDEBT4!bQCPyR0lw^n90Xg6H}3T`0d%mC{GIVu<~PnBJOwM!wMhXw9N2nJ3z} z!!gsumUb+f%ooqvVX+4yq5WH?6)p{qEwhp|f!XcZB8+$MV3^ja9SqZYp#wvHRaiQ* zF#FT6FHE4^n*C{5H0ub6Trs92s}IY$Nw%`Y`HrkTDm5Cy^1bL3%_2}ujs`8i7u%!R zy5dLUQfev3qp=v;iACa=%Q~@!06W9wNs5@&w;bOM-VEF!1Jm`VreW5q($+}89&+ElL0K*^kVq;)!2lmFH;q({u zVLidswS8GNq4Z^e_+6Oz8^EQ^biOwKzsE$tfuCxtkLI< zV6l`e);(ibO=ogmZ!(5`MX~s;ajZ2?T4OvkV1ej19#ly*1Ao;<-9`F%HV^~}`H0OW zxNEGN0GiGh$0x7_xNY|Sm{l$5aPh`RN!T^SF!5uE;XM&P(GbIq6AdxkGLbC=`5R0^ zXMz|oi4~C?y}@M23+(m3rm&7kwC$b3UV9vo)WoNK9?B6tb1DuAp-GqqHD4}vO+zHI zSe%^(e|=7j_>>LB*zr#h2^|-1pFzrUMZ{-pmG!8B!c}V!V|7LN+cw7P0%FEn4Nbwf zN5{mC&)7SF4xSG2TOwLc$LW`d5z~#+LkLQXlhdK|LRe?8Lu9G=VFu*WcntLypo^Ob ziDlhE_A#;SAT7S!8Z?*6C_ir!&1ONE7m9te*kW+4U7W$S5pnE1jvqCf9R$l?%!bD; zzGg4RcPhp%!SV)k*)Xy~tey*DU8Danm%XCotbXka7zb=;zBNW#q@i4G@^?B76fwDqcL^z$St&BQ~-<j~6RU+gpXj`q#gm(&a5LLX zZi(1bOuwaHO=WEexvp3GiXr`ROWfWHrOp$9Y2fu5(I^cHe_yOg!-{vr^E5V{{47pv zN4UFU8yi*3(nm-m%6tV;0p`3@FIfg@)ZYfH=cx5q9U7x?D?Ov zw>+{0$}7FcF+h_)#qr}1p;zMZakdv#YCgM4ei!j4AVSwf)01qN=L>^y&Km9~FU5|N ztgh=!sZGis;_gXSi@uH%WlzBq92OH#v6TOH?yNU+tGXE}2gSq?CQhGbwN%G@CjMv( zTBSvfim6K@JV1{bxR(%Rg(!c9RrNQ*Baf0sqR#%OPK9Fd8FmEv8*!F3`X}WS6VI~i zQ03m|SkGd!A`=nDr#LVxS?5@hnDKy?6Pb^wv&cBl78PghRP%~0pQtm$;0yS+AVL59 z0vk`n7q{3(NMGb_HVD-cv+7%9T>7RLv6kZGb>>A*h*L$-;so)uh&_Y5Vus^8pPIr>?;O{w99BhNuI8KOktkA>w}k(|^;q|G@lY z@-yp4_7V10_c|-*oh#Wb|3<+B-;d{tA=jZ?31aSbR>3F7kObuPWN!3i9FP1ez}tKa zxA&bAm#@RS?GvMJu(tMOi~Pn+erV>2FLa7O=oY7Lu&!{a)}I)@N)aFZ1n-_G@_vE? z-6tOZgve-v@VE(m&JuHOvK^&X8umNTP--l1$OcsVg^0d|t6q|rcMBdNNj$y8FUY+iI7uP_swhxWs zCoYyXUg>-5t9}MjWP~r>Wi>*v^%AbmJYR>zn;z=ryo8WFIzFhWx8wf-4{DSw diff --git a/wasm_for_tests/tx_proposal_masp_reward.wasm b/wasm_for_tests/tx_proposal_masp_reward.wasm index b26cbcc89e9a507976762b50bb7f7a0e4f9eddaf..d395c65d3b767419d282cce40395c68c5573a9e4 100755 GIT binary patch delta 11176 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 delta 11318 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 U(A<`@{UCl{!!Bw8>zH!zKlEod4*&oF delta 7403 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ģ#IdEF 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 delta 17681 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 delta 519 zcmZ4elYjM3{td~DZ0tb5!LT`#@dy(m|7JawNJhrq%^j?#Ss8mLujV#0=xk_cU{GMz zU}8{U0TKdTU_PT`eU>7l0<$AemLf9`12?w<14spvK=))po^GJlxja6s{UD{2Be^3s zzvnr?&e*YegGe%mOb6Hi4h^Oq?2bTYLxmeJqXLKH4)!d8j>-D65kPevveF#f5Q}*g zxCOd4uT$k?g$jr(hyewTYc()2_5hWOO^(ymV(i)6sVmRV*tdD5O?0#fL?_rmj1c#7 zr%elGme_1C<0hXVM3xccT#&B>x+Y64S7hwoY_t3V6HKckOBO=DSz*<7g;k6{BN%(9 z-xX%o-tNlGq!`QCyFERD>AxUQFlG;v!t~#Jn7Fr3Dq`xg2Fl2;WBSU@)(i3}_jLJ0 zCW-9^+n9C-0cGBBFh67l(&u=XH!=a~27cz%K>ljA4B$Fr243vQw_J9elZ2?%@eraY&pthUR%$FVj06wvr Ar2qf` diff --git a/wasm_for_tests/vp_infinite_guest_gas.wasm b/wasm_for_tests/vp_infinite_guest_gas.wasm index 3a7d8b8471f1d494b8cedfc656ee5a0cf32d03a3..ef15c1b341a36592364bc24630cdd2fbe383785a 100755 GIT binary patch delta 5983 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 MVT|1JrVz>h2S7anumAu6 diff --git a/wasm_for_tests/vp_memory_limit.wasm b/wasm_for_tests/vp_memory_limit.wasm index 5a66580cd6d90a5d659ed8cf550c02a52c480455..11145a4f5fa92c7fe9d8f5807a96e036546870f0 100755 GIT binary patch delta 11071 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 Otv>~u6V9oLll~tBLF%#q delta 10952 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 Date: Thu, 23 May 2024 21:35:55 -0700 Subject: [PATCH 09/70] empty commit From 48709ce5608632d898d0893e69ea189e07c005fd Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Mon, 20 May 2024 17:54:50 +0200 Subject: [PATCH 10/70] Fixes fee payment --- crates/namada/src/ledger/protocol/mod.rs | 177 +++---- crates/node/src/shell/finalize_block.rs | 576 ++++++++++++----------- crates/node/src/shell/governance.rs | 1 + 3 files changed, 392 insertions(+), 362 deletions(-) diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index 74e17fbae3..3417eaa924 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -184,6 +184,7 @@ impl From for DispatchError { #[allow(clippy::too_many_arguments)] pub fn dispatch_tx<'a, D, H, CA>( tx: Tx, + //FIXME: some params are only needed for some tx types, should also pass the txtype with the associated data here? Maybe yes tx_bytes: &'a [u8], tx_index: TxIndex, tx_gas_meter: &'a RefCell, @@ -191,6 +192,7 @@ pub fn dispatch_tx<'a, D, H, CA>( vp_wasm_cache: &'a mut VpCache, tx_wasm_cache: &'a mut TxCache, block_proposer: Option<&Address>, + wrapper_tx_result: Option>, ) -> std::result::Result, DispatchError> where D: 'static + DB + for<'iter> DBIter<'iter> + Sync, @@ -200,27 +202,98 @@ where match tx.header().tx_type { // Raw trasaction type is allowed only for governance proposals TxType::Raw => { - // No bundles of governance transactions, just take the first one - let cmt = tx.first_commitments().ok_or(Error::MissingInnerTxs)?; - let batched_tx_result = apply_wasm_tx( - BatchedTxRef { tx: &tx, cmt }, - &tx_index, - ShellParams { - tx_gas_meter, - state, - vp_wasm_cache, - tx_wasm_cache, - }, - )?; + if let Some(mut tx_result) = wrapper_tx_result { + // Replay protection check on the batch + let tx_hash = tx.raw_header_hash(); + if state.write_log().has_replay_protection_entry(&tx_hash) { + // If the same batch has already been committed in + // this block, skip execution and return + return Err(DispatchError { + error: Error::ReplayAttempt(tx_hash), + tx_result: None, + }); + } - Ok(TxResult { - gas_used: tx_gas_meter.borrow().get_tx_consumed_gas(), - batch_results: BatchResults( - [(cmt.get_hash(), Ok(batched_tx_result))] - .into_iter() - .collect(), - ), - }) + // TODO(namada#2597): handle masp fee payment in the first inner tx + // if necessary + for cmt in tx.commitments() { + match apply_wasm_tx( + tx.batch_ref_tx(cmt), + &tx_index, + ShellParams { + tx_gas_meter, + state, + vp_wasm_cache, + tx_wasm_cache, + }, + ) { + Err(Error::GasError(ref msg)) => { + // Gas error aborts the execution of the entire batch + tx_result.gas_used = + tx_gas_meter.borrow().get_tx_consumed_gas(); + tx_result.batch_results.0.insert( + cmt.get_hash(), + Err(Error::GasError(msg.to_owned())), + ); + state.write_log_mut().drop_tx(); + return Err(DispatchError { + error: Error::GasError(msg.to_owned()), + tx_result: Some(tx_result), + }); + } + res => { + let is_accepted = matches!(&res, Ok(result) if result.is_accepted()); + + tx_result + .batch_results + .0 + .insert(cmt.get_hash(), res); + tx_result.gas_used = + tx_gas_meter.borrow().get_tx_consumed_gas(); + if is_accepted { + state.write_log_mut().commit_tx_to_batch(); + } else { + state.write_log_mut().drop_tx(); + + if tx.header.atomic { + // Stop the execution of an atomic batch at the + // first failed transaction + return Err(DispatchError { + error: Error::FailingAtomicBatch( + cmt.get_hash(), + ), + tx_result: Some(tx_result), + }); + } + } + } + }; + } + + Ok(tx_result) + } else { + // No bundles of governance transactions, just take the first one + let cmt = + tx.first_commitments().ok_or(Error::MissingInnerTxs)?; + let batched_tx_result = apply_wasm_tx( + BatchedTxRef { tx: &tx, cmt }, + &tx_index, + ShellParams { + tx_gas_meter, + state, + vp_wasm_cache, + tx_wasm_cache, + }, + )?; + Ok(TxResult { + gas_used: tx_gas_meter.borrow().get_tx_consumed_gas(), + batch_results: BatchResults( + [(cmt.get_hash(), Ok(batched_tx_result))] + .into_iter() + .collect(), + ), + }) + } } TxType::Protocol(protocol_tx) => { // No bundles of protocol transactions, only take the first one @@ -252,70 +325,6 @@ where ) .map_err(|e| Error::WrapperRunnerError(e.to_string()))?; - // Replay protection check on the batch - let tx_hash = tx.raw_header_hash(); - if state.write_log().has_replay_protection_entry(&tx_hash) { - // If the same batch has already been committed in - // this block, skip execution and return - return Err(DispatchError { - error: Error::ReplayAttempt(tx_hash), - tx_result: None, - }); - } - - // TODO(namada#2597): handle masp fee payment in the first inner tx - // if necessary - for cmt in tx.commitments() { - match apply_wasm_tx( - tx.batch_ref_tx(cmt), - &tx_index, - ShellParams { - tx_gas_meter, - state, - vp_wasm_cache, - tx_wasm_cache, - }, - ) { - Err(Error::GasError(ref msg)) => { - // Gas error aborts the execution of the entire batch - tx_result.gas_used = - tx_gas_meter.borrow().get_tx_consumed_gas(); - tx_result.batch_results.0.insert( - cmt.get_hash(), - Err(Error::GasError(msg.to_owned())), - ); - state.write_log_mut().drop_tx(); - return Err(DispatchError { - error: Error::GasError(msg.to_owned()), - tx_result: Some(tx_result), - }); - } - res => { - let is_accepted = - matches!(&res, Ok(result) if result.is_accepted()); - - tx_result.batch_results.0.insert(cmt.get_hash(), res); - tx_result.gas_used = - tx_gas_meter.borrow().get_tx_consumed_gas(); - if is_accepted { - state.write_log_mut().commit_tx_to_batch(); - } else { - state.write_log_mut().drop_tx(); - - if tx.header.atomic { - // Stop the execution of an atomic batch at the - // first failed transaction - return Err(DispatchError { - error: Error::FailingAtomicBatch( - cmt.get_hash(), - ), - tx_result: Some(tx_result), - }); - } - } - } - }; - } Ok(tx_result) } } diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 257d16216e..80660e7a9b 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -142,10 +142,16 @@ where proposer from tendermint raw hash", ) }; + //FIXME: need uni test on fee pyament when inner txs touch balance of fee payer (also run this test on the old version with the bug to check that the bug was indeed there) // Tracks the accepted transactions self.state.in_mem_mut().block.results = BlockResults::default(); let mut changed_keys = BTreeSet::new(); + //FIXME: maybe better to cache the transactions themselves to avoid another deserialization + let mut successful_wrappers = vec![]; + + //FIXME: move this to a separate function? Maybe yes + // Execute wrapper and protocol transactions for (tx_index, processed_tx) in req.txs.iter().enumerate() { let tx = if let Ok(tx) = Tx::try_from(processed_tx.tx.as_ref()) { tx @@ -303,21 +309,13 @@ where } }, }; - let replay_protection_hashes = - if matches!(tx_header.tx_type, TxType::Wrapper(_)) { - Some(ReplayProtectionHashes { - raw_header_hash: tx.raw_header_hash(), - header_hash: tx.header_hash(), - }) - } else { - None - }; let tx_gas_meter = RefCell::new(tx_gas_meter); - let mut tx_event = new_tx_event(&tx, height.0); + let tx_event = new_tx_event(&tx, height.0); let is_atomic_batch = tx.header.atomic; let commitments_len = tx.commitments().len() as u64; let tx_hash = tx.header_hash(); + //FIXME: this thing is the same for raw txs, merge them? Maybe not let dispatch_result = protocol::dispatch_tx( tx, processed_tx.tx.as_ref(), @@ -327,6 +325,7 @@ where &mut self.vp_wasm_cache, &mut self.tx_wasm_cache, block_proposer, + None, ); let tx_gas_meter = tx_gas_meter.into_inner(); let consumed_gas = tx_gas_meter.get_tx_consumed_gas(); @@ -334,6 +333,82 @@ where // save the gas cost self.update_tx_gas(tx_hash, consumed_gas.into()); + //FIXME: this is becoming very cluttered because it needs to handle wrappers, inners and protocols, should split in different functions? + if let Some(wrapper_cache) = self.evaluate_tx_result( + &mut response, + dispatch_result, + TxData { + is_atomic_batch, + tx_header: &tx_header, + commitments_len, + tx_index, + replay_protection_hashes: None, + tx_gas_meter, + height, + }, + TxLogs { + tx_event, + stats: &mut stats, + changed_keys: &mut changed_keys, + }, + ) { + successful_wrappers.push(wrapper_cache); + } + } + + // Execute inner transactions + //FIXME: export this to another function + for WrapperCache { + tx_index, + gas_meter: tx_gas_meter, + event: tx_event, + tx_result: wrapper_tx_result, + } in successful_wrappers + { + //FIXME: should also enqueue the tx directly to avoid deserializing again? POssibly yes + //FIXME: manage unwrap + let processed_tx = req.txs.get(tx_index).unwrap(); + let mut tx = if let Ok(tx) = Tx::try_from(processed_tx.tx.as_ref()) + { + tx + } else { + tracing::error!( + "FinalizeBlock received a tx that could not be \ + deserialized to a Tx type. This is likely a protocol \ + transaction." + ); + continue; + }; + + let tx_header = tx.header(); + let tx_hash = tx.header_hash(); + let is_atomic_batch = tx.header.atomic; + let commitments_len = tx.commitments().len() as u64; + let replay_protection_hashes = Some(ReplayProtectionHashes { + raw_header_hash: tx.raw_header_hash(), + header_hash: tx.header_hash(), + }); + + // change tx type to raw for execution + tx.update_header(TxType::Raw); + let tx_gas_meter = RefCell::new(tx_gas_meter); + let dispatch_result = protocol::dispatch_tx( + tx, + processed_tx.tx.as_ref(), + TxIndex::must_from_usize(tx_index), + &tx_gas_meter, + &mut self.state, + &mut self.vp_wasm_cache, + &mut self.tx_wasm_cache, + None, + Some(wrapper_tx_result), + ); + let tx_gas_meter = tx_gas_meter.into_inner(); + let consumed_gas = tx_gas_meter.get_tx_consumed_gas(); + + // update the gas cost of the corresponding wrapper + self.update_tx_gas(tx_hash, consumed_gas.into()); + self.evaluate_tx_result( &mut response, dispatch_result, @@ -343,16 +418,15 @@ where commitments_len, tx_index, replay_protection_hashes, - consumed_gas, + tx_gas_meter, height, }, TxLogs { - tx_event: &mut tx_event, + tx_event, stats: &mut stats, changed_keys: &mut changed_keys, }, ); - response.events.emit(tx_event); } stats.set_tx_cache_size( @@ -524,8 +598,8 @@ where } } - // Evaluate the result of a batch. Commit or drop the storage changes, - // update stats and event, manage replay protection. + // Evaluate the result of a transaction. Commit or drop the storage changes, + // update stats and event, manage replay protection. For successful wrapper transactions return the relevant data and delay the evaluation after the batch execution fn evaluate_tx_result( &mut self, response: &mut shim::response::FinalizeBlock, @@ -535,14 +609,27 @@ where >, tx_data: TxData<'_>, mut tx_logs: TxLogs<'_>, - ) { + ) -> Option { match dispatch_result { - Ok(tx_result) => self.handle_inner_tx_results( - response, - tx_result, - tx_data, - &mut tx_logs, - ), + Ok(tx_result) => match tx_data.tx_header.tx_type { + //FIXME: manage unwrap + TxType::Wrapper(_) => + // Return withouth emitting the event + { + return Some(WrapperCache { + tx_index: tx_data.tx_index, + gas_meter: tx_data.tx_gas_meter, + event: tx_logs.tx_event, + tx_result, + }) + } + _ => self.handle_inner_tx_results( + response, + tx_result, + tx_data, + &mut tx_logs, + ), + }, Err(DispatchError { error: protocol::Error::WrapperRunnerError(msg), tx_result: _, @@ -557,7 +644,7 @@ where ); tx_logs .tx_event - .extend(GasUsed(tx_data.consumed_gas)) + .extend(GasUsed(tx_data.tx_gas_meter.get_tx_consumed_gas())) .extend(Info(msg.to_string())) .extend(Code(ResultCode::InvalidTx)); // Make sure to clean the write logs for the next transaction @@ -582,7 +669,7 @@ where tx_logs .tx_event - .extend(GasUsed(tx_data.consumed_gas)) + .extend(GasUsed(tx_data.tx_gas_meter.get_tx_consumed_gas())) .extend(Info(msg.to_string())) .extend(Code(ResultCode::WasmRuntimeError)); @@ -595,6 +682,9 @@ where ); } } + + response.events.emit(tx_logs.tx_event); + None } // Evaluate the results of all the transactions of the batch. Commit or drop @@ -747,18 +837,28 @@ where } } +// Caches the execution of a wrapper transaction to be used when later executing the inner batch +struct WrapperCache { + tx_index: usize, + gas_meter: TxGasMeter, + event: Event, + tx_result: namada::tx::data::TxResult, +} + struct TxData<'tx> { is_atomic_batch: bool, + // FIXME: need the actual tx but it's hard becasue that is passed to dispatch_tx so I'd need to clone it + //FIXME: actually I need the tx only for wrappers, for everything else I only need the header tx_header: &'tx namada::tx::Header, commitments_len: u64, tx_index: usize, replay_protection_hashes: Option, - consumed_gas: Gas, + tx_gas_meter: TxGasMeter, height: BlockHeight, } struct TxLogs<'finalize> { - tx_event: &'finalize mut Event, + tx_event: Event, stats: &'finalize mut InternalStats, changed_keys: &'finalize mut BTreeSet, } @@ -2798,25 +2898,21 @@ mod test_finalize_block { assert_eq!(root_pre.0, root_post.0); // Check transaction's hash in storage - assert!( - shell - .shell - .state - .write_log() - .has_replay_protection_entry(&wrapper_tx.raw_header_hash()) - ); + assert!(shell + .shell + .state + .write_log() + .has_replay_protection_entry(&wrapper_tx.raw_header_hash())); // Check that the hash is not present in the merkle tree shell.state.commit_block().unwrap(); - assert!( - !shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&wrapper_hash_key) - .unwrap() - ); + assert!(!shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&wrapper_hash_key) + .unwrap()); // test that a commitment to replay protection gets added. let reprot_key = replay_protection::commitment_key(); @@ -2863,26 +2959,22 @@ mod test_finalize_block { assert_eq!(root_pre.0, root_post.0); // Check that the hashes are present in the merkle tree shell.state.commit_block().unwrap(); - assert!( - shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&convert_key) - .unwrap() - ); - assert!( - shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&commitment_key) - .unwrap() - ); + assert!(shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&convert_key) + .unwrap()); + assert!(shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&commitment_key) + .unwrap()); } /// Test that a tx that has already been applied in the same block @@ -2960,34 +3052,26 @@ mod test_finalize_block { assert_eq!(code, ResultCode::WasmRuntimeError); for wrapper in [&wrapper, &new_wrapper] { - assert!( - shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.raw_header_hash()) - ); - assert!( - !shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.header_hash()) - ); + assert!(shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.raw_header_hash())); + assert!(!shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.header_hash())); } // Commit to check the hashes from storage shell.commit(); for wrapper in [&wrapper, &new_wrapper] { - assert!( - shell - .state - .has_replay_protection_entry(&wrapper.raw_header_hash()) - .unwrap() - ); - assert!( - !shell - .state - .has_replay_protection_entry(&wrapper.header_hash()) - .unwrap() - ); + assert!(shell + .state + .has_replay_protection_entry(&wrapper.raw_header_hash()) + .unwrap()); + assert!(!shell + .state + .has_replay_protection_entry(&wrapper.header_hash()) + .unwrap()); } } @@ -3270,29 +3354,23 @@ mod test_finalize_block { &unsigned_wrapper, &wrong_commitment_wrapper, ] { - assert!( - !shell.state.write_log().has_replay_protection_entry( - &valid_wrapper.raw_header_hash() - ) - ); - assert!( - shell - .state - .write_log() - .has_replay_protection_entry(&valid_wrapper.header_hash()) - ); - } - assert!( - shell.state.write_log().has_replay_protection_entry( - &failing_wrapper.raw_header_hash() - ) - ); - assert!( - !shell + assert!(!shell .state .write_log() - .has_replay_protection_entry(&failing_wrapper.header_hash()) - ); + .has_replay_protection_entry(&valid_wrapper.raw_header_hash())); + assert!(shell + .state + .write_log() + .has_replay_protection_entry(&valid_wrapper.header_hash())); + } + assert!(shell + .state + .write_log() + .has_replay_protection_entry(&failing_wrapper.raw_header_hash())); + assert!(!shell + .state + .write_log() + .has_replay_protection_entry(&failing_wrapper.header_hash())); // Commit to check the hashes from storage shell.commit(); @@ -3301,33 +3379,23 @@ mod test_finalize_block { unsigned_wrapper, wrong_commitment_wrapper, ] { - assert!( - !shell - .state - .has_replay_protection_entry( - &valid_wrapper.raw_header_hash() - ) - .unwrap() - ); - assert!( - shell - .state - .has_replay_protection_entry(&valid_wrapper.header_hash()) - .unwrap() - ); - } - assert!( - shell + assert!(!shell .state - .has_replay_protection_entry(&failing_wrapper.raw_header_hash()) - .unwrap() - ); - assert!( - !shell + .has_replay_protection_entry(&valid_wrapper.raw_header_hash()) + .unwrap()); + assert!(shell .state - .has_replay_protection_entry(&failing_wrapper.header_hash()) - .unwrap() - ); + .has_replay_protection_entry(&valid_wrapper.header_hash()) + .unwrap()); + } + assert!(shell + .state + .has_replay_protection_entry(&failing_wrapper.raw_header_hash()) + .unwrap()); + assert!(!shell + .state + .has_replay_protection_entry(&failing_wrapper.header_hash()) + .unwrap()); } #[test] @@ -3387,18 +3455,14 @@ mod test_finalize_block { let code = event[0].read_attribute::().expect("Test failed"); assert_eq!(code, ResultCode::InvalidTx); - assert!( - shell - .state - .write_log() - .has_replay_protection_entry(&wrapper_hash) - ); - assert!( - !shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.raw_header_hash()) - ); + assert!(shell + .state + .write_log() + .has_replay_protection_entry(&wrapper_hash)); + assert!(!shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.raw_header_hash())); } // Test that the fees are paid even if the inner transaction fails and its @@ -3796,11 +3860,9 @@ mod test_finalize_block { .unwrap(), Some(ValidatorState::Consensus) ); - assert!( - enqueued_slashes_handle() - .at(&Epoch::default()) - .is_empty(&shell.state)? - ); + assert!(enqueued_slashes_handle() + .at(&Epoch::default()) + .is_empty(&shell.state)?); assert_eq!( get_num_consensus_validators(&shell.state, Epoch::default()) .unwrap(), @@ -3819,21 +3881,17 @@ mod test_finalize_block { .unwrap(), Some(ValidatorState::Jailed) ); - assert!( - enqueued_slashes_handle() - .at(&epoch) - .is_empty(&shell.state)? - ); + assert!(enqueued_slashes_handle() + .at(&epoch) + .is_empty(&shell.state)?); assert_eq!( get_num_consensus_validators(&shell.state, epoch).unwrap(), 5_u64 ); } - assert!( - !enqueued_slashes_handle() - .at(&processing_epoch) - .is_empty(&shell.state)? - ); + assert!(!enqueued_slashes_handle() + .at(&processing_epoch) + .is_empty(&shell.state)?); // Advance to the processing epoch loop { @@ -3856,11 +3914,9 @@ mod test_finalize_block { // println!("Reached processing epoch"); break; } else { - assert!( - enqueued_slashes_handle() - .at(&shell.state.in_mem().block.epoch) - .is_empty(&shell.state)? - ); + assert!(enqueued_slashes_handle() + .at(&shell.state.in_mem().block.epoch) + .is_empty(&shell.state)?); let stake1 = read_validator_stake( &shell.state, ¶ms, @@ -4344,13 +4400,11 @@ mod test_finalize_block { ) .unwrap(); assert_eq!(last_slash, Some(misbehavior_epoch)); - assert!( - namada_proof_of_stake::storage::validator_slashes_handle( - &val1.address - ) - .is_empty(&shell.state) - .unwrap() - ); + assert!(namada_proof_of_stake::storage::validator_slashes_handle( + &val1.address + ) + .is_empty(&shell.state) + .unwrap()); tracing::debug!("Advancing to epoch 7"); @@ -4415,22 +4469,18 @@ mod test_finalize_block { ) .unwrap(); assert_eq!(last_slash, Some(Epoch(4))); - assert!( - namada_proof_of_stake::is_validator_frozen( - &shell.state, - &val1.address, - current_epoch, - ¶ms - ) - .unwrap() - ); - assert!( - namada_proof_of_stake::storage::validator_slashes_handle( - &val1.address - ) - .is_empty(&shell.state) - .unwrap() - ); + assert!(namada_proof_of_stake::is_validator_frozen( + &shell.state, + &val1.address, + current_epoch, + ¶ms + ) + .unwrap()); + assert!(namada_proof_of_stake::storage::validator_slashes_handle( + &val1.address + ) + .is_empty(&shell.state) + .unwrap()); let pre_stake_10 = namada_proof_of_stake::storage::read_validator_stake( @@ -5308,11 +5358,9 @@ mod test_finalize_block { shell.vp_wasm_cache.clone(), ); let parameters = ParametersVp { ctx }; - assert!( - parameters - .validate_tx(&batched_tx, &keys_changed, &verifiers) - .is_ok() - ); + assert!(parameters + .validate_tx(&batched_tx, &keys_changed, &verifiers) + .is_ok()); // we advance forward to the next epoch let mut req = FinalizeBlock::default(); @@ -5385,13 +5433,11 @@ mod test_finalize_block { let inner_results = inner_tx_result.batch_results.0; for cmt in batch.commitments() { - assert!( - inner_results - .get(&cmt.get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted()) - ); + assert!(inner_results + .get(&cmt.get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted())); } // Check storage modifications @@ -5429,24 +5475,18 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!( - inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted()) - ); - assert!( - inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err() - ); + assert!(inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted())); + assert!(inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err()); // Assert that the last tx didn't run - assert!( - !inner_results.contains_key(&batch.commitments()[2].get_hash()) - ); + assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); // Check storage modifications are missing for key in ["random_key_1", "random_key_2", "random_key_3"] { @@ -5477,27 +5517,21 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!( - inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted()) - ); - assert!( - inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err() - ); - assert!( - inner_results - .get(&batch.commitments()[2].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted()) - ); + assert!(inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted())); + assert!(inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err()); + assert!(inner_results + .get(&batch.commitments()[2].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted())); // Check storage modifications assert_eq!( @@ -5508,12 +5542,10 @@ mod test_finalize_block { .unwrap(), STORAGE_VALUE ); - assert!( - !shell - .state - .has_key(&"random_key_2".parse().unwrap()) - .unwrap() - ); + assert!(!shell + .state + .has_key(&"random_key_2".parse().unwrap()) + .unwrap()); assert_eq!( shell .state @@ -5545,24 +5577,18 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!( - inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted()) - ); - assert!( - inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err() - ); + assert!(inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted())); + assert!(inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err()); // Assert that the last tx didn't run - assert!( - !inner_results.contains_key(&batch.commitments()[2].get_hash()) - ); + assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); // Check storage modifications are missing for key in ["random_key_1", "random_key_2", "random_key_3"] { @@ -5592,24 +5618,18 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!( - inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted()) - ); - assert!( - inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err() - ); + assert!(inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted())); + assert!(inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err()); // Assert that the last tx didn't run - assert!( - !inner_results.contains_key(&batch.commitments()[2].get_hash()) - ); + assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); // Check storage modifications assert_eq!( diff --git a/crates/node/src/shell/governance.rs b/crates/node/src/shell/governance.rs index dbde3d0204..b8d82d6df4 100644 --- a/crates/node/src/shell/governance.rs +++ b/crates/node/src/shell/governance.rs @@ -413,6 +413,7 @@ where &mut shell.vp_wasm_cache, &mut shell.tx_wasm_cache, None, + None, ); shell .state From 57e5f46a6273fc516dd670171736832bd3038719 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Mon, 20 May 2024 18:42:34 +0200 Subject: [PATCH 11/70] Refactors tx execution of `finalize_block` into separate functions --- crates/node/src/shell/finalize_block.rs | 582 +++++++++++++----------- 1 file changed, 305 insertions(+), 277 deletions(-) diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 80660e7a9b..c7e477afab 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -147,287 +147,27 @@ where // Tracks the accepted transactions self.state.in_mem_mut().block.results = BlockResults::default(); let mut changed_keys = BTreeSet::new(); - //FIXME: maybe better to cache the transactions themselves to avoid another deserialization - let mut successful_wrappers = vec![]; - //FIXME: move this to a separate function? Maybe yes // Execute wrapper and protocol transactions - for (tx_index, processed_tx) in req.txs.iter().enumerate() { - let tx = if let Ok(tx) = Tx::try_from(processed_tx.tx.as_ref()) { - tx - } else { - tracing::error!( - "FinalizeBlock received a tx that could not be \ - deserialized to a Tx type. This is likely a protocol \ - transaction." - ); - continue; - }; - - let result_code = ResultCode::from_u32(processed_tx.result.code) - .expect("Result code conversion should not fail"); - - // If [`process_proposal`] rejected a Tx due to invalid signature, - // emit an event here and move on to next tx. - if result_code == ResultCode::InvalidSig { - let base_event = match tx.header().tx_type { - TxType::Wrapper(_) | TxType::Protocol(_) => { - new_tx_event(&tx, height.0) - } - _ => { - tracing::error!( - "Internal logic error: FinalizeBlock received a \ - tx with an invalid signature error code that \ - could not be deserialized to a WrapperTx / \ - ProtocolTx type" - ); - continue; - } - }; - response.events.emit( - base_event - .with(Code(result_code)) - .with(Info(format!( - "Tx rejected: {}", - &processed_tx.result.info - ))) - .with(GasUsed(0.into())), - ); - continue; - } - - if tx.validate_tx().is_err() { - tracing::error!( - "Internal logic error: FinalizeBlock received tx that \ - could not be deserialized to a valid TxType" - ); - continue; - }; - let tx_header = tx.header(); - // If [`process_proposal`] rejected a Tx, emit an event here and - // move on to next tx - if result_code != ResultCode::Ok { - response.events.emit( - new_tx_event(&tx, height.0) - .with(Code(result_code)) - .with(Info(format!( - "Tx rejected: {}", - &processed_tx.result.info - ))) - .with(GasUsed(0.into())), - ); - continue; - } - - let (tx_gas_meter, block_proposer) = match &tx_header.tx_type { - TxType::Wrapper(wrapper) => { - stats.increment_wrapper_txs(); - let gas_limit = match Gas::try_from(wrapper.gas_limit) { - Ok(value) => value, - Err(_) => { - response.events.emit( - new_tx_event(&tx, height.0) - .with(Code(ResultCode::InvalidTx)) - .with(Info( - "The wrapper gas limit overflowed gas \ - representation" - .to_owned(), - )) - .with(GasUsed(0.into())), - ); - continue; - } - }; - let gas_meter = TxGasMeter::new(gas_limit); - for cmt in tx.commitments() { - if let Some(code_sec) = tx - .get_section(cmt.code_sechash()) - .and_then(|x| Section::code_sec(x.as_ref())) - { - stats.increment_tx_type( - code_sec.code.hash().to_string(), - ); - } - } - (gas_meter, Some(&native_block_proposer_address)) - } - TxType::Raw => { - tracing::error!( - "Internal logic error: FinalizeBlock received a \ - TxType::Raw transaction" - ); - continue; - } - TxType::Protocol(protocol_tx) => match protocol_tx.tx { - ProtocolTxType::BridgePoolVext - | ProtocolTxType::BridgePool - | ProtocolTxType::ValSetUpdateVext - | ProtocolTxType::ValidatorSetUpdate => { - (TxGasMeter::new_from_sub_limit(0.into()), None) - } - ProtocolTxType::EthEventsVext => { - let ext = - ethereum_tx_data_variants::EthEventsVext::try_from( - &tx, - ) - .unwrap(); - if self - .mode - .get_validator_address() - .map(|validator| { - validator == &ext.data.validator_addr - }) - .unwrap_or(false) - { - for event in ext.data.ethereum_events.iter() { - self.mode.dequeue_eth_event(event); - } - } - (TxGasMeter::new_from_sub_limit(0.into()), None) - } - ProtocolTxType::EthereumEvents => { - let digest = - ethereum_tx_data_variants::EthereumEvents::try_from( - &tx - ).unwrap(); - if let Some(address) = - self.mode.get_validator_address().cloned() - { - let this_signer = &( - address, - self.state.in_mem().get_last_block_height(), - ); - for MultiSignedEthEvent { event, signers } in - &digest.events - { - if signers.contains(this_signer) { - self.mode.dequeue_eth_event(event); - } - } - } - (TxGasMeter::new_from_sub_limit(0.into()), None) - } - }, - }; - let tx_gas_meter = RefCell::new(tx_gas_meter); - let tx_event = new_tx_event(&tx, height.0); - let is_atomic_batch = tx.header.atomic; - let commitments_len = tx.commitments().len() as u64; - let tx_hash = tx.header_hash(); - - //FIXME: this thing is the same for raw txs, merge them? Maybe not - let dispatch_result = protocol::dispatch_tx( - tx, - processed_tx.tx.as_ref(), - TxIndex::must_from_usize(tx_index), - &tx_gas_meter, - &mut self.state, - &mut self.vp_wasm_cache, - &mut self.tx_wasm_cache, - block_proposer, - None, - ); - let tx_gas_meter = tx_gas_meter.into_inner(); - let consumed_gas = tx_gas_meter.get_tx_consumed_gas(); - - // save the gas cost - self.update_tx_gas(tx_hash, consumed_gas.into()); - - //FIXME: this is becoming very cluttered because it needs to handle wrappers, inners and protocols, should split in different functions? - if let Some(wrapper_cache) = self.evaluate_tx_result( - &mut response, - dispatch_result, - TxData { - is_atomic_batch, - tx_header: &tx_header, - commitments_len, - tx_index, - replay_protection_hashes: None, - tx_gas_meter, - height, - }, - TxLogs { - tx_event, - stats: &mut stats, - changed_keys: &mut changed_keys, - }, - ) { - successful_wrappers.push(wrapper_cache); - } - } + let successful_wrappers = self.retrieve_and_execute_transactions( + &req.txs, + &mut response, + &mut changed_keys, + &mut stats, + height, + &native_block_proposer_address, + ); // Execute inner transactions - //FIXME: export this to another function - for WrapperCache { - tx_index, - gas_meter: tx_gas_meter, - event: tx_event, - tx_result: wrapper_tx_result, - } in successful_wrappers - { - //FIXME: should also enqueue the tx directly to avoid deserializing again? POssibly yes - //FIXME: manage unwrap - let processed_tx = req.txs.get(tx_index).unwrap(); - let mut tx = if let Ok(tx) = Tx::try_from(processed_tx.tx.as_ref()) - { - tx - } else { - tracing::error!( - "FinalizeBlock received a tx that could not be \ - deserialized to a Tx type. This is likely a protocol \ - transaction." - ); - continue; - }; - - let tx_header = tx.header(); - let tx_hash = tx.header_hash(); - let is_atomic_batch = tx.header.atomic; - let commitments_len = tx.commitments().len() as u64; - let replay_protection_hashes = Some(ReplayProtectionHashes { - raw_header_hash: tx.raw_header_hash(), - header_hash: tx.header_hash(), - }); - - // change tx type to raw for execution - tx.update_header(TxType::Raw); - let tx_gas_meter = RefCell::new(tx_gas_meter); - let dispatch_result = protocol::dispatch_tx( - tx, - processed_tx.tx.as_ref(), - TxIndex::must_from_usize(tx_index), - &tx_gas_meter, - &mut self.state, - &mut self.vp_wasm_cache, - &mut self.tx_wasm_cache, - None, - Some(wrapper_tx_result), - ); - let tx_gas_meter = tx_gas_meter.into_inner(); - let consumed_gas = tx_gas_meter.get_tx_consumed_gas(); - - // update the gas cost of the corresponding wrapper - self.update_tx_gas(tx_hash, consumed_gas.into()); - - self.evaluate_tx_result( - &mut response, - dispatch_result, - TxData { - is_atomic_batch, - tx_header: &tx_header, - commitments_len, - tx_index, - replay_protection_hashes, - tx_gas_meter, - height, - }, - TxLogs { - tx_event, - stats: &mut stats, - changed_keys: &mut changed_keys, - }, - ); - } + self.execute_tx_batches( + successful_wrappers, + //FIXME: same args as the previous function, use a struct + &req.txs, + &mut response, + &mut changed_keys, + &mut stats, + height, + ); stats.set_tx_cache_size( self.tx_wasm_cache.get_size(), @@ -835,6 +575,294 @@ where } } } + + // Get the transactions from the consensus engine, preprocess and execute them. Return the cache of successful wrapper transactions later used when executing the inner txs. + fn retrieve_and_execute_transactions( + &mut self, + processed_txs: &[shim::request::ProcessedTx], + response: &mut shim::response::FinalizeBlock, + //FIXME: review how we pass these, custom struct? + changed_keys: &mut BTreeSet, + stats: &mut InternalStats, + height: BlockHeight, + native_block_proposer_address: &Address, + //FIXME: maybe better to cache the transactions themselves to avoid another deserialization + ) -> Vec { + let mut successful_wrappers = vec![]; + + for (tx_index, processed_tx) in processed_txs.iter().enumerate() { + let tx = if let Ok(tx) = Tx::try_from(processed_tx.tx.as_ref()) { + tx + } else { + tracing::error!( + "FinalizeBlock received a tx that could not be \ + deserialized to a Tx type. This is likely a protocol \ + transaction." + ); + continue; + }; + + let result_code = ResultCode::from_u32(processed_tx.result.code) + .expect("Result code conversion should not fail"); + + // If [`process_proposal`] rejected a Tx due to invalid signature, + // emit an event here and move on to next tx. + if result_code == ResultCode::InvalidSig { + let base_event = match tx.header().tx_type { + TxType::Wrapper(_) | TxType::Protocol(_) => { + new_tx_event(&tx, height.0) + } + _ => { + tracing::error!( + "Internal logic error: FinalizeBlock received a \ + tx with an invalid signature error code that \ + could not be deserialized to a WrapperTx / \ + ProtocolTx type" + ); + continue; + } + }; + response.events.emit( + base_event + .with(Code(result_code)) + .with(Info(format!( + "Tx rejected: {}", + &processed_tx.result.info + ))) + .with(GasUsed(0.into())), + ); + continue; + } + + if tx.validate_tx().is_err() { + tracing::error!( + "Internal logic error: FinalizeBlock received tx that \ + could not be deserialized to a valid TxType" + ); + continue; + }; + let tx_header = tx.header(); + // If [`process_proposal`] rejected a Tx, emit an event here and + // move on to next tx + if result_code != ResultCode::Ok { + response.events.emit( + new_tx_event(&tx, height.0) + .with(Code(result_code)) + .with(Info(format!( + "Tx rejected: {}", + &processed_tx.result.info + ))) + .with(GasUsed(0.into())), + ); + continue; + } + + let (tx_gas_meter, block_proposer) = + match &tx_header.tx_type { + TxType::Wrapper(wrapper) => { + stats.increment_wrapper_txs(); + let gas_meter = TxGasMeter::new(wrapper.gas_limit); + for cmt in tx.commitments() { + if let Some(code_sec) = tx + .get_section(cmt.code_sechash()) + .and_then(|x| Section::code_sec(x.as_ref())) + { + stats.increment_tx_type( + code_sec.code.hash().to_string(), + ); + } + } + (gas_meter, Some(native_block_proposer_address)) + } + TxType::Raw => { + tracing::error!( + "Internal logic error: FinalizeBlock received a \ + TxType::Raw transaction" + ); + continue; + } + TxType::Protocol(protocol_tx) => match protocol_tx.tx { + ProtocolTxType::BridgePoolVext + | ProtocolTxType::BridgePool + | ProtocolTxType::ValSetUpdateVext + | ProtocolTxType::ValidatorSetUpdate => { + (TxGasMeter::new_from_sub_limit(0.into()), None) + } + ProtocolTxType::EthEventsVext => { + let ext = + ethereum_tx_data_variants::EthEventsVext::try_from(&tx) + .unwrap(); + if self + .mode + .get_validator_address() + .map(|validator| { + validator == &ext.data.validator_addr + }) + .unwrap_or(false) + { + for event in ext.data.ethereum_events.iter() { + self.mode.dequeue_eth_event(event); + } + } + (TxGasMeter::new_from_sub_limit(0.into()), None) + } + ProtocolTxType::EthereumEvents => { + let digest = + ethereum_tx_data_variants::EthereumEvents::try_from( + &tx, + ) + .unwrap(); + if let Some(address) = + self.mode.get_validator_address().cloned() + { + let this_signer = &( + address, + self.state.in_mem().get_last_block_height(), + ); + for MultiSignedEthEvent { event, signers } in + &digest.events + { + if signers.contains(this_signer) { + self.mode.dequeue_eth_event(event); + } + } + } + (TxGasMeter::new_from_sub_limit(0.into()), None) + } + }, + }; + let tx_gas_meter = RefCell::new(tx_gas_meter); + let tx_event = new_tx_event(&tx, height.0); + let is_atomic_batch = tx.header.atomic; + let commitments_len = tx.commitments().len() as u64; + let tx_hash = tx.header_hash(); + + let dispatch_result = protocol::dispatch_tx( + tx, + processed_tx.tx.as_ref(), + TxIndex::must_from_usize(tx_index), + &tx_gas_meter, + &mut self.state, + &mut self.vp_wasm_cache, + &mut self.tx_wasm_cache, + block_proposer, + None, + ); + let tx_gas_meter = tx_gas_meter.into_inner(); + let consumed_gas = tx_gas_meter.get_tx_consumed_gas(); + + // save the gas cost + self.update_tx_gas(tx_hash, consumed_gas.into()); + + //FIXME: this is becoming very cluttered because it needs to handle wrappers, inners and protocols, should split in different functions? + if let Some(wrapper_cache) = self.evaluate_tx_result( + response, + dispatch_result, + TxData { + is_atomic_batch, + tx_header: &tx_header, + commitments_len, + tx_index, + replay_protection_hashes: None, + tx_gas_meter, + height, + }, + TxLogs { + tx_event, + stats, + changed_keys, + }, + ) { + successful_wrappers.push(wrapper_cache); + } + } + + successful_wrappers + } + + // Execute the transaction batches for successful wrapper transactions + fn execute_tx_batches( + &mut self, + //FIXME: iter trait? + successful_wrappers: Vec, + processed_txs: &[shim::request::ProcessedTx], + response: &mut shim::response::FinalizeBlock, + //FIXME: review how we pass these, custom struct? + changed_keys: &mut BTreeSet, + stats: &mut InternalStats, + height: BlockHeight, + ) { + for WrapperCache { + tx_index, + gas_meter: tx_gas_meter, + event: tx_event, + tx_result: wrapper_tx_result, + } in successful_wrappers + { + //FIXME: should also enqueue the tx directly to avoid deserializing again? POssibly yes + //FIXME: manage unwrap + let processed_tx = processed_txs.get(tx_index).unwrap(); + let mut tx = if let Ok(tx) = Tx::try_from(processed_tx.tx.as_ref()) + { + tx + } else { + tracing::error!( + "FinalizeBlock received a tx that could not be \ + deserialized to a Tx type. This is likely a protocol \ + transaction." + ); + continue; + }; + + let tx_header = tx.header(); + let tx_hash = tx.header_hash(); + let is_atomic_batch = tx.header.atomic; + let commitments_len = tx.commitments().len() as u64; + let replay_protection_hashes = Some(ReplayProtectionHashes { + raw_header_hash: tx.raw_header_hash(), + header_hash: tx.header_hash(), + }); + + // change tx type to raw for execution + tx.update_header(TxType::Raw); + let tx_gas_meter = RefCell::new(tx_gas_meter); + let dispatch_result = protocol::dispatch_tx( + tx, + processed_tx.tx.as_ref(), + TxIndex::must_from_usize(tx_index), + &tx_gas_meter, + &mut self.state, + &mut self.vp_wasm_cache, + &mut self.tx_wasm_cache, + None, + Some(wrapper_tx_result), + ); + let tx_gas_meter = tx_gas_meter.into_inner(); + let consumed_gas = tx_gas_meter.get_tx_consumed_gas(); + + // update the gas cost of the corresponding wrapper + self.update_tx_gas(tx_hash, consumed_gas.into()); + + self.evaluate_tx_result( + response, + dispatch_result, + TxData { + is_atomic_batch, + tx_header: &tx_header, + commitments_len, + tx_index, + replay_protection_hashes, + tx_gas_meter, + height, + }, + TxLogs { + tx_event, + stats, + changed_keys, + }, + ); + } + } } // Caches the execution of a wrapper transaction to be used when later executing the inner batch From d1eafb2817f3d5c7ab0bc30ef77f8aeec8fd64af Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Mon, 20 May 2024 19:10:13 +0200 Subject: [PATCH 12/70] Reorganizes arguments for tx execution --- crates/node/src/shell/finalize_block.rs | 60 +++++++++++++++---------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index c7e477afab..25a3ab6d38 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -150,23 +150,26 @@ where // Execute wrapper and protocol transactions let successful_wrappers = self.retrieve_and_execute_transactions( - &req.txs, - &mut response, - &mut changed_keys, - &mut stats, - height, &native_block_proposer_address, + ExecutionArgs { + processed_txs: &req.txs, + response: &mut response, + changed_keys: &mut changed_keys, + stats: &mut stats, + height, + }, ); // Execute inner transactions self.execute_tx_batches( successful_wrappers, - //FIXME: same args as the previous function, use a struct - &req.txs, - &mut response, - &mut changed_keys, - &mut stats, - height, + ExecutionArgs { + processed_txs: &req.txs, + response: &mut response, + changed_keys: &mut changed_keys, + stats: &mut stats, + height, + }, ); stats.set_tx_cache_size( @@ -579,13 +582,14 @@ where // Get the transactions from the consensus engine, preprocess and execute them. Return the cache of successful wrapper transactions later used when executing the inner txs. fn retrieve_and_execute_transactions( &mut self, - processed_txs: &[shim::request::ProcessedTx], - response: &mut shim::response::FinalizeBlock, - //FIXME: review how we pass these, custom struct? - changed_keys: &mut BTreeSet, - stats: &mut InternalStats, - height: BlockHeight, native_block_proposer_address: &Address, + ExecutionArgs { + processed_txs, + response, + changed_keys, + stats, + height, + }: ExecutionArgs, //FIXME: maybe better to cache the transactions themselves to avoid another deserialization ) -> Vec { let mut successful_wrappers = vec![]; @@ -783,14 +787,14 @@ where // Execute the transaction batches for successful wrapper transactions fn execute_tx_batches( &mut self, - //FIXME: iter trait? successful_wrappers: Vec, - processed_txs: &[shim::request::ProcessedTx], - response: &mut shim::response::FinalizeBlock, - //FIXME: review how we pass these, custom struct? - changed_keys: &mut BTreeSet, - stats: &mut InternalStats, - height: BlockHeight, + ExecutionArgs { + processed_txs, + response, + changed_keys, + stats, + height, + }: ExecutionArgs, ) { for WrapperCache { tx_index, @@ -865,6 +869,14 @@ where } } +struct ExecutionArgs<'finalize> { + processed_txs: &'finalize [shim::request::ProcessedTx], + response: &'finalize mut shim::response::FinalizeBlock, + changed_keys: &'finalize mut BTreeSet, + stats: &'finalize mut InternalStats, + height: BlockHeight, +} + // Caches the execution of a wrapper transaction to be used when later executing the inner batch struct WrapperCache { tx_index: usize, From 5711946231b83b03a53b3e2cb3acfbe02bea4090 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Mon, 20 May 2024 19:39:01 +0200 Subject: [PATCH 13/70] Cache wrapper transaction to avoid second deserialization --- crates/namada/src/ledger/protocol/mod.rs | 4 +- crates/node/src/shell/finalize_block.rs | 56 ++++++++---------------- crates/node/src/shell/governance.rs | 2 +- 3 files changed, 21 insertions(+), 41 deletions(-) diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index 3417eaa924..56ad5a49a2 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -183,7 +183,7 @@ impl From for DispatchError { /// environment, in which case validity predicates will be bypassed. #[allow(clippy::too_many_arguments)] pub fn dispatch_tx<'a, D, H, CA>( - tx: Tx, + tx: &Tx, //FIXME: some params are only needed for some tx types, should also pass the txtype with the associated data here? Maybe yes tx_bytes: &'a [u8], tx_index: TxIndex, @@ -311,7 +311,7 @@ where }) } TxType::Wrapper(ref wrapper) => { - let mut tx_result = apply_wrapper_tx( + let tx_result = apply_wrapper_tx( tx.clone(), wrapper, tx_bytes, diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 25a3ab6d38..310abb7f15 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -151,8 +151,8 @@ where // Execute wrapper and protocol transactions let successful_wrappers = self.retrieve_and_execute_transactions( &native_block_proposer_address, + &req.txs, ExecutionArgs { - processed_txs: &req.txs, response: &mut response, changed_keys: &mut changed_keys, stats: &mut stats, @@ -164,7 +164,6 @@ where self.execute_tx_batches( successful_wrappers, ExecutionArgs { - processed_txs: &req.txs, response: &mut response, changed_keys: &mut changed_keys, stats: &mut stats, @@ -354,17 +353,17 @@ where mut tx_logs: TxLogs<'_>, ) -> Option { match dispatch_result { - Ok(tx_result) => match tx_data.tx_header.tx_type { - //FIXME: manage unwrap + Ok(tx_result) => match tx_data.tx.header.tx_type { TxType::Wrapper(_) => - // Return withouth emitting the event + // Return withouth emitting any events { return Some(WrapperCache { + tx: tx_data.tx.to_owned(), tx_index: tx_data.tx_index, gas_meter: tx_data.tx_gas_meter, event: tx_logs.tx_event, tx_result, - }) + }); } _ => self.handle_inner_tx_results( response, @@ -446,7 +445,7 @@ where is_any_tx_invalid, } = temp_log.check_inner_results( &tx_result, - tx_data.tx_header, + &tx_data.tx.header, tx_data.tx_index, tx_data.height, ); @@ -507,7 +506,7 @@ where is_any_tx_invalid: _, } = temp_log.check_inner_results( &tx_result, - tx_data.tx_header, + &tx_data.tx.header, tx_data.tx_index, tx_data.height, ); @@ -554,7 +553,7 @@ where // If user transaction didn't fail because of out of gas nor // invalid section commitment, commit its hash to prevent // replays - if matches!(tx_data.tx_header.tx_type, TxType::Wrapper(_)) { + if matches!(tx_data.tx.header.tx_type, TxType::Wrapper(_)) { if !matches!( err, Error::TxApply(protocol::Error::GasError(_)) @@ -583,14 +582,13 @@ where fn retrieve_and_execute_transactions( &mut self, native_block_proposer_address: &Address, + processed_txs: &[shim::request::ProcessedTx], ExecutionArgs { - processed_txs, response, changed_keys, stats, height, }: ExecutionArgs, - //FIXME: maybe better to cache the transactions themselves to avoid another deserialization ) -> Vec { let mut successful_wrappers = vec![]; @@ -742,7 +740,7 @@ where let tx_hash = tx.header_hash(); let dispatch_result = protocol::dispatch_tx( - tx, + &tx, processed_tx.tx.as_ref(), TxIndex::must_from_usize(tx_index), &tx_gas_meter, @@ -758,13 +756,12 @@ where // save the gas cost self.update_tx_gas(tx_hash, consumed_gas.into()); - //FIXME: this is becoming very cluttered because it needs to handle wrappers, inners and protocols, should split in different functions? if let Some(wrapper_cache) = self.evaluate_tx_result( response, dispatch_result, TxData { is_atomic_batch, - tx_header: &tx_header, + tx: &tx, commitments_len, tx_index, replay_protection_hashes: None, @@ -789,7 +786,6 @@ where &mut self, successful_wrappers: Vec, ExecutionArgs { - processed_txs, response, changed_keys, stats, @@ -797,28 +793,13 @@ where }: ExecutionArgs, ) { for WrapperCache { + mut tx, tx_index, gas_meter: tx_gas_meter, event: tx_event, tx_result: wrapper_tx_result, } in successful_wrappers { - //FIXME: should also enqueue the tx directly to avoid deserializing again? POssibly yes - //FIXME: manage unwrap - let processed_tx = processed_txs.get(tx_index).unwrap(); - let mut tx = if let Ok(tx) = Tx::try_from(processed_tx.tx.as_ref()) - { - tx - } else { - tracing::error!( - "FinalizeBlock received a tx that could not be \ - deserialized to a Tx type. This is likely a protocol \ - transaction." - ); - continue; - }; - - let tx_header = tx.header(); let tx_hash = tx.header_hash(); let is_atomic_batch = tx.header.atomic; let commitments_len = tx.commitments().len() as u64; @@ -831,8 +812,9 @@ where tx.update_header(TxType::Raw); let tx_gas_meter = RefCell::new(tx_gas_meter); let dispatch_result = protocol::dispatch_tx( - tx, - processed_tx.tx.as_ref(), + &tx, + // not needed here for gas computation + &[], TxIndex::must_from_usize(tx_index), &tx_gas_meter, &mut self.state, @@ -852,7 +834,7 @@ where dispatch_result, TxData { is_atomic_batch, - tx_header: &tx_header, + tx: &tx, commitments_len, tx_index, replay_protection_hashes, @@ -870,7 +852,6 @@ where } struct ExecutionArgs<'finalize> { - processed_txs: &'finalize [shim::request::ProcessedTx], response: &'finalize mut shim::response::FinalizeBlock, changed_keys: &'finalize mut BTreeSet, stats: &'finalize mut InternalStats, @@ -879,6 +860,7 @@ struct ExecutionArgs<'finalize> { // Caches the execution of a wrapper transaction to be used when later executing the inner batch struct WrapperCache { + tx: Tx, tx_index: usize, gas_meter: TxGasMeter, event: Event, @@ -887,9 +869,7 @@ struct WrapperCache { struct TxData<'tx> { is_atomic_batch: bool, - // FIXME: need the actual tx but it's hard becasue that is passed to dispatch_tx so I'd need to clone it - //FIXME: actually I need the tx only for wrappers, for everything else I only need the header - tx_header: &'tx namada::tx::Header, + tx: &'tx Tx, commitments_len: u64, tx_index: usize, replay_protection_hashes: Option, diff --git a/crates/node/src/shell/governance.rs b/crates/node/src/shell/governance.rs index b8d82d6df4..f4a73c29ee 100644 --- a/crates/node/src/shell/governance.rs +++ b/crates/node/src/shell/governance.rs @@ -403,7 +403,7 @@ where let cmt = tx.first_commitments().unwrap().to_owned(); let dispatch_result = protocol::dispatch_tx( - tx, + &tx, &[], /* this is used to compute the fee * based on the code size. We dont * need it here. */ From a329373bfb64dd20430fea82745953dcb3970ae5 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Tue, 21 May 2024 12:42:27 +0200 Subject: [PATCH 14/70] Refactors the arguments of `dispatch_tx` for every tx type --- crates/namada/src/ledger/protocol/mod.rs | 63 +++++++++++----- crates/node/src/shell/finalize_block.rs | 94 +++++++++++++----------- crates/node/src/shell/governance.rs | 17 ++--- crates/tx/src/data/protocol.rs | 1 + 4 files changed, 104 insertions(+), 71 deletions(-) diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index 56ad5a49a2..f3ad6f627b 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -16,7 +16,7 @@ use namada_gas::TxGasMeter; use namada_sdk::tx::TX_TRANSFER_WASM; use namada_state::StorageWrite; use namada_token::event::{TokenEvent, TokenOperation, UserAccount}; -use namada_tx::data::protocol::ProtocolTxType; +use namada_tx::data::protocol::{ProtocolTx, ProtocolTxType}; use namada_tx::data::{ BatchResults, BatchedTxResult, TxResult, TxType, VpStatusFlags, VpsResult, WrapperTx, @@ -178,30 +178,49 @@ impl From for DispatchError { } } +/// Arguments for transactions' execution +pub enum DispatchArgs<'a, CA: 'static + WasmCacheAccess + Sync> { + //FIXME: do we need thide header and the wrapper one or should we get them from the tx itself? + Protocol(&'a ProtocolTx), + Raw { + tx_index: TxIndex, + wrapper_tx_result: Option>, + vp_wasm_cache: &'a mut VpCache, + tx_wasm_cache: &'a mut TxCache, + }, + Wrapper { + wrapper: &'a WrapperTx, + tx_bytes: &'a [u8], + block_proposer: &'a Address, + //FIXME: why does a wrapper need the caches? We don't, remove! + vp_wasm_cache: &'a mut VpCache, + tx_wasm_cache: &'a mut TxCache, + }, +} + /// Dispatch a given transaction to be applied based on its type. Some storage /// updates may be derived and applied natively rather than via the wasm /// environment, in which case validity predicates will be bypassed. -#[allow(clippy::too_many_arguments)] pub fn dispatch_tx<'a, D, H, CA>( tx: &Tx, - //FIXME: some params are only needed for some tx types, should also pass the txtype with the associated data here? Maybe yes - tx_bytes: &'a [u8], - tx_index: TxIndex, + //FIXME: rename? + dispatch_args: DispatchArgs, + //FIXME: try to move this into the args tx_gas_meter: &'a RefCell, state: &'a mut WlState, - vp_wasm_cache: &'a mut VpCache, - tx_wasm_cache: &'a mut TxCache, - block_proposer: Option<&Address>, - wrapper_tx_result: Option>, ) -> std::result::Result, DispatchError> where D: 'static + DB + for<'iter> DBIter<'iter> + Sync, H: 'static + StorageHasher + Sync, CA: 'static + WasmCacheAccess + Sync, { - match tx.header().tx_type { - // Raw trasaction type is allowed only for governance proposals - TxType::Raw => { + match dispatch_args { + DispatchArgs::Raw { + tx_index, + wrapper_tx_result, + vp_wasm_cache, + tx_wasm_cache, + } => { if let Some(mut tx_result) = wrapper_tx_result { // Replay protection check on the batch let tx_hash = tx.raw_header_hash(); @@ -272,11 +291,11 @@ where Ok(tx_result) } else { - // No bundles of governance transactions, just take the first one + // Governance proposal. We don't allow tx batches in this case, just take the first one let cmt = tx.first_commitments().ok_or(Error::MissingInnerTxs)?; let batched_tx_result = apply_wasm_tx( - BatchedTxRef { tx: &tx, cmt }, + tx.batch_ref_tx(cmt), &tx_index, ShellParams { tx_gas_meter, @@ -295,7 +314,7 @@ where }) } } - TxType::Protocol(protocol_tx) => { + DispatchArgs::Protocol(protocol_tx) => { // No bundles of protocol transactions, only take the first one let cmt = tx.first_commitments().ok_or(Error::MissingInnerTxs)?; let batched_tx_result = @@ -310,9 +329,16 @@ where ..Default::default() }) } - TxType::Wrapper(ref wrapper) => { + DispatchArgs::Wrapper { + wrapper, + tx_bytes, + block_proposer, + vp_wasm_cache, + tx_wasm_cache, + } => { let tx_result = apply_wrapper_tx( - tx.clone(), + //FIXME: actually, do I need to pass ownership? + tx.to_owned(), wrapper, tx_bytes, ShellParams { @@ -321,7 +347,7 @@ where vp_wasm_cache, tx_wasm_cache, }, - block_proposer, + Some(block_proposer), ) .map_err(|e| Error::WrapperRunnerError(e.to_string()))?; @@ -397,6 +423,7 @@ where fn charge_fee( wrapper: &WrapperTx, wrapper_tx_hash: Hash, + //FIXME: don't need the shell param here anymore, just the state! shell_params: &mut ShellParams<'_, S, D, H, CA>, block_proposer: Option<&Address>, ) -> Result<()> diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 310abb7f15..e029fa8e80 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -15,7 +15,7 @@ use namada::ledger::events::EmitEvents; use namada::ledger::gas::GasMetering; use namada::ledger::ibc; use namada::ledger::pos::namada_proof_of_stake; -use namada::ledger::protocol::DispatchError; +use namada::ledger::protocol::{DispatchArgs, DispatchError}; use namada::proof_of_stake; use namada::proof_of_stake::storage::{ find_validator_by_raw_hash, write_last_block_proposer_address, @@ -659,37 +659,46 @@ where continue; } - let (tx_gas_meter, block_proposer) = - match &tx_header.tx_type { - TxType::Wrapper(wrapper) => { - stats.increment_wrapper_txs(); - let gas_meter = TxGasMeter::new(wrapper.gas_limit); - for cmt in tx.commitments() { - if let Some(code_sec) = tx - .get_section(cmt.code_sechash()) - .and_then(|x| Section::code_sec(x.as_ref())) - { - stats.increment_tx_type( - code_sec.code.hash().to_string(), - ); - } + //FIXME: rename? + let (dispatch_args, tx_gas_meter) = match &tx_header.tx_type { + TxType::Wrapper(wrapper) => { + stats.increment_wrapper_txs(); + let tx_gas_meter = TxGasMeter::new(wrapper.gas_limit); + for cmt in tx.commitments() { + if let Some(code_sec) = tx + .get_section(cmt.code_sechash()) + .and_then(|x| Section::code_sec(x.as_ref())) + { + stats.increment_tx_type( + code_sec.code.hash().to_string(), + ); } - (gas_meter, Some(native_block_proposer_address)) } - TxType::Raw => { - tracing::error!( - "Internal logic error: FinalizeBlock received a \ + ( + DispatchArgs::Wrapper { + wrapper, + tx_bytes: processed_tx.tx.as_ref(), + block_proposer: native_block_proposer_address, + vp_wasm_cache: &mut self.vp_wasm_cache, + tx_wasm_cache: &mut self.tx_wasm_cache, + }, + tx_gas_meter, + ) + } + TxType::Raw => { + tracing::error!( + "Internal logic error: FinalizeBlock received a \ TxType::Raw transaction" - ); - continue; - } - TxType::Protocol(protocol_tx) => match protocol_tx.tx { + ); + continue; + } + TxType::Protocol(protocol_tx) => { + match protocol_tx.tx { ProtocolTxType::BridgePoolVext | ProtocolTxType::BridgePool | ProtocolTxType::ValSetUpdateVext - | ProtocolTxType::ValidatorSetUpdate => { - (TxGasMeter::new_from_sub_limit(0.into()), None) - } + | ProtocolTxType::ValidatorSetUpdate => (), + ProtocolTxType::EthEventsVext => { let ext = ethereum_tx_data_variants::EthEventsVext::try_from(&tx) @@ -706,7 +715,6 @@ where self.mode.dequeue_eth_event(event); } } - (TxGasMeter::new_from_sub_limit(0.into()), None) } ProtocolTxType::EthereumEvents => { let digest = @@ -729,26 +737,25 @@ where } } } - (TxGasMeter::new_from_sub_limit(0.into()), None) } - }, - }; - let tx_gas_meter = RefCell::new(tx_gas_meter); + } + ( + DispatchArgs::Protocol(protocol_tx), + TxGasMeter::new_from_sub_limit(0.into()), + ) + } + }; let tx_event = new_tx_event(&tx, height.0); let is_atomic_batch = tx.header.atomic; let commitments_len = tx.commitments().len() as u64; let tx_hash = tx.header_hash(); + let tx_gas_meter = RefCell::new(tx_gas_meter); let dispatch_result = protocol::dispatch_tx( &tx, - processed_tx.tx.as_ref(), - TxIndex::must_from_usize(tx_index), + dispatch_args, &tx_gas_meter, &mut self.state, - &mut self.vp_wasm_cache, - &mut self.tx_wasm_cache, - block_proposer, - None, ); let tx_gas_meter = tx_gas_meter.into_inner(); let consumed_gas = tx_gas_meter.get_tx_consumed_gas(); @@ -813,15 +820,14 @@ where let tx_gas_meter = RefCell::new(tx_gas_meter); let dispatch_result = protocol::dispatch_tx( &tx, - // not needed here for gas computation - &[], - TxIndex::must_from_usize(tx_index), + DispatchArgs::Raw { + tx_index: TxIndex::must_from_usize(tx_index), + wrapper_tx_result: Some(wrapper_tx_result), + vp_wasm_cache: &mut self.vp_wasm_cache, + tx_wasm_cache: &mut self.tx_wasm_cache, + }, &tx_gas_meter, &mut self.state, - &mut self.vp_wasm_cache, - &mut self.tx_wasm_cache, - None, - Some(wrapper_tx_result), ); let tx_gas_meter = tx_gas_meter.into_inner(); let consumed_gas = tx_gas_meter.get_tx_consumed_gas(); diff --git a/crates/node/src/shell/governance.rs b/crates/node/src/shell/governance.rs index f4a73c29ee..18a68e0218 100644 --- a/crates/node/src/shell/governance.rs +++ b/crates/node/src/shell/governance.rs @@ -404,16 +404,15 @@ where let dispatch_result = protocol::dispatch_tx( &tx, - &[], /* this is used to compute the fee - * based on the code size. We dont - * need it here. */ - TxIndex::default(), - &RefCell::new(TxGasMeter::new_from_sub_limit(u64::MAX.into())), /* No gas limit for governance proposal */ + protocol::DispatchArgs::Raw { + tx_index: TxIndex::default(), + wrapper_tx_result: None, + vp_wasm_cache: &mut shell.vp_wasm_cache, + tx_wasm_cache: &mut shell.tx_wasm_cache, + }, + // No gas limit for governance proposal + &RefCell::new(TxGasMeter::new_from_sub_limit(u64::MAX.into())), &mut shell.state, - &mut shell.vp_wasm_cache, - &mut shell.tx_wasm_cache, - None, - None, ); shell .state diff --git a/crates/tx/src/data/protocol.rs b/crates/tx/src/data/protocol.rs index 33995d8a81..6f0125aaf3 100644 --- a/crates/tx/src/data/protocol.rs +++ b/crates/tx/src/data/protocol.rs @@ -56,6 +56,7 @@ impl ProtocolTx { } #[derive( + Copy, Clone, Debug, BorshSerialize, From 2bd2650bfcb12121e8abbf3a268c61597c0ff3ef Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Tue, 21 May 2024 13:11:24 +0200 Subject: [PATCH 15/70] Removes unused wasm caches for wrapper execution --- crates/namada/src/ledger/mod.rs | 32 +++++++--------- crates/namada/src/ledger/protocol/mod.rs | 49 ++++++++---------------- crates/node/src/shell/finalize_block.rs | 7 ++-- 3 files changed, 34 insertions(+), 54 deletions(-) diff --git a/crates/namada/src/ledger/mod.rs b/crates/namada/src/ledger/mod.rs index 14c4a8b622..d962c9848e 100644 --- a/crates/namada/src/ledger/mod.rs +++ b/crates/namada/src/ledger/mod.rs @@ -64,12 +64,8 @@ mod dry_run_tx { tx.clone(), &wrapper, &request.data, - ShellParams::new( - &tx_gas_meter, - &mut temp_state, - &mut ctx.vp_wasm_cache, - &mut ctx.tx_wasm_cache, - ), + &tx_gas_meter, + &mut temp_state, None, ) .into_storage_result()?; @@ -256,8 +252,8 @@ mod test { } #[tokio::test] - async fn test_shell_queries_router_with_client() - -> namada_state::StorageResult<()> { + async fn test_shell_queries_router_with_client( + ) -> namada_state::StorageResult<()> { // Initialize the `TestClient` let mut client = TestClient::new(RPC); // store the wasm code @@ -291,17 +287,15 @@ mod test { .dry_run_tx(&client, Some(tx_bytes), None, false) .await .unwrap(); - assert!( - result - .data - .batch_results - .0 - .get(&cmt.get_hash()) - .unwrap() - .as_ref() - .unwrap() - .is_accepted() - ); + assert!(result + .data + .batch_results + .0 + .get(&cmt.get_hash()) + .unwrap() + .as_ref() + .unwrap() + .is_accepted()); // Request storage value for a balance key ... let token_addr = address::testing::established_address_1(); diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index f3ad6f627b..264d3f632d 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -192,9 +192,6 @@ pub enum DispatchArgs<'a, CA: 'static + WasmCacheAccess + Sync> { wrapper: &'a WrapperTx, tx_bytes: &'a [u8], block_proposer: &'a Address, - //FIXME: why does a wrapper need the caches? We don't, remove! - vp_wasm_cache: &'a mut VpCache, - tx_wasm_cache: &'a mut TxCache, }, } @@ -333,20 +330,14 @@ where wrapper, tx_bytes, block_proposer, - vp_wasm_cache, - tx_wasm_cache, } => { let tx_result = apply_wrapper_tx( //FIXME: actually, do I need to pass ownership? tx.to_owned(), wrapper, tx_bytes, - ShellParams { - tx_gas_meter, - state, - vp_wasm_cache, - tx_wasm_cache, - }, + tx_gas_meter, + state, Some(block_proposer), ) .map_err(|e| Error::WrapperRunnerError(e.to_string()))?; @@ -378,40 +369,39 @@ where /// - gas accounting // TODO(namada#2597): this must signal to the caller if we need masp fee payment // in the first inner tx of the batch -pub(crate) fn apply_wrapper_tx( +pub(crate) fn apply_wrapper_tx( tx: Tx, + //FIXME: pass dispatch args? wrapper: &WrapperTx, tx_bytes: &[u8], - mut shell_params: ShellParams<'_, S, D, H, CA>, + tx_gas_meter: &RefCell, + state: &mut S, block_proposer: Option<&Address>, ) -> Result> where S: State + Sync, D: 'static + DB + for<'iter> DBIter<'iter> + Sync, H: 'static + StorageHasher + Sync, - CA: 'static + WasmCacheAccess + Sync, { let wrapper_tx_hash = tx.header_hash(); // Write wrapper tx hash to storage - shell_params - .state + state .write_log_mut() .write_tx_hash(wrapper_tx_hash) .expect("Error while writing tx hash to storage"); // Charge fee before performing any fallible operations - charge_fee(wrapper, wrapper_tx_hash, &mut shell_params, block_proposer)?; + charge_fee(wrapper, wrapper_tx_hash, state, block_proposer)?; // Account for gas - shell_params - .tx_gas_meter + tx_gas_meter .borrow_mut() .add_wrapper_gas(tx_bytes) .map_err(|err| Error::GasError(err.to_string()))?; Ok(TxResult { - gas_used: shell_params.tx_gas_meter.borrow().get_tx_consumed_gas(), + gas_used: tx_gas_meter.borrow().get_tx_consumed_gas(), batch_results: BatchResults::default(), }) } @@ -420,35 +410,30 @@ where /// - Fee amount overflows /// - Not enough funds are available to pay the entire amount of the fee /// - The accumulated fee amount to be credited to the block proposer overflows -fn charge_fee( +fn charge_fee( wrapper: &WrapperTx, wrapper_tx_hash: Hash, - //FIXME: don't need the shell param here anymore, just the state! - shell_params: &mut ShellParams<'_, S, D, H, CA>, + state: &mut S, block_proposer: Option<&Address>, ) -> Result<()> where S: State + Sync, D: 'static + DB + for<'iter> DBIter<'iter> + Sync, H: 'static + StorageHasher + Sync, - CA: 'static + WasmCacheAccess + Sync, { // Charge or check fees before propagating any possible error let payment_result = match block_proposer { - Some(block_proposer) => transfer_fee( - shell_params.state, - block_proposer, - wrapper, - wrapper_tx_hash, - ), + Some(block_proposer) => { + transfer_fee(state, block_proposer, wrapper, wrapper_tx_hash) + } None => { - check_fees(shell_params.state, wrapper)?; + check_fees(state, wrapper)?; Ok(()) } }; // Commit tx write log even in case of subsequent errors - shell_params.state.write_log_mut().commit_tx(); + state.write_log_mut().commit_tx(); payment_result } diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index e029fa8e80..5b45bc6593 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -660,7 +660,10 @@ where } //FIXME: rename? - let (dispatch_args, tx_gas_meter) = match &tx_header.tx_type { + let (dispatch_args, tx_gas_meter): ( + DispatchArgs<'_, WasmCacheRwAccess>, + TxGasMeter, + ) = match &tx_header.tx_type { TxType::Wrapper(wrapper) => { stats.increment_wrapper_txs(); let tx_gas_meter = TxGasMeter::new(wrapper.gas_limit); @@ -679,8 +682,6 @@ where wrapper, tx_bytes: processed_tx.tx.as_ref(), block_proposer: native_block_proposer_address, - vp_wasm_cache: &mut self.vp_wasm_cache, - tx_wasm_cache: &mut self.tx_wasm_cache, }, tx_gas_meter, ) From efe95ccecd8d6c6a07e5abaad08b72524635d20a Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Tue, 21 May 2024 13:17:01 +0200 Subject: [PATCH 16/70] Pass tx by reference in `apply_wrapper_tx` --- crates/namada/src/ledger/mod.rs | 26 ++++++++-------- crates/namada/src/ledger/protocol/mod.rs | 38 ++++++++++++++---------- crates/node/src/shell/finalize_block.rs | 16 ++++++---- 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/crates/namada/src/ledger/mod.rs b/crates/namada/src/ledger/mod.rs index d962c9848e..a7d4dbd705 100644 --- a/crates/namada/src/ledger/mod.rs +++ b/crates/namada/src/ledger/mod.rs @@ -61,7 +61,7 @@ mod dry_run_tx { Gas::try_from(wrapper.gas_limit).into_storage_result()?; let tx_gas_meter = RefCell::new(TxGasMeter::new(gas_limit)); let tx_result = protocol::apply_wrapper_tx( - tx.clone(), + &tx, &wrapper, &request.data, &tx_gas_meter, @@ -252,8 +252,8 @@ mod test { } #[tokio::test] - async fn test_shell_queries_router_with_client( - ) -> namada_state::StorageResult<()> { + async fn test_shell_queries_router_with_client() + -> namada_state::StorageResult<()> { // Initialize the `TestClient` let mut client = TestClient::new(RPC); // store the wasm code @@ -287,15 +287,17 @@ mod test { .dry_run_tx(&client, Some(tx_bytes), None, false) .await .unwrap(); - assert!(result - .data - .batch_results - .0 - .get(&cmt.get_hash()) - .unwrap() - .as_ref() - .unwrap() - .is_accepted()); + assert!( + result + .data + .batch_results + .0 + .get(&cmt.get_hash()) + .unwrap() + .as_ref() + .unwrap() + .is_accepted() + ); // Request storage value for a balance key ... let token_addr = address::testing::established_address_1(); diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index 264d3f632d..8045814ec6 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -18,7 +18,7 @@ use namada_state::StorageWrite; use namada_token::event::{TokenEvent, TokenOperation, UserAccount}; use namada_tx::data::protocol::{ProtocolTx, ProtocolTxType}; use namada_tx::data::{ - BatchResults, BatchedTxResult, TxResult, TxType, VpStatusFlags, VpsResult, + BatchResults, BatchedTxResult, TxResult, VpStatusFlags, VpsResult, WrapperTx, }; use namada_tx::{BatchedTxRef, Tx}; @@ -180,17 +180,27 @@ impl From for DispatchError { /// Arguments for transactions' execution pub enum DispatchArgs<'a, CA: 'static + WasmCacheAccess + Sync> { - //FIXME: do we need thide header and the wrapper one or should we get them from the tx itself? + /// Protocoli tx data Protocol(&'a ProtocolTx), + /// Raw tx data Raw { + /// The tx index tx_index: TxIndex, + /// The result of the corresponding wrapper tx (missing if governance + /// transaction) wrapper_tx_result: Option>, + /// Vp cache vp_wasm_cache: &'a mut VpCache, + /// Tx cache tx_wasm_cache: &'a mut TxCache, }, + /// Wrapper tx data Wrapper { + /// The wrapper header wrapper: &'a WrapperTx, + /// The transaction bytes for gas accounting tx_bytes: &'a [u8], + /// The block proposer block_proposer: &'a Address, }, } @@ -200,9 +210,7 @@ pub enum DispatchArgs<'a, CA: 'static + WasmCacheAccess + Sync> { /// environment, in which case validity predicates will be bypassed. pub fn dispatch_tx<'a, D, H, CA>( tx: &Tx, - //FIXME: rename? dispatch_args: DispatchArgs, - //FIXME: try to move this into the args tx_gas_meter: &'a RefCell, state: &'a mut WlState, ) -> std::result::Result, DispatchError> @@ -230,8 +238,8 @@ where }); } - // TODO(namada#2597): handle masp fee payment in the first inner tx - // if necessary + // TODO(namada#2597): handle masp fee payment in the first inner + // tx if necessary for cmt in tx.commitments() { match apply_wasm_tx( tx.batch_ref_tx(cmt), @@ -244,7 +252,8 @@ where }, ) { Err(Error::GasError(ref msg)) => { - // Gas error aborts the execution of the entire batch + // Gas error aborts the execution of the entire + // batch tx_result.gas_used = tx_gas_meter.borrow().get_tx_consumed_gas(); tx_result.batch_results.0.insert( @@ -272,8 +281,8 @@ where state.write_log_mut().drop_tx(); if tx.header.atomic { - // Stop the execution of an atomic batch at the - // first failed transaction + // Stop the execution of an atomic batch at + // the first failed transaction return Err(DispatchError { error: Error::FailingAtomicBatch( cmt.get_hash(), @@ -288,7 +297,8 @@ where Ok(tx_result) } else { - // Governance proposal. We don't allow tx batches in this case, just take the first one + // Governance proposal. We don't allow tx batches in this case, + // just take the first one let cmt = tx.first_commitments().ok_or(Error::MissingInnerTxs)?; let batched_tx_result = apply_wasm_tx( @@ -332,8 +342,7 @@ where block_proposer, } => { let tx_result = apply_wrapper_tx( - //FIXME: actually, do I need to pass ownership? - tx.to_owned(), + tx, wrapper, tx_bytes, tx_gas_meter, @@ -370,8 +379,7 @@ where // TODO(namada#2597): this must signal to the caller if we need masp fee payment // in the first inner tx of the batch pub(crate) fn apply_wrapper_tx( - tx: Tx, - //FIXME: pass dispatch args? + tx: &Tx, wrapper: &WrapperTx, tx_bytes: &[u8], tx_gas_meter: &RefCell, @@ -1291,7 +1299,7 @@ mod tests { // "execute" a dummy tx, by manually performing its state changes let (dummy_tx, changed_keys, verifiers) = { - let mut tx = Tx::from_type(TxType::Raw); + let mut tx = Tx::from_type(namada_tx::data::TxType::Raw); tx.set_code(namada_tx::Code::new(vec![], None)); tx.set_data(namada_tx::Data::new(vec![])); diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 5b45bc6593..00b1561471 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -142,7 +142,9 @@ where proposer from tendermint raw hash", ) }; - //FIXME: need uni test on fee pyament when inner txs touch balance of fee payer (also run this test on the old version with the bug to check that the bug was indeed there) + // FIXME: need uni test on fee pyament when inner txs touch balance of + // fee payer (also run this test on the old version with the bug to + // check that the bug was indeed there) // Tracks the accepted transactions self.state.in_mem_mut().block.results = BlockResults::default(); @@ -341,7 +343,9 @@ where } // Evaluate the result of a transaction. Commit or drop the storage changes, - // update stats and event, manage replay protection. For successful wrapper transactions return the relevant data and delay the evaluation after the batch execution + // update stats and event, manage replay protection. For successful wrapper + // transactions return the relevant data and delay the evaluation after the + // batch execution fn evaluate_tx_result( &mut self, response: &mut shim::response::FinalizeBlock, @@ -578,7 +582,9 @@ where } } - // Get the transactions from the consensus engine, preprocess and execute them. Return the cache of successful wrapper transactions later used when executing the inner txs. + // Get the transactions from the consensus engine, preprocess and execute + // them. Return the cache of successful wrapper transactions later used when + // executing the inner txs. fn retrieve_and_execute_transactions( &mut self, native_block_proposer_address: &Address, @@ -659,7 +665,6 @@ where continue; } - //FIXME: rename? let (dispatch_args, tx_gas_meter): ( DispatchArgs<'_, WasmCacheRwAccess>, TxGasMeter, @@ -865,7 +870,8 @@ struct ExecutionArgs<'finalize> { height: BlockHeight, } -// Caches the execution of a wrapper transaction to be used when later executing the inner batch +// Caches the execution of a wrapper transaction to be used when later executing +// the inner batch struct WrapperCache { tx: Tx, tx_index: usize, From b27f45e90aaa00b729ea0c5eff43fa87b172628e Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Tue, 21 May 2024 18:22:12 +0200 Subject: [PATCH 17/70] Fixes unit tests --- crates/node/src/shell/finalize_block.rs | 62 ++++++++++++++++++------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 00b1561471..102f6d553d 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -358,9 +358,18 @@ where ) -> Option { match dispatch_result { Ok(tx_result) => match tx_data.tx.header.tx_type { - TxType::Wrapper(_) => - // Return withouth emitting any events - { + TxType::Wrapper(_) => { + // FIXME: review this, really need to do all this stuff? + // Wait if the inenr transaction is empty (no cmts?) + self.state.write_log_mut().commit_tx(); + self.state + .in_mem_mut() + .block + .results + .accept(tx_data.tx_index); + tx_logs.tx_event.extend(Code(ResultCode::Ok)); + + // Return withouth emitting any events return Some(WrapperCache { tx: tx_data.tx.to_owned(), tx_index: tx_data.tx_index, @@ -555,9 +564,12 @@ where fn handle_batch_error_reprot(&mut self, err: &Error, tx_data: TxData<'_>) { // If user transaction didn't fail because of out of gas nor - // invalid section commitment, commit its hash to prevent + // replay attempt, commit its hash to prevent // replays - if matches!(tx_data.tx.header.tx_type, TxType::Wrapper(_)) { + // FIXME: really need the match on the tx type? Wrapper cannot get here + // anyway and I don't know if this is a problem with protocol + // transactions + if matches!(tx_data.tx.header.tx_type, TxType::Raw) { if !matches!( err, Error::TxApply(protocol::Error::GasError(_)) @@ -1009,11 +1021,12 @@ impl<'finalize> TempTxLogs { } } Err(e) => { - // this branch can only be reached by inner txs + // FIXME: what about wrong signatures??? tracing::trace!("Inner tx {} failed: {}", cmt_hash, e); // If inner transaction didn't fail because of invalid // section commitment, commit its hash to prevent replays - if matches!(tx_header.tx_type, TxType::Wrapper(_)) + // FIXME: need the match on the tx type? + if matches!(tx_header.tx_type, TxType::Raw) && !matches!(e, protocol::Error::MissingSection(_)) { flags.commit_batch_hash = true; @@ -1304,9 +1317,8 @@ mod test_finalize_block { ) } - /// Check that if a wrapper tx was rejected by [`process_proposal`], - /// check that the correct event is returned. Check that it does - /// not appear in the queue of txs to be decrypted + /// Check that if a wrapper tx was rejected by [`process_proposal`], the + /// correct event is returned. #[test] fn test_process_proposal_rejected_wrapper_tx() { let (mut shell, _, _, _) = setup(); @@ -1323,24 +1335,40 @@ mod test_finalize_block { ) .unwrap(); + // Need ordered tx hashes because the events can be emitted out of order + let mut ordered_hashes = vec![]; // create some wrapper txs for i in 0u64..4 { - let (_, mut processed_tx) = mk_wrapper_tx(&shell, &keypair); + let (tx, mut processed_tx) = mk_wrapper_tx(&shell, &keypair); processed_tx.result.code = u32::try_from(i.rem_euclid(2)).unwrap(); processed_txs.push(processed_tx); + ordered_hashes.push(tx.header_hash()); } // check that the correct events were created - for (index, event) in shell + for event in shell .finalize_block(FinalizeBlock { txs: processed_txs.clone(), ..Default::default() }) .expect("Test failed") .iter() - .enumerate() { assert_eq!(*event.kind(), APPLIED_TX); + let hash = event.read_attribute::().expect("Test failed"); + let index = ordered_hashes + .iter() + .enumerate() + .find_map( + |(idx, tx_hash)| { + if tx_hash == &hash { + Some(idx) + } else { + None + } + }, + ) + .unwrap(); let code = event .read_attribute::() .expect("Test failed") @@ -3215,10 +3243,10 @@ mod test_finalize_block { // transaction } - /// Test that if a transaction fails because of out-of-gas, - /// invalid signature or wrong section commitment, its hash - /// is not committed to storage. Also checks that a tx failing for other - /// reason has its hash written to storage. + /// Test that if a transaction fails because of out-of-gas, invalid + /// signature or wrong section commitment, its hash is not committed to + /// storage. Also checks that a tx failing for other reasons has its + /// hash written to storage. #[test] fn test_tx_hash_handling() { let (mut shell, _broadcaster, _, _) = setup(); From b0d770828d3aee2cbaff61413e52ec5078bdebba Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Tue, 21 May 2024 18:33:55 +0200 Subject: [PATCH 18/70] Removes useless check on tx type for reprot management --- crates/node/src/shell/finalize_block.rs | 55 ++++++++++--------------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 102f6d553d..313b4bd3b5 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -563,34 +563,27 @@ where } fn handle_batch_error_reprot(&mut self, err: &Error, tx_data: TxData<'_>) { - // If user transaction didn't fail because of out of gas nor - // replay attempt, commit its hash to prevent - // replays - // FIXME: really need the match on the tx type? Wrapper cannot get here - // anyway and I don't know if this is a problem with protocol - // transactions - if matches!(tx_data.tx.header.tx_type, TxType::Raw) { - if !matches!( - err, - Error::TxApply(protocol::Error::GasError(_)) - | Error::TxApply(protocol::Error::ReplayAttempt(_)) - ) { - self.commit_batch_hash(tx_data.replay_protection_hashes); - } else if let Error::TxApply(protocol::Error::ReplayAttempt(_)) = - err - { - // Remove the wrapper hash but keep the inner tx - // hash. A replay of the wrapper is impossible since - // the inner tx hash is committed to storage and - // we validate the wrapper against that hash too - let header_hash = tx_data - .replay_protection_hashes - .expect("This cannot fail") - .header_hash; - self.state - .redundant_tx_hash(&header_hash) - .expect("Error while marking tx hash as redundant"); - } + // If user transaction didn't fail because of out of gas nor replay + // attempt, commit its hash to prevent replays. If it failed because of + // a replay attempt just remove the redundant wrapper hash + if !matches!( + err, + Error::TxApply(protocol::Error::GasError(_)) + | Error::TxApply(protocol::Error::ReplayAttempt(_)) + ) { + self.commit_batch_hash(tx_data.replay_protection_hashes); + } else if let Error::TxApply(protocol::Error::ReplayAttempt(_)) = err { + // Remove the wrapper hash but keep the inner tx + // hash. A replay of the wrapper is impossible since + // the inner tx hash is committed to storage and + // we validate the wrapper against that hash too + let header_hash = tx_data + .replay_protection_hashes + .expect("This cannot fail") + .header_hash; + self.state + .redundant_tx_hash(&header_hash) + .expect("Error while marking tx hash as redundant"); } } @@ -1021,14 +1014,10 @@ impl<'finalize> TempTxLogs { } } Err(e) => { - // FIXME: what about wrong signatures??? tracing::trace!("Inner tx {} failed: {}", cmt_hash, e); // If inner transaction didn't fail because of invalid // section commitment, commit its hash to prevent replays - // FIXME: need the match on the tx type? - if matches!(tx_header.tx_type, TxType::Raw) - && !matches!(e, protocol::Error::MissingSection(_)) - { + if !matches!(e, protocol::Error::MissingSection(_)) { flags.commit_batch_hash = true; } From bd6df8d8a1964ff1efa354e061cf08fe1101f6d8 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Tue, 21 May 2024 18:47:35 +0200 Subject: [PATCH 19/70] Removes useless operations on wrapper transactions --- crates/node/src/shell/finalize_block.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 313b4bd3b5..216475056e 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -359,16 +359,6 @@ where match dispatch_result { Ok(tx_result) => match tx_data.tx.header.tx_type { TxType::Wrapper(_) => { - // FIXME: review this, really need to do all this stuff? - // Wait if the inenr transaction is empty (no cmts?) - self.state.write_log_mut().commit_tx(); - self.state - .in_mem_mut() - .block - .results - .accept(tx_data.tx_index); - tx_logs.tx_event.extend(Code(ResultCode::Ok)); - // Return withouth emitting any events return Some(WrapperCache { tx: tx_data.tx.to_owned(), @@ -458,7 +448,6 @@ where is_any_tx_invalid, } = temp_log.check_inner_results( &tx_result, - &tx_data.tx.header, tx_data.tx_index, tx_data.height, ); @@ -519,7 +508,6 @@ where is_any_tx_invalid: _, } = temp_log.check_inner_results( &tx_result, - &tx_data.tx.header, tx_data.tx_index, tx_data.height, ); @@ -956,7 +944,6 @@ impl<'finalize> TempTxLogs { fn check_inner_results( &mut self, tx_result: &namada::tx::data::TxResult, - tx_header: &namada::tx::Header, tx_index: usize, height: BlockHeight, ) -> ValidityFlags { From d5cab98289447f86b11316b38cd619548486ec64 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Wed, 22 May 2024 12:02:58 +0200 Subject: [PATCH 20/70] Adds integration test for enforced fees --- crates/node/src/shell/finalize_block.rs | 3 - crates/tests/src/integration/ledger_tests.rs | 227 ++++++++++++++++++- 2 files changed, 221 insertions(+), 9 deletions(-) diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 216475056e..4e02325d6b 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -142,9 +142,6 @@ where proposer from tendermint raw hash", ) }; - // FIXME: need uni test on fee pyament when inner txs touch balance of - // fee payer (also run this test on the old version with the bug to - // check that the bug was indeed there) // Tracks the accepted transactions self.state.in_mem_mut().block.results = BlockResults::default(); diff --git a/crates/tests/src/integration/ledger_tests.rs b/crates/tests/src/integration/ledger_tests.rs index 40816bdf67..ef649e2328 100644 --- a/crates/tests/src/integration/ledger_tests.rs +++ b/crates/tests/src/integration/ledger_tests.rs @@ -5,13 +5,15 @@ use assert_matches::assert_matches; use borsh_ext::BorshSerializeExt; use color_eyre::eyre::Result; use data_encoding::HEXLOWER; +use namada::account::AccountPublicKeysMap; use namada::core::collections::HashMap; -use namada::token; -use namada_apps_lib::wallet::defaults; +use namada::token::{self, Amount, DenominatedAmount}; +use namada_apps_lib::wallet::defaults::{self, albert_keypair}; use namada_core::dec::Dec; use namada_core::storage::Epoch; use namada_core::token::NATIVE_MAX_DECIMAL_PLACES; use namada_node::shell::testing::client::run; +use namada_node::shell::testing::node::NodeResults; use namada_node::shell::testing::utils::{Bin, CapturedOutput}; use namada_sdk::tx::{TX_TRANSFER_WASM, VP_USER_WASM}; use namada_test_utils::TestWasms; @@ -1326,10 +1328,8 @@ fn pgf_steward_change_commission() -> Result<()> { assert!( captured.contains(&format!("- 0.7 to {}", defaults::bertha_address())) ); - assert!( - captured - .contains(&format!("- 0.05 to {}", defaults::christel_address())) - ); + assert!(captured + .contains(&format!("- 0.05 to {}", defaults::christel_address()))); assert!(captured.contains("Pgf fundings: no fundings are currently set.")); Ok(()) @@ -1578,3 +1578,218 @@ fn change_validator_metadata() -> Result<()> { Ok(()) } + +// Test that fee payment is enforced and aligned with process proposal. The test +// generates a tx that subtract funds from the fee payer of a following tx. Test +// that wrappers (and fee payments) are evaluated before the inner transactions. +#[test] +fn enforce_fee_payment() -> Result<()> { + // This address doesn't matter for tests. But an argument is required. + let validator_one_rpc = "http://127.0.0.1:26567"; + // 1. start the ledger node + let (node, _services) = setup::setup()?; + + let tempdir = tempfile::tempdir().unwrap(); + let mut txs_bytes = vec![]; + + let captured = CapturedOutput::of(|| { + run( + &node, + Bin::Client, + vec![ + "balance", + "--owner", + ALBERT_KEY, + "--token", + NAM, + "--node", + validator_one_rpc, + ], + ) + }); + assert!(captured.result.is_ok()); + assert!(captured.contains("nam: 2000000")); + + run( + &node, + Bin::Client, + vec![ + "transfer", + "--source", + ALBERT_KEY, + "--target", + BERTHA, + "--token", + NAM, + "--amount", + // We want this transaction to consume all the remaining available + // balance. If we executed the inner txs right after the + // corresponding wrapper's fee paymwent this would succeed (but + // this is not the case) + "1900000", + "--output-folder-path", + tempdir.path().to_str().unwrap(), + "--dump-tx", + "--ledger-address", + validator_one_rpc, + ], + )?; + node.assert_success(); + let file_path = tempdir + .path() + .read_dir() + .unwrap() + .next() + .unwrap() + .unwrap() + .path(); + txs_bytes.push(std::fs::read(&file_path).unwrap()); + std::fs::remove_file(&file_path).unwrap(); + + run( + &node, + Bin::Client, + vec![ + "transfer", + "--source", + ALBERT_KEY, + "--target", + CHRISTEL, + "--token", + NAM, + "--amount", + "50", + "--gas-payer", + ALBERT_KEY, + "--output-folder-path", + tempdir.path().to_str().unwrap(), + "--dump-tx", + "--ledger-address", + validator_one_rpc, + ], + )?; + node.assert_success(); + let file_path = tempdir + .path() + .read_dir() + .unwrap() + .next() + .unwrap() + .unwrap() + .path(); + txs_bytes.push(std::fs::read(&file_path).unwrap()); + std::fs::remove_file(&file_path).unwrap(); + + let sk = albert_keypair(); + let pk = sk.to_public(); + + let native_token = node + .shell + .lock() + .unwrap() + .state + .in_mem() + .native_token + .clone(); + + let mut txs = vec![]; + for bytes in txs_bytes { + let mut tx = namada::tx::Tx::deserialize(&bytes).unwrap(); + tx.add_wrapper( + namada::tx::data::wrapper_tx::Fee { + amount_per_gas_unit: DenominatedAmount::native( + Amount::native_whole(1), + ), + token: native_token.clone(), + }, + pk.clone(), + 100_000.into(), + ); + tx.sign_raw(vec![sk.clone()], AccountPublicKeysMap::default(), None); + tx.sign_wrapper(sk.clone()); + + txs.push(tx.to_bytes()); + } + + node.clear_results(); + node.submit_txs(txs); + { + let results = node.results.lock().unwrap(); + // If empty than failed in process proposal + assert!(!results.is_empty()); + + for result in results.iter() { + assert!(matches!(result, NodeResults::Ok)); + } + } + // Finalize the next block to execute the txs + node.clear_results(); + node.finalize_and_commit(); + { + let results = node.results.lock().unwrap(); + for result in results.iter() { + assert!(matches!(result, NodeResults::Ok)); + } + } + + // Assert balances + let captured = CapturedOutput::of(|| { + run( + &node, + Bin::Client, + vec![ + "balance", + "--owner", + ALBERT_KEY, + "--token", + NAM, + "--node", + validator_one_rpc, + ], + ) + }); + assert!(captured.result.is_ok()); + // This is the result of the two fee payemnts and the successful transfer to + // Christel + assert!(captured.contains("nam: 1799950")); + + let captured = CapturedOutput::of(|| { + run( + &node, + Bin::Client, + vec![ + "balance", + "--owner", + BERTHA, + "--token", + NAM, + "--node", + validator_one_rpc, + ], + ) + }); + assert!(captured.result.is_ok()); + // Bertha must not receive anything because the transaction fails. This is + // because we evaluate fee payments before the inner transactions, so by the + // time we execute the transfer, Albert doesn't have enough funds anynmore + assert!(captured.contains("nam: 2000000")); + + let captured = CapturedOutput::of(|| { + run( + &node, + Bin::Client, + vec![ + "balance", + "--owner", + CHRISTEL, + "--token", + NAM, + "--node", + validator_one_rpc, + ], + ) + }); + assert!(captured.result.is_ok()); + assert!(captured.contains("nam: 2000050")); + Ok(()) +} From b6f200adba9232a906ed2ff151ac44e0994aa5cf Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Wed, 22 May 2024 15:09:04 +0200 Subject: [PATCH 21/70] Misc adjustments to v36 --- crates/namada/src/ledger/protocol/mod.rs | 2 +- crates/node/src/shell/finalize_block.rs | 23 +++++++++++++++++--- crates/tests/src/integration/ledger_tests.rs | 8 ++++--- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index 8045814ec6..2a374a65c0 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -210,7 +210,7 @@ pub enum DispatchArgs<'a, CA: 'static + WasmCacheAccess + Sync> { /// environment, in which case validity predicates will be bypassed. pub fn dispatch_tx<'a, D, H, CA>( tx: &Tx, - dispatch_args: DispatchArgs, + dispatch_args: DispatchArgs<'a, CA>, tx_gas_meter: &'a RefCell, state: &'a mut WlState, ) -> std::result::Result, DispatchError> diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 4e02325d6b..215ed23420 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -584,7 +584,7 @@ where changed_keys, stats, height, - }: ExecutionArgs, + }: ExecutionArgs<'_>, ) -> Vec { let mut successful_wrappers = vec![]; @@ -661,7 +661,24 @@ where ) = match &tx_header.tx_type { TxType::Wrapper(wrapper) => { stats.increment_wrapper_txs(); - let tx_gas_meter = TxGasMeter::new(wrapper.gas_limit); + + let gas_limit = match Gas::try_from(wrapper.gas_limit) { + Ok(value) => value, + Err(_) => { + response.events.emit( + new_tx_event(&tx, height.0) + .with(Code(ResultCode::InvalidTx)) + .with(Info( + "The wrapper gas limit overflowed gas \ + representation" + .to_owned(), + )) + .with(GasUsed(0.into())), + ); + continue; + } + }; + let tx_gas_meter = TxGasMeter::new(gas_limit); for cmt in tx.commitments() { if let Some(code_sec) = tx .get_section(cmt.code_sechash()) @@ -793,7 +810,7 @@ where changed_keys, stats, height, - }: ExecutionArgs, + }: ExecutionArgs<'_>, ) { for WrapperCache { mut tx, diff --git a/crates/tests/src/integration/ledger_tests.rs b/crates/tests/src/integration/ledger_tests.rs index ef649e2328..561e93df49 100644 --- a/crates/tests/src/integration/ledger_tests.rs +++ b/crates/tests/src/integration/ledger_tests.rs @@ -1328,8 +1328,10 @@ fn pgf_steward_change_commission() -> Result<()> { assert!( captured.contains(&format!("- 0.7 to {}", defaults::bertha_address())) ); - assert!(captured - .contains(&format!("- 0.05 to {}", defaults::christel_address()))); + assert!( + captured + .contains(&format!("- 0.05 to {}", defaults::christel_address())) + ); assert!(captured.contains("Pgf fundings: no fundings are currently set.")); Ok(()) @@ -1696,7 +1698,7 @@ fn enforce_fee_payment() -> Result<()> { for bytes in txs_bytes { let mut tx = namada::tx::Tx::deserialize(&bytes).unwrap(); tx.add_wrapper( - namada::tx::data::wrapper_tx::Fee { + namada::tx::data::wrapper::Fee { amount_per_gas_unit: DenominatedAmount::native( Amount::native_whole(1), ), From 3c526c4e3fcd27cb280f65f33e033189d82d935c Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Thu, 23 May 2024 17:58:59 +0200 Subject: [PATCH 22/70] Fixes typo --- crates/namada/src/ledger/protocol/mod.rs | 2 +- crates/tests/src/integration/ledger_tests.rs | 2 +- crates/tx/src/data/protocol.rs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index 2a374a65c0..5d67b45d3d 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -180,7 +180,7 @@ impl From for DispatchError { /// Arguments for transactions' execution pub enum DispatchArgs<'a, CA: 'static + WasmCacheAccess + Sync> { - /// Protocoli tx data + /// Protocol tx data Protocol(&'a ProtocolTx), /// Raw tx data Raw { diff --git a/crates/tests/src/integration/ledger_tests.rs b/crates/tests/src/integration/ledger_tests.rs index 561e93df49..04138c2eff 100644 --- a/crates/tests/src/integration/ledger_tests.rs +++ b/crates/tests/src/integration/ledger_tests.rs @@ -1626,7 +1626,7 @@ fn enforce_fee_payment() -> Result<()> { "--amount", // We want this transaction to consume all the remaining available // balance. If we executed the inner txs right after the - // corresponding wrapper's fee paymwent this would succeed (but + // corresponding wrapper's fee payment this would succeed (but // this is not the case) "1900000", "--output-folder-path", diff --git a/crates/tx/src/data/protocol.rs b/crates/tx/src/data/protocol.rs index 6f0125aaf3..fd994cb47c 100644 --- a/crates/tx/src/data/protocol.rs +++ b/crates/tx/src/data/protocol.rs @@ -67,7 +67,6 @@ impl ProtocolTx { Deserialize, PartialEq, )] -#[allow(clippy::large_enum_variant)] /// Types of protocol messages to be sent pub enum ProtocolTxType { /// Ethereum events contained in vote extensions that From e82d57d54c4d3c99699e73d17892fda981d47c12 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Wed, 22 May 2024 15:55:57 +0200 Subject: [PATCH 23/70] Changelog #3075 --- .changelog/unreleased/bug-fixes/3075-force-fee-payment.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/bug-fixes/3075-force-fee-payment.md diff --git a/.changelog/unreleased/bug-fixes/3075-force-fee-payment.md b/.changelog/unreleased/bug-fixes/3075-force-fee-payment.md new file mode 100644 index 0000000000..7b15a59a63 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/3075-force-fee-payment.md @@ -0,0 +1,2 @@ +- Fixed the fee collection logic in `finalize_block` to match that of + `process_proposal`. ([\#3075](https://github.com/anoma/namada/issues/3075)) \ No newline at end of file From 2310bf7cc2354764912c45de84a033b006a57f4f Mon Sep 17 00:00:00 2001 From: stanisloe Date: Wed, 3 Apr 2024 17:23:48 +0100 Subject: [PATCH 24/70] remove deprecated dependency from app crate --- Cargo.lock | 523 +++++++++++++++++---------- Cargo.toml | 2 +- crates/apps_lib/src/config/global.rs | 11 +- crates/apps_lib/src/config/mod.rs | 20 +- 4 files changed, 347 insertions(+), 209 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a9d914fe1..69a6f7c85d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -59,6 +59,18 @@ dependencies = [ "version_check", ] +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.2" @@ -68,6 +80,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -229,16 +247,16 @@ dependencies = [ ] [[package]] -name = "arrayref" -version = "0.3.7" +name = "arraydeque" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" [[package]] -name = "arrayvec" -version = "0.5.2" +name = "arrayref" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" [[package]] name = "arrayvec" @@ -349,7 +367,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustversion", - "serde 1.0.193", + "serde", "sync_wrapper", "tower", "tower-layer", @@ -433,7 +451,7 @@ dependencies = [ "displaydoc", "ics23", "prost 0.12.3", - "serde 1.0.193", + "serde", "serde_json", "sha2 0.10.8", "tendermint 0.35.0", @@ -479,7 +497,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -488,7 +506,7 @@ version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -552,7 +570,7 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -584,7 +602,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" dependencies = [ "arrayref", - "arrayvec 0.7.4", + "arrayvec", "constant_time_eq", ] @@ -595,7 +613,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94230421e395b9920d23df13ea5d77a20e1725331f90fbbf6df6040b33f756ae" dependencies = [ "arrayref", - "arrayvec 0.7.4", + "arrayvec", "constant_time_eq", ] @@ -606,7 +624,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" dependencies = [ "arrayref", - "arrayvec 0.7.4", + "arrayvec", "cc", "cfg-if", "constant_time_eq", @@ -765,7 +783,7 @@ version = "4.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da78b32057b8fdfc352504708feeba7216dcd65a2c9ab02978cbd288d1279b6c" dependencies = [ - "serde 1.0.193", + "serde", "utf8-width", ] @@ -803,7 +821,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -823,7 +841,7 @@ version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -832,7 +850,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -844,7 +862,7 @@ dependencies = [ "camino", "cargo-platform", "semver 1.0.20", - "serde 1.0.193", + "serde", "serde_json", "thiserror", ] @@ -880,7 +898,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom 7.1.3", + "nom", ] [[package]] @@ -941,7 +959,7 @@ checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" dependencies = [ "ciborium-io", "ciborium-ll", - "serde 1.0.193", + "serde", ] [[package]] @@ -1034,7 +1052,7 @@ dependencies = [ "digest 0.10.7", "hmac 0.12.1", "k256", - "serde 1.0.193", + "serde", "sha2 0.10.8", "thiserror", ] @@ -1068,7 +1086,7 @@ dependencies = [ "generic-array", "hex", "ripemd", - "serde 1.0.193", + "serde", "serde_derive", "sha2 0.10.8", "sha3", @@ -1120,18 +1138,21 @@ dependencies = [ [[package]] name = "config" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1b9d958c2b1368a663f05538fc1b5975adce1e19f435acceae987aceeeb369" +version = "0.14.0" +source = "git+https://github.com/mehcode/config-rs.git?rev=e3c1d0b452639478662a44f15ef6d5b6d969bf9b#e3c1d0b452639478662a44f15ef6d5b6d969bf9b" dependencies = [ + "async-trait", + "convert_case", + "json5", "lazy_static", - "nom 5.1.3", + "nom", + "pathdiff", + "ron", "rust-ini", - "serde 1.0.193", - "serde-hjson", + "serde", "serde_json", - "toml 0.5.11", - "yaml-rust", + "toml 0.8.2", + "yaml-rust2", ] [[package]] @@ -1153,7 +1174,7 @@ dependencies = [ "cpufeatures", "hex", "proptest", - "serde 1.0.193", + "serde", ] [[package]] @@ -1162,6 +1183,26 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.11", + "once_cell", + "tiny-keccak", +] + [[package]] name = "const_panic" version = "0.2.8" @@ -1185,6 +1226,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -1245,7 +1295,7 @@ checksum = "7879036156092ad1c22fe0d7316efc5a5eceec2bc3906462a2560215f2a2f929" dependencies = [ "cosmwasm-schema-derive", "schemars", - "serde 1.0.193", + "serde", "serde_json", "thiserror", ] @@ -1276,7 +1326,7 @@ dependencies = [ "forward_ref", "hex", "schemars", - "serde 1.0.193", + "serde", "serde-json-wasm 0.5.2", "sha2 0.10.8", "static_assertions", @@ -1379,7 +1429,7 @@ dependencies = [ "plotters", "rayon", "regex", - "serde 1.0.193", + "serde", "serde_derive", "serde_json", "tinytemplate", @@ -1556,7 +1606,7 @@ checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" dependencies = [ "cosmwasm-std", "schemars", - "serde 1.0.193", + "serde", ] [[package]] @@ -1710,6 +1760,15 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -1742,7 +1801,7 @@ checksum = "7c1a2e028bbf7921549873b291ddc0cfe08b673d9489da81ac28898cd5a0e6e0" dependencies = [ "chrono", "rust_decimal", - "serde 1.0.193", + "serde", "thiserror", "time", "winnow 0.6.8", @@ -1814,7 +1873,7 @@ dependencies = [ "curve25519-dalek-ng", "hex", "rand_core 0.6.4", - "serde 1.0.193", + "serde", "sha2 0.9.9", "thiserror", "zeroize", @@ -1828,7 +1887,7 @@ checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" dependencies = [ "curve25519-dalek 4.1.2", "ed25519", - "serde 1.0.193", + "serde", "sha2 0.10.8", "subtle", "zeroize", @@ -1844,7 +1903,7 @@ dependencies = [ "hashbrown 0.12.3", "hex", "rand_core 0.6.4", - "serde 1.0.193", + "serde", "sha2 0.9.9", "zeroize", ] @@ -1897,7 +1956,7 @@ dependencies = [ "log", "rand 0.8.5", "rlp", - "serde 1.0.193", + "serde", "sha3", "zeroize", ] @@ -1967,7 +2026,7 @@ checksum = "768064bd3a0e2bedcba91dc87ace90beea91acc41b6a01a3ca8e9aa8827461bf" dependencies = [ "log", "once_cell", - "serde 1.0.193", + "serde", "serde_json", ] @@ -1985,7 +2044,7 @@ dependencies = [ "pbkdf2 0.11.0", "rand 0.8.5", "scrypt", - "serde 1.0.193", + "serde", "serde_json", "sha2 0.10.8", "sha3", @@ -2003,7 +2062,7 @@ dependencies = [ "hex", "once_cell", "regex", - "serde 1.0.193", + "serde", "serde_json", "sha3", "thiserror", @@ -2105,7 +2164,7 @@ checksum = "8c405f24ea3a517899ba7985385c43dc4a7eb1209af3b1e0a1a32d7dcc7f8d09" dependencies = [ "ethers-core", "once_cell", - "serde 1.0.193", + "serde", "serde_json", ] @@ -2123,7 +2182,7 @@ dependencies = [ "futures-util", "once_cell", "pin-project", - "serde 1.0.193", + "serde", "serde_json", "thiserror", ] @@ -2143,7 +2202,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "serde 1.0.193", + "serde", "serde_json", "syn 2.0.52", "toml 0.8.2", @@ -2172,7 +2231,7 @@ version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f03e0bdc216eeb9e355b90cf610ef6c5bb8aca631f97b5ae9980ce34ea7878d" dependencies = [ - "arrayvec 0.7.4", + "arrayvec", "bytes", "cargo_metadata", "chrono", @@ -2186,7 +2245,7 @@ dependencies = [ "open-fastrlp", "rand 0.8.5", "rlp", - "serde 1.0.193", + "serde", "serde_json", "strum 0.25.0", "syn 2.0.52", @@ -2206,7 +2265,7 @@ dependencies = [ "ethers-core", "reqwest", "semver 1.0.20", - "serde 1.0.193", + "serde", "serde_json", "thiserror", "tracing", @@ -2229,7 +2288,7 @@ dependencies = [ "futures-util", "instant", "reqwest", - "serde 1.0.193", + "serde", "serde_json", "thiserror", "tokio", @@ -2261,7 +2320,7 @@ dependencies = [ "once_cell", "pin-project", "reqwest", - "serde 1.0.193", + "serde", "serde_json", "thiserror", "tokio", @@ -2732,7 +2791,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash", + "ahash 0.7.8", ] [[package]] @@ -2741,7 +2800,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "ahash 0.7.8", ] [[package]] @@ -2749,6 +2808,10 @@ name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash 0.8.11", + "allocator-api2", +] [[package]] name = "hashers" @@ -2759,6 +2822,15 @@ dependencies = [ "fxhash", ] +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown 0.14.3", +] + [[package]] name = "hdrhistogram" version = "7.5.4" @@ -3031,7 +3103,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde", "serde-json-wasm 1.0.1", ] @@ -3061,7 +3133,7 @@ dependencies = [ "primitive-types", "scale-info", "schemars", - "serde 1.0.193", + "serde", "uint", ] @@ -3088,7 +3160,7 @@ dependencies = [ "ibc-client-wasm-types", "ibc-core", "prost 0.12.3", - "serde 1.0.193", + "serde", ] [[package]] @@ -3104,7 +3176,7 @@ dependencies = [ "ibc-core-handler-types", "ibc-core-host", "ibc-primitives", - "serde 1.0.193", + "serde", "tendermint 0.36.0", "tendermint-light-client-verifier", ] @@ -3133,7 +3205,7 @@ dependencies = [ "ibc-core-host-types", "ibc-primitives", "ibc-proto", - "serde 1.0.193", + "serde", "tendermint 0.36.0", "tendermint-light-client-verifier", "tendermint-proto 0.36.0", @@ -3152,7 +3224,7 @@ dependencies = [ "ibc-core-host-types", "ibc-primitives", "ibc-proto", - "serde 1.0.193", + "serde", ] [[package]] @@ -3216,7 +3288,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde", "sha2 0.10.8", "subtle-encoding", "tendermint 0.36.0", @@ -3269,7 +3341,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde", "subtle-encoding", "tendermint 0.36.0", ] @@ -3289,7 +3361,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde", "subtle-encoding", ] @@ -3323,7 +3395,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde", "subtle-encoding", "tendermint 0.36.0", ] @@ -3364,7 +3436,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde", "subtle-encoding", "tendermint 0.36.0", ] @@ -3406,7 +3478,7 @@ dependencies = [ "ibc-core-host-types", "ibc-primitives", "ibc-proto", - "serde 1.0.193", + "serde", "sha2 0.10.8", "subtle-encoding", "tendermint 0.36.0", @@ -3425,7 +3497,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde", ] [[package]] @@ -3458,7 +3530,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde", "subtle-encoding", "tendermint 0.36.0", ] @@ -3488,7 +3560,7 @@ dependencies = [ "prost 0.12.3", "scale-info", "schemars", - "serde 1.0.193", + "serde", "tendermint 0.36.0", "time", ] @@ -3509,7 +3581,7 @@ dependencies = [ "prost 0.12.3", "scale-info", "schemars", - "serde 1.0.193", + "serde", "subtle-encoding", "tendermint-proto 0.36.0", "tonic", @@ -3561,7 +3633,7 @@ dependencies = [ "informalsystems-pbjson 0.6.0", "prost 0.12.3", "ripemd", - "serde 1.0.193", + "serde", "sha2 0.10.8", "sha3", ] @@ -3617,7 +3689,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -3637,7 +3709,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5ad43a3f5795945459d577f6589cf62a476e92c79b75e70cd954364e14ce17b" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -3652,7 +3724,7 @@ version = "0.8.0" source = "git+https://github.com/heliaxdev/index-set?tag=v0.8.1#b0d928f83cf0d465ccda299d131e8df2859b5184" dependencies = [ "borsh 1.2.1", - "serde 1.0.193", + "serde", ] [[package]] @@ -3663,7 +3735,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", - "serde 1.0.193", + "serde", ] [[package]] @@ -3684,7 +3756,7 @@ dependencies = [ "borsh 1.2.1", "equivalent", "hashbrown 0.14.3", - "serde 1.0.193", + "serde", ] [[package]] @@ -3694,7 +3766,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4eecd90f87bea412eac91c6ef94f6b1e390128290898cbe14f2b926787ae1fb" dependencies = [ "base64 0.13.1", - "serde 1.0.193", + "serde", ] [[package]] @@ -3704,7 +3776,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aa4a0980c8379295100d70854354e78df2ee1c6ca0f96ffe89afeb3140e3a3d" dependencies = [ "base64 0.21.7", - "serde 1.0.193", + "serde", ] [[package]] @@ -3802,6 +3874,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + [[package]] name = "jsonwebtoken" version = "8.3.0" @@ -3811,7 +3894,7 @@ dependencies = [ "base64 0.21.7", "pem", "ring 0.16.20", - "serde 1.0.193", + "serde", "serde_json", "simple_asn1", ] @@ -3954,23 +4037,10 @@ checksum = "02036c84eab9c48e85bc568d269221ba4f5e1cfbc785c3c2c2f6bb8c131f9287" dependencies = [ "async-trait", "ledger-transport", - "serde 1.0.193", + "serde", "thiserror", ] -[[package]] -name = "lexical-core" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" -dependencies = [ - "arrayvec 0.5.2", - "bitflags 1.3.2", - "cfg-if", - "ryu", - "static_assertions", -] - [[package]] name = "libc" version = "0.2.150" @@ -4049,7 +4119,7 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -4133,7 +4203,7 @@ dependencies = [ "indexmap 1.9.3", "linked-hash-map", "regex", - "serde 1.0.193", + "serde", "serde_derive", "serde_yaml", ] @@ -4420,7 +4490,7 @@ dependencies = [ "rayon", "regex", "ripemd", - "serde 1.0.193", + "serde", "serde_json", "sha2 0.9.9", "slip10_ed25519", @@ -4460,7 +4530,7 @@ dependencies = [ "namada_migrations", "namada_storage", "proptest", - "serde 1.0.193", + "serde", ] [[package]] @@ -4528,7 +4598,7 @@ dependencies = [ "rand_core 0.6.4", "reqwest", "rpassword", - "serde 1.0.193", + "serde", "serde_json", "sha2 0.9.9", "tar", @@ -4615,7 +4685,7 @@ dependencies = [ "prost-types 0.12.3", "rand 0.8.5", "rand_core 0.6.4", - "serde 1.0.193", + "serde", "serde_json", "sha2 0.9.9", "smooth-operator", @@ -4669,7 +4739,7 @@ dependencies = [ "namada_tx", "namada_vote_ext", "rand 0.8.5", - "serde 1.0.193", + "serde", "serde_json", "tendermint 0.36.0", "tendermint-proto 0.36.0", @@ -4687,7 +4757,7 @@ dependencies = [ "namada_core", "namada_macros", "namada_migrations", - "serde 1.0.193", + "serde", "serde_json", "thiserror", "tracing", @@ -4725,7 +4795,7 @@ dependencies = [ "namada_macros", "namada_migrations", "proptest", - "serde 1.0.193", + "serde", "thiserror", ] @@ -4745,7 +4815,7 @@ dependencies = [ "namada_storage", "namada_trans_token", "proptest", - "serde 1.0.193", + "serde", "serde_json", "smooth-operator", "thiserror", @@ -4778,7 +4848,7 @@ dependencies = [ "primitive-types", "proptest", "prost 0.12.3", - "serde 1.0.193", + "serde", "serde_json", "sha2 0.9.9", "thiserror", @@ -4938,7 +5008,7 @@ dependencies = [ "pretty_assertions", "proptest", "proptest-state-machine", - "serde 1.0.193", + "serde", "smooth-operator", "test-log", "thiserror", @@ -5009,7 +5079,7 @@ dependencies = [ "rand_core 0.6.4", "regex", "ripemd", - "serde 1.0.193", + "serde", "serde_json", "sha2 0.9.9", "slip10_ed25519", @@ -5041,7 +5111,7 @@ dependencies = [ "namada_tx", "proptest", "rayon", - "serde 1.0.193", + "serde", "smooth-operator", "test-log", "tracing", @@ -5092,7 +5162,7 @@ dependencies = [ "namada_migrations", "namada_replay_protection", "regex", - "serde 1.0.193", + "serde", "smooth-operator", "thiserror", "tracing", @@ -5148,7 +5218,7 @@ dependencies = [ "prost 0.12.3", "rand 0.8.5", "regex", - "serde 1.0.193", + "serde", "serde_json", "sha2 0.9.9", "tar", @@ -5206,7 +5276,7 @@ dependencies = [ "prost 0.12.3", "prost-types 0.12.3", "rand 0.8.5", - "serde 1.0.193", + "serde", "serde_json", "sha2 0.9.9", "thiserror", @@ -5265,7 +5335,7 @@ dependencies = [ "namada_macros", "namada_migrations", "namada_tx", - "serde 1.0.193", + "serde", ] [[package]] @@ -5342,17 +5412,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" -[[package]] -name = "nom" -version = "5.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" -dependencies = [ - "lexical-core", - "memchr", - "version_check", -] - [[package]] name = "nom" version = "7.1.3" @@ -5477,15 +5536,6 @@ dependencies = [ "num-traits 0.2.17", ] -[[package]] -name = "num-traits" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -dependencies = [ - "num-traits 0.2.17", -] - [[package]] name = "num-traits" version = "0.2.17" @@ -5514,7 +5564,7 @@ dependencies = [ "num", "num-derive 0.3.3", "num-traits 0.2.17", - "serde 1.0.193", + "serde", "serde_derive", ] @@ -5594,7 +5644,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" dependencies = [ - "arrayvec 0.7.4", + "arrayvec", "auto_impl", "bytes", "ethereum-types", @@ -5657,6 +5707,16 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "ordered-multimap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" +dependencies = [ + "dlv-list", + "hashbrown 0.14.3", +] + [[package]] name = "orion" version = "0.16.1" @@ -5696,12 +5756,12 @@ version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" dependencies = [ - "arrayvec 0.7.4", + "arrayvec", "bitvec", "byte-slice-cast", "impl-trait-for-tuples", "parity-scale-codec-derive", - "serde 1.0.193", + "serde", ] [[package]] @@ -5775,6 +5835,12 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "patricia_tree" version = "0.8.0" @@ -5866,6 +5932,40 @@ dependencies = [ "ucd-trie", ] +[[package]] +name = "pest_derive" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "pest_meta" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" +dependencies = [ + "once_cell", + "pest", + "sha2 0.10.8", +] + [[package]] name = "petgraph" version = "0.6.4" @@ -6400,7 +6500,7 @@ dependencies = [ "jubjub", "pasta_curves", "rand_core 0.6.4", - "serde 1.0.193", + "serde", "thiserror", "zeroize", ] @@ -6413,7 +6513,7 @@ checksum = "7a60db2c3bc9c6fd1e8631fee75abc008841d27144be744951d6b9b75f9b569c" dependencies = [ "rand_core 0.6.4", "reddsa", - "serde 1.0.193", + "serde", "thiserror", "zeroize", ] @@ -6542,7 +6642,7 @@ dependencies = [ "rustls", "rustls-native-certs", "rustls-pemfile", - "serde 1.0.193", + "serde", "serde_json", "serde_urlencoded", "system-configuration", @@ -6673,6 +6773,18 @@ dependencies = [ "librocksdb-sys", ] +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags 2.5.0", + "serde", + "serde_derive", +] + [[package]] name = "rpassword" version = "5.0.1" @@ -6685,9 +6797,13 @@ dependencies = [ [[package]] name = "rust-ini" -version = "0.13.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" +checksum = "3e0698206bcb8882bf2a9ecb4c1e7785db57ff052297085a6efd4fe42302068a" +dependencies = [ + "cfg-if", + "ordered-multimap", +] [[package]] name = "rust_decimal" @@ -6695,7 +6811,7 @@ version = "1.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a" dependencies = [ - "arrayvec 0.7.4", + "arrayvec", "num-traits 0.2.17", ] @@ -6874,7 +6990,7 @@ checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" dependencies = [ "dyn-clone", "schemars_derive", - "serde 1.0.193", + "serde", "serde_json", ] @@ -6983,7 +7099,7 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -7007,12 +7123,6 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" -[[package]] -name = "serde" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" - [[package]] name = "serde" version = "1.0.193" @@ -7022,25 +7132,13 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-hjson" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8" -dependencies = [ - "lazy_static", - "num-traits 0.1.43", - "regex", - "serde 0.8.23", -] - [[package]] name = "serde-json-wasm" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -7049,7 +7147,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f05da0d153dd4595bdffd5099dc0e9ce425b205ee648eb93437ff7302af8c9a5" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -7058,7 +7156,7 @@ version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -7068,7 +7166,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ "half", - "serde 1.0.193", + "serde", ] [[package]] @@ -7101,7 +7199,7 @@ checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", - "serde 1.0.193", + "serde", ] [[package]] @@ -7121,7 +7219,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -7133,7 +7231,7 @@ dependencies = [ "form_urlencoded", "itoa", "ryu", - "serde 1.0.193", + "serde", ] [[package]] @@ -7144,7 +7242,7 @@ checksum = "ef8099d3df28273c99a1728190c7a9f19d444c941044f64adf986bee7ec53051" dependencies = [ "dtoa", "linked-hash-map", - "serde 1.0.193", + "serde", "yaml-rust", ] @@ -7155,7 +7253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" dependencies = [ "base16ct", - "serde 1.0.193", + "serde", ] [[package]] @@ -7595,7 +7693,7 @@ dependencies = [ "once_cell", "prost 0.12.3", "prost-types 0.12.3", - "serde 1.0.193", + "serde", "serde_bytes", "serde_json", "serde_repr", @@ -7625,7 +7723,7 @@ dependencies = [ "prost 0.12.3", "prost-types 0.12.3", "ripemd", - "serde 1.0.193", + "serde", "serde_bytes", "serde_json", "serde_repr", @@ -7645,7 +7743,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e07b383dc8780ebbec04cfb603f3fdaba6ea6663d8dd861425b1ffa7761fe90d" dependencies = [ "flex-error", - "serde 1.0.193", + "serde", "serde_json", "tendermint 0.36.0", "toml 0.8.2", @@ -7664,7 +7762,7 @@ dependencies = [ "flex-error", "futures", "regex", - "serde 1.0.193", + "serde", "serde_cbor", "serde_derive", "serde_json", @@ -7685,7 +7783,7 @@ checksum = "4216e487165e5dbd7af79952eaa0d5f06c5bde861eb76c690acd7f2d2a19395c" dependencies = [ "derive_more", "flex-error", - "serde 1.0.193", + "serde", "tendermint 0.36.0", "time", ] @@ -7702,7 +7800,7 @@ dependencies = [ "num-traits 0.2.17", "prost 0.12.3", "prost-types 0.12.3", - "serde 1.0.193", + "serde", "serde_bytes", "subtle-encoding", "time", @@ -7718,7 +7816,7 @@ dependencies = [ "flex-error", "prost 0.12.3", "prost-types 0.12.3", - "serde 1.0.193", + "serde", "serde_bytes", "subtle-encoding", "time", @@ -7740,7 +7838,7 @@ dependencies = [ "rand 0.8.5", "reqwest", "semver 1.0.20", - "serde 1.0.193", + "serde", "serde_bytes", "serde_json", "subtle", @@ -7765,7 +7863,7 @@ checksum = "b233cec83c56c413ccc346af866cb9206a14d468fcecf0255080107bc9b103c0" dependencies = [ "ed25519-consensus", "gumdrop", - "serde 1.0.193", + "serde", "serde_json", "simple-error", "tempfile", @@ -7882,7 +7980,7 @@ dependencies = [ "deranged", "itoa", "powerfmt", - "serde 1.0.193", + "serde", "time-core", "time-macros", ] @@ -7947,7 +8045,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ - "serde 1.0.193", + "serde", "serde_json", ] @@ -8096,7 +8194,7 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -8105,7 +8203,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" dependencies = [ - "serde 1.0.193", + "serde", "serde_spanned", "toml_datetime", "toml_edit 0.20.2", @@ -8117,7 +8215,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ - "serde 1.0.193", + "serde", ] [[package]] @@ -8138,7 +8236,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ "indexmap 2.1.0", - "serde 1.0.193", + "serde", "serde_spanned", "toml_datetime", "winnow 0.5.25", @@ -8318,7 +8416,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" dependencies = [ - "serde 1.0.193", + "serde", "tracing-core", ] @@ -8332,7 +8430,7 @@ dependencies = [ "nu-ansi-term", "once_cell", "regex", - "serde 1.0.193", + "serde", "serde_json", "sharded-slab", "thread_local", @@ -8468,6 +8566,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + [[package]] name = "unicode-width" version = "0.1.11" @@ -8538,7 +8642,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ "getrandom 0.2.11", - "serde 1.0.193", + "serde", ] [[package]] @@ -8613,7 +8717,7 @@ dependencies = [ "pin-project", "rustls-pemfile", "scoped-tls", - "serde 1.0.193", + "serde", "serde_json", "serde_urlencoded", "tokio", @@ -8777,7 +8881,7 @@ dependencies = [ "enumset", "loupe", "rkyv", - "serde 1.0.193", + "serde", "serde_bytes", "smallvec", "target-lexicon", @@ -8848,7 +8952,7 @@ dependencies = [ "memmap2", "more-asserts", "rustc-demangle", - "serde 1.0.193", + "serde", "serde_bytes", "target-lexicon", "thiserror", @@ -8871,7 +8975,7 @@ dependencies = [ "loupe", "object 0.28.4", "rkyv", - "serde 1.0.193", + "serde", "tempfile", "tracing", "wasmer-artifact", @@ -8938,7 +9042,7 @@ dependencies = [ "indexmap 1.9.3", "loupe", "rkyv", - "serde 1.0.193", + "serde", "thiserror", ] @@ -8962,7 +9066,7 @@ dependencies = [ "region", "rkyv", "scopeguard", - "serde 1.0.193", + "serde", "thiserror", "wasmer-artifact", "wasmer-types", @@ -9403,6 +9507,17 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "yaml-rust2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498f4d102a79ea1c9d4dd27573c0fc96ad74c023e8da38484e47883076da25fb" +dependencies = [ + "arraydeque", + "encoding_rs", + "hashlink", +] + [[package]] name = "yansi" version = "0.5.1" @@ -9418,6 +9533,26 @@ dependencies = [ "nonempty", ] +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "zeroize" version = "1.7.0" diff --git a/Cargo.toml b/Cargo.toml index 0d1f58a577..baa436189b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,7 +86,7 @@ clap = "4.3.4" clru = {git = "https://github.com/marmeladema/clru-rs.git", rev = "71ca566"} color-eyre = "0.6.2" concat-idents = "1.1.2" -config = "0.11.0" +config = { git = "https://github.com/mehcode/config-rs.git", rev = "e3c1d0b452639478662a44f15ef6d5b6d969bf9b" } data-encoding = "2.3.2" derivation-path = "0.2.0" derivative = "2.2.0" diff --git a/crates/apps_lib/src/config/global.rs b/crates/apps_lib/src/config/global.rs index f6d917c770..ef1d5ecf5d 100644 --- a/crates/apps_lib/src/config/global.rs +++ b/crates/apps_lib/src/config/global.rs @@ -43,13 +43,16 @@ impl GlobalConfig { pub fn read(base_dir: impl AsRef) -> Result { let file_path = Self::file_path(base_dir.as_ref()); let file_name = file_path.to_str().expect("Expected UTF-8 file path"); - let mut config = config::Config::new(); + let mut config = config::Config::default(); if file_path.exists() { - config - .merge(config::File::with_name(file_name)) + config = config::Config::builder() + .add_source(config::File::with_name(file_name)) + .build() .map_err(Error::ReadError)?; } - config.try_into().map_err(Error::DeserializationError) + config + .try_deserialize() + .map_err(|e: config::ConfigError| Error::DeserializationError(e)) } /// Write configuration to a file. diff --git a/crates/apps_lib/src/config/mod.rs b/crates/apps_lib/src/config/mod.rs index d5041b184b..c6484d10b0 100644 --- a/crates/apps_lib/src/config/mod.rs +++ b/crates/apps_lib/src/config/mod.rs @@ -273,17 +273,17 @@ impl Config { mode, )) .map_err(Error::ReadError)?; - let mut config = config::Config::new(); + let builder = config::Config::builder() + .add_source(defaults) + .add_source(config::File::with_name(file_name)) + .add_source( + config::Environment::with_prefix("NAMADA").separator("__"), + ); + + let config = builder.build().map_err(Error::ReadError)?; config - .merge(defaults) - .and_then(|c| c.merge(config::File::with_name(file_name))) - .and_then(|c| { - c.merge( - config::Environment::with_prefix("NAMADA").separator("__"), - ) - }) - .map_err(Error::ReadError)?; - config.try_into().map_err(Error::DeserializationError) + .try_deserialize() + .map_err(Error::DeserializationError) } /// Generate configuration and write it to a file. From 826f3efce026b4eedf2f128215cddb036f89c634 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Thu, 4 Apr 2024 23:44:56 +0200 Subject: [PATCH 25/70] Run masp verification in parallel --- crates/gas/src/lib.rs | 34 +++- crates/sdk/src/masp.rs | 444 +++++++++++++++++++---------------------- 2 files changed, 228 insertions(+), 250 deletions(-) diff --git a/crates/gas/src/lib.rs b/crates/gas/src/lib.rs index c015542008..88c73b7d8d 100644 --- a/crates/gas/src/lib.rs +++ b/crates/gas/src/lib.rs @@ -84,14 +84,32 @@ pub const WASM_MEMORY_PAGE_GAS: u32 = pub const IBC_ACTION_VALIDATE_GAS: u64 = 1_472_023; /// The cost to execute an Ibc action pub const IBC_ACTION_EXECUTE_GAS: u64 = 3_678_745; -/// The cost to verify a masp spend note -pub const MASP_VERIFY_SPEND_GAS: u64 = 66_822_000; -/// The cost to verify a masp convert note -pub const MASP_VERIFY_CONVERT_GAS: u64 = 45_240_000; -/// The cost to verify a masp output note -pub const MASP_VERIFY_OUTPUT_GAS: u64 = 55_023_000; -/// The cost to run the final masp verification -pub const MASP_VERIFY_FINAL_GAS: u64 = 3_475_200; +// FIXME: update costs +/// The cost of masp sig verification +pub const MASP_VERIFY_SIG_GAS: u64 = 1; +/// The fixed cost of spend note verification +pub const MASP_FIXED_SPEND_GAS: u64 = 1; +/// The variable cost of spend note verification +pub const MASP_VARIABLE_SPEND_GAS: u64 = 1; +/// The fixed cost of convert note verification +pub const MASP_FIXED_CONVERT_GAS: u64 = 1; +/// The variable cost of convert note verification +pub const MASP_VARIABLE_CONVERT_GAS: u64 = 1; +/// The fixed cost of output note verification +pub const MASP_FIXED_OUTPUT_GAS: u64 = 1; +/// The variable cost of output note verification +pub const MASP_VARIABLE_OUTPUT_GAS: u64 = 1; +/// The cost to process a masp spend note in the bundle +pub const MASP_SPEND_CHECK_GAS: u64 = 1; +/// The cost to process a masp convert note in the bundle +pub const MASP_CONVERT_CHECK_GAS: u64 = 1; +/// The cost to process a masp output note in the bundle +pub const MASP_OUTPUT_CHECK_GAS: u64 = 1; +/// The cost to run the final masp check in the bundle +pub const MASP_FINAL_CHECK_GAS: u64 = 1; +/// Gas divider specific for the masp vp. Only allocates half of the cores to +/// the masp vp since we can expect the other half to be busy with other vps +pub const MASP_PARALLEL_GAS_DIVIDER: u64 = PARALLEL_GAS_DIVIDER / 2; /// Gas module result for functions that may fail pub type Result = std::result::Result; diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 7247d3e2c5..caa9a19d5a 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -17,14 +17,12 @@ use masp_primitives::consensus::MainNetwork as Network; use masp_primitives::consensus::TestNetwork as Network; use masp_primitives::convert::AllowedConversion; use masp_primitives::ff::PrimeField; -use masp_primitives::group::GroupEncoding; use masp_primitives::memo::MemoBytes; use masp_primitives::merkle_tree::{ CommitmentTree, IncrementalWitness, MerklePath, }; use masp_primitives::sapling::keys::FullViewingKey; use masp_primitives::sapling::note_encryption::*; -use masp_primitives::sapling::redjubjub::PublicKey; use masp_primitives::sapling::{ Diversifier, Node, Note, Nullifier, ViewingKey, }; @@ -34,8 +32,7 @@ use masp_primitives::transaction::components::sapling::builder::{ }; use masp_primitives::transaction::components::transparent::builder::TransparentBuilder; use masp_primitives::transaction::components::{ - ConvertDescription, I128Sum, OutputDescription, SpendDescription, TxOut, - U64Sum, ValueSum, + I128Sum, OutputDescription, TxOut, U64Sum, ValueSum, }; use masp_primitives::transaction::fees::fixed::FeeRule; use masp_primitives::transaction::sighash::{signature_hash, SignableInput}; @@ -45,11 +42,10 @@ use masp_primitives::transaction::{ TransparentAddress, Unauthorized, }; use masp_primitives::zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}; -use masp_proofs::bellman::groth16::PreparedVerifyingKey; +use masp_proofs::bellman::groth16::VerifyingKey; use masp_proofs::bls12_381::Bls12; use masp_proofs::prover::LocalTxProver; -#[cfg(not(feature = "testing"))] -use masp_proofs::sapling::SaplingVerificationContext; +use masp_proofs::sapling::BatchValidator; use namada_core::address::Address; use namada_core::collections::{HashMap, HashSet}; use namada_core::dec::Dec; @@ -70,7 +66,8 @@ use namada_migrations::*; use namada_state::StorageError; use namada_token::{self as token, Denomination, MaspDigitPos, Transfer}; use namada_tx::{IndexedTx, Tx, TxCommitments}; -use rand_core::{CryptoRng, OsRng, RngCore}; +use rand::rngs::StdRng; +use rand_core::{CryptoRng, OsRng, RngCore, SeedableRng}; use ripemd::Digest as RipemdDigest; use sha2::Digest; use thiserror::Error; @@ -148,11 +145,11 @@ struct ExtractedMaspTxs(Vec<(TxCommitments, Transaction)>); /// MASP verifying keys pub struct PVKs { /// spend verifying key - pub spend_vk: PreparedVerifyingKey, + pub spend_vk: VerifyingKey, /// convert verifying key - pub convert_vk: PreparedVerifyingKey, + pub convert_vk: VerifyingKey, /// output verifying key - pub output_vk: PreparedVerifyingKey, + pub output_vk: VerifyingKey, } lazy_static! { @@ -186,9 +183,9 @@ lazy_static! { convert_path.as_path(), ); PVKs { - spend_vk: params.spend_vk, - convert_vk: params.convert_vk, - output_vk: params.output_vk + spend_vk: params.spend_params.vk, + convert_vk: params.convert_params.vk, + output_vk: params.output_params.vk } }; } @@ -202,76 +199,6 @@ fn load_pvks() -> &'static PVKs { &VERIFIYING_KEYS } -/// check_spend wrapper -pub fn check_spend( - spend: &SpendDescription<::SaplingAuth>, - sighash: &[u8; 32], - #[cfg(not(feature = "testing"))] ctx: &mut SaplingVerificationContext, - #[cfg(feature = "testing")] - ctx: &mut testing::MockSaplingVerificationContext, - parameters: &PreparedVerifyingKey, -) -> bool { - let zkproof = - masp_proofs::bellman::groth16::Proof::read(spend.zkproof.as_slice()); - let zkproof = match zkproof { - Ok(zkproof) => zkproof, - _ => return false, - }; - - ctx.check_spend( - spend.cv, - spend.anchor, - &spend.nullifier.0, - PublicKey(spend.rk.0), - sighash, - spend.spend_auth_sig, - zkproof, - parameters, - ) -} - -/// check_output wrapper -pub fn check_output( - output: &OutputDescription<<::SaplingAuth as masp_primitives::transaction::components::sapling::Authorization>::Proof>, - #[cfg(not(feature = "testing"))] ctx: &mut SaplingVerificationContext, - #[cfg(feature = "testing")] - ctx: &mut testing::MockSaplingVerificationContext, - parameters: &PreparedVerifyingKey, -) -> bool { - let zkproof = - masp_proofs::bellman::groth16::Proof::read(output.zkproof.as_slice()); - let zkproof = match zkproof { - Ok(zkproof) => zkproof, - _ => return false, - }; - let epk = - masp_proofs::jubjub::ExtendedPoint::from_bytes(&output.ephemeral_key.0); - let epk = match epk.into() { - Some(p) => p, - None => return false, - }; - - ctx.check_output(output.cv, output.cmu, epk, zkproof, parameters) -} - -/// check convert wrapper -pub fn check_convert( - convert: &ConvertDescription<<::SaplingAuth as masp_primitives::transaction::components::sapling::Authorization>::Proof>, - #[cfg(not(feature = "testing"))] ctx: &mut SaplingVerificationContext, - #[cfg(feature = "testing")] - ctx: &mut testing::MockSaplingVerificationContext, - parameters: &PreparedVerifyingKey, -) -> bool { - let zkproof = - masp_proofs::bellman::groth16::Proof::read(convert.zkproof.as_slice()); - let zkproof = match zkproof { - Ok(zkproof) => zkproof, - _ => return false, - }; - - ctx.check_convert(convert.cv, convert.anchor, zkproof, parameters) -} - /// Represents an authorization where the Sapling bundle is authorized and the /// transparent bundle is unauthorized. pub struct PartialAuthorized; @@ -317,12 +244,12 @@ pub fn partial_deauthorize( /// Verify a shielded transaction. pub fn verify_shielded_tx( transaction: &Transaction, - mut consume_verify_gas: F, + consume_verify_gas: F, ) -> Result<(), StorageError> where - F: FnMut(u64) -> std::result::Result<(), StorageError>, + F: Fn(u64) -> std::result::Result<(), StorageError>, { - tracing::info!("entered verify_shielded_tx()"); + tracing::debug!("entered verify_shielded_tx()"); let sapling_bundle = if let Some(bundle) = transaction.sapling_bundle() { bundle @@ -347,8 +274,7 @@ where // for now we need to continue to compute it here. let sighash = signature_hash(&unauth_tx_data, &SignableInput::Shielded, &txid_parts); - - tracing::info!("sighash computed"); + tracing::debug!("sighash computed"); let PVKs { spend_vk, @@ -357,49 +283,154 @@ where } = load_pvks(); #[cfg(not(feature = "testing"))] - let mut ctx = SaplingVerificationContext::new(true); + let mut ctx = BatchValidator::new(); #[cfg(feature = "testing")] - let mut ctx = testing::MockSaplingVerificationContext::new(true); - for spend in &sapling_bundle.shielded_spends { - consume_verify_gas(namada_gas::MASP_VERIFY_SPEND_GAS)?; - if !check_spend(spend, sighash.as_ref(), &mut ctx, spend_vk) { - return Err(StorageError::SimpleMessage("Invalid shielded spend")); - } - } - for convert in &sapling_bundle.shielded_converts { - consume_verify_gas(namada_gas::MASP_VERIFY_CONVERT_GAS)?; - if !check_convert(convert, &mut ctx, convert_vk) { - return Err(StorageError::SimpleMessage( - "Invalid shielded conversion", - )); - } - } - for output in &sapling_bundle.shielded_outputs { - consume_verify_gas(namada_gas::MASP_VERIFY_OUTPUT_GAS)?; - if !check_output(output, &mut ctx, output_vk) { - return Err(StorageError::SimpleMessage("Invalid shielded output")); - } + let mut ctx = testing::MockBatchValidator::default(); + + // Charge gas before check bundle + let spends_len = sapling_bundle.shielded_spends.len() as u64; + let converts_len = sapling_bundle.shielded_converts.len() as u64; + let outputs_len = sapling_bundle.shielded_outputs.len() as u64; + charge_masp_check_bundle_gas( + spends_len, + converts_len, + outputs_len, + &consume_verify_gas, + )?; + + if !ctx.check_bundle(sapling_bundle.to_owned(), sighash.as_ref().to_owned()) + { + tracing::debug!("failed check bundle"); + return Err(StorageError::SimpleMessage("Invalid sapling bundle")); + } + tracing::debug!("passed check bundle"); + + // Charge gas before final validation + charge_masp_validate_gas( + spends_len, + converts_len, + outputs_len, + consume_verify_gas, + )?; + if !ctx.validate(spend_vk, convert_vk, output_vk, OsRng) { + return Err(StorageError::SimpleMessage( + "Invalid proofs or signatures", + )); } + Ok(()) +} - tracing::info!("passed spend/output verification"); +// Charge gas for the check_bundle operation which does not leverage concurrency +fn charge_masp_check_bundle_gas( + spends_len: u64, + converts_len: u64, + outputs_len: u64, + consume_verify_gas: F, +) -> Result<(), namada_state::StorageError> +where + F: Fn(u64) -> std::result::Result<(), namada_state::StorageError>, +{ + consume_verify_gas( + spends_len + .checked_mul(namada_gas::MASP_SPEND_CHECK_GAS) + .ok_or(namada_state::StorageError::SimpleMessage( + "Overflow in gas calculation", + ))?, + )?; + + consume_verify_gas( + converts_len + .checked_mul(namada_gas::MASP_CONVERT_CHECK_GAS) + .ok_or(namada_state::StorageError::SimpleMessage( + "Overflow in gas calculation", + ))?, + )?; + + consume_verify_gas( + outputs_len + .checked_mul(namada_gas::MASP_OUTPUT_CHECK_GAS) + .ok_or(namada_state::StorageError::SimpleMessage( + "Overflow in gas calculation", + ))?, + )?; + + Ok(()) +} - let assets_and_values: I128Sum = sapling_bundle.value_balance.clone(); +// Charge gas for the final validation, taking advtange of concurrency for +// proofs verification but not for signature (because of the fallback) +fn charge_masp_validate_gas( + spends_len: u64, + converts_len: u64, + outputs_len: u64, + consume_verify_gas: F, +) -> Result<(), namada_state::StorageError> +where + F: Fn(u64) -> std::result::Result<(), namada_state::StorageError>, +{ + // Signatures pay the entire cost (no discount because of the possible + // fallback) + consume_verify_gas( + spends_len + // Add one for the binding signature + .checked_add(1) + .ok_or(namada_state::StorageError::SimpleMessage( + "Overflow in gas calculation", + ))? + .checked_mul(namada_gas::MASP_VERIFY_SIG_GAS) + .ok_or(namada_state::StorageError::SimpleMessage( + "Overflow in gas calculation", + ))?, + )?; + + // If at least one note is present charge the fixed costs. Then charge the + // variable cost for every note, amortized on the fixed expected number of + // cores + if spends_len != 0 { + consume_verify_gas(namada_gas::MASP_FIXED_SPEND_GAS)?; + consume_verify_gas( + namada_gas::MASP_VARIABLE_SPEND_GAS + .checked_mul(spends_len) + .ok_or(namada_state::StorageError::SimpleMessage( + "Overflow in gas calculation", + ))? + .checked_div(namada_gas::MASP_PARALLEL_GAS_DIVIDER) + .ok_or(namada_state::StorageError::SimpleMessage( + "Overflow in gas calculation", + ))?, + )?; + } - tracing::info!( - "accumulated {} assets/values", - assets_and_values.components().len() - ); + if converts_len != 0 { + consume_verify_gas(namada_gas::MASP_FIXED_CONVERT_GAS)?; + consume_verify_gas( + namada_gas::MASP_VARIABLE_CONVERT_GAS + .checked_mul(converts_len) + .ok_or(namada_state::StorageError::SimpleMessage( + "Overflow in gas calculation", + ))? + .checked_div(namada_gas::MASP_PARALLEL_GAS_DIVIDER) + .ok_or(namada_state::StorageError::SimpleMessage( + "Overflow in gas calculation", + ))?, + )?; + } - consume_verify_gas(namada_gas::MASP_VERIFY_FINAL_GAS)?; - let result = ctx.final_check( - assets_and_values, - sighash.as_ref(), - sapling_bundle.authorization.binding_sig, - ); - tracing::info!("final check result {result}"); - if !result { - return Err(StorageError::SimpleMessage("MASP final check failed")); + if outputs_len != 0 { + consume_verify_gas(namada_gas::MASP_FIXED_OUTPUT_GAS)?; + consume_verify_gas( + namada_gas::MASP_VARIABLE_OUTPUT_GAS + .checked_mul(outputs_len) + .ok_or(namada_state::StorageError::SimpleMessage( + "Overflow in gas calculation", + ))? + .checked_div(namada_gas::MASP_PARALLEL_GAS_DIVIDER) + .ok_or(namada_state::StorageError::SimpleMessage( + "Overflow in gas calculation", + ))?, + )?; } + Ok(()) } @@ -1559,9 +1590,6 @@ impl ShieldedContext { // No shielded components are needed when neither source nor destination // are shielded - use rand::rngs::StdRng; - use rand_core::SeedableRng; - let spending_key = source.spending_key(); let payment_address = target.payment_address(); // No shielded components are needed when neither source nor @@ -2216,11 +2244,13 @@ pub mod testing { use bls12_381::{G1Affine, G2Affine}; use masp_primitives::consensus::testing::arb_height; use masp_primitives::constants::SPENDING_KEY_GENERATOR; + use masp_primitives::group::GroupEncoding; use masp_primitives::sapling::prover::TxProver; - use masp_primitives::sapling::redjubjub::Signature; + use masp_primitives::sapling::redjubjub::{PublicKey, Signature}; use masp_primitives::sapling::{ProofGenerationKey, Rseed}; + use masp_primitives::transaction::components::sapling::Bundle; use masp_primitives::transaction::components::GROTH_PROOF_SIZE; - use masp_proofs::bellman::groth16::Proof; + use masp_proofs::bellman::groth16::{self, Proof}; use proptest::prelude::*; use proptest::sample::SizeRange; use proptest::test_runner::TestRng; @@ -2234,129 +2264,59 @@ pub mod testing { use crate::masp_primitives::sapling::keys::OutgoingViewingKey; use crate::masp_primitives::sapling::redjubjub::PrivateKey; use crate::masp_primitives::transaction::components::transparent::testing::arb_transparent_address; - use crate::masp_proofs::sapling::SaplingVerificationContextInner; use crate::storage::testing::arb_epoch; use crate::token::testing::arb_denomination; - /// A context object for verifying the Sapling components of a single Zcash - /// transaction. Same as SaplingVerificationContext, but always assumes the - /// proofs to be valid. - pub struct MockSaplingVerificationContext { - inner: SaplingVerificationContextInner, - zip216_enabled: bool, + /// A context object for verifying the Sapling components of MASP + /// transactions. Same as BatchValidator, but always assumes the + /// proofs and signatures to be valid. + pub struct MockBatchValidator { + inner: BatchValidator, } - impl MockSaplingVerificationContext { - /// Construct a new context to be used with a single transaction. - pub fn new(zip216_enabled: bool) -> Self { - MockSaplingVerificationContext { - inner: SaplingVerificationContextInner::new(), - zip216_enabled, + impl Default for MockBatchValidator { + fn default() -> Self { + MockBatchValidator { + inner: BatchValidator::new(), } } + } - /// Perform consensus checks on a Sapling SpendDescription, while - /// accumulating its value commitment inside the context for later use. - #[allow(clippy::too_many_arguments)] - pub fn check_spend( - &mut self, - cv: jubjub::ExtendedPoint, - anchor: bls12_381::Scalar, - nullifier: &[u8; 32], - rk: PublicKey, - sighash_value: &[u8; 32], - spend_auth_sig: Signature, - zkproof: Proof, - _verifying_key: &PreparedVerifyingKey, - ) -> bool { - let zip216_enabled = true; - self.inner.check_spend( - cv, - anchor, - nullifier, - rk, - sighash_value, - spend_auth_sig, - zkproof, - &mut (), - |_, rk, msg, spend_auth_sig| { - rk.verify_with_zip216( - &msg, - &spend_auth_sig, - SPENDING_KEY_GENERATOR, - zip216_enabled, - ) - }, - |_, _proof, _public_inputs| true, - ) - } - - /// Perform consensus checks on a Sapling SpendDescription, while - /// accumulating its value commitment inside the context for later use. - #[allow(clippy::too_many_arguments)] - pub fn check_convert( + impl MockBatchValidator { + /// Checks the bundle against Sapling-specific consensus rules, and adds + /// its proof and signatures to the validator. + /// + /// Returns `false` if the bundle doesn't satisfy all of the consensus + /// rules. This `BatchValidator` can continue to be used + /// regardless, but some or all of the proofs and signatures + /// from this bundle may have already been added to the batch even if + /// it fails other consensus rules. + pub fn check_bundle( &mut self, - cv: jubjub::ExtendedPoint, - anchor: bls12_381::Scalar, - zkproof: Proof, - _verifying_key: &PreparedVerifyingKey, + bundle: Bundle< + masp_primitives::transaction::components::sapling::Authorized, + >, + sighash: [u8; 32], ) -> bool { - self.inner.check_convert( - cv, - anchor, - zkproof, - &mut (), - |_, _proof, _public_inputs| true, - ) - } - - /// Perform consensus checks on a Sapling OutputDescription, while - /// accumulating its value commitment inside the context for later use. - pub fn check_output( - &mut self, - cv: jubjub::ExtendedPoint, - cmu: bls12_381::Scalar, - epk: jubjub::ExtendedPoint, - zkproof: Proof, - _verifying_key: &PreparedVerifyingKey, + self.inner.check_bundle(bundle, sighash) + } + + /// Batch-validates the accumulated bundles. + /// + /// Returns `true` if every proof and signature in every bundle added to + /// the batch validator is valid, or `false` if one or more are + /// invalid. No attempt is made to figure out which of the + /// accumulated bundles might be invalid; if that information is + /// desired, construct separate [`BatchValidator`]s for sub-batches of + /// the bundles. + pub fn validate( + self, + _spend_vk: &groth16::VerifyingKey, + _convert_vk: &groth16::VerifyingKey, + _output_vk: &groth16::VerifyingKey, + mut _rng: R, ) -> bool { - self.inner.check_output( - cv, - cmu, - epk, - zkproof, - |_proof, _public_inputs| true, - ) - } - - /// Perform consensus checks on the valueBalance and bindingSig parts of - /// a Sapling transaction. All SpendDescriptions and - /// OutputDescriptions must have been checked before calling - /// this function. - pub fn final_check( - &self, - value_balance: I128Sum, - sighash_value: &[u8; 32], - binding_sig: Signature, - ) -> bool { - self.inner.final_check( - value_balance, - sighash_value, - binding_sig, - |bvk, msg, binding_sig| { - // Compute the signature's message for bvk/binding_sig - let mut data_to_be_signed = [0u8; 64]; - data_to_be_signed[0..32].copy_from_slice(&bvk.0.to_bytes()); - data_to_be_signed[32..64].copy_from_slice(msg); - - bvk.verify_with_zip216( - &data_to_be_signed, - &binding_sig, - VALUE_COMMITMENT_RANDOMNESS_GENERATOR, - self.zip216_enabled, - ) - }, - ) + true } } From 6fe54a4dff6d1889021ff3798bc3e47ed85214bc Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Thu, 11 Apr 2024 20:02:28 +0200 Subject: [PATCH 26/70] Updates benchmarks for parallel masp verification --- Cargo.lock | 1 + crates/benches/Cargo.toml | 1 + crates/benches/native_vps.rs | 380 +++++++++++++++++++++++++----- crates/benches/process_wrapper.rs | 20 +- 4 files changed, 335 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a9d914fe1..3b3d63a1ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4557,6 +4557,7 @@ dependencies = [ "criterion", "lazy_static", "masp_primitives", + "masp_proofs", "namada", "namada_apps_lib", "namada_node", diff --git a/crates/benches/Cargo.toml b/crates/benches/Cargo.toml index ca308f9100..01d25fa777 100644 --- a/crates/benches/Cargo.toml +++ b/crates/benches/Cargo.toml @@ -46,6 +46,7 @@ namada = { path = "../namada", features = ["rand", "benches"] } namada_apps_lib = { path = "../apps_lib" } namada_node = { path = "../node", features = ["benches"] } masp_primitives.workspace = true +masp_proofs = { workspace = true, features = ["multicore"] } borsh.workspace = true borsh-ext.workspace = true criterion = { version = "0.5", features = ["html_reports"] } diff --git a/crates/benches/native_vps.rs b/crates/benches/native_vps.rs index 0ad8a637b5..965a3dfe65 100644 --- a/crates/benches/native_vps.rs +++ b/crates/benches/native_vps.rs @@ -5,9 +5,13 @@ use std::rc::Rc; use std::str::FromStr; use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; +use masp_primitives::sapling::redjubjub::PublicKey; use masp_primitives::sapling::Node; use masp_primitives::transaction::sighash::{signature_hash, SignableInput}; use masp_primitives::transaction::txid::TxIdDigester; +use masp_primitives::transaction::TransactionData; +use masp_proofs::group::GroupEncoding; +use masp_proofs::sapling::BatchValidator; use namada::core::address::{self, Address, InternalAddress}; use namada::core::collections::HashMap; use namada::core::eth_bridge_pool::{GasFee, PendingTransfer}; @@ -46,13 +50,10 @@ use namada::ledger::pgf::PgfVp; use namada::ledger::pos::PosVP; use namada::proof_of_stake; use namada::proof_of_stake::KeySeg; -use namada::sdk::masp::{ - check_convert, check_output, check_spend, partial_deauthorize, - preload_verifying_keys, PVKs, -}; +use namada::sdk::masp::{partial_deauthorize, preload_verifying_keys, PVKs}; use namada::sdk::masp_primitives::merkle_tree::CommitmentTree; use namada::sdk::masp_primitives::transaction::Transaction; -use namada::sdk::masp_proofs::sapling::SaplingVerificationContext; +use namada::sdk::masp_proofs::sapling::SaplingVerificationContextInner; use namada::state::{Epoch, StorageRead, StorageWrite, TxIndex}; use namada::token::{Amount, Transfer}; use namada::tx::{BatchedTx, Code, Section, Tx}; @@ -63,6 +64,7 @@ use namada_node::bench_utils::{ TX_BRIDGE_POOL_WASM, TX_IBC_WASM, TX_INIT_PROPOSAL_WASM, TX_RESIGN_STEWARD, TX_TRANSFER_WASM, TX_UPDATE_STEWARD_COMMISSION, TX_VOTE_PROPOSAL_WASM, }; +use rand_core::OsRng; fn governance(c: &mut Criterion) { let mut group = c.benchmark_group("vp_governance"); @@ -455,8 +457,7 @@ fn ibc(c: &mut Criterion) { ibc.ctx.keys_changed, ibc.ctx.verifiers, ) - .is_ok() - ) + .is_ok()) }) }); } @@ -633,8 +634,7 @@ fn masp(c: &mut Criterion) { masp.ctx.keys_changed, masp.ctx.verifiers, ) - .is_ok() - ); + .is_ok()); }) }); } @@ -642,11 +642,11 @@ fn masp(c: &mut Criterion) { group.finish(); } +// Instead of benchmarking BatchValidator::check_bundle we benchmark the 4 +// functions that are called internally for better resolution fn masp_check_spend(c: &mut Criterion) { - let spend_vk = &preload_verifying_keys().spend_vk; - c.bench_function("vp_masp_check_spend", |b| { - b.iter_batched_ref( + b.iter_batched( || { let (_, _verifiers_from_tx, signed_tx) = setup_storage_for_masp_verification("shielded"); @@ -670,7 +670,7 @@ fn masp_check_spend(c: &mut Criterion) { .first() .unwrap() .to_owned(); - let ctx = SaplingVerificationContext::new(true); + let ctx = SaplingVerificationContextInner::new(); let tx_data = transaction.deref(); // Partially deauthorize the transparent bundle let unauth_tx_data = partial_deauthorize(tx_data).unwrap(); @@ -680,11 +680,28 @@ fn masp_check_spend(c: &mut Criterion) { &SignableInput::Shielded, &txid_parts, ); + let zkproof = masp_proofs::bellman::groth16::Proof::read( + spend.zkproof.as_slice(), + ) + .unwrap(); - (ctx, spend, sighash) + (ctx, spend, sighash, zkproof) }, - |(ctx, spend, sighash)| { - assert!(check_spend(spend, sighash.as_ref(), ctx, spend_vk)); + |(mut ctx, spend, sighash, zkproof)| { + assert!(ctx.check_spend( + spend.cv, + spend.anchor, + &spend.nullifier.0, + PublicKey(spend.rk.0), + sighash.as_ref(), + spend.spend_auth_sig, + zkproof, + &mut (), + // We do sig and proofs verification in parallel, so just + // use dummy verifiers here + |_, _, _, _| true, + |_, _, _| true + )); }, BatchSize::SmallInput, ) @@ -692,10 +709,8 @@ fn masp_check_spend(c: &mut Criterion) { } fn masp_check_convert(c: &mut Criterion) { - let convert_vk = &preload_verifying_keys().convert_vk; - c.bench_function("vp_masp_check_convert", |b| { - b.iter_batched_ref( + b.iter_batched( || { let (_, _verifiers_from_tx, signed_tx) = setup_storage_for_masp_verification("shielded"); @@ -719,12 +734,24 @@ fn masp_check_convert(c: &mut Criterion) { .first() .unwrap() .to_owned(); - let ctx = SaplingVerificationContext::new(true); + let ctx = SaplingVerificationContextInner::new(); + let zkproof = masp_proofs::bellman::groth16::Proof::read( + convert.zkproof.as_slice(), + ) + .unwrap(); - (ctx, convert) + (ctx, convert, zkproof) }, - |(ctx, convert)| { - assert!(check_convert(convert, ctx, convert_vk)); + |(mut ctx, convert, zkproof)| { + assert!(ctx.check_convert( + convert.cv, + convert.anchor, + zkproof, + &mut (), + // We do proofs verification in parallel, so just use dummy + // verifier here + |_, _, _| true, + )); }, BatchSize::SmallInput, ) @@ -732,10 +759,8 @@ fn masp_check_convert(c: &mut Criterion) { } fn masp_check_output(c: &mut Criterion) { - let output_vk = &preload_verifying_keys().output_vk; - c.bench_function("masp_vp_check_output", |b| { - b.iter_batched_ref( + b.iter_batched( || { let (_, _verifiers_from_tx, signed_tx) = setup_storage_for_masp_verification("shielded"); @@ -759,12 +784,28 @@ fn masp_check_output(c: &mut Criterion) { .first() .unwrap() .to_owned(); - let ctx = SaplingVerificationContext::new(true); + let ctx = SaplingVerificationContextInner::new(); + let zkproof = masp_proofs::bellman::groth16::Proof::read( + output.zkproof.as_slice(), + ) + .unwrap(); + let epk = masp_proofs::jubjub::ExtendedPoint::from_bytes( + &output.ephemeral_key.0, + ) + .unwrap(); - (ctx, output) + (ctx, output, epk, zkproof) }, - |(ctx, output)| { - assert!(check_output(output, ctx, output_vk)); + |(mut ctx, output, epk, zkproof)| { + assert!(ctx.check_output( + output.cv, + output.cmu, + epk, + zkproof, + // We do proofs verification in parallel, so just use dummy + // verifier here + |_, _| true + )); }, BatchSize::SmallInput, ) @@ -772,12 +813,6 @@ fn masp_check_output(c: &mut Criterion) { } fn masp_final_check(c: &mut Criterion) { - let PVKs { - spend_vk, - convert_vk, - output_vk, - } = preload_verifying_keys(); - let (_, _verifiers_from_tx, signed_tx) = setup_storage_for_masp_verification("shielded"); @@ -794,41 +829,274 @@ fn masp_final_check(c: &mut Criterion) { .unwrap() .to_owned(); let sapling_bundle = transaction.sapling_bundle().unwrap(); - let mut ctx = SaplingVerificationContext::new(true); // Partially deauthorize the transparent bundle let unauth_tx_data = partial_deauthorize(transaction.deref()).unwrap(); let txid_parts = unauth_tx_data.digest(TxIdDigester); let sighash = signature_hash(&unauth_tx_data, &SignableInput::Shielded, &txid_parts); + let mut ctx = SaplingVerificationContextInner::new(); // Check spends, converts and outputs before the final check assert!(sapling_bundle.shielded_spends.iter().all(|spend| { - check_spend(spend, sighash.as_ref(), &mut ctx, spend_vk) + let zkproof = masp_proofs::bellman::groth16::Proof::read( + spend.zkproof.as_slice(), + ) + .unwrap(); + + ctx.check_spend( + spend.cv, + spend.anchor, + &spend.nullifier.0, + PublicKey(spend.rk.0), + sighash.as_ref(), + spend.spend_auth_sig, + zkproof, + &mut (), + |_, _, _, _| true, + |_, _, _| true, + ) + })); + assert!(sapling_bundle.shielded_converts.iter().all(|convert| { + let zkproof = masp_proofs::bellman::groth16::Proof::read( + convert.zkproof.as_slice(), + ) + .unwrap(); + ctx.check_convert( + convert.cv, + convert.anchor, + zkproof, + &mut (), + |_, _, _| true, + ) + })); + assert!(sapling_bundle.shielded_outputs.iter().all(|output| { + let zkproof = masp_proofs::bellman::groth16::Proof::read( + output.zkproof.as_slice(), + ) + .unwrap(); + let epk = masp_proofs::jubjub::ExtendedPoint::from_bytes( + &output.ephemeral_key.0, + ) + .unwrap(); + ctx.check_output( + output.cv, + output.cmu, + epk.to_owned(), + zkproof, + |_, _| true, + ) })); - assert!( - sapling_bundle - .shielded_converts - .iter() - .all(|convert| check_convert(convert, &mut ctx, convert_vk)) - ); - assert!( - sapling_bundle - .shielded_outputs - .iter() - .all(|output| check_output(output, &mut ctx, output_vk)) - ); c.bench_function("vp_masp_final_check", |b| { b.iter(|| { assert!(ctx.final_check( sapling_bundle.value_balance.clone(), sighash.as_ref(), - sapling_bundle.authorization.binding_sig + sapling_bundle.authorization.binding_sig, + // We do sig verification in parallel, so just use dummy + // verifier here + |_, _, _| true )) }) }); } +#[derive(Debug)] +enum RequestedItem { + Signature, + Spend, + Convert, + Output, +} + +// Removes the unneeded notes from the generated transaction and replicates the +// remaining ones if needed +fn customize_masp_tx_data( + multi: bool, + request: &RequestedItem, +) -> Option<( + TransactionData, + Transaction, +)> { + let (_, tx) = setup_storage_for_masp_verification("unshielding"); + let transaction = tx + .sections + .into_iter() + .filter_map(|section| match section { + Section::MaspTx(transaction) => Some(transaction), + _ => None, + }) + .collect::>() + .first() + .unwrap() + .to_owned(); + let mut sapling_bundle = transaction.sapling_bundle().unwrap().to_owned(); + + match request { + RequestedItem::Signature => { + if multi { + // No multisig benchmark + return None; + } + // ensure we only have one signature to verify (the binding one) and + // no proofs + sapling_bundle.shielded_spends.clear(); + sapling_bundle.shielded_converts.clear(); + sapling_bundle.shielded_outputs.clear(); + assert_eq!(sapling_bundle.shielded_spends.len(), 0); + assert_eq!(sapling_bundle.shielded_converts.len(), 0); + assert_eq!(sapling_bundle.shielded_outputs.len(), 0); + } + RequestedItem::Spend => { + if multi { + // ensure we only have two spend proofs + sapling_bundle.shielded_spends = [ + sapling_bundle.shielded_spends.clone(), + sapling_bundle.shielded_spends, + ] + .concat(); + sapling_bundle.shielded_outputs.clear(); + sapling_bundle.shielded_converts.clear(); + assert_eq!(sapling_bundle.shielded_spends.len(), 2); + } else { + // ensure we only have one spend proof + sapling_bundle.shielded_outputs.clear(); + sapling_bundle.shielded_converts.clear(); + assert_eq!(sapling_bundle.shielded_spends.len(), 1); + } + assert_eq!(sapling_bundle.shielded_converts.len(), 0); + assert_eq!(sapling_bundle.shielded_outputs.len(), 0); + } + RequestedItem::Convert => { + if multi { + // ensure we only have two convert proofs + sapling_bundle.shielded_converts = [ + sapling_bundle.shielded_converts.clone(), + sapling_bundle.shielded_converts, + ] + .concat(); + sapling_bundle.shielded_spends.clear(); + sapling_bundle.shielded_outputs.clear(); + assert_eq!(sapling_bundle.shielded_converts.len(), 2); + } else { + // ensure we only have one convert proof + sapling_bundle.shielded_spends.clear(); + sapling_bundle.shielded_outputs.clear(); + assert_eq!(sapling_bundle.shielded_converts.len(), 1); + } + assert_eq!(sapling_bundle.shielded_spends.len(), 0); + assert_eq!(sapling_bundle.shielded_outputs.len(), 0); + } + RequestedItem::Output => { + // From the cost remove the cost of signature(s) validation + if multi { + // ensure we only have two output proofs + sapling_bundle.shielded_outputs = [ + sapling_bundle.shielded_outputs.clone(), + sapling_bundle.shielded_outputs, + ] + .concat(); + sapling_bundle.shielded_spends.clear(); + sapling_bundle.shielded_converts.clear(); + assert_eq!(sapling_bundle.shielded_outputs.len(), 2); + } else { + // ensure we only have one output proof + sapling_bundle.shielded_spends.clear(); + sapling_bundle.shielded_converts.clear(); + assert_eq!(sapling_bundle.shielded_outputs.len(), 1); + } + assert_eq!(sapling_bundle.shielded_spends.len(), 0); + assert_eq!(sapling_bundle.shielded_converts.len(), 0); + } + }; + + Some(( + TransactionData::from_parts( + transaction.version(), + transaction.consensus_branch_id(), + transaction.lock_time(), + transaction.expiry_height(), + transaction.transparent_bundle().cloned(), + Some(sapling_bundle), + ), + transaction, + )) +} + +// For signatures: it's impossible to benchmark more than one signature without +// pulling in the cost of a proof, so we just benchmark the cost of one binding +// signature and then use its cost. We don't discount by the numebr of cores +// because there might be the need for a call to the fallback single +// verification.. For proofs: benchmarks both one and two proofs and take the +// difference as the variable cost for every proofs/sigs. Compute the cost of +// the non parallel parts (with the diff) and charge that if at least one note +// is present, then charge the variable cost multiplied by the number of notes +// and divided by the number of cores +fn masp_batch_validate(c: &mut Criterion) { + let mut group = c.benchmark_group("masp_batch_validate"); + let PVKs { + spend_vk, + convert_vk, + output_vk, + } = preload_verifying_keys(); + + for multi in [true, false] { + for bench in [ + RequestedItem::Signature, + RequestedItem::Spend, + RequestedItem::Convert, + RequestedItem::Output, + ] { + // From the cost of proofs remove the cost of signature(s) + // validation + let (tx_data, transaction) = + if let Some(data) = customize_masp_tx_data(multi, &bench) { + data + } else { + continue; + }; + + // Partially deauthorize the transparent bundle + let unauth_tx_data = + partial_deauthorize(transaction.deref()).unwrap(); + let txid_parts = unauth_tx_data.digest(TxIdDigester); + let sighash = signature_hash( + &unauth_tx_data, + &SignableInput::Shielded, + &txid_parts, + ) + .as_ref() + .to_owned(); + let sapling_bundle = tx_data.sapling_bundle().unwrap(); + + let bench_name = if multi { + format!("{:#?}_multi", bench) + } else { + format!("{:#?}_single", bench) + }; + group.bench_function(bench_name, |b| { + b.iter_batched( + || { + let mut ctx = BatchValidator::new(); + // Check bundle first + if !ctx.check_bundle(sapling_bundle.to_owned(), sighash) + { + panic!("Failed check bundle"); + } + + ctx + }, + |ctx| { + assert!(ctx + .validate(spend_vk, convert_vk, output_vk, OsRng)) + }, + BatchSize::SmallInput, + ) + }); + } + } +} + fn pgf(c: &mut Criterion) { let mut group = c.benchmark_group("vp_pgf"); @@ -909,8 +1177,7 @@ fn pgf(c: &mut Criterion) { pgf.ctx.keys_changed, pgf.ctx.verifiers, ) - .is_ok() - ) + .is_ok()) }) }); } @@ -986,8 +1253,7 @@ fn eth_bridge_nut(c: &mut Criterion) { nut.ctx.keys_changed, nut.ctx.verifiers, ) - .is_ok() - ) + .is_ok()) }) }); } @@ -1303,8 +1569,7 @@ fn pos(c: &mut Criterion) { pos.ctx.keys_changed, pos.ctx.verifiers, ) - .is_ok() - ) + .is_ok()) }) }); } @@ -1439,6 +1704,7 @@ criterion_group!( masp_check_convert, masp_check_output, masp_final_check, + masp_batch_validate, vp_multitoken, pgf, eth_bridge_nut, diff --git a/crates/benches/process_wrapper.rs b/crates/benches/process_wrapper.rs index 26ad6d2e74..2d1c1241ba 100644 --- a/crates/benches/process_wrapper.rs +++ b/crates/benches/process_wrapper.rs @@ -56,7 +56,7 @@ fn process_tx(c: &mut Criterion) { let datetime = DateTimeUtc::now(); c.bench_function("wrapper_tx_validation", |b| { - b.iter_batched( + b.iter_batched_ref( || { ( // Prevent block out of gas and replay protection @@ -68,10 +68,10 @@ fn process_tx(c: &mut Criterion) { ) }, |( - mut temp_state, - mut validation_meta, - mut vp_wasm_cache, - mut tx_wasm_cache, + temp_state, + validation_meta, + vp_wasm_cache, + tx_wasm_cache, block_proposer, )| { assert_eq!( @@ -79,12 +79,12 @@ fn process_tx(c: &mut Criterion) { shell .check_proposal_tx( &wrapper, - &mut validation_meta, - &mut temp_state, + validation_meta, + temp_state, datetime, - &mut vp_wasm_cache, - &mut tx_wasm_cache, - &block_proposer + vp_wasm_cache, + tx_wasm_cache, + block_proposer ) .code, 0 From 87472f07d65a253e46056750a9d29387b60ed5a4 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Wed, 15 May 2024 11:58:10 +0200 Subject: [PATCH 27/70] Updates masp dep. Patch reddsa dep --- Cargo.lock | 158 +++++++++++++++++++++++++++++++++-- Cargo.toml | 10 ++- crates/benches/native_vps.rs | 24 ++++-- wasm/Cargo.lock | 6 +- wasm_for_tests/Cargo.lock | 6 +- 5 files changed, 182 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3b3d63a1ee..aa335fa313 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -310,6 +310,15 @@ dependencies = [ "rustc_version 0.4.0", ] +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "auto_impl" version = "1.1.0" @@ -1023,6 +1032,12 @@ name = "clru" version = "0.5.0" source = "git+https://github.com/marmeladema/clru-rs.git?rev=71ca566#71ca566915f21f3c308091ca7756a91b0f8b5afc" +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + [[package]] name = "coins-bip32" version = "0.8.7" @@ -1143,6 +1158,12 @@ dependencies = [ "windows", ] +[[package]] +name = "const-crc32" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68d13f542d70e5b339bf46f6f74704ac052cfd526c58cd87996bd1ef4615b9a0" + [[package]] name = "const-hex" version = "1.10.0" @@ -1396,6 +1417,12 @@ dependencies = [ "itertools 0.10.5", ] +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + [[package]] name = "crossbeam-channel" version = "0.5.12" @@ -1599,6 +1626,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +[[package]] +name = "debugless-unwrap" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f400d0750c0c069e8493f2256cb4da6f604b6d2eeb69a0ca8863acde352f8400" + [[package]] name = "der" version = "0.7.8" @@ -1635,6 +1668,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-getters" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2c35ab6e03642397cdda1dd58abbc05d418aef8e36297f336d5aba060fe8df" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -1716,6 +1760,15 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "document-features" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +dependencies = [ + "litrs", +] + [[package]] name = "drain_filter_polyfill" version = "0.1.3" @@ -1875,6 +1928,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + [[package]] name = "encoding_rs" version = "0.8.33" @@ -2454,6 +2513,40 @@ dependencies = [ "num-traits 0.2.17", ] +[[package]] +name = "frost-core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45d6280625f1603d160df24b23e4984a6a7286f41455ae606823d0104c32e834" +dependencies = [ + "byteorder", + "const-crc32", + "debugless-unwrap", + "derive-getters", + "document-features", + "hex", + "itertools 0.12.1", + "postcard", + "rand_core 0.6.4", + "serde 1.0.193", + "serdect", + "thiserror", + "visibility", + "zeroize", +] + +[[package]] +name = "frost-rerandomized" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c58f58ea009000db490efd9a3936d0035647a2b00c7ba8f3868c2ed0306b0b" +dependencies = [ + "derive-getters", + "document-features", + "frost-core", + "rand_core 0.6.4", +] + [[package]] name = "fs_extra" version = "1.3.0" @@ -2726,6 +2819,15 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -2793,6 +2895,20 @@ dependencies = [ "http 0.2.11", ] +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version 0.4.0", + "serde 1.0.193", + "spin 0.9.8", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.4.1" @@ -4078,6 +4194,12 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + [[package]] name = "lock_api" version = "0.4.11" @@ -4141,7 +4263,7 @@ dependencies = [ [[package]] name = "masp_note_encryption" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=3689da58610bb65aaa303912750f1fa89f8c4a34#3689da58610bb65aaa303912750f1fa89f8c4a34" dependencies = [ "borsh 1.2.1", "chacha20", @@ -4154,7 +4276,7 @@ dependencies = [ [[package]] name = "masp_primitives" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=3689da58610bb65aaa303912750f1fa89f8c4a34#3689da58610bb65aaa303912750f1fa89f8c4a34" dependencies = [ "aes", "bip0039", @@ -4186,7 +4308,7 @@ dependencies = [ [[package]] name = "masp_proofs" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=3689da58610bb65aaa303912750f1fa89f8c4a34#3689da58610bb65aaa303912750f1fa89f8c4a34" dependencies = [ "bellman", "blake2b_simd", @@ -5980,6 +6102,18 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "embedded-io", + "heapless", + "serde 1.0.193", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -6391,11 +6525,11 @@ dependencies = [ [[package]] name = "reddsa" version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78a5191930e84973293aa5f532b513404460cd2216c1cfb76d08748c15b40b02" +source = "git+https://github.com/heliaxdev/reddsa?rev=46d363b929e1b940688fa0c53d637e304a755185#46d363b929e1b940688fa0c53d637e304a755185" dependencies = [ "blake2b_simd", "byteorder", + "frost-rerandomized", "group", "hex", "jubjub", @@ -7376,6 +7510,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spki" @@ -8566,6 +8703,17 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "visibility" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3fd98999db9227cf28e59d83e1f120f42bc233d4b152e8fab9bc87d5bb1e0f8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "wait-timeout" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index 0d1f58a577..e35094a7f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -124,9 +124,9 @@ ledger-transport-hid = "0.10.0" libc = "0.2.97" libloading = "0.7.2" linkme = "0.3.24" -# branch = "main" -masp_primitives = { git = "https://github.com/anoma/masp", rev = "3aacc707c5948e7423589ac617305448bead9842" } -masp_proofs = { git = "https://github.com/anoma/masp", rev = "3aacc707c5948e7423589ac617305448bead9842", default-features = false, features = ["local-prover"] } +# branch = "murisi/namada-integration" +masp_primitives = { git = "https://github.com/anoma/masp", rev = "3689da58610bb65aaa303912750f1fa89f8c4a34" } +masp_proofs = { git = "https://github.com/anoma/masp", rev = "3689da58610bb65aaa303912750f1fa89f8c4a34", default-features = false, features = ["local-prover"] } num256 = "0.3.5" num_cpus = "1.13.0" num-derive = "0.4" @@ -196,6 +196,10 @@ winapi = "0.3.9" yansi = "0.5.1" zeroize = { version = "1.5.5", features = ["zeroize_derive"] } +[patch.crates-io] +# Patch to the fork containing the correct personalization and basepoints for masp +reddsa = { git = "https://github.com/heliaxdev/reddsa", rev = "46d363b929e1b940688fa0c53d637e304a755185" } + [profile.release] lto = true opt-level = 3 diff --git a/crates/benches/native_vps.rs b/crates/benches/native_vps.rs index 965a3dfe65..28dae6a57c 100644 --- a/crates/benches/native_vps.rs +++ b/crates/benches/native_vps.rs @@ -457,7 +457,8 @@ fn ibc(c: &mut Criterion) { ibc.ctx.keys_changed, ibc.ctx.verifiers, ) - .is_ok()) + .is_ok() + ) }) }); } @@ -634,7 +635,8 @@ fn masp(c: &mut Criterion) { masp.ctx.keys_changed, masp.ctx.verifiers, ) - .is_ok()); + .is_ok() + ); }) }); } @@ -918,7 +920,7 @@ fn customize_masp_tx_data( TransactionData, Transaction, )> { - let (_, tx) = setup_storage_for_masp_verification("unshielding"); + let (_, _, tx) = setup_storage_for_masp_verification("unshielding"); let transaction = tx .sections .into_iter() @@ -1087,8 +1089,11 @@ fn masp_batch_validate(c: &mut Criterion) { ctx }, |ctx| { - assert!(ctx - .validate(spend_vk, convert_vk, output_vk, OsRng)) + assert!( + ctx.validate( + spend_vk, convert_vk, output_vk, OsRng + ) + ) }, BatchSize::SmallInput, ) @@ -1177,7 +1182,8 @@ fn pgf(c: &mut Criterion) { pgf.ctx.keys_changed, pgf.ctx.verifiers, ) - .is_ok()) + .is_ok() + ) }) }); } @@ -1253,7 +1259,8 @@ fn eth_bridge_nut(c: &mut Criterion) { nut.ctx.keys_changed, nut.ctx.verifiers, ) - .is_ok()) + .is_ok() + ) }) }); } @@ -1569,7 +1576,8 @@ fn pos(c: &mut Criterion) { pos.ctx.keys_changed, pos.ctx.verifiers, ) - .is_ok()) + .is_ok() + ) }) }); } diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 2a00208e8a..4a07422fff 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -3384,7 +3384,7 @@ dependencies = [ [[package]] name = "masp_note_encryption" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=3689da58610bb65aaa303912750f1fa89f8c4a34#3689da58610bb65aaa303912750f1fa89f8c4a34" dependencies = [ "borsh 1.4.0", "chacha20", @@ -3397,7 +3397,7 @@ dependencies = [ [[package]] name = "masp_primitives" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=3689da58610bb65aaa303912750f1fa89f8c4a34#3689da58610bb65aaa303912750f1fa89f8c4a34" dependencies = [ "aes", "bip0039", @@ -3429,7 +3429,7 @@ dependencies = [ [[package]] name = "masp_proofs" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=3689da58610bb65aaa303912750f1fa89f8c4a34#3689da58610bb65aaa303912750f1fa89f8c4a34" dependencies = [ "bellman", "blake2b_simd", diff --git a/wasm_for_tests/Cargo.lock b/wasm_for_tests/Cargo.lock index 59aa30e730..5afaaed8f5 100644 --- a/wasm_for_tests/Cargo.lock +++ b/wasm_for_tests/Cargo.lock @@ -3364,7 +3364,7 @@ dependencies = [ [[package]] name = "masp_note_encryption" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=3689da58610bb65aaa303912750f1fa89f8c4a34#3689da58610bb65aaa303912750f1fa89f8c4a34" dependencies = [ "borsh 1.2.1", "chacha20", @@ -3377,7 +3377,7 @@ dependencies = [ [[package]] name = "masp_primitives" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=3689da58610bb65aaa303912750f1fa89f8c4a34#3689da58610bb65aaa303912750f1fa89f8c4a34" dependencies = [ "aes", "bip0039", @@ -3409,7 +3409,7 @@ dependencies = [ [[package]] name = "masp_proofs" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=3689da58610bb65aaa303912750f1fa89f8c4a34#3689da58610bb65aaa303912750f1fa89f8c4a34" dependencies = [ "bellman", "blake2b_simd", From ee2fd4600a88160608cc7e9fbfc8fe1de6f69bce Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Thu, 16 May 2024 17:08:19 +0200 Subject: [PATCH 28/70] Fixes masp benchmarks --- crates/benches/Cargo.toml | 26 +-- crates/benches/native_vps.rs | 324 +++++++++++++++++++++-------------- 2 files changed, 210 insertions(+), 140 deletions(-) diff --git a/crates/benches/Cargo.toml b/crates/benches/Cargo.toml index 01d25fa777..74bf5960e0 100644 --- a/crates/benches/Cargo.toml +++ b/crates/benches/Cargo.toml @@ -17,20 +17,20 @@ name = "native_vps" harness = false path = "native_vps.rs" -[[bench]] -name = "process_wrapper" -harness = false -path = "process_wrapper.rs" +# [[bench]] +# name = "process_wrapper" +# harness = false +# path = "process_wrapper.rs" -[[bench]] -name = "host_env" -harness = false -path = "host_env.rs" +# [[bench]] +# name = "host_env" +# harness = false +# path = "host_env.rs" -[[bench]] -name = "wasm_opcodes" -harness = false -path = "wasm_opcodes.rs" +# [[bench]] +# name = "wasm_opcodes" +# harness = false +# path = "wasm_opcodes.rs" [features] namada-eth-bridge = [ @@ -46,7 +46,7 @@ namada = { path = "../namada", features = ["rand", "benches"] } namada_apps_lib = { path = "../apps_lib" } namada_node = { path = "../node", features = ["benches"] } masp_primitives.workspace = true -masp_proofs = { workspace = true, features = ["multicore"] } +masp_proofs = { workspace = true, features = ["benchmarks"] } borsh.workspace = true borsh-ext.workspace = true criterion = { version = "0.5", features = ["html_reports"] } diff --git a/crates/benches/native_vps.rs b/crates/benches/native_vps.rs index 28dae6a57c..5f2b4455e4 100644 --- a/crates/benches/native_vps.rs +++ b/crates/benches/native_vps.rs @@ -904,24 +904,23 @@ fn masp_final_check(c: &mut Criterion) { } #[derive(Debug)] -enum RequestedItem { - Signature, +enum BenchNote { Spend, Convert, Output, } -// Removes the unneeded notes from the generated transaction and replicates the -// remaining ones if needed +// Tweaks the transaction to match the desired benchmark fn customize_masp_tx_data( multi: bool, - request: &RequestedItem, -) -> Option<( + request: &BenchNote, +) -> ( TransactionData, Transaction, -)> { +) { let (_, _, tx) = setup_storage_for_masp_verification("unshielding"); let transaction = tx + .tx .sections .into_iter() .filter_map(|section| match section { @@ -935,84 +934,47 @@ fn customize_masp_tx_data( let mut sapling_bundle = transaction.sapling_bundle().unwrap().to_owned(); match request { - RequestedItem::Signature => { + BenchNote::Spend => { if multi { - // No multisig benchmark - return None; - } - // ensure we only have one signature to verify (the binding one) and - // no proofs - sapling_bundle.shielded_spends.clear(); - sapling_bundle.shielded_converts.clear(); - sapling_bundle.shielded_outputs.clear(); - assert_eq!(sapling_bundle.shielded_spends.len(), 0); - assert_eq!(sapling_bundle.shielded_converts.len(), 0); - assert_eq!(sapling_bundle.shielded_outputs.len(), 0); - } - RequestedItem::Spend => { - if multi { - // ensure we only have two spend proofs + // ensure we have two spend proofs sapling_bundle.shielded_spends = [ sapling_bundle.shielded_spends.clone(), sapling_bundle.shielded_spends, ] .concat(); - sapling_bundle.shielded_outputs.clear(); - sapling_bundle.shielded_converts.clear(); assert_eq!(sapling_bundle.shielded_spends.len(), 2); } else { - // ensure we only have one spend proof - sapling_bundle.shielded_outputs.clear(); - sapling_bundle.shielded_converts.clear(); + // ensure we have one spend proof assert_eq!(sapling_bundle.shielded_spends.len(), 1); } - assert_eq!(sapling_bundle.shielded_converts.len(), 0); - assert_eq!(sapling_bundle.shielded_outputs.len(), 0); } - RequestedItem::Convert => { + BenchNote::Convert => { if multi { - // ensure we only have two convert proofs + // ensure we have two convert proofs sapling_bundle.shielded_converts = [ sapling_bundle.shielded_converts.clone(), sapling_bundle.shielded_converts, ] .concat(); - sapling_bundle.shielded_spends.clear(); - sapling_bundle.shielded_outputs.clear(); assert_eq!(sapling_bundle.shielded_converts.len(), 2); } else { - // ensure we only have one convert proof - sapling_bundle.shielded_spends.clear(); - sapling_bundle.shielded_outputs.clear(); + // ensure we have one convert proof assert_eq!(sapling_bundle.shielded_converts.len(), 1); } - assert_eq!(sapling_bundle.shielded_spends.len(), 0); - assert_eq!(sapling_bundle.shielded_outputs.len(), 0); } - RequestedItem::Output => { - // From the cost remove the cost of signature(s) validation + BenchNote::Output => { if multi { - // ensure we only have two output proofs - sapling_bundle.shielded_outputs = [ - sapling_bundle.shielded_outputs.clone(), - sapling_bundle.shielded_outputs, - ] - .concat(); - sapling_bundle.shielded_spends.clear(); - sapling_bundle.shielded_converts.clear(); + // ensure we have two output proofs assert_eq!(sapling_bundle.shielded_outputs.len(), 2); } else { - // ensure we only have one output proof - sapling_bundle.shielded_spends.clear(); - sapling_bundle.shielded_converts.clear(); + // ensure we have one output proof + sapling_bundle.shielded_outputs.truncate(1); assert_eq!(sapling_bundle.shielded_outputs.len(), 1); } - assert_eq!(sapling_bundle.shielded_spends.len(), 0); - assert_eq!(sapling_bundle.shielded_converts.len(), 0); } }; - Some(( + ( TransactionData::from_parts( transaction.version(), transaction.consensus_branch_id(), @@ -1022,84 +984,189 @@ fn customize_masp_tx_data( Some(sapling_bundle), ), transaction, - )) + ) } -// For signatures: it's impossible to benchmark more than one signature without -// pulling in the cost of a proof, so we just benchmark the cost of one binding -// signature and then use its cost. We don't discount by the numebr of cores -// because there might be the need for a call to the fallback single -// verification.. For proofs: benchmarks both one and two proofs and take the -// difference as the variable cost for every proofs/sigs. Compute the cost of -// the non parallel parts (with the diff) and charge that if at least one note -// is present, then charge the variable cost multiplied by the number of notes -// and divided by the number of cores -fn masp_batch_validate(c: &mut Criterion) { - let mut group = c.benchmark_group("masp_batch_validate"); - let PVKs { - spend_vk, - convert_vk, - output_vk, - } = preload_verifying_keys(); - - for multi in [true, false] { - for bench in [ - RequestedItem::Signature, - RequestedItem::Spend, - RequestedItem::Convert, - RequestedItem::Output, - ] { - // From the cost of proofs remove the cost of signature(s) - // validation - let (tx_data, transaction) = - if let Some(data) = customize_masp_tx_data(multi, &bench) { - data - } else { - continue; - }; +// benchmark the cost of validating two signatures in a batch. +fn masp_batch_signature_verification(c: &mut Criterion) { + let (_, _, tx) = setup_storage_for_masp_verification("unshielding"); + let transaction = tx + .tx + .sections + .into_iter() + .filter_map(|section| match section { + Section::MaspTx(transaction) => Some(transaction), + _ => None, + }) + .collect::>() + .first() + .unwrap() + .to_owned(); + let sapling_bundle = transaction.sapling_bundle().unwrap(); + // ensure we have two signatures to verify (the binding and one spending) + assert_eq!(sapling_bundle.shielded_spends.len(), 1); - // Partially deauthorize the transparent bundle - let unauth_tx_data = - partial_deauthorize(transaction.deref()).unwrap(); - let txid_parts = unauth_tx_data.digest(TxIdDigester); - let sighash = signature_hash( - &unauth_tx_data, - &SignableInput::Shielded, - &txid_parts, - ) + // Partially deauthorize the transparent bundle + let unauth_tx_data = partial_deauthorize(transaction.deref()).unwrap(); + let txid_parts = unauth_tx_data.digest(TxIdDigester); + let sighash = + signature_hash(&unauth_tx_data, &SignableInput::Shielded, &txid_parts) .as_ref() .to_owned(); - let sapling_bundle = tx_data.sapling_bundle().unwrap(); - let bench_name = if multi { - format!("{:#?}_multi", bench) - } else { - format!("{:#?}_single", bench) - }; - group.bench_function(bench_name, |b| { - b.iter_batched( - || { - let mut ctx = BatchValidator::new(); - // Check bundle first - if !ctx.check_bundle(sapling_bundle.to_owned(), sighash) - { - panic!("Failed check bundle"); - } - - ctx - }, - |ctx| { - assert!( - ctx.validate( - spend_vk, convert_vk, output_vk, OsRng - ) - ) - }, - BatchSize::SmallInput, - ) - }); - } + c.bench_function("masp_batch_signature_verification", |b| { + b.iter_batched( + || { + let mut ctx = BatchValidator::new(); + // Check bundle first + if !ctx.check_bundle(sapling_bundle.to_owned(), sighash) { + panic!("Failed check bundle"); + } + + ctx + }, + |ctx| assert!(ctx.verify_signatures(OsRng).is_ok()), + BatchSize::SmallInput, + ) + }); +} + +// Benchmark both one and two proofs and take the difference as the variable +// cost for every proofs. Charge the full cost for the first note and then +// charge the variable cost multiplied by the number of remaining notes and +// divided by the number of cores +fn masp_batch_spend_proofs_validate(c: &mut Criterion) { + let mut group = c.benchmark_group("masp_batch_spend_proofs_validate"); + let PVKs { spend_vk, .. } = preload_verifying_keys(); + + for double in [true, false] { + let (tx_data, transaction) = + customize_masp_tx_data(double, &BenchNote::Spend); + + // Partially deauthorize the transparent bundle + let unauth_tx_data = partial_deauthorize(transaction.deref()).unwrap(); + let txid_parts = unauth_tx_data.digest(TxIdDigester); + // Compute the sighash from the original, unmodified transaction + let sighash = signature_hash( + &unauth_tx_data, + &SignableInput::Shielded, + &txid_parts, + ) + .as_ref() + .to_owned(); + let sapling_bundle = tx_data.sapling_bundle().unwrap(); + + let bench_name = if double { "double" } else { "single" }; + group.bench_function(bench_name, |b| { + b.iter_batched( + || { + let mut ctx = BatchValidator::new(); + // Check bundle first + if !ctx.check_bundle(sapling_bundle.to_owned(), sighash) { + panic!("Failed check bundle"); + } + + ctx + }, + |ctx| assert!(ctx.verify_spend_proofs(spend_vk).is_ok()), + BatchSize::SmallInput, + ) + }); + } + + group.finish(); +} + +// Benchmark both one and two proofs and take the difference as the variable +// cost for every proofs. Charge the full cost for the first note and then +// charge the variable cost multiplied by the number of remaining notes and +// divided by the number of cores +fn masp_batch_convert_proofs_validate(c: &mut Criterion) { + let mut group = c.benchmark_group("masp_batch_convert_proofs_validate"); + let PVKs { convert_vk, .. } = preload_verifying_keys(); + + for double in [true, false] { + let (tx_data, transaction) = + customize_masp_tx_data(double, &BenchNote::Convert); + + // Partially deauthorize the transparent bundle + let unauth_tx_data = partial_deauthorize(transaction.deref()).unwrap(); + let txid_parts = unauth_tx_data.digest(TxIdDigester); + // Compute the sighash from the original, unmodified transaction + let sighash = signature_hash( + &unauth_tx_data, + &SignableInput::Shielded, + &txid_parts, + ) + .as_ref() + .to_owned(); + let sapling_bundle = tx_data.sapling_bundle().unwrap(); + + let bench_name = if double { "double" } else { "single" }; + group.bench_function(bench_name, |b| { + b.iter_batched( + || { + let mut ctx = BatchValidator::new(); + // Check bundle first + if !ctx.check_bundle(sapling_bundle.to_owned(), sighash) { + panic!("Failed check bundle"); + } + + ctx + }, + |ctx| assert!(ctx.verify_convert_proofs(convert_vk).is_ok()), + BatchSize::SmallInput, + ) + }); + } + + group.finish(); +} + +// Benchmark both one and two proofs and take the difference as the variable +// cost for every proofs. Charge the full cost for the first note and then +// charge the variable cost multiplied by the number of remaining notes and +// divided by the number of cores +fn masp_batch_output_proofs_validate(c: &mut Criterion) { + let mut group = c.benchmark_group("masp_batch_output_proofs_validate"); + let PVKs { output_vk, .. } = preload_verifying_keys(); + + for double in [true, false] { + let (tx_data, transaction) = + customize_masp_tx_data(double, &BenchNote::Output); + + // Partially deauthorize the transparent bundle + let unauth_tx_data = partial_deauthorize(transaction.deref()).unwrap(); + let txid_parts = unauth_tx_data.digest(TxIdDigester); + // Compute the sighash from the original, unmodified transaction + let sighash = signature_hash( + &unauth_tx_data, + &SignableInput::Shielded, + &txid_parts, + ) + .as_ref() + .to_owned(); + let sapling_bundle = tx_data.sapling_bundle().unwrap(); + + let bench_name = if double { "double" } else { "single" }; + group.bench_function(bench_name, |b| { + b.iter_batched( + || { + let mut ctx = BatchValidator::new(); + // Check bundle first + if !ctx.check_bundle(sapling_bundle.to_owned(), sighash) { + panic!("Failed check bundle"); + } + + ctx + }, + |ctx| assert!(ctx.verify_output_proofs(output_vk).is_ok()), + BatchSize::SmallInput, + ) + }); } + + group.finish(); } fn pgf(c: &mut Criterion) { @@ -1712,7 +1779,10 @@ criterion_group!( masp_check_convert, masp_check_output, masp_final_check, - masp_batch_validate, + masp_batch_signature_verification, + masp_batch_spend_proofs_validate, + masp_batch_convert_proofs_validate, + masp_batch_output_proofs_validate, vp_multitoken, pgf, eth_bridge_nut, From c2849f883e4fa3a7956436250e5b5fd85abd57e9 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Thu, 16 May 2024 19:11:18 +0200 Subject: [PATCH 29/70] Reworks gas metering for masp validation --- crates/sdk/src/masp.rs | 151 ++++++++++++++--------------------------- 1 file changed, 52 insertions(+), 99 deletions(-) diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index caa9a19d5a..b2934f341e 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -30,6 +30,9 @@ use masp_primitives::transaction::builder::{self, *}; use masp_primitives::transaction::components::sapling::builder::{ RngBuildParams, SaplingMetadata, }; +use masp_primitives::transaction::components::sapling::{ + Authorized as SaplingAuthorized, Bundle as SaplingBundle, +}; use masp_primitives::transaction::components::transparent::builder::TransparentBuilder; use masp_primitives::transaction::components::{ I128Sum, OutputDescription, TxOut, U64Sum, ValueSum, @@ -70,6 +73,7 @@ use rand::rngs::StdRng; use rand_core::{CryptoRng, OsRng, RngCore, SeedableRng}; use ripemd::Digest as RipemdDigest; use sha2::Digest; +use smooth_operator::checked; use thiserror::Error; use crate::error::{Error, QueryError}; @@ -288,15 +292,7 @@ where let mut ctx = testing::MockBatchValidator::default(); // Charge gas before check bundle - let spends_len = sapling_bundle.shielded_spends.len() as u64; - let converts_len = sapling_bundle.shielded_converts.len() as u64; - let outputs_len = sapling_bundle.shielded_outputs.len() as u64; - charge_masp_check_bundle_gas( - spends_len, - converts_len, - outputs_len, - &consume_verify_gas, - )?; + charge_masp_check_bundle_gas(sapling_bundle, &consume_verify_gas)?; if !ctx.check_bundle(sapling_bundle.to_owned(), sighash.as_ref().to_owned()) { @@ -306,12 +302,7 @@ where tracing::debug!("passed check bundle"); // Charge gas before final validation - charge_masp_validate_gas( - spends_len, - converts_len, - outputs_len, - consume_verify_gas, - )?; + charge_masp_validate_gas(sapling_bundle, consume_verify_gas)?; if !ctx.validate(spend_vk, convert_vk, output_vk, OsRng) { return Err(StorageError::SimpleMessage( "Invalid proofs or signatures", @@ -322,113 +313,75 @@ where // Charge gas for the check_bundle operation which does not leverage concurrency fn charge_masp_check_bundle_gas( - spends_len: u64, - converts_len: u64, - outputs_len: u64, + sapling_bundle: &SaplingBundle, consume_verify_gas: F, ) -> Result<(), namada_state::StorageError> where F: Fn(u64) -> std::result::Result<(), namada_state::StorageError>, { - consume_verify_gas( - spends_len - .checked_mul(namada_gas::MASP_SPEND_CHECK_GAS) - .ok_or(namada_state::StorageError::SimpleMessage( - "Overflow in gas calculation", - ))?, - )?; - - consume_verify_gas( - converts_len - .checked_mul(namada_gas::MASP_CONVERT_CHECK_GAS) - .ok_or(namada_state::StorageError::SimpleMessage( - "Overflow in gas calculation", - ))?, - )?; - - consume_verify_gas( - outputs_len - .checked_mul(namada_gas::MASP_OUTPUT_CHECK_GAS) - .ok_or(namada_state::StorageError::SimpleMessage( - "Overflow in gas calculation", - ))?, - )?; - - Ok(()) + consume_verify_gas(checked!( + (sapling_bundle.shielded_spends.len() as u64) + * namada_gas::MASP_SPEND_CHECK_GAS + )?)?; + + consume_verify_gas(checked!( + (sapling_bundle.shielded_converts.len() as u64) + * namada_gas::MASP_CONVERT_CHECK_GAS + )?)?; + + consume_verify_gas(checked!( + (sapling_bundle.shielded_outputs.len() as u64) + * namada_gas::MASP_OUTPUT_CHECK_GAS + )?) } // Charge gas for the final validation, taking advtange of concurrency for -// proofs verification but not for signature (because of the fallback) +// proofs verification but not for signatures fn charge_masp_validate_gas( - spends_len: u64, - converts_len: u64, - outputs_len: u64, + sapling_bundle: &SaplingBundle, consume_verify_gas: F, ) -> Result<(), namada_state::StorageError> where F: Fn(u64) -> std::result::Result<(), namada_state::StorageError>, { - // Signatures pay the entire cost (no discount because of the possible - // fallback) - consume_verify_gas( - spends_len - // Add one for the binding signature - .checked_add(1) - .ok_or(namada_state::StorageError::SimpleMessage( - "Overflow in gas calculation", - ))? - .checked_mul(namada_gas::MASP_VERIFY_SIG_GAS) - .ok_or(namada_state::StorageError::SimpleMessage( - "Overflow in gas calculation", - ))?, - )?; + // Signatures gas + consume_verify_gas(checked!( + // Add one for the binding signature + ((sapling_bundle.shielded_spends.len() as u64) + 1) + * namada_gas::MASP_VERIFY_SIG_GAS + )?)?; // If at least one note is present charge the fixed costs. Then charge the - // variable cost for every note, amortized on the fixed expected number of - // cores - if spends_len != 0 { + // variable cost for every other note, amortized on the fixed expected + // number of cores + if let Some(remaining_notes) = + sapling_bundle.shielded_spends.len().checked_sub(1) + { consume_verify_gas(namada_gas::MASP_FIXED_SPEND_GAS)?; - consume_verify_gas( - namada_gas::MASP_VARIABLE_SPEND_GAS - .checked_mul(spends_len) - .ok_or(namada_state::StorageError::SimpleMessage( - "Overflow in gas calculation", - ))? - .checked_div(namada_gas::MASP_PARALLEL_GAS_DIVIDER) - .ok_or(namada_state::StorageError::SimpleMessage( - "Overflow in gas calculation", - ))?, - )?; + consume_verify_gas(checked!( + namada_gas::MASP_VARIABLE_SPEND_GAS * remaining_notes as u64 + / namada_gas::MASP_PARALLEL_GAS_DIVIDER + )?)?; } - if converts_len != 0 { + if let Some(remaining_notes) = + sapling_bundle.shielded_converts.len().checked_sub(1) + { consume_verify_gas(namada_gas::MASP_FIXED_CONVERT_GAS)?; - consume_verify_gas( - namada_gas::MASP_VARIABLE_CONVERT_GAS - .checked_mul(converts_len) - .ok_or(namada_state::StorageError::SimpleMessage( - "Overflow in gas calculation", - ))? - .checked_div(namada_gas::MASP_PARALLEL_GAS_DIVIDER) - .ok_or(namada_state::StorageError::SimpleMessage( - "Overflow in gas calculation", - ))?, - )?; + consume_verify_gas(checked!( + namada_gas::MASP_VARIABLE_CONVERT_GAS * remaining_notes as u64 + / namada_gas::MASP_PARALLEL_GAS_DIVIDER + )?)?; } - if outputs_len != 0 { + if let Some(remaining_notes) = + sapling_bundle.shielded_outputs.len().checked_sub(1) + { consume_verify_gas(namada_gas::MASP_FIXED_OUTPUT_GAS)?; - consume_verify_gas( - namada_gas::MASP_VARIABLE_OUTPUT_GAS - .checked_mul(outputs_len) - .ok_or(namada_state::StorageError::SimpleMessage( - "Overflow in gas calculation", - ))? - .checked_div(namada_gas::MASP_PARALLEL_GAS_DIVIDER) - .ok_or(namada_state::StorageError::SimpleMessage( - "Overflow in gas calculation", - ))?, - )?; + consume_verify_gas(checked!( + namada_gas::MASP_VARIABLE_OUTPUT_GAS * remaining_notes as u64 + / namada_gas::MASP_PARALLEL_GAS_DIVIDER + )?)?; } Ok(()) From b8b25f2461c7953c071adf21c6122d05aac6d939 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Fri, 17 May 2024 19:25:40 +0200 Subject: [PATCH 30/70] Updates masp gas costs --- crates/gas/src/lib.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/crates/gas/src/lib.rs b/crates/gas/src/lib.rs index 88c73b7d8d..89e24209ff 100644 --- a/crates/gas/src/lib.rs +++ b/crates/gas/src/lib.rs @@ -84,29 +84,28 @@ pub const WASM_MEMORY_PAGE_GAS: u32 = pub const IBC_ACTION_VALIDATE_GAS: u64 = 1_472_023; /// The cost to execute an Ibc action pub const IBC_ACTION_EXECUTE_GAS: u64 = 3_678_745; -// FIXME: update costs /// The cost of masp sig verification -pub const MASP_VERIFY_SIG_GAS: u64 = 1; +pub const MASP_VERIFY_SIG_GAS: u64 = 5_443_000; /// The fixed cost of spend note verification -pub const MASP_FIXED_SPEND_GAS: u64 = 1; +pub const MASP_FIXED_SPEND_GAS: u64 = 87_866_000; /// The variable cost of spend note verification -pub const MASP_VARIABLE_SPEND_GAS: u64 = 1; +pub const MASP_VARIABLE_SPEND_GAS: u64 = 14_384_000; /// The fixed cost of convert note verification -pub const MASP_FIXED_CONVERT_GAS: u64 = 1; +pub const MASP_FIXED_CONVERT_GAS: u64 = 70_308_000; /// The variable cost of convert note verification -pub const MASP_VARIABLE_CONVERT_GAS: u64 = 1; +pub const MASP_VARIABLE_CONVERT_GAS: u64 = 12_664_000; /// The fixed cost of output note verification -pub const MASP_FIXED_OUTPUT_GAS: u64 = 1; +pub const MASP_FIXED_OUTPUT_GAS: u64 = 78_203_000; /// The variable cost of output note verification -pub const MASP_VARIABLE_OUTPUT_GAS: u64 = 1; +pub const MASP_VARIABLE_OUTPUT_GAS: u64 = 14_586_000; /// The cost to process a masp spend note in the bundle -pub const MASP_SPEND_CHECK_GAS: u64 = 1; +pub const MASP_SPEND_CHECK_GAS: u64 = 479_730; /// The cost to process a masp convert note in the bundle -pub const MASP_CONVERT_CHECK_GAS: u64 = 1; +pub const MASP_CONVERT_CHECK_GAS: u64 = 173_570; /// The cost to process a masp output note in the bundle -pub const MASP_OUTPUT_CHECK_GAS: u64 = 1; +pub const MASP_OUTPUT_CHECK_GAS: u64 = 310_260; /// The cost to run the final masp check in the bundle -pub const MASP_FINAL_CHECK_GAS: u64 = 1; +pub const MASP_FINAL_CHECK_GAS: u64 = 44; /// Gas divider specific for the masp vp. Only allocates half of the cores to /// the masp vp since we can expect the other half to be busy with other vps pub const MASP_PARALLEL_GAS_DIVIDER: u64 = PARALLEL_GAS_DIVIDER / 2; From 15affec2d5e8f14ec420a1cfd9891868369ab710 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Wed, 22 May 2024 14:50:01 +0200 Subject: [PATCH 31/70] Changelog #2972 --- .../unreleased/improvements/2972-masp-parallel-verification.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/2972-masp-parallel-verification.md diff --git a/.changelog/unreleased/improvements/2972-masp-parallel-verification.md b/.changelog/unreleased/improvements/2972-masp-parallel-verification.md new file mode 100644 index 0000000000..4aa10651bb --- /dev/null +++ b/.changelog/unreleased/improvements/2972-masp-parallel-verification.md @@ -0,0 +1,2 @@ +- Improved masp vp verification to run in parallel. + ([\#2972](https://github.com/anoma/namada/pull/2972)) \ No newline at end of file From 915127ad4405f04235487c46b80f541229847974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Fri, 24 May 2024 10:03:49 +0200 Subject: [PATCH 32/70] changelog: add #3305 --- .changelog/unreleased/improvements/3305-update-config-rs.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/unreleased/improvements/3305-update-config-rs.md diff --git a/.changelog/unreleased/improvements/3305-update-config-rs.md b/.changelog/unreleased/improvements/3305-update-config-rs.md new file mode 100644 index 0000000000..f5eaa5dd32 --- /dev/null +++ b/.changelog/unreleased/improvements/3305-update-config-rs.md @@ -0,0 +1,3 @@ +- Replaced unmaintained config-rs to an unreleased version + that replaces its also unmaintained yaml dependency. + ([\#3305](https://github.com/anoma/namada/pull/3305)) \ No newline at end of file From d063ac19f4b469eff5b9ed4aba7c1d30b6318993 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Fri, 24 May 2024 10:09:33 +0200 Subject: [PATCH 33/70] Fmt --- crates/node/src/shell/finalize_block.rs | 430 ++++++++++++++---------- 1 file changed, 253 insertions(+), 177 deletions(-) diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 215ed23420..ee65f3b057 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -1351,11 +1351,7 @@ mod test_finalize_block { .enumerate() .find_map( |(idx, tx_hash)| { - if tx_hash == &hash { - Some(idx) - } else { - None - } + if tx_hash == &hash { Some(idx) } else { None } }, ) .unwrap(); @@ -2949,21 +2945,25 @@ mod test_finalize_block { assert_eq!(root_pre.0, root_post.0); // Check transaction's hash in storage - assert!(shell - .shell - .state - .write_log() - .has_replay_protection_entry(&wrapper_tx.raw_header_hash())); + assert!( + shell + .shell + .state + .write_log() + .has_replay_protection_entry(&wrapper_tx.raw_header_hash()) + ); // Check that the hash is not present in the merkle tree shell.state.commit_block().unwrap(); - assert!(!shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&wrapper_hash_key) - .unwrap()); + assert!( + !shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&wrapper_hash_key) + .unwrap() + ); // test that a commitment to replay protection gets added. let reprot_key = replay_protection::commitment_key(); @@ -3010,22 +3010,26 @@ mod test_finalize_block { assert_eq!(root_pre.0, root_post.0); // Check that the hashes are present in the merkle tree shell.state.commit_block().unwrap(); - assert!(shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&convert_key) - .unwrap()); - assert!(shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&commitment_key) - .unwrap()); + assert!( + shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&convert_key) + .unwrap() + ); + assert!( + shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&commitment_key) + .unwrap() + ); } /// Test that a tx that has already been applied in the same block @@ -3103,26 +3107,34 @@ mod test_finalize_block { assert_eq!(code, ResultCode::WasmRuntimeError); for wrapper in [&wrapper, &new_wrapper] { - assert!(shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.raw_header_hash())); - assert!(!shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.header_hash())); + assert!( + shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.raw_header_hash()) + ); + assert!( + !shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.header_hash()) + ); } // Commit to check the hashes from storage shell.commit(); for wrapper in [&wrapper, &new_wrapper] { - assert!(shell - .state - .has_replay_protection_entry(&wrapper.raw_header_hash()) - .unwrap()); - assert!(!shell - .state - .has_replay_protection_entry(&wrapper.header_hash()) - .unwrap()); + assert!( + shell + .state + .has_replay_protection_entry(&wrapper.raw_header_hash()) + .unwrap() + ); + assert!( + !shell + .state + .has_replay_protection_entry(&wrapper.header_hash()) + .unwrap() + ); } } @@ -3405,23 +3417,29 @@ mod test_finalize_block { &unsigned_wrapper, &wrong_commitment_wrapper, ] { - assert!(!shell - .state - .write_log() - .has_replay_protection_entry(&valid_wrapper.raw_header_hash())); - assert!(shell + assert!( + !shell.state.write_log().has_replay_protection_entry( + &valid_wrapper.raw_header_hash() + ) + ); + assert!( + shell + .state + .write_log() + .has_replay_protection_entry(&valid_wrapper.header_hash()) + ); + } + assert!( + shell.state.write_log().has_replay_protection_entry( + &failing_wrapper.raw_header_hash() + ) + ); + assert!( + !shell .state .write_log() - .has_replay_protection_entry(&valid_wrapper.header_hash())); - } - assert!(shell - .state - .write_log() - .has_replay_protection_entry(&failing_wrapper.raw_header_hash())); - assert!(!shell - .state - .write_log() - .has_replay_protection_entry(&failing_wrapper.header_hash())); + .has_replay_protection_entry(&failing_wrapper.header_hash()) + ); // Commit to check the hashes from storage shell.commit(); @@ -3430,23 +3448,33 @@ mod test_finalize_block { unsigned_wrapper, wrong_commitment_wrapper, ] { - assert!(!shell + assert!( + !shell + .state + .has_replay_protection_entry( + &valid_wrapper.raw_header_hash() + ) + .unwrap() + ); + assert!( + shell + .state + .has_replay_protection_entry(&valid_wrapper.header_hash()) + .unwrap() + ); + } + assert!( + shell .state - .has_replay_protection_entry(&valid_wrapper.raw_header_hash()) - .unwrap()); - assert!(shell + .has_replay_protection_entry(&failing_wrapper.raw_header_hash()) + .unwrap() + ); + assert!( + !shell .state - .has_replay_protection_entry(&valid_wrapper.header_hash()) - .unwrap()); - } - assert!(shell - .state - .has_replay_protection_entry(&failing_wrapper.raw_header_hash()) - .unwrap()); - assert!(!shell - .state - .has_replay_protection_entry(&failing_wrapper.header_hash()) - .unwrap()); + .has_replay_protection_entry(&failing_wrapper.header_hash()) + .unwrap() + ); } #[test] @@ -3506,14 +3534,18 @@ mod test_finalize_block { let code = event[0].read_attribute::().expect("Test failed"); assert_eq!(code, ResultCode::InvalidTx); - assert!(shell - .state - .write_log() - .has_replay_protection_entry(&wrapper_hash)); - assert!(!shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.raw_header_hash())); + assert!( + shell + .state + .write_log() + .has_replay_protection_entry(&wrapper_hash) + ); + assert!( + !shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.raw_header_hash()) + ); } // Test that the fees are paid even if the inner transaction fails and its @@ -3911,9 +3943,11 @@ mod test_finalize_block { .unwrap(), Some(ValidatorState::Consensus) ); - assert!(enqueued_slashes_handle() - .at(&Epoch::default()) - .is_empty(&shell.state)?); + assert!( + enqueued_slashes_handle() + .at(&Epoch::default()) + .is_empty(&shell.state)? + ); assert_eq!( get_num_consensus_validators(&shell.state, Epoch::default()) .unwrap(), @@ -3932,17 +3966,21 @@ mod test_finalize_block { .unwrap(), Some(ValidatorState::Jailed) ); - assert!(enqueued_slashes_handle() - .at(&epoch) - .is_empty(&shell.state)?); + assert!( + enqueued_slashes_handle() + .at(&epoch) + .is_empty(&shell.state)? + ); assert_eq!( get_num_consensus_validators(&shell.state, epoch).unwrap(), 5_u64 ); } - assert!(!enqueued_slashes_handle() - .at(&processing_epoch) - .is_empty(&shell.state)?); + assert!( + !enqueued_slashes_handle() + .at(&processing_epoch) + .is_empty(&shell.state)? + ); // Advance to the processing epoch loop { @@ -3965,9 +4003,11 @@ mod test_finalize_block { // println!("Reached processing epoch"); break; } else { - assert!(enqueued_slashes_handle() - .at(&shell.state.in_mem().block.epoch) - .is_empty(&shell.state)?); + assert!( + enqueued_slashes_handle() + .at(&shell.state.in_mem().block.epoch) + .is_empty(&shell.state)? + ); let stake1 = read_validator_stake( &shell.state, ¶ms, @@ -4451,11 +4491,13 @@ mod test_finalize_block { ) .unwrap(); assert_eq!(last_slash, Some(misbehavior_epoch)); - assert!(namada_proof_of_stake::storage::validator_slashes_handle( - &val1.address - ) - .is_empty(&shell.state) - .unwrap()); + assert!( + namada_proof_of_stake::storage::validator_slashes_handle( + &val1.address + ) + .is_empty(&shell.state) + .unwrap() + ); tracing::debug!("Advancing to epoch 7"); @@ -4520,18 +4562,22 @@ mod test_finalize_block { ) .unwrap(); assert_eq!(last_slash, Some(Epoch(4))); - assert!(namada_proof_of_stake::is_validator_frozen( - &shell.state, - &val1.address, - current_epoch, - ¶ms - ) - .unwrap()); - assert!(namada_proof_of_stake::storage::validator_slashes_handle( - &val1.address - ) - .is_empty(&shell.state) - .unwrap()); + assert!( + namada_proof_of_stake::is_validator_frozen( + &shell.state, + &val1.address, + current_epoch, + ¶ms + ) + .unwrap() + ); + assert!( + namada_proof_of_stake::storage::validator_slashes_handle( + &val1.address + ) + .is_empty(&shell.state) + .unwrap() + ); let pre_stake_10 = namada_proof_of_stake::storage::read_validator_stake( @@ -5409,9 +5455,11 @@ mod test_finalize_block { shell.vp_wasm_cache.clone(), ); let parameters = ParametersVp { ctx }; - assert!(parameters - .validate_tx(&batched_tx, &keys_changed, &verifiers) - .is_ok()); + assert!( + parameters + .validate_tx(&batched_tx, &keys_changed, &verifiers) + .is_ok() + ); // we advance forward to the next epoch let mut req = FinalizeBlock::default(); @@ -5484,11 +5532,13 @@ mod test_finalize_block { let inner_results = inner_tx_result.batch_results.0; for cmt in batch.commitments() { - assert!(inner_results - .get(&cmt.get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); + assert!( + inner_results + .get(&cmt.get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); } // Check storage modifications @@ -5526,18 +5576,24 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!(inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); - assert!(inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err()); + assert!( + inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); + assert!( + inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err() + ); // Assert that the last tx didn't run - assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); + assert!( + !inner_results.contains_key(&batch.commitments()[2].get_hash()) + ); // Check storage modifications are missing for key in ["random_key_1", "random_key_2", "random_key_3"] { @@ -5568,21 +5624,27 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!(inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); - assert!(inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err()); - assert!(inner_results - .get(&batch.commitments()[2].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); + assert!( + inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); + assert!( + inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err() + ); + assert!( + inner_results + .get(&batch.commitments()[2].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); // Check storage modifications assert_eq!( @@ -5593,10 +5655,12 @@ mod test_finalize_block { .unwrap(), STORAGE_VALUE ); - assert!(!shell - .state - .has_key(&"random_key_2".parse().unwrap()) - .unwrap()); + assert!( + !shell + .state + .has_key(&"random_key_2".parse().unwrap()) + .unwrap() + ); assert_eq!( shell .state @@ -5628,18 +5692,24 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!(inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); - assert!(inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err()); + assert!( + inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); + assert!( + inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err() + ); // Assert that the last tx didn't run - assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); + assert!( + !inner_results.contains_key(&batch.commitments()[2].get_hash()) + ); // Check storage modifications are missing for key in ["random_key_1", "random_key_2", "random_key_3"] { @@ -5669,18 +5739,24 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!(inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); - assert!(inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err()); + assert!( + inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); + assert!( + inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err() + ); // Assert that the last tx didn't run - assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); + assert!( + !inner_results.contains_key(&batch.commitments()[2].get_hash()) + ); // Check storage modifications assert_eq!( From 8eaa020afabf2ed06c6b12538a42ac1b8553db71 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Mon, 13 May 2024 17:01:42 +0200 Subject: [PATCH 34/70] Adds new masp `Action` --- crates/tx/src/action.rs | 8 ++++++++ wasm/vp_implicit/src/lib.rs | 1 + wasm/vp_user/src/lib.rs | 1 + 3 files changed, 10 insertions(+) diff --git a/crates/tx/src/action.rs b/crates/tx/src/action.rs index c61575305f..2502ca945d 100644 --- a/crates/tx/src/action.rs +++ b/crates/tx/src/action.rs @@ -8,6 +8,7 @@ use std::fmt; use namada_core::address::Address; use namada_core::borsh::{BorshDeserialize, BorshSerialize}; +use namada_core::hash::Hash; use namada_core::storage::KeySeg; use namada_core::{address, storage}; @@ -25,6 +26,7 @@ pub enum Action { Pos(PosAction), Gov(GovAction), Pgf(PgfAction), + Masp(MaspAction), } /// PoS tx actions. @@ -61,6 +63,12 @@ pub enum PgfAction { UpdateStewardCommission(Address), } +/// MASP tx action. +#[derive(Clone, Debug, BorshDeserialize, BorshSerialize)] +pub struct MaspAction { + pub masp_section_ref: Hash, +} + /// Read actions from temporary storage pub trait Read { /// Storage access errors diff --git a/wasm/vp_implicit/src/lib.rs b/wasm/vp_implicit/src/lib.rs index 991e682551..db89216caf 100644 --- a/wasm/vp_implicit/src/lib.rs +++ b/wasm/vp_implicit/src/lib.rs @@ -101,6 +101,7 @@ fn validate_tx( &tx, &addr, )?, + Action::Masp(_) => (), } } diff --git a/wasm/vp_user/src/lib.rs b/wasm/vp_user/src/lib.rs index 1bf41684fb..4071c6fdc5 100644 --- a/wasm/vp_user/src/lib.rs +++ b/wasm/vp_user/src/lib.rs @@ -101,6 +101,7 @@ fn validate_tx( &tx, &addr, )?, + Action::Masp(_) => (), } } From 5cfa7ad2bc91b7d4b4bbc1f738c062cff461c3d9 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Mon, 13 May 2024 17:02:39 +0200 Subject: [PATCH 35/70] Removes masp vp dependency on `Transfer` --- crates/namada/src/ledger/native_vp/masp.rs | 24 ++++++++++++- crates/vp_env/src/lib.rs | 41 +--------------------- 2 files changed, 24 insertions(+), 41 deletions(-) diff --git a/crates/namada/src/ledger/native_vp/masp.rs b/crates/namada/src/ledger/native_vp/masp.rs index edca2b17d0..636aa67aa2 100644 --- a/crates/namada/src/ledger/native_vp/masp.rs +++ b/crates/namada/src/ledger/native_vp/masp.rs @@ -25,6 +25,7 @@ use namada_proof_of_stake::Epoch; use namada_sdk::masp::verify_shielded_tx; use namada_state::{ConversionState, OptionExt, ResultExt, StateRead}; use namada_token::read_denom; +use namada_tx::action::{Action, MaspAction, Read}; use namada_tx::BatchedTxRef; use namada_vp_env::VpEnv; use ripemd::Digest as RipemdDigest; @@ -350,7 +351,28 @@ where ) -> Result<()> { let epoch = self.ctx.get_block_epoch()?; let conversion_state = self.ctx.state.in_mem().get_conversion_state(); - let shielded_tx = self.ctx.get_shielded_action(tx_data)?; + + // Get the Transaction object from the actions + let shielded_tx = self + .ctx + .read_actions()? + .iter() + .find_map(|action| { + // In case of multiple masp actions we only get the first one + if let Action::Masp(MaspAction { + ref masp_section_ref, + }) = action + { + tx_data.get_section(masp_section_ref)?.masp_tx() + } else { + None + } + }) + .ok_or_else(|| { + native_vp::Error::new_const( + "Missing MASP section in transaction", + ) + })?; if u64::from(self.ctx.get_block_height()?) > u64::from(shielded_tx.expiry_height()) diff --git a/crates/vp_env/src/lib.rs b/crates/vp_env/src/lib.rs index a4931c31b7..642d2a7fc9 100644 --- a/crates/vp_env/src/lib.rs +++ b/crates/vp_env/src/lib.rs @@ -20,15 +20,13 @@ pub mod collection_validation; -use masp_primitives::transaction::Transaction; use namada_core::address::Address; use namada_core::borsh::BorshDeserialize; use namada_core::hash::Hash; use namada_core::storage::{BlockHeight, Epoch, Epochs, Header, Key, TxIndex}; use namada_core::token::Transfer; use namada_events::{Event, EventType}; -use namada_ibc::{decode_message, IbcMessage}; -use namada_storage::{OptionExt, StorageRead}; +use namada_storage::StorageRead; use namada_tx::BatchedTxRef; /// Validity predicate's environment is available for native VPs and WASM VPs @@ -122,43 +120,6 @@ where /// Get a tx hash fn get_tx_code_hash(&self) -> Result, namada_storage::Error>; - /// Get the masp tx part of the shielded action - fn get_shielded_action( - &self, - batched_tx: &BatchedTxRef<'_>, - ) -> Result { - let data = batched_tx - .tx - .data(batched_tx.cmt) - .ok_or_err_msg("No transaction data")?; - let transfer = match Transfer::try_from_slice(&data) { - Ok(transfer) => Some(transfer), - Err(_) => { - match decode_message(&data).map_err(|_| { - namada_storage::Error::new_const("Unknown IBC message") - })? { - IbcMessage::Transfer(msg) => msg.transfer, - IbcMessage::NftTransfer(msg) => msg.transfer, - IbcMessage::RecvPacket(msg) => msg.transfer, - IbcMessage::AckPacket(msg) => msg.transfer, - IbcMessage::Timeout(msg) => msg.transfer, - IbcMessage::Envelope(_) => None, - } - } - }; - - let shielded_hash = transfer - .ok_or_err_msg("Missing transfer")? - .shielded - .ok_or_err_msg("unable to find shielded hash")?; - let masp_tx = batched_tx - .tx - .get_section(&shielded_hash) - .and_then(|x| x.as_ref().masp_tx()) - .ok_or_err_msg("unable to find shielded section")?; - Ok(masp_tx) - } - /// Charge the provided gas for the current vp fn charge_gas(&self, used_gas: u64) -> Result<(), namada_storage::Error>; From 7da6dc2f3e9df9558d411b2a4c9cfb1d67c84690 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Mon, 13 May 2024 17:03:18 +0200 Subject: [PATCH 36/70] Updates wasm transaction to push masp action --- crates/namada/src/ledger/native_vp/masp.rs | 2 +- wasm/tx_ibc/src/lib.rs | 39 ++++++++++++---------- wasm/tx_transfer/src/lib.rs | 33 ++++++++---------- 3 files changed, 36 insertions(+), 38 deletions(-) diff --git a/crates/namada/src/ledger/native_vp/masp.rs b/crates/namada/src/ledger/native_vp/masp.rs index 636aa67aa2..19ca2a292a 100644 --- a/crates/namada/src/ledger/native_vp/masp.rs +++ b/crates/namada/src/ledger/native_vp/masp.rs @@ -363,7 +363,7 @@ where ref masp_section_ref, }) = action { - tx_data.get_section(masp_section_ref)?.masp_tx() + tx_data.tx.get_section(masp_section_ref)?.masp_tx() } else { None } diff --git a/wasm/tx_ibc/src/lib.rs b/wasm/tx_ibc/src/lib.rs index 96f07dbe69..f7c27f9eb9 100644 --- a/wasm/tx_ibc/src/lib.rs +++ b/wasm/tx_ibc/src/lib.rs @@ -3,6 +3,7 @@ //! tx_data. This tx uses an IBC message wrapped inside //! `key::ed25519::SignedTxData` as its input as declared in `ibc` crate. +use namada_tx_prelude::action::{Action, MaspAction, Write}; use namada_tx_prelude::*; #[transaction] @@ -12,24 +13,26 @@ fn apply_tx(ctx: &mut Ctx, tx_data: BatchedTx) -> TxResult { ibc::ibc_actions(ctx).execute(&data).into_storage_result()?; if let Some(transfer) = transfer { - let shielded = transfer - .shielded - .as_ref() - .map(|hash| { - tx_data - .tx - .get_section(hash) - .and_then(|x| x.as_ref().masp_tx()) - .ok_or_err_msg("unable to find shielded section") - .map_err(|err| { - ctx.set_commitment_sentinel(); - err - }) - }) - .transpose()?; - if let Some(shielded) = shielded { - token::utils::handle_masp_tx(ctx, &shielded)?; - update_masp_note_commitment_tree(&shielded)?; + if let Some(masp_section_ref) = transfer.shielded { + let shielded = signed + .get_section(&masp_section_ref) + .and_then(|x| x.as_ref().masp_tx()) + .ok_or_err_msg( + "Unable to find required shielded section in tx data", + ) + .map_err(|err| { + ctx.set_commitment_sentinel(); + err + })?; + token::utils::handle_masp_tx( + ctx, + &shielded, + transfer.key.as_deref(), + ) + .wrap_err("Encountered error while handling MASP transaction")?; + update_masp_note_commitment_tree(&shielded) + .wrap_err("Failed to update the MASP commitment tree")?; + ctx.push_action(Action::Masp(MaspAction { masp_section_ref }))?; } } diff --git a/wasm/tx_transfer/src/lib.rs b/wasm/tx_transfer/src/lib.rs index b08b40eba2..871cb836fc 100644 --- a/wasm/tx_transfer/src/lib.rs +++ b/wasm/tx_transfer/src/lib.rs @@ -2,6 +2,7 @@ //! This tx uses `token::Transfer` wrapped inside `SignedTxData` //! as its input as declared in `namada` crate. +use namada_tx_prelude::action::{Action, MaspAction, Write}; use namada_tx_prelude::*; #[transaction] @@ -20,28 +21,22 @@ fn apply_tx(ctx: &mut Ctx, tx_data: BatchedTx) -> TxResult { ) .wrap_err("Token transfer failed")?; - let shielded = transfer - .shielded - .as_ref() - .map(|hash| { - tx_data - .tx - .get_section(hash) - .and_then(|x| x.as_ref().masp_tx()) - .ok_or_err_msg( - "Unable to find required shielded section in tx data", - ) - .map_err(|err| { - ctx.set_commitment_sentinel(); - err - }) - }) - .transpose()?; - if let Some(shielded) = shielded { - token::utils::handle_masp_tx(ctx, &shielded) + if let Some(masp_section_ref) = transfer.shielded { + let shielded = signed + .get_section(&masp_section_ref) + .and_then(|x| x.as_ref().masp_tx()) + .ok_or_err_msg( + "Unable to find required shielded section in tx data", + ) + .map_err(|err| { + ctx.set_commitment_sentinel(); + err + })?; + token::utils::handle_masp_tx(ctx, &shielded, transfer.key.as_deref()) .wrap_err("Encountered error while handling MASP transaction")?; update_masp_note_commitment_tree(&shielded) .wrap_err("Failed to update the MASP commitment tree")?; + ctx.push_action(Action::Masp(MaspAction { masp_section_ref }))?; } Ok(()) } From 86579632e2b364ac4cc2bf4867e39e1da8e9e6ac Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Tue, 14 May 2024 12:56:28 +0200 Subject: [PATCH 37/70] Removes unused error variant --- crates/namada/src/ledger/protocol/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index 74e17fbae3..bb79852389 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -63,8 +63,6 @@ pub enum Error { TxRunnerError(vm::wasm::run::Error), #[error("{0:?}")] ProtocolTxError(#[from] eyre::Error), - #[error("Txs must either be encrypted or a decryption of an encrypted tx")] - TxTypeError, #[error("The atomic batch failed at inner transaction {0}")] FailingAtomicBatch(Hash), #[error("Gas error: {0}")] From b8000dbb20eb60ec551d683af6e82fd3a81474b3 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Tue, 14 May 2024 13:07:19 +0200 Subject: [PATCH 38/70] Emit masp sections references in the events --- crates/events/src/extend.rs | 38 +- crates/namada/src/ledger/protocol/mod.rs | 64 ++- crates/node/src/bench_utils.rs | 30 +- crates/node/src/shell/finalize_block.rs | 477 ++++++++++------------- crates/node/src/shell/governance.rs | 7 +- crates/sdk/src/masp.rs | 2 + crates/shielded_token/src/utils.rs | 11 +- crates/state/src/wl_state.rs | 25 ++ crates/tx/src/data/mod.rs | 27 ++ crates/tx/src/types.rs | 4 +- 10 files changed, 357 insertions(+), 328 deletions(-) diff --git a/crates/events/src/extend.rs b/crates/events/src/extend.rs index fdd098b401..0d90cebde4 100644 --- a/crates/events/src/extend.rs +++ b/crates/events/src/extend.rs @@ -2,7 +2,7 @@ use std::fmt::Display; use std::marker::PhantomData; -use std::ops::ControlFlow; +use std::ops::{ControlFlow, DerefMut}; use std::str::FromStr; use namada_core::collections::HashMap; @@ -498,28 +498,34 @@ impl EventAttributeEntry<'static> for MaspTxBlockIndex { } } -/// A displyable collection of hashes. -#[derive(Serialize, Deserialize)] -pub struct DisplayableHashVec(Vec); +//FIXME: move to tx crate? +/// Reference to a valid masp transaction +#[derive(Clone, Serialize, Deserialize)] +pub struct MaspTxRef { + //FIXME: actually, are we using the commitment? Probably if I give the masp section ref I don't need the commitment anymore right? + //FIXME: If we don't need the commitment then we definetely need to section ref to be in the event and not in the result otherwise we need to loop + pub cmt: Hash, + pub masp_section_ref: Hash, +} + +/// The collection of valid masp transactions +#[derive(Default, Clone, Serialize, Deserialize)] +//FIXME: move somewhere else? +//FIXME: maybe rename +pub struct ValidMaspTxs(pub Vec); -impl Display for DisplayableHashVec { +impl Display for ValidMaspTxs { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", serde_json::to_string(self).unwrap()) } } -impl From> for DisplayableHashVec { - fn from(value: Vec) -> Self { - Self(value) - } -} - /// Extend an [`Event`] with `masp_tx_batch_refs` data, indicating the specific -/// inner transactions inside the batch that are valid masp txs. -pub struct MaspTxBatchRefs(pub DisplayableHashVec); +/// inner transactions inside the batch that are valid masp txs and the references to the relative masp sections.. +pub struct MaspTxBatchRefs(pub ValidMaspTxs); impl EventAttributeEntry<'static> for MaspTxBatchRefs { - type Value = DisplayableHashVec; + type Value = ValidMaspTxs; type ValueOwned = Self::Value; const KEY: &'static str = "masp_tx_batch_refs"; @@ -621,8 +627,8 @@ where } /// Return a new implementation of [`EventAttributeChecker`]. -pub fn attribute_checker<'value, DATA, ATTR>() --> Box> +pub fn attribute_checker<'value, DATA, ATTR>( +) -> Box> where DATA: EventAttributeEntry<'value> + 'static, ATTR: AttributesMap, diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index bb79852389..d5381d9e24 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -9,17 +9,18 @@ use namada_core::booleans::BoolResultUnitExt; use namada_core::hash::Hash; use namada_core::storage::Key; use namada_events::extend::{ - ComposeEvent, Height as HeightAttr, TxHash as TxHashAttr, + ComposeEvent, Height as HeightAttr, MaspTxRef, TxHash as TxHashAttr }; use namada_events::EventLevel; use namada_gas::TxGasMeter; use namada_sdk::tx::TX_TRANSFER_WASM; -use namada_state::StorageWrite; +use namada_state::{StateRead, StorageWrite}; use namada_token::event::{TokenEvent, TokenOperation, UserAccount}; +use namada_tx::action::{Action, MaspAction, Read}; use namada_tx::data::protocol::ProtocolTxType; use namada_tx::data::{ - BatchResults, BatchedTxResult, TxResult, TxType, VpStatusFlags, VpsResult, - WrapperTx, + BatchResults, BatchedTxResult, ExtendedTxResult, TxResult, TxType, + VpStatusFlags, VpsResult, WrapperTx, }; use namada_tx::{BatchedTxRef, Tx}; use namada_vote_ext::EthereumTxData; @@ -163,8 +164,8 @@ pub type Result = std::result::Result; pub struct DispatchError { /// The result of the function call pub error: Error, - /// The tx result produced. It could produced even in case of an error - pub tx_result: Option>, + /// The extended tx result produced. It could be produced even in case of an error + pub tx_result: Option>, } impl From for DispatchError { @@ -189,7 +190,7 @@ pub fn dispatch_tx<'a, D, H, CA>( vp_wasm_cache: &'a mut VpCache, tx_wasm_cache: &'a mut TxCache, block_proposer: Option<&Address>, -) -> std::result::Result, DispatchError> +) -> std::result::Result, DispatchError> where D: 'static + DB + for<'iter> DBIter<'iter> + Sync, H: 'static + StorageHasher + Sync, @@ -218,7 +219,8 @@ where .into_iter() .collect(), ), - }) + } + .to_extended_result(None)) } TxType::Protocol(protocol_tx) => { // No bundles of protocol transactions, only take the first one @@ -233,10 +235,11 @@ where .collect(), ), ..Default::default() - }) + } + .to_extended_result(None)) } TxType::Wrapper(ref wrapper) => { - let mut tx_result = apply_wrapper_tx( + let tx_result = apply_wrapper_tx( tx.clone(), wrapper, tx_bytes, @@ -261,6 +264,8 @@ where }); } + let mut extended_tx_result = tx_result.to_extended_result(None); + // TODO(namada#2597): handle masp fee payment in the first inner tx // if necessary for cmt in tx.commitments() { @@ -276,26 +281,51 @@ where ) { Err(Error::GasError(ref msg)) => { // Gas error aborts the execution of the entire batch - tx_result.gas_used = + extended_tx_result.tx_result.gas_used = tx_gas_meter.borrow().get_tx_consumed_gas(); - tx_result.batch_results.0.insert( + extended_tx_result.tx_result.batch_results.0.insert( cmt.get_hash(), Err(Error::GasError(msg.to_owned())), ); state.write_log_mut().drop_tx(); return Err(DispatchError { error: Error::GasError(msg.to_owned()), - tx_result: Some(tx_result), + tx_result: Some(extended_tx_result), }); } res => { + //FIXME: move out to seaparate function, maybe the entire loop let is_accepted = matches!(&res, Ok(result) if result.is_accepted()); - tx_result.batch_results.0.insert(cmt.get_hash(), res); - tx_result.gas_used = + extended_tx_result + .tx_result + .batch_results + .0 + .insert(cmt.get_hash(), res); + extended_tx_result.tx_result.gas_used = tx_gas_meter.borrow().get_tx_consumed_gas(); if is_accepted { + // If the transaction was a masp one append the transaction refs for the events + if let Some(masp_section_ref) = state.read_actions().map_err(|e| Error::StateError(e))?.into_iter().find_map(|action| + // In case of multiple masp actions we only get the first one + if let Action::Masp(MaspAction{ + masp_section_ref, + }) = action + { + Some(masp_section_ref) + + } else { + None + } + + ) { + + extended_tx_result.masp_tx_refs.0.push(MaspTxRef { + cmt: cmt.get_hash(), + masp_section_ref + }); + } state.write_log_mut().commit_tx_to_batch(); } else { state.write_log_mut().drop_tx(); @@ -307,14 +337,14 @@ where error: Error::FailingAtomicBatch( cmt.get_hash(), ), - tx_result: Some(tx_result), + tx_result: Some(extended_tx_result), }); } } } }; } - Ok(tx_result) + Ok(extended_tx_result) } } } diff --git a/crates/node/src/bench_utils.rs b/crates/node/src/bench_utils.rs index da0828ecc7..5803db5aa2 100644 --- a/crates/node/src/bench_utils.rs +++ b/crates/node/src/bench_utils.rs @@ -27,7 +27,9 @@ use namada::core::masp::{ use namada::core::storage::{BlockHeight, Epoch, Key, KeySeg, TxIndex}; use namada::core::time::DateTimeUtc; use namada::core::token::{Amount, DenominatedAmount, Transfer}; -use namada::events::extend::{ComposeEvent, MaspTxBatchRefs, MaspTxBlockIndex}; +use namada::events::extend::{ + ComposeEvent, MaspTxBatchRefs, MaspTxBlockIndex, MaspTxRef, ValidMaspTxs, +}; use namada::events::Event; use namada::governance::storage::proposal::ProposalType; use namada::governance::InitProposalData; @@ -922,12 +924,26 @@ impl Client for BenchShell { .with(MaspTxBlockIndex(TxIndex::must_from_usize( idx, ))) - .with(MaspTxBatchRefs( - vec![ - tx.first_commitments().unwrap().get_hash(), - ] - .into(), - )) + .with(MaspTxBatchRefs(ValidMaspTxs(vec![ + MaspTxRef { + cmt: tx + .first_commitments() + .unwrap() + .get_hash(), + masp_section_ref: tx + .sections + .iter() + .find_map(|section| { + if let Section::MaspTx(_) = section + { + Some(section.get_hash()) + } else { + None + } + }) + .unwrap(), + }, + ]))) .into(); namada::tendermint::abci::Event::from(event) }) diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 257d16216e..490861ee85 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -4,6 +4,7 @@ use data_encoding::HEXUPPER; use masp_primitives::merkle_tree::CommitmentTree; use masp_primitives::sapling::Node; use namada::core::storage::{BlockResults, Epoch, Header}; +use namada::events::extend::ValidMaspTxs; use namada::events::Event; use namada::gas::event::GasUsed; use namada::governance::pgf::inflation as pgf_inflation; @@ -22,7 +23,6 @@ use namada::proof_of_stake::storage::{ }; use namada::state::write_log::StorageModification; use namada::state::{ResultExt, StorageWrite, EPOCH_SWITCH_BLOCKS_DELAY}; -use namada::token::utils::is_masp_tx; use namada::tx::data::protocol::ProtocolTxType; use namada::tx::data::VpStatusFlags; use namada::tx::event::{Batch, Code}; @@ -529,17 +529,17 @@ where fn evaluate_tx_result( &mut self, response: &mut shim::response::FinalizeBlock, - dispatch_result: std::result::Result< - namada::tx::data::TxResult, + extended_dispatch_result: std::result::Result< + namada::tx::data::ExtendedTxResult, DispatchError, >, tx_data: TxData<'_>, mut tx_logs: TxLogs<'_>, ) { - match dispatch_result { - Ok(tx_result) => self.handle_inner_tx_results( + match extended_dispatch_result { + Ok(extended_tx_result) => self.handle_inner_tx_results( response, - tx_result, + extended_tx_result, tx_data, &mut tx_logs, ), @@ -602,7 +602,7 @@ where fn handle_inner_tx_results( &mut self, response: &mut shim::response::FinalizeBlock, - tx_result: namada::tx::data::TxResult, + extended_tx_result: namada::tx::data::ExtendedTxResult, tx_data: TxData<'_>, tx_logs: &mut TxLogs<'_>, ) { @@ -612,7 +612,7 @@ where commit_batch_hash, is_any_tx_invalid, } = temp_log.check_inner_results( - &tx_result, + &extended_tx_result, tx_data.tx_header, tx_data.tx_index, tx_data.height, @@ -624,8 +624,10 @@ where let unrun_txs = tx_data .commitments_len .checked_sub( - u64::try_from(tx_result.batch_results.0.len()) - .expect("Should be able to convert to u64"), + u64::try_from( + extended_tx_result.tx_result.batch_results.0.len(), + ) + .expect("Should be able to convert to u64"), ) .expect("Shouldn't underflow"); temp_log.stats.set_failing_atomic_batch(unrun_txs); @@ -654,16 +656,16 @@ where tx_logs .tx_event - .extend(GasUsed(tx_result.gas_used)) + .extend(GasUsed(extended_tx_result.tx_result.gas_used)) .extend(Info("Check batch for result.".to_string())) - .extend(Batch(&tx_result.to_result_string())); + .extend(Batch(&extended_tx_result.tx_result.to_result_string())); } fn handle_batch_error( &mut self, response: &mut shim::response::FinalizeBlock, msg: &Error, - tx_result: namada::tx::data::TxResult, + extended_tx_result: namada::tx::data::ExtendedTxResult, tx_data: TxData<'_>, tx_logs: &mut TxLogs<'_>, ) { @@ -673,7 +675,7 @@ where commit_batch_hash, is_any_tx_invalid: _, } = temp_log.check_inner_results( - &tx_result, + &extended_tx_result, tx_data.tx_header, tx_data.tx_index, tx_data.height, @@ -682,8 +684,10 @@ where let unrun_txs = tx_data .commitments_len .checked_sub( - u64::try_from(tx_result.batch_results.0.len()) - .expect("Should be able to convert to u64"), + u64::try_from( + extended_tx_result.tx_result.batch_results.0.len(), + ) + .expect("Should be able to convert to u64"), ) .expect("Shouldn't underflow"); @@ -714,7 +718,7 @@ where tx_logs .tx_event - .extend(Batch(&tx_result.to_result_string())); + .extend(Batch(&extended_tx_result.tx_result.to_result_string())); } fn handle_batch_error_reprot(&mut self, err: &Error, tx_data: TxData<'_>) { @@ -817,21 +821,20 @@ impl<'finalize> TempTxLogs { fn check_inner_results( &mut self, - tx_result: &namada::tx::data::TxResult, + namada::tx::data::ExtendedTxResult { + tx_result, + masp_tx_refs, + }: &namada::tx::data::ExtendedTxResult, tx_header: &namada::tx::Header, tx_index: usize, height: BlockHeight, ) -> ValidityFlags { let mut flags = ValidityFlags::default(); - let mut masp_cmts = vec![]; for (cmt_hash, batched_result) in &tx_result.batch_results.0 { match batched_result { Ok(result) => { if result.is_accepted() { - if is_masp_tx(&result.changed_keys) { - masp_cmts.push(*cmt_hash); - } tracing::trace!( "all VPs accepted inner tx {} storage \ modification {:#?}", @@ -894,10 +897,12 @@ impl<'finalize> TempTxLogs { // If at least one of the inner transactions is a valid masp tx, update // the events - if !masp_cmts.is_empty() { + if !masp_tx_refs.0.is_empty() { self.tx_event .extend(MaspTxBlockIndex(TxIndex::must_from_usize(tx_index))); - self.tx_event.extend(MaspTxBatchRefs(masp_cmts.into())); + //FIXME: avoid clone here if possible + self.tx_event + .extend(MaspTxBatchRefs(masp_tx_refs.to_owned())); } flags @@ -2798,25 +2803,21 @@ mod test_finalize_block { assert_eq!(root_pre.0, root_post.0); // Check transaction's hash in storage - assert!( - shell - .shell - .state - .write_log() - .has_replay_protection_entry(&wrapper_tx.raw_header_hash()) - ); + assert!(shell + .shell + .state + .write_log() + .has_replay_protection_entry(&wrapper_tx.raw_header_hash())); // Check that the hash is not present in the merkle tree shell.state.commit_block().unwrap(); - assert!( - !shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&wrapper_hash_key) - .unwrap() - ); + assert!(!shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&wrapper_hash_key) + .unwrap()); // test that a commitment to replay protection gets added. let reprot_key = replay_protection::commitment_key(); @@ -2863,26 +2864,22 @@ mod test_finalize_block { assert_eq!(root_pre.0, root_post.0); // Check that the hashes are present in the merkle tree shell.state.commit_block().unwrap(); - assert!( - shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&convert_key) - .unwrap() - ); - assert!( - shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&commitment_key) - .unwrap() - ); + assert!(shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&convert_key) + .unwrap()); + assert!(shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&commitment_key) + .unwrap()); } /// Test that a tx that has already been applied in the same block @@ -2960,34 +2957,26 @@ mod test_finalize_block { assert_eq!(code, ResultCode::WasmRuntimeError); for wrapper in [&wrapper, &new_wrapper] { - assert!( - shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.raw_header_hash()) - ); - assert!( - !shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.header_hash()) - ); + assert!(shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.raw_header_hash())); + assert!(!shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.header_hash())); } // Commit to check the hashes from storage shell.commit(); for wrapper in [&wrapper, &new_wrapper] { - assert!( - shell - .state - .has_replay_protection_entry(&wrapper.raw_header_hash()) - .unwrap() - ); - assert!( - !shell - .state - .has_replay_protection_entry(&wrapper.header_hash()) - .unwrap() - ); + assert!(shell + .state + .has_replay_protection_entry(&wrapper.raw_header_hash()) + .unwrap()); + assert!(!shell + .state + .has_replay_protection_entry(&wrapper.header_hash()) + .unwrap()); } } @@ -3270,29 +3259,23 @@ mod test_finalize_block { &unsigned_wrapper, &wrong_commitment_wrapper, ] { - assert!( - !shell.state.write_log().has_replay_protection_entry( - &valid_wrapper.raw_header_hash() - ) - ); - assert!( - shell - .state - .write_log() - .has_replay_protection_entry(&valid_wrapper.header_hash()) - ); - } - assert!( - shell.state.write_log().has_replay_protection_entry( - &failing_wrapper.raw_header_hash() - ) - ); - assert!( - !shell + assert!(!shell .state .write_log() - .has_replay_protection_entry(&failing_wrapper.header_hash()) - ); + .has_replay_protection_entry(&valid_wrapper.raw_header_hash())); + assert!(shell + .state + .write_log() + .has_replay_protection_entry(&valid_wrapper.header_hash())); + } + assert!(shell + .state + .write_log() + .has_replay_protection_entry(&failing_wrapper.raw_header_hash())); + assert!(!shell + .state + .write_log() + .has_replay_protection_entry(&failing_wrapper.header_hash())); // Commit to check the hashes from storage shell.commit(); @@ -3301,33 +3284,23 @@ mod test_finalize_block { unsigned_wrapper, wrong_commitment_wrapper, ] { - assert!( - !shell - .state - .has_replay_protection_entry( - &valid_wrapper.raw_header_hash() - ) - .unwrap() - ); - assert!( - shell - .state - .has_replay_protection_entry(&valid_wrapper.header_hash()) - .unwrap() - ); - } - assert!( - shell + assert!(!shell .state - .has_replay_protection_entry(&failing_wrapper.raw_header_hash()) - .unwrap() - ); - assert!( - !shell + .has_replay_protection_entry(&valid_wrapper.raw_header_hash()) + .unwrap()); + assert!(shell .state - .has_replay_protection_entry(&failing_wrapper.header_hash()) - .unwrap() - ); + .has_replay_protection_entry(&valid_wrapper.header_hash()) + .unwrap()); + } + assert!(shell + .state + .has_replay_protection_entry(&failing_wrapper.raw_header_hash()) + .unwrap()); + assert!(!shell + .state + .has_replay_protection_entry(&failing_wrapper.header_hash()) + .unwrap()); } #[test] @@ -3387,18 +3360,14 @@ mod test_finalize_block { let code = event[0].read_attribute::().expect("Test failed"); assert_eq!(code, ResultCode::InvalidTx); - assert!( - shell - .state - .write_log() - .has_replay_protection_entry(&wrapper_hash) - ); - assert!( - !shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.raw_header_hash()) - ); + assert!(shell + .state + .write_log() + .has_replay_protection_entry(&wrapper_hash)); + assert!(!shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.raw_header_hash())); } // Test that the fees are paid even if the inner transaction fails and its @@ -3796,11 +3765,9 @@ mod test_finalize_block { .unwrap(), Some(ValidatorState::Consensus) ); - assert!( - enqueued_slashes_handle() - .at(&Epoch::default()) - .is_empty(&shell.state)? - ); + assert!(enqueued_slashes_handle() + .at(&Epoch::default()) + .is_empty(&shell.state)?); assert_eq!( get_num_consensus_validators(&shell.state, Epoch::default()) .unwrap(), @@ -3819,21 +3786,17 @@ mod test_finalize_block { .unwrap(), Some(ValidatorState::Jailed) ); - assert!( - enqueued_slashes_handle() - .at(&epoch) - .is_empty(&shell.state)? - ); + assert!(enqueued_slashes_handle() + .at(&epoch) + .is_empty(&shell.state)?); assert_eq!( get_num_consensus_validators(&shell.state, epoch).unwrap(), 5_u64 ); } - assert!( - !enqueued_slashes_handle() - .at(&processing_epoch) - .is_empty(&shell.state)? - ); + assert!(!enqueued_slashes_handle() + .at(&processing_epoch) + .is_empty(&shell.state)?); // Advance to the processing epoch loop { @@ -3856,11 +3819,9 @@ mod test_finalize_block { // println!("Reached processing epoch"); break; } else { - assert!( - enqueued_slashes_handle() - .at(&shell.state.in_mem().block.epoch) - .is_empty(&shell.state)? - ); + assert!(enqueued_slashes_handle() + .at(&shell.state.in_mem().block.epoch) + .is_empty(&shell.state)?); let stake1 = read_validator_stake( &shell.state, ¶ms, @@ -4344,13 +4305,11 @@ mod test_finalize_block { ) .unwrap(); assert_eq!(last_slash, Some(misbehavior_epoch)); - assert!( - namada_proof_of_stake::storage::validator_slashes_handle( - &val1.address - ) - .is_empty(&shell.state) - .unwrap() - ); + assert!(namada_proof_of_stake::storage::validator_slashes_handle( + &val1.address + ) + .is_empty(&shell.state) + .unwrap()); tracing::debug!("Advancing to epoch 7"); @@ -4415,22 +4374,18 @@ mod test_finalize_block { ) .unwrap(); assert_eq!(last_slash, Some(Epoch(4))); - assert!( - namada_proof_of_stake::is_validator_frozen( - &shell.state, - &val1.address, - current_epoch, - ¶ms - ) - .unwrap() - ); - assert!( - namada_proof_of_stake::storage::validator_slashes_handle( - &val1.address - ) - .is_empty(&shell.state) - .unwrap() - ); + assert!(namada_proof_of_stake::is_validator_frozen( + &shell.state, + &val1.address, + current_epoch, + ¶ms + ) + .unwrap()); + assert!(namada_proof_of_stake::storage::validator_slashes_handle( + &val1.address + ) + .is_empty(&shell.state) + .unwrap()); let pre_stake_10 = namada_proof_of_stake::storage::read_validator_stake( @@ -5308,11 +5263,9 @@ mod test_finalize_block { shell.vp_wasm_cache.clone(), ); let parameters = ParametersVp { ctx }; - assert!( - parameters - .validate_tx(&batched_tx, &keys_changed, &verifiers) - .is_ok() - ); + assert!(parameters + .validate_tx(&batched_tx, &keys_changed, &verifiers) + .is_ok()); // we advance forward to the next epoch let mut req = FinalizeBlock::default(); @@ -5385,13 +5338,11 @@ mod test_finalize_block { let inner_results = inner_tx_result.batch_results.0; for cmt in batch.commitments() { - assert!( - inner_results - .get(&cmt.get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted()) - ); + assert!(inner_results + .get(&cmt.get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted())); } // Check storage modifications @@ -5429,24 +5380,18 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!( - inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted()) - ); - assert!( - inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err() - ); + assert!(inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted())); + assert!(inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err()); // Assert that the last tx didn't run - assert!( - !inner_results.contains_key(&batch.commitments()[2].get_hash()) - ); + assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); // Check storage modifications are missing for key in ["random_key_1", "random_key_2", "random_key_3"] { @@ -5477,27 +5422,21 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!( - inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted()) - ); - assert!( - inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err() - ); - assert!( - inner_results - .get(&batch.commitments()[2].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted()) - ); + assert!(inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted())); + assert!(inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err()); + assert!(inner_results + .get(&batch.commitments()[2].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted())); // Check storage modifications assert_eq!( @@ -5508,12 +5447,10 @@ mod test_finalize_block { .unwrap(), STORAGE_VALUE ); - assert!( - !shell - .state - .has_key(&"random_key_2".parse().unwrap()) - .unwrap() - ); + assert!(!shell + .state + .has_key(&"random_key_2".parse().unwrap()) + .unwrap()); assert_eq!( shell .state @@ -5545,24 +5482,18 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!( - inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted()) - ); - assert!( - inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err() - ); + assert!(inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted())); + assert!(inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err()); // Assert that the last tx didn't run - assert!( - !inner_results.contains_key(&batch.commitments()[2].get_hash()) - ); + assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); // Check storage modifications are missing for key in ["random_key_1", "random_key_2", "random_key_3"] { @@ -5592,24 +5523,18 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!( - inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted()) - ); - assert!( - inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err() - ); + assert!(inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted())); + assert!(inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err()); // Assert that the last tx didn't run - assert!( - !inner_results.contains_key(&batch.commitments()[2].get_hash()) - ); + assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); // Check storage modifications assert_eq!( diff --git a/crates/node/src/shell/governance.rs b/crates/node/src/shell/governance.rs index dbde3d0204..21b4bb5b66 100644 --- a/crates/node/src/shell/governance.rs +++ b/crates/node/src/shell/governance.rs @@ -419,7 +419,12 @@ where .delete(&pending_execution_key) .expect("Should be able to delete the storage."); match dispatch_result { - Ok(tx_result) => match tx_result.batch_results.0.get(&cmt.get_hash()) { + Ok(extended_tx_result) => match extended_tx_result + .tx_result + .batch_results + .0 + .get(&cmt.get_hash()) + { Some(Ok(batched_result)) if batched_result.is_accepted() => { shell.state.commit_tx(); Ok(true) diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 7247d3e2c5..7b84fce48b 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -865,6 +865,8 @@ impl ShieldedContext { let mut txs = vec![]; // Expect transaction + // FIXME: update this to rely on the masp section hash emitted in the + // event instead of deserializing to Transfer for cmt in tx.commitments() { let tx_data = tx.data(cmt).ok_or_else(|| { Error::Other("Missing data section".to_string()) diff --git a/crates/shielded_token/src/utils.rs b/crates/shielded_token/src/utils.rs index c29c3185c0..22d783f67f 100644 --- a/crates/shielded_token/src/utils.rs +++ b/crates/shielded_token/src/utils.rs @@ -9,7 +9,8 @@ use namada_core::storage; use namada_storage::{Error, Result, StorageRead, StorageWrite}; use crate::storage_key::{ - is_masp_key, masp_commitment_tree_key, masp_nullifier_key, + is_masp_key, is_masp_transfer_key, masp_commitment_tree_key, + masp_nullifier_key, }; // Writes the nullifiers of the provided masp transaction to storage @@ -72,11 +73,3 @@ pub fn handle_masp_tx( Ok(()) } - -/// Check if a transaction was a MASP transaction. This means -/// that at least one key owned by MASP was changed. We cannot -/// simply check that the MASP VP was triggered, as this can -/// be manually requested to be triggered by users. -pub fn is_masp_tx(changed_keys: &BTreeSet) -> bool { - changed_keys.iter().any(is_masp_key) -} diff --git a/crates/state/src/wl_state.rs b/crates/state/src/wl_state.rs index dbf6fac944..9dae670426 100644 --- a/crates/state/src/wl_state.rs +++ b/crates/state/src/wl_state.rs @@ -1344,3 +1344,28 @@ where Ok(()) } } + +//FIXME: can join this with FullAccessState? +impl namada_tx::action::Read for WlState +where + D: 'static + DB + for<'iter> DBIter<'iter>, + H: 'static + StorageHasher, +{ + type Err = Error; + + fn read_temp( + &self, + key: &storage::Key, + ) -> Result> { + let (log_val, _) = self.write_log().read_temp(key).unwrap(); + match log_val { + Some(value) => { + let value = + namada_core::borsh::BorshDeserialize::try_from_slice(value) + .map_err(Error::BorshCodingError)?; + Ok(Some(value)) + } + None => Ok(None), + } + } +} diff --git a/crates/tx/src/data/mod.rs b/crates/tx/src/data/mod.rs index 24dc596c80..c4819a25a9 100644 --- a/crates/tx/src/data/mod.rs +++ b/crates/tx/src/data/mod.rs @@ -22,6 +22,7 @@ use namada_core::borsh::{ }; use namada_core::hash::Hash; use namada_core::storage; +use namada_events::extend::{MaspTxRef, ValidMaspTxs}; use namada_events::Event; use namada_gas::{Gas, VpsGas}; use namada_macros::BorshDeserializer; @@ -238,6 +239,21 @@ impl<'de, T: Deserialize<'de>> serde::Deserialize<'de> for BatchResults { } } +/// The extended transaction result, containing the optional references to masp sections +pub struct ExtendedTxResult { + pub tx_result: TxResult, + pub masp_tx_refs: ValidMaspTxs, +} + +impl Default for ExtendedTxResult { + fn default() -> Self { + Self { + tx_result: Default::default(), + masp_tx_refs: Default::default(), + } + } +} + /// Transaction application result // TODO derive BorshSchema after #[derive( @@ -279,6 +295,17 @@ impl TxResult { batch_results: BatchResults(batch_results), } } + + /// Converts this result to [`ExtendedTxResult`] + pub fn to_extended_result( + self, + masp_tx_refs: Option, + ) -> ExtendedTxResult { + ExtendedTxResult { + tx_result: self, + masp_tx_refs: masp_tx_refs.unwrap_or_default(), + } + } } #[cfg(feature = "migrations")] diff --git a/crates/tx/src/types.rs b/crates/tx/src/types.rs index c1fe7e99ab..c783ce6076 100644 --- a/crates/tx/src/types.rs +++ b/crates/tx/src/types.rs @@ -1731,8 +1731,7 @@ impl<'tx> Tx { } /// Represents the pointers of an indexed tx, which are the block height, the -/// index inside that block and the commitment inside the tx bundle (if inner -/// tx) +/// index inside that block and the commitment inside the tx bundle #[derive( Debug, Clone, @@ -1751,6 +1750,7 @@ pub struct IndexedTx { /// The index in the block of the tx pub index: TxIndex, /// This is a pointer to the inner tx inside the batch + //FIXME: do we really need this? Probably not for the masp pub inner_tx: TxCommitments, } From d16e1982e771b22d4576d72ea2b3044894187a2c Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Thu, 23 May 2024 12:50:24 +0200 Subject: [PATCH 39/70] Updates sdk to retrieve masp data based on events --- crates/events/src/extend.rs | 10 ++++- crates/sdk/src/masp.rs | 82 +++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/crates/events/src/extend.rs b/crates/events/src/extend.rs index 0d90cebde4..e8a2d5c040 100644 --- a/crates/events/src/extend.rs +++ b/crates/events/src/extend.rs @@ -511,7 +511,7 @@ pub struct MaspTxRef { /// The collection of valid masp transactions #[derive(Default, Clone, Serialize, Deserialize)] //FIXME: move somewhere else? -//FIXME: maybe rename +//FIXME: maybe rename, yes pub struct ValidMaspTxs(pub Vec); impl Display for ValidMaspTxs { @@ -520,6 +520,14 @@ impl Display for ValidMaspTxs { } } +impl FromStr for ValidMaspTxs { + type Err = serde_json::Error; + + fn from_str(s: &str) -> Result { + serde_json::from_str(s) + } +} + /// Extend an [`Event`] with `masp_tx_batch_refs` data, indicating the specific /// inner transactions inside the batch that are valid masp txs and the references to the relative masp sections.. pub struct MaspTxBatchRefs(pub ValidMaspTxs); diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 7b84fce48b..2645049f48 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -61,7 +61,9 @@ use namada_core::storage::{BlockHeight, Epoch, TxIndex}; use namada_core::time::{DateTimeUtc, DurationSecs}; use namada_core::uint::Uint; use namada_events::extend::{ - MaspTxBlockIndex as MaspTxBlockIndexAttr, ReadFromEventAttributes, + MaspTxBatchRefs as MaspTxBatchRefsAttr, + MaspTxBlockIndex as MaspTxBlockIndexAttr, MaspTxRef, + ReadFromEventAttributes, ValidMaspTxs, }; use namada_ibc::IbcMessage; use namada_macros::BorshDeserializer; @@ -833,10 +835,11 @@ impl ShieldedContext { .block .data; - for idx in txs_results { + for (idx, masp_sections_refs) in txs_results { let tx = Tx::try_from(block[idx.0 as usize].as_ref()) .map_err(|e| Error::Other(e.to_string()))?; - let extracted_masp_txs = Self::extract_masp_tx(&tx).await?; + let extracted_masp_txs = + Self::extract_masp_tx(&tx, &masp_sections_refs).await?; // Collect the current transactions for (inner_tx, transaction) in extracted_masp_txs.0 { shielded_txs.insert( @@ -855,7 +858,10 @@ impl ShieldedContext { } /// Extract the relevant shield portions of a [`Tx`], if any. - async fn extract_masp_tx(tx: &Tx) -> Result { + async fn extract_masp_tx( + tx: &Tx, + masp_section_refs: &ValidMaspTxs, + ) -> Result { // NOTE: simply looking for masp sections attached to the tx // is not safe. We don't validate the sections attached to a // transaction se we could end up with transactions carrying @@ -864,47 +870,26 @@ impl ShieldedContext { // of the transactions' data sections let mut txs = vec![]; - // Expect transaction - // FIXME: update this to rely on the masp section hash emitted in the - // event instead of deserializing to Transfer - for cmt in tx.commitments() { - let tx_data = tx.data(cmt).ok_or_else(|| { - Error::Other("Missing data section".to_string()) - })?; - let maybe_masp_tx = match Transfer::try_from_slice(&tx_data) { - Ok(transfer) => Some(transfer), - Err(_) => { - // This should be a MASP over IBC transaction, it - // could be a ShieldedTransfer or an Envelope - // message, need to try both - extract_payload_from_shielded_action(&tx_data).await.ok() - } - } - .map(|transfer| { - if let Some(hash) = transfer.shielded { - let masp_tx = tx - .get_section(&hash) - .ok_or_else(|| { - Error::Other( - "Missing masp section in transaction" - .to_string(), - ) - })? - .masp_tx() - .ok_or_else(|| { - Error::Other("Missing masp transaction".to_string()) - })?; + for MaspTxRef { + cmt, + masp_section_ref, + } in &masp_section_refs.0 + { + //FIXME: improve here + let masp_section = tx.get_section(masp_section_ref); - Ok::<_, Error>(Some(masp_tx)) - } else { - Ok(None) - } - }) - .transpose()? - .flatten(); + let maybe_transaction = + masp_section.map(|section| section.masp_tx()).flatten(); - if let Some(transaction) = maybe_masp_tx { - txs.push((cmt.to_owned(), transaction)); + if let Some(transaction) = maybe_transaction { + let inner_tx = tx + .commitments() + .iter() + .find(|inner_tx| &inner_tx.get_hash() == cmt); + + if let Some(cmt) = inner_tx { + txs.push((cmt.to_owned(), transaction)); + } } } @@ -2031,7 +2016,7 @@ async fn get_indexed_masp_events_at_height( client: &C, height: BlockHeight, first_idx_to_query: Option, -) -> Result>, Error> { +) -> Result>, Error> { let first_idx_to_query = first_idx_to_query.unwrap_or_default(); Ok(client @@ -2050,7 +2035,14 @@ async fn get_indexed_masp_events_at_height( .ok()?; if tx_index >= first_idx_to_query { - Some(tx_index) + // Extract the references to the correct masp sections + let masp_section_refs = + MaspTxBatchRefsAttr::read_from_event_attributes( + &event.attributes, + ) + .ok()?; + + Some((tx_index, masp_section_refs)) } else { None } From 2b88265c13fd4c853d525585807967aa62a7f473 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Thu, 23 May 2024 13:35:42 +0200 Subject: [PATCH 40/70] Misc refactors --- crates/namada/src/ledger/protocol/mod.rs | 181 +++++++++++++---------- crates/node/src/shell/finalize_block.rs | 16 +- crates/sdk/src/masp.rs | 36 +++-- crates/state/src/wl_state.rs | 1 - 4 files changed, 131 insertions(+), 103 deletions(-) diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index d5381d9e24..bb36e399c9 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -9,7 +9,7 @@ use namada_core::booleans::BoolResultUnitExt; use namada_core::hash::Hash; use namada_core::storage::Key; use namada_events::extend::{ - ComposeEvent, Height as HeightAttr, MaspTxRef, TxHash as TxHashAttr + ComposeEvent, Height as HeightAttr, MaspTxRef, TxHash as TxHashAttr, }; use namada_events::EventLevel; use namada_gas::TxGasMeter; @@ -164,7 +164,8 @@ pub type Result = std::result::Result; pub struct DispatchError { /// The result of the function call pub error: Error, - /// The extended tx result produced. It could be produced even in case of an error + /// The extended tx result produced. It could be produced even in case of + /// an error pub tx_result: Option>, } @@ -264,89 +265,115 @@ where }); } - let mut extended_tx_result = tx_result.to_extended_result(None); + dispatch_inner_txs( + tx, + tx_result, + tx_index, + tx_gas_meter, + state, + vp_wasm_cache, + tx_wasm_cache, + ) + } + } +} - // TODO(namada#2597): handle masp fee payment in the first inner tx - // if necessary - for cmt in tx.commitments() { - match apply_wasm_tx( - tx.batch_ref_tx(cmt), - &tx_index, - ShellParams { - tx_gas_meter, - state, - vp_wasm_cache, - tx_wasm_cache, - }, - ) { - Err(Error::GasError(ref msg)) => { - // Gas error aborts the execution of the entire batch - extended_tx_result.tx_result.gas_used = - tx_gas_meter.borrow().get_tx_consumed_gas(); - extended_tx_result.tx_result.batch_results.0.insert( - cmt.get_hash(), - Err(Error::GasError(msg.to_owned())), - ); - state.write_log_mut().drop_tx(); - return Err(DispatchError { - error: Error::GasError(msg.to_owned()), - tx_result: Some(extended_tx_result), +fn dispatch_inner_txs<'a, D, H, CA>( + tx: Tx, + tx_result: TxResult, + tx_index: TxIndex, + tx_gas_meter: &'a RefCell, + state: &'a mut WlState, + vp_wasm_cache: &'a mut VpCache, + tx_wasm_cache: &'a mut TxCache, +) -> std::result::Result, DispatchError> +where + D: 'static + DB + for<'iter> DBIter<'iter> + Sync, + H: 'static + StorageHasher + Sync, + CA: 'static + WasmCacheAccess + Sync, +{ + let mut extended_tx_result = tx_result.to_extended_result(None); + + // TODO(namada#2597): handle masp fee payment in the first inner tx + // if necessary + for cmt in tx.commitments() { + match apply_wasm_tx( + tx.batch_ref_tx(cmt), + &tx_index, + ShellParams { + tx_gas_meter, + state, + vp_wasm_cache, + tx_wasm_cache, + }, + ) { + Err(Error::GasError(ref msg)) => { + // Gas error aborts the execution of the entire batch + extended_tx_result.tx_result.gas_used = + tx_gas_meter.borrow().get_tx_consumed_gas(); + extended_tx_result.tx_result.batch_results.0.insert( + cmt.get_hash(), + Err(Error::GasError(msg.to_owned())), + ); + state.write_log_mut().drop_tx(); + return Err(DispatchError { + error: Error::GasError(msg.to_owned()), + tx_result: Some(extended_tx_result), + }); + } + res => { + let is_accepted = + matches!(&res, Ok(result) if result.is_accepted()); + + extended_tx_result + .tx_result + .batch_results + .0 + .insert(cmt.get_hash(), res); + extended_tx_result.tx_result.gas_used = + tx_gas_meter.borrow().get_tx_consumed_gas(); + if is_accepted { + // If the transaction was a masp one append the + // transaction refs for the events + if let Some(masp_section_ref) = state + .read_actions() + .map_err(|e| Error::StateError(e))? + .into_iter() + .find_map(|action| { + // In case of multiple masp actions we get the first one + if let Action::Masp(MaspAction { + masp_section_ref, + }) = action + { + Some(masp_section_ref) + } else { + None + } + }) + { + extended_tx_result.masp_tx_refs.0.push(MaspTxRef { + cmt: cmt.get_hash(), + masp_section_ref, }); } - res => { - //FIXME: move out to seaparate function, maybe the entire loop - let is_accepted = - matches!(&res, Ok(result) if result.is_accepted()); - - extended_tx_result - .tx_result - .batch_results - .0 - .insert(cmt.get_hash(), res); - extended_tx_result.tx_result.gas_used = - tx_gas_meter.borrow().get_tx_consumed_gas(); - if is_accepted { - // If the transaction was a masp one append the transaction refs for the events - if let Some(masp_section_ref) = state.read_actions().map_err(|e| Error::StateError(e))?.into_iter().find_map(|action| - // In case of multiple masp actions we only get the first one - if let Action::Masp(MaspAction{ - masp_section_ref, - }) = action - { - Some(masp_section_ref) - + state.write_log_mut().commit_tx_to_batch(); } else { - None - } + state.write_log_mut().drop_tx(); - ) { - - extended_tx_result.masp_tx_refs.0.push(MaspTxRef { - cmt: cmt.get_hash(), - masp_section_ref - }); - } - state.write_log_mut().commit_tx_to_batch(); - } else { - state.write_log_mut().drop_tx(); - - if tx.header.atomic { - // Stop the execution of an atomic batch at the - // first failed transaction - return Err(DispatchError { - error: Error::FailingAtomicBatch( - cmt.get_hash(), - ), - tx_result: Some(extended_tx_result), - }); - } - } + if tx.header.atomic { + // Stop the execution of an atomic batch at the + // first failed transaction + return Err(DispatchError { + error: Error::FailingAtomicBatch(cmt.get_hash()), + tx_result: Some(extended_tx_result), + }); } - }; + } } - Ok(extended_tx_result) - } + }; } + + Ok(extended_tx_result) } /// Load the wasm hash for a transfer from storage. diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 490861ee85..a9ce16da36 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -612,7 +612,8 @@ where commit_batch_hash, is_any_tx_invalid, } = temp_log.check_inner_results( - &extended_tx_result, + &extended_tx_result.tx_result, + extended_tx_result.masp_tx_refs, tx_data.tx_header, tx_data.tx_index, tx_data.height, @@ -675,7 +676,8 @@ where commit_batch_hash, is_any_tx_invalid: _, } = temp_log.check_inner_results( - &extended_tx_result, + &extended_tx_result.tx_result, + extended_tx_result.masp_tx_refs, tx_data.tx_header, tx_data.tx_index, tx_data.height, @@ -821,10 +823,8 @@ impl<'finalize> TempTxLogs { fn check_inner_results( &mut self, - namada::tx::data::ExtendedTxResult { - tx_result, - masp_tx_refs, - }: &namada::tx::data::ExtendedTxResult, + tx_result: &namada::tx::data::TxResult, + masp_tx_refs: ValidMaspTxs, tx_header: &namada::tx::Header, tx_index: usize, height: BlockHeight, @@ -900,9 +900,7 @@ impl<'finalize> TempTxLogs { if !masp_tx_refs.0.is_empty() { self.tx_event .extend(MaspTxBlockIndex(TxIndex::must_from_usize(tx_index))); - //FIXME: avoid clone here if possible - self.tx_event - .extend(MaspTxBatchRefs(masp_tx_refs.to_owned())); + self.tx_event.extend(MaspTxBatchRefs(masp_tx_refs)); } flags diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 2645049f48..a98228fb6d 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -866,8 +866,7 @@ impl ShieldedContext { // is not safe. We don't validate the sections attached to a // transaction se we could end up with transactions carrying // an unnecessary masp section. We must instead look for the - // required masp sections in the signed commitments (hashes) - // of the transactions' data sections + // required masp sections coming from the events let mut txs = vec![]; for MaspTxRef { @@ -875,22 +874,27 @@ impl ShieldedContext { masp_section_ref, } in &masp_section_refs.0 { - //FIXME: improve here - let masp_section = tx.get_section(masp_section_ref); - - let maybe_transaction = - masp_section.map(|section| section.masp_tx()).flatten(); + let transaction = tx + .get_section(masp_section_ref) + .map(|section| section.masp_tx()) + .flatten() + .ok_or_else(|| { + Error::Other( + "Missing expected masp transaction".to_string(), + ) + })?; - if let Some(transaction) = maybe_transaction { - let inner_tx = tx - .commitments() - .iter() - .find(|inner_tx| &inner_tx.get_hash() == cmt); + let cmt = tx + .commitments() + .iter() + .find(|inner_tx| &inner_tx.get_hash() == cmt) + .ok_or_else(|| { + Error::Other( + "Missing expected inner transaction".to_string(), + ) + })?; - if let Some(cmt) = inner_tx { - txs.push((cmt.to_owned(), transaction)); - } - } + txs.push((cmt.to_owned(), transaction)); } Ok(ExtractedMaspTxs(txs)) diff --git a/crates/state/src/wl_state.rs b/crates/state/src/wl_state.rs index 9dae670426..edb1bedb63 100644 --- a/crates/state/src/wl_state.rs +++ b/crates/state/src/wl_state.rs @@ -1345,7 +1345,6 @@ where } } -//FIXME: can join this with FullAccessState? impl namada_tx::action::Read for WlState where D: 'static + DB + for<'iter> DBIter<'iter>, From 1b05850529ec8d510cf800b1eb83944a9738004a Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Thu, 23 May 2024 14:03:34 +0200 Subject: [PATCH 41/70] Moves masp events data to core --- crates/core/src/masp.rs | 30 +++++++++++++++++++ crates/events/src/extend.rs | 38 ++++-------------------- crates/namada/src/ledger/protocol/mod.rs | 4 ++- crates/node/src/bench_utils.rs | 7 ++--- crates/node/src/shell/finalize_block.rs | 4 +-- crates/sdk/src/masp.rs | 8 ++--- crates/tx/src/data/mod.rs | 9 +++--- 7 files changed, 52 insertions(+), 48 deletions(-) diff --git a/crates/core/src/masp.rs b/crates/core/src/masp.rs index a63c055d5f..2c72ab1c38 100644 --- a/crates/core/src/masp.rs +++ b/crates/core/src/masp.rs @@ -14,6 +14,7 @@ use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use crate::address::{Address, DecodeError, HASH_HEX_LEN, MASP}; +use crate::hash::Hash; use crate::impl_display_and_from_str_via_format; use crate::storage::Epoch; use crate::string_encoding::{ @@ -532,3 +533,32 @@ impl FromStr for MaspValue { }) } } + +/// Reference to a masp transaction inside a [`BatchedTx`] +#[derive(Clone, Serialize, Deserialize)] +pub struct MaspTxRef { + // FIXME: actually, are we using the commitment? Probably if I give the + // masp section ref I don't need the commitment anymore right? + /// The inner tx commitment's hash + pub cmt: Hash, + /// The hash of the masp [`Section::MaspTx`] + pub masp_section_ref: Hash, +} + +/// The masp transactions' references of a given batch +#[derive(Default, Clone, Serialize, Deserialize)] +pub struct BatchMaspTxRefs(pub Vec); + +impl Display for BatchMaspTxRefs { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", serde_json::to_string(self).unwrap()) + } +} + +impl FromStr for BatchMaspTxRefs { + type Err = serde_json::Error; + + fn from_str(s: &str) -> Result { + serde_json::from_str(s) + } +} diff --git a/crates/events/src/extend.rs b/crates/events/src/extend.rs index e8a2d5c040..78058e5436 100644 --- a/crates/events/src/extend.rs +++ b/crates/events/src/extend.rs @@ -7,6 +7,7 @@ use std::str::FromStr; use namada_core::collections::HashMap; use namada_core::hash::Hash; +use namada_core::masp::BatchMaspTxRefs; use namada_core::storage::{BlockHeight, TxIndex}; use super::*; @@ -498,42 +499,13 @@ impl EventAttributeEntry<'static> for MaspTxBlockIndex { } } -//FIXME: move to tx crate? -/// Reference to a valid masp transaction -#[derive(Clone, Serialize, Deserialize)] -pub struct MaspTxRef { - //FIXME: actually, are we using the commitment? Probably if I give the masp section ref I don't need the commitment anymore right? - //FIXME: If we don't need the commitment then we definetely need to section ref to be in the event and not in the result otherwise we need to loop - pub cmt: Hash, - pub masp_section_ref: Hash, -} - -/// The collection of valid masp transactions -#[derive(Default, Clone, Serialize, Deserialize)] -//FIXME: move somewhere else? -//FIXME: maybe rename, yes -pub struct ValidMaspTxs(pub Vec); - -impl Display for ValidMaspTxs { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", serde_json::to_string(self).unwrap()) - } -} - -impl FromStr for ValidMaspTxs { - type Err = serde_json::Error; - - fn from_str(s: &str) -> Result { - serde_json::from_str(s) - } -} - /// Extend an [`Event`] with `masp_tx_batch_refs` data, indicating the specific -/// inner transactions inside the batch that are valid masp txs and the references to the relative masp sections.. -pub struct MaspTxBatchRefs(pub ValidMaspTxs); +/// inner transactions inside the batch that are valid masp txs and the +/// references to the relative masp sections. +pub struct MaspTxBatchRefs(pub BatchMaspTxRefs); impl EventAttributeEntry<'static> for MaspTxBatchRefs { - type Value = ValidMaspTxs; + type Value = BatchMaspTxRefs; type ValueOwned = Self::Value; const KEY: &'static str = "masp_tx_batch_refs"; diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index bb36e399c9..ff72bf0515 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -7,9 +7,10 @@ use borsh_ext::BorshSerializeExt; use eyre::{eyre, WrapErr}; use namada_core::booleans::BoolResultUnitExt; use namada_core::hash::Hash; +use namada_core::masp::MaspTxRef; use namada_core::storage::Key; use namada_events::extend::{ - ComposeEvent, Height as HeightAttr, MaspTxRef, TxHash as TxHashAttr, + ComposeEvent, Height as HeightAttr, TxHash as TxHashAttr, }; use namada_events::EventLevel; use namada_gas::TxGasMeter; @@ -335,6 +336,7 @@ where if is_accepted { // If the transaction was a masp one append the // transaction refs for the events + //FIXME: should join this logic with the one used by the vp? if let Some(masp_section_ref) = state .read_actions() .map_err(|e| Error::StateError(e))? diff --git a/crates/node/src/bench_utils.rs b/crates/node/src/bench_utils.rs index 5803db5aa2..44268d3fae 100644 --- a/crates/node/src/bench_utils.rs +++ b/crates/node/src/bench_utils.rs @@ -27,9 +27,7 @@ use namada::core::masp::{ use namada::core::storage::{BlockHeight, Epoch, Key, KeySeg, TxIndex}; use namada::core::time::DateTimeUtc; use namada::core::token::{Amount, DenominatedAmount, Transfer}; -use namada::events::extend::{ - ComposeEvent, MaspTxBatchRefs, MaspTxBlockIndex, MaspTxRef, ValidMaspTxs, -}; +use namada::events::extend::{ComposeEvent, MaspTxBatchRefs, MaspTxBlockIndex}; use namada::events::Event; use namada::governance::storage::proposal::ProposalType; use namada::governance::InitProposalData; @@ -76,6 +74,7 @@ use namada::ledger::native_vp::ibc::get_dummy_header; use namada::ledger::queries::{ Client, EncodedResponseQuery, RequestCtx, RequestQuery, Router, RPC, }; +use namada::masp::{BatchMaspTxRefs, MaspTxRef}; use namada::state::StorageRead; use namada::tx::data::pos::Bond; use namada::tx::data::{ @@ -924,7 +923,7 @@ impl Client for BenchShell { .with(MaspTxBlockIndex(TxIndex::must_from_usize( idx, ))) - .with(MaspTxBatchRefs(ValidMaspTxs(vec![ + .with(MaspTxBatchRefs(BatchMaspTxRefs(vec![ MaspTxRef { cmt: tx .first_commitments() diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index a9ce16da36..a124dbc5ed 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -4,7 +4,6 @@ use data_encoding::HEXUPPER; use masp_primitives::merkle_tree::CommitmentTree; use masp_primitives::sapling::Node; use namada::core::storage::{BlockResults, Epoch, Header}; -use namada::events::extend::ValidMaspTxs; use namada::events::Event; use namada::gas::event::GasUsed; use namada::governance::pgf::inflation as pgf_inflation; @@ -17,6 +16,7 @@ use namada::ledger::gas::GasMetering; use namada::ledger::ibc; use namada::ledger::pos::namada_proof_of_stake; use namada::ledger::protocol::DispatchError; +use namada::masp::BatchMaspTxRefs; use namada::proof_of_stake; use namada::proof_of_stake::storage::{ find_validator_by_raw_hash, write_last_block_proposer_address, @@ -824,7 +824,7 @@ impl<'finalize> TempTxLogs { fn check_inner_results( &mut self, tx_result: &namada::tx::data::TxResult, - masp_tx_refs: ValidMaspTxs, + masp_tx_refs: BatchMaspTxRefs, tx_header: &namada::tx::Header, tx_index: usize, height: BlockHeight, diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index a98228fb6d..e5fd6e2760 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -57,13 +57,13 @@ pub use namada_core::masp::{ encode_asset_type, AssetData, BalanceOwner, ExtendedViewingKey, PaymentAddress, TransferSource, TransferTarget, }; +use namada_core::masp::{BatchMaspTxRefs, MaspTxRef}; use namada_core::storage::{BlockHeight, Epoch, TxIndex}; use namada_core::time::{DateTimeUtc, DurationSecs}; use namada_core::uint::Uint; use namada_events::extend::{ MaspTxBatchRefs as MaspTxBatchRefsAttr, - MaspTxBlockIndex as MaspTxBlockIndexAttr, MaspTxRef, - ReadFromEventAttributes, ValidMaspTxs, + MaspTxBlockIndex as MaspTxBlockIndexAttr, ReadFromEventAttributes, }; use namada_ibc::IbcMessage; use namada_macros::BorshDeserializer; @@ -860,7 +860,7 @@ impl ShieldedContext { /// Extract the relevant shield portions of a [`Tx`], if any. async fn extract_masp_tx( tx: &Tx, - masp_section_refs: &ValidMaspTxs, + masp_section_refs: &BatchMaspTxRefs, ) -> Result { // NOTE: simply looking for masp sections attached to the tx // is not safe. We don't validate the sections attached to a @@ -2020,7 +2020,7 @@ async fn get_indexed_masp_events_at_height( client: &C, height: BlockHeight, first_idx_to_query: Option, -) -> Result>, Error> { +) -> Result>, Error> { let first_idx_to_query = first_idx_to_query.unwrap_or_default(); Ok(client diff --git a/crates/tx/src/data/mod.rs b/crates/tx/src/data/mod.rs index c4819a25a9..e2100ce509 100644 --- a/crates/tx/src/data/mod.rs +++ b/crates/tx/src/data/mod.rs @@ -21,8 +21,8 @@ use namada_core::borsh::{ BorshDeserialize, BorshSchema, BorshSerialize, BorshSerializeExt, }; use namada_core::hash::Hash; +use namada_core::masp::BatchMaspTxRefs; use namada_core::storage; -use namada_events::extend::{MaspTxRef, ValidMaspTxs}; use namada_events::Event; use namada_gas::{Gas, VpsGas}; use namada_macros::BorshDeserializer; @@ -239,10 +239,11 @@ impl<'de, T: Deserialize<'de>> serde::Deserialize<'de> for BatchResults { } } -/// The extended transaction result, containing the optional references to masp sections +/// The extended transaction result, containing the references to masp +/// sections (if any) pub struct ExtendedTxResult { pub tx_result: TxResult, - pub masp_tx_refs: ValidMaspTxs, + pub masp_tx_refs: BatchMaspTxRefs, } impl Default for ExtendedTxResult { @@ -299,7 +300,7 @@ impl TxResult { /// Converts this result to [`ExtendedTxResult`] pub fn to_extended_result( self, - masp_tx_refs: Option, + masp_tx_refs: Option, ) -> ExtendedTxResult { ExtendedTxResult { tx_result: self, From c3bd934de7c53d96e5b220c81ef32e084bc63f7f Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Thu, 23 May 2024 14:36:50 +0200 Subject: [PATCH 42/70] Helper function for masp action handling --- crates/namada/src/ledger/native_vp/masp.rs | 28 ++++++++++------------ crates/namada/src/ledger/protocol/mod.rs | 19 +++------------ crates/tx/src/action.rs | 14 +++++++++++ 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/crates/namada/src/ledger/native_vp/masp.rs b/crates/namada/src/ledger/native_vp/masp.rs index 19ca2a292a..9ae17dd5a5 100644 --- a/crates/namada/src/ledger/native_vp/masp.rs +++ b/crates/namada/src/ledger/native_vp/masp.rs @@ -353,21 +353,19 @@ where let conversion_state = self.ctx.state.in_mem().get_conversion_state(); // Get the Transaction object from the actions - let shielded_tx = self - .ctx - .read_actions()? - .iter() - .find_map(|action| { - // In case of multiple masp actions we only get the first one - if let Action::Masp(MaspAction { - ref masp_section_ref, - }) = action - { - tx_data.tx.get_section(masp_section_ref)?.masp_tx() - } else { - None - } - }) + let masp_section_ref = namada_tx::action::get_masp_section_ref( + &self.ctx, + )? + .ok_or_else(|| { + native_vp::Error::new_const( + "Missing MASP section reference in action", + ) + })?; + let shielded_tx = tx_data + .tx + .get_section(&masp_section_ref) + .map(|section| section.masp_tx()) + .flatten() .ok_or_else(|| { native_vp::Error::new_const( "Missing MASP section in transaction", diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index ff72bf0515..16d0f48295 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -336,22 +336,9 @@ where if is_accepted { // If the transaction was a masp one append the // transaction refs for the events - //FIXME: should join this logic with the one used by the vp? - if let Some(masp_section_ref) = state - .read_actions() - .map_err(|e| Error::StateError(e))? - .into_iter() - .find_map(|action| { - // In case of multiple masp actions we get the first one - if let Action::Masp(MaspAction { - masp_section_ref, - }) = action - { - Some(masp_section_ref) - } else { - None - } - }) + if let Some(masp_section_ref) = + namada_tx::action::get_masp_section_ref(state) + .map_err(|e| Error::StateError(e))? { extended_tx_result.masp_tx_refs.0.push(MaspTxRef { cmt: cmt.get_hash(), diff --git a/crates/tx/src/action.rs b/crates/tx/src/action.rs index 2502ca945d..29d0be536a 100644 --- a/crates/tx/src/action.rs +++ b/crates/tx/src/action.rs @@ -116,3 +116,17 @@ fn storage_key() -> storage::Key { .push(&TX_ACTIONS_KEY.to_owned()) .expect("Cannot obtain a storage key") } + +/// Helper function to get the optional masp section reference from the [`Actions`]. If more than one [`MaspAction`] has been found we return the first one +pub fn get_masp_section_ref( + reader: &T, +) -> Result, ::Err> { + Ok(reader.read_actions()?.into_iter().find_map(|action| { + // In case of multiple masp actions we get the first one + if let Action::Masp(MaspAction { masp_section_ref }) = action { + Some(masp_section_ref) + } else { + None + } + })) +} From f018033a004d770576cc8d915ad57f7204ce974f Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Thu, 23 May 2024 15:15:25 +0200 Subject: [PATCH 43/70] Reworks masp tx indexing --- crates/core/src/masp.rs | 17 +- crates/events/src/extend.rs | 12 +- crates/namada/src/ledger/native_vp/masp.rs | 4 +- crates/namada/src/ledger/protocol/mod.rs | 14 +- crates/node/src/bench_utils.rs | 32 +-- crates/node/src/shell/finalize_block.rs | 4 +- crates/sdk/src/masp.rs | 296 +++++++++------------ crates/shielded_token/src/utils.rs | 8 +- crates/tx/src/action.rs | 5 +- crates/tx/src/data/mod.rs | 8 +- crates/tx/src/types.rs | 8 +- crates/vp_env/src/lib.rs | 1 - wasm/tx_ibc/src/lib.rs | 37 ++- wasm/tx_transfer/src/lib.rs | 5 +- 14 files changed, 185 insertions(+), 266 deletions(-) diff --git a/crates/core/src/masp.rs b/crates/core/src/masp.rs index 2c72ab1c38..58278eced6 100644 --- a/crates/core/src/masp.rs +++ b/crates/core/src/masp.rs @@ -534,28 +534,17 @@ impl FromStr for MaspValue { } } -/// Reference to a masp transaction inside a [`BatchedTx`] -#[derive(Clone, Serialize, Deserialize)] -pub struct MaspTxRef { - // FIXME: actually, are we using the commitment? Probably if I give the - // masp section ref I don't need the commitment anymore right? - /// The inner tx commitment's hash - pub cmt: Hash, - /// The hash of the masp [`Section::MaspTx`] - pub masp_section_ref: Hash, -} - /// The masp transactions' references of a given batch #[derive(Default, Clone, Serialize, Deserialize)] -pub struct BatchMaspTxRefs(pub Vec); +pub struct MaspTxRefs(pub Vec); -impl Display for BatchMaspTxRefs { +impl Display for MaspTxRefs { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", serde_json::to_string(self).unwrap()) } } -impl FromStr for BatchMaspTxRefs { +impl FromStr for MaspTxRefs { type Err = serde_json::Error; fn from_str(s: &str) -> Result { diff --git a/crates/events/src/extend.rs b/crates/events/src/extend.rs index 78058e5436..f51052a0f5 100644 --- a/crates/events/src/extend.rs +++ b/crates/events/src/extend.rs @@ -2,12 +2,12 @@ use std::fmt::Display; use std::marker::PhantomData; -use std::ops::{ControlFlow, DerefMut}; +use std::ops::ControlFlow; use std::str::FromStr; use namada_core::collections::HashMap; use namada_core::hash::Hash; -use namada_core::masp::BatchMaspTxRefs; +use namada_core::masp::MaspTxRefs; use namada_core::storage::{BlockHeight, TxIndex}; use super::*; @@ -502,10 +502,10 @@ impl EventAttributeEntry<'static> for MaspTxBlockIndex { /// Extend an [`Event`] with `masp_tx_batch_refs` data, indicating the specific /// inner transactions inside the batch that are valid masp txs and the /// references to the relative masp sections. -pub struct MaspTxBatchRefs(pub BatchMaspTxRefs); +pub struct MaspTxBatchRefs(pub MaspTxRefs); impl EventAttributeEntry<'static> for MaspTxBatchRefs { - type Value = BatchMaspTxRefs; + type Value = MaspTxRefs; type ValueOwned = Self::Value; const KEY: &'static str = "masp_tx_batch_refs"; @@ -607,8 +607,8 @@ where } /// Return a new implementation of [`EventAttributeChecker`]. -pub fn attribute_checker<'value, DATA, ATTR>( -) -> Box> +pub fn attribute_checker<'value, DATA, ATTR>() +-> Box> where DATA: EventAttributeEntry<'value> + 'static, ATTR: AttributesMap, diff --git a/crates/namada/src/ledger/native_vp/masp.rs b/crates/namada/src/ledger/native_vp/masp.rs index 9ae17dd5a5..a344629983 100644 --- a/crates/namada/src/ledger/native_vp/masp.rs +++ b/crates/namada/src/ledger/native_vp/masp.rs @@ -25,7 +25,6 @@ use namada_proof_of_stake::Epoch; use namada_sdk::masp::verify_shielded_tx; use namada_state::{ConversionState, OptionExt, ResultExt, StateRead}; use namada_token::read_denom; -use namada_tx::action::{Action, MaspAction, Read}; use namada_tx::BatchedTxRef; use namada_vp_env::VpEnv; use ripemd::Digest as RipemdDigest; @@ -364,8 +363,7 @@ where let shielded_tx = tx_data .tx .get_section(&masp_section_ref) - .map(|section| section.masp_tx()) - .flatten() + .and_then(|section| section.masp_tx()) .ok_or_else(|| { native_vp::Error::new_const( "Missing MASP section in transaction", diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index 16d0f48295..4b74de75ca 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -7,7 +7,6 @@ use borsh_ext::BorshSerializeExt; use eyre::{eyre, WrapErr}; use namada_core::booleans::BoolResultUnitExt; use namada_core::hash::Hash; -use namada_core::masp::MaspTxRef; use namada_core::storage::Key; use namada_events::extend::{ ComposeEvent, Height as HeightAttr, TxHash as TxHashAttr, @@ -15,9 +14,8 @@ use namada_events::extend::{ use namada_events::EventLevel; use namada_gas::TxGasMeter; use namada_sdk::tx::TX_TRANSFER_WASM; -use namada_state::{StateRead, StorageWrite}; +use namada_state::StorageWrite; use namada_token::event::{TokenEvent, TokenOperation, UserAccount}; -use namada_tx::action::{Action, MaspAction, Read}; use namada_tx::data::protocol::ProtocolTxType; use namada_tx::data::{ BatchResults, BatchedTxResult, ExtendedTxResult, TxResult, TxType, @@ -338,12 +336,12 @@ where // transaction refs for the events if let Some(masp_section_ref) = namada_tx::action::get_masp_section_ref(state) - .map_err(|e| Error::StateError(e))? + .map_err(Error::StateError)? { - extended_tx_result.masp_tx_refs.0.push(MaspTxRef { - cmt: cmt.get_hash(), - masp_section_ref, - }); + extended_tx_result + .masp_tx_refs + .0 + .push(masp_section_ref); } state.write_log_mut().commit_tx_to_batch(); } else { diff --git a/crates/node/src/bench_utils.rs b/crates/node/src/bench_utils.rs index 44268d3fae..4231f65d01 100644 --- a/crates/node/src/bench_utils.rs +++ b/crates/node/src/bench_utils.rs @@ -74,7 +74,7 @@ use namada::ledger::native_vp::ibc::get_dummy_header; use namada::ledger::queries::{ Client, EncodedResponseQuery, RequestCtx, RequestQuery, Router, RPC, }; -use namada::masp::{BatchMaspTxRefs, MaspTxRef}; +use namada::masp::MaspTxRefs; use namada::state::StorageRead; use namada::tx::data::pos::Bond; use namada::tx::data::{ @@ -923,25 +923,17 @@ impl Client for BenchShell { .with(MaspTxBlockIndex(TxIndex::must_from_usize( idx, ))) - .with(MaspTxBatchRefs(BatchMaspTxRefs(vec![ - MaspTxRef { - cmt: tx - .first_commitments() - .unwrap() - .get_hash(), - masp_section_ref: tx - .sections - .iter() - .find_map(|section| { - if let Section::MaspTx(_) = section - { - Some(section.get_hash()) - } else { - None - } - }) - .unwrap(), - }, + .with(MaspTxBatchRefs(MaspTxRefs(vec![ + tx.sections + .iter() + .find_map(|section| { + if let Section::MaspTx(_) = section { + Some(section.get_hash()) + } else { + None + } + }) + .unwrap(), ]))) .into(); namada::tendermint::abci::Event::from(event) diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index a124dbc5ed..0fac63841d 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -16,7 +16,7 @@ use namada::ledger::gas::GasMetering; use namada::ledger::ibc; use namada::ledger::pos::namada_proof_of_stake; use namada::ledger::protocol::DispatchError; -use namada::masp::BatchMaspTxRefs; +use namada::masp::MaspTxRefs; use namada::proof_of_stake; use namada::proof_of_stake::storage::{ find_validator_by_raw_hash, write_last_block_proposer_address, @@ -824,7 +824,7 @@ impl<'finalize> TempTxLogs { fn check_inner_results( &mut self, tx_result: &namada::tx::data::TxResult, - masp_tx_refs: BatchMaspTxRefs, + masp_tx_refs: MaspTxRefs, tx_header: &namada::tx::Header, tx_index: usize, height: BlockHeight, diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index e5fd6e2760..3fe9c0f222 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -53,11 +53,11 @@ use masp_proofs::sapling::SaplingVerificationContext; use namada_core::address::Address; use namada_core::collections::{HashMap, HashSet}; use namada_core::dec::Dec; +use namada_core::masp::MaspTxRefs; pub use namada_core::masp::{ encode_asset_type, AssetData, BalanceOwner, ExtendedViewingKey, PaymentAddress, TransferSource, TransferTarget, }; -use namada_core::masp::{BatchMaspTxRefs, MaspTxRef}; use namada_core::storage::{BlockHeight, Epoch, TxIndex}; use namada_core::time::{DateTimeUtc, DurationSecs}; use namada_core::uint::Uint; @@ -65,13 +65,12 @@ use namada_events::extend::{ MaspTxBatchRefs as MaspTxBatchRefsAttr, MaspTxBlockIndex as MaspTxBlockIndexAttr, ReadFromEventAttributes, }; -use namada_ibc::IbcMessage; use namada_macros::BorshDeserializer; #[cfg(feature = "migrations")] use namada_migrations::*; use namada_state::StorageError; -use namada_token::{self as token, Denomination, MaspDigitPos, Transfer}; -use namada_tx::{IndexedTx, Tx, TxCommitments}; +use namada_token::{self as token, Denomination, MaspDigitPos}; +use namada_tx::{IndexedTx, Tx}; use rand_core::{CryptoRng, OsRng, RngCore}; use ripemd::Digest as RipemdDigest; use sha2::Digest; @@ -103,10 +102,10 @@ pub const OUTPUT_NAME: &str = "masp-output.params"; pub const CONVERT_NAME: &str = "masp-convert.params"; /// Type alias for convenience and profit -pub type IndexedNoteData = BTreeMap; +pub type IndexedNoteData = BTreeMap>; /// Type alias for the entries of [`IndexedNoteData`] iterators -pub type IndexedNoteEntry = (IndexedTx, Transaction); +pub type IndexedNoteEntry = (IndexedTx, Vec); /// Shielded transfer #[derive(Clone, Debug, BorshSerialize, BorshDeserialize, BorshDeserializer)] @@ -144,9 +143,6 @@ pub enum TransferErr { General(#[from] Error), } -#[derive(Debug, Clone)] -struct ExtractedMaspTxs(Vec<(TxCommitments, Transaction)>); - /// MASP verifying keys pub struct PVKs { /// spend verifying key @@ -668,35 +664,37 @@ impl ShieldedContext { } /// Update the merkle tree of witnesses the first time we - /// scan a new MASP transaction. + /// scan new MASP transactions. fn update_witness_map( &mut self, indexed_tx: IndexedTx, - shielded: &Transaction, + shielded: &[Transaction], ) -> Result<(), Error> { let mut note_pos = self.tree.size(); self.tx_note_map.insert(indexed_tx, note_pos); - for so in shielded - .sapling_bundle() - .map_or(&vec![], |x| &x.shielded_outputs) - { - // Create merkle tree leaf node from note commitment - let node = Node::new(so.cmu.to_repr()); - // Update each merkle tree in the witness map with the latest - // addition - for (_, witness) in self.witness_map.iter_mut() { - witness.append(node).map_err(|()| { + + for tx in shielded { + for so in + tx.sapling_bundle().map_or(&vec![], |x| &x.shielded_outputs) + { + // Create merkle tree leaf node from note commitment + let node = Node::new(so.cmu.to_repr()); + // Update each merkle tree in the witness map with the latest + // addition + for (_, witness) in self.witness_map.iter_mut() { + witness.append(node).map_err(|()| { + Error::Other("note commitment tree is full".to_string()) + })?; + } + self.tree.append(node).map_err(|()| { Error::Other("note commitment tree is full".to_string()) })?; + // Finally, make it easier to construct merkle paths to this new + // note + let witness = IncrementalWitness::::from_tree(&self.tree); + self.witness_map.insert(note_pos, witness); + note_pos += 1; } - self.tree.append(node).map_err(|()| { - Error::Other("note commitment tree is full".to_string()) - })?; - // Finally, make it easier to construct merkle paths to this new - // note - let witness = IncrementalWitness::::from_tree(&self.tree); - self.witness_map.insert(note_pos, witness); - note_pos += 1; } Ok(()) } @@ -841,16 +839,13 @@ impl ShieldedContext { let extracted_masp_txs = Self::extract_masp_tx(&tx, &masp_sections_refs).await?; // Collect the current transactions - for (inner_tx, transaction) in extracted_masp_txs.0 { - shielded_txs.insert( - IndexedTx { - height: height.into(), - index: idx, - inner_tx, - }, - transaction, - ); - } + shielded_txs.insert( + IndexedTx { + height: height.into(), + index: idx, + }, + extracted_masp_txs, + ); } } @@ -860,44 +855,33 @@ impl ShieldedContext { /// Extract the relevant shield portions of a [`Tx`], if any. async fn extract_masp_tx( tx: &Tx, - masp_section_refs: &BatchMaspTxRefs, - ) -> Result { + masp_section_refs: &MaspTxRefs, + ) -> Result, Error> { // NOTE: simply looking for masp sections attached to the tx // is not safe. We don't validate the sections attached to a // transaction se we could end up with transactions carrying // an unnecessary masp section. We must instead look for the // required masp sections coming from the events - let mut txs = vec![]; - for MaspTxRef { - cmt, - masp_section_ref, - } in &masp_section_refs.0 - { - let transaction = tx - .get_section(masp_section_ref) - .map(|section| section.masp_tx()) - .flatten() - .ok_or_else(|| { - Error::Other( - "Missing expected masp transaction".to_string(), - ) - })?; - - let cmt = tx - .commitments() - .iter() - .find(|inner_tx| &inner_tx.get_hash() == cmt) - .ok_or_else(|| { - Error::Other( - "Missing expected inner transaction".to_string(), - ) - })?; - - txs.push((cmt.to_owned(), transaction)); - } - - Ok(ExtractedMaspTxs(txs)) + masp_section_refs + .0 + .iter() + .try_fold(vec![], |mut acc, hash| { + match tx + .get_section(hash) + .and_then(|section| section.masp_tx()) + .ok_or_else(|| { + Error::Other( + "Missing expected masp transaction".to_string(), + ) + }) { + Ok(transaction) => { + acc.push(transaction); + Ok(acc) + } + Err(e) => Err(e), + } + }) } /// Applies the given transaction to the supplied context. More precisely, @@ -911,7 +895,7 @@ impl ShieldedContext { pub fn scan_tx( &mut self, indexed_tx: IndexedTx, - shielded: &Transaction, + shielded: &[Transaction], vk: &ViewingKey, ) -> Result<(), Error> { // For tracking the account changes caused by this Transaction @@ -920,42 +904,78 @@ impl ShieldedContext { let mut note_pos = self.tx_note_map[&indexed_tx]; // Listen for notes sent to our viewing keys, only if we are syncing // (i.e. in a confirmed status) - for so in shielded - .sapling_bundle() - .map_or(&vec![], |x| &x.shielded_outputs) - { - // Let's try to see if this viewing key can decrypt latest - // note - let notes = self.pos_map.entry(*vk).or_default(); - let decres = try_sapling_note_decryption::<_, OutputDescription<<::SaplingAuth as masp_primitives::transaction::components::sapling::Authorization>::Proof>>( + for tx in shielded { + for so in + tx.sapling_bundle().map_or(&vec![], |x| &x.shielded_outputs) + { + // Let's try to see if this viewing key can decrypt latest + // note + let notes = self.pos_map.entry(*vk).or_default(); + let decres = try_sapling_note_decryption::<_, OutputDescription<<::SaplingAuth as masp_primitives::transaction::components::sapling::Authorization>::Proof>>( &NETWORK, 1.into(), &PreparedIncomingViewingKey::new(&vk.ivk()), so, ); - // So this current viewing key does decrypt this current note... - if let Some((note, pa, memo)) = decres { - // Add this note to list of notes decrypted by this viewing - // key - notes.insert(note_pos); - // Compute the nullifier now to quickly recognize when spent - let nf = note.nf( - &vk.nk, - note_pos.try_into().map_err(|_| { - Error::Other("Can not get nullifier".to_string()) - })?, - ); - self.note_map.insert(note_pos, note); - self.memo_map.insert(note_pos, memo); - // The payment address' diversifier is required to spend - // note - self.div_map.insert(note_pos, *pa.diversifier()); - self.nf_map.insert(nf, note_pos); + // So this current viewing key does decrypt this current + // note... + if let Some((note, pa, memo)) = decres { + // Add this note to list of notes decrypted by this + // viewing key + notes.insert(note_pos); + // Compute the nullifier now to quickly recognize when + // spent + let nf = note.nf( + &vk.nk, + note_pos.try_into().map_err(|_| { + Error::Other( + "Can not get nullifier".to_string(), + ) + })?, + ); + self.note_map.insert(note_pos, note); + self.memo_map.insert(note_pos, memo); + // The payment address' diversifier is required to spend + // note + self.div_map.insert(note_pos, *pa.diversifier()); + self.nf_map.insert(nf, note_pos); + // Note the account changes + let balance = transaction_delta + .entry(*vk) + .or_insert_with(I128Sum::zero); + *balance += I128Sum::from_nonnegative( + note.asset_type, + note.value as i128, + ) + .map_err(|()| { + Error::Other( + "found note with invalid value or asset type" + .to_string(), + ) + })?; + self.vk_map.insert(note_pos, *vk); + } + note_pos += 1; + } + } + } + + // Cancel out those of our notes that have been spent + for tx in shielded { + for ss in + tx.sapling_bundle().map_or(&vec![], |x| &x.shielded_spends) + { + // If the shielded spend's nullifier is in our map, then target + // note is rendered unusable + if let Some(note_pos) = self.nf_map.get(&ss.nullifier) { + self.spents.insert(*note_pos); // Note the account changes let balance = transaction_delta - .entry(*vk) + .entry(self.vk_map[note_pos]) .or_insert_with(I128Sum::zero); - *balance += I128Sum::from_nonnegative( + let note = self.note_map[note_pos]; + + *balance -= I128Sum::from_nonnegative( note.asset_type, note.value as i128, ) @@ -965,37 +985,7 @@ impl ShieldedContext { .to_string(), ) })?; - self.vk_map.insert(note_pos, *vk); } - note_pos += 1; - } - } - - // Cancel out those of our notes that have been spent - for ss in shielded - .sapling_bundle() - .map_or(&vec![], |x| &x.shielded_spends) - { - // If the shielded spend's nullifier is in our map, then target note - // is rendered unusable - if let Some(note_pos) = self.nf_map.get(&ss.nullifier) { - self.spents.insert(*note_pos); - // Note the account changes - let balance = transaction_delta - .entry(self.vk_map[note_pos]) - .or_insert_with(I128Sum::zero); - let note = self.note_map[note_pos]; - - *balance -= I128Sum::from_nonnegative( - note.asset_type, - note.value as i128, - ) - .map_err(|()| { - Error::Other( - "found note with invalid value or asset type" - .to_string(), - ) - })?; } } @@ -1899,7 +1889,7 @@ impl ShieldedContext { // Cache the generated transfer let mut shielded_ctx = context.shielded_mut().await; shielded_ctx - .pre_cache_transaction(context, &masp_tx) + .pre_cache_transaction(context, &[masp_tx.clone()]) .await?; } @@ -1918,7 +1908,7 @@ impl ShieldedContext { async fn pre_cache_transaction( &mut self, context: &impl Namada, - masp_tx: &Transaction, + masp_tx: &[Transaction], ) -> Result<(), Error> { let vks: Vec<_> = context .wallet() @@ -1938,7 +1928,6 @@ impl ShieldedContext { .index .checked_add(1) .expect("Tx index shouldn't overflow"), - inner_tx: TxCommitments::default(), } }); self.sync_status = ContextSyncStatus::Speculative; @@ -2020,7 +2009,7 @@ async fn get_indexed_masp_events_at_height( client: &C, height: BlockHeight, first_idx_to_query: Option, -) -> Result>, Error> { +) -> Result>, Error> { let first_idx_to_query = first_idx_to_query.unwrap_or_default(); Ok(client @@ -2055,45 +2044,6 @@ async fn get_indexed_masp_events_at_height( })) } -// Extract the Transaction hash from a masp over ibc message -async fn extract_payload_from_shielded_action( - tx_data: &[u8], -) -> Result { - let message = namada_ibc::decode_message(tx_data) - .map_err(|e| Error::Other(e.to_string()))?; - - let result = match message { - IbcMessage::Transfer(msg) => msg.transfer.ok_or_else(|| { - Error::Other("Missing masp tx in the ibc message".to_string()) - })?, - IbcMessage::NftTransfer(msg) => msg.transfer.ok_or_else(|| { - Error::Other("Missing masp tx in the ibc message".to_string()) - })?, - IbcMessage::RecvPacket(msg) => msg.transfer.ok_or_else(|| { - Error::Other("Missing masp tx in the ibc message".to_string()) - })?, - IbcMessage::AckPacket(msg) => { - // Refund tokens by the ack message - msg.transfer.ok_or_else(|| { - Error::Other("Missing masp tx in the ibc message".to_string()) - })? - } - IbcMessage::Timeout(msg) => { - // Refund tokens by the timeout message - msg.transfer.ok_or_else(|| { - Error::Other("Missing masp tx in the ibc message".to_string()) - })? - } - IbcMessage::Envelope(_) => { - return Err(Error::Other( - "Unexpected ibc message for masp".to_string(), - )); - } - }; - - Ok(result) -} - mod tests { /// quick and dirty test. will fail on size check #[test] diff --git a/crates/shielded_token/src/utils.rs b/crates/shielded_token/src/utils.rs index 22d783f67f..3d3240b18d 100644 --- a/crates/shielded_token/src/utils.rs +++ b/crates/shielded_token/src/utils.rs @@ -1,17 +1,11 @@ //! MASP utilities -use std::collections::BTreeSet; - use masp_primitives::merkle_tree::CommitmentTree; use masp_primitives::sapling::Node; use masp_primitives::transaction::Transaction; -use namada_core::storage; use namada_storage::{Error, Result, StorageRead, StorageWrite}; -use crate::storage_key::{ - is_masp_key, is_masp_transfer_key, masp_commitment_tree_key, - masp_nullifier_key, -}; +use crate::storage_key::{masp_commitment_tree_key, masp_nullifier_key}; // Writes the nullifiers of the provided masp transaction to storage fn reveal_nullifiers( diff --git a/crates/tx/src/action.rs b/crates/tx/src/action.rs index 29d0be536a..c43820c019 100644 --- a/crates/tx/src/action.rs +++ b/crates/tx/src/action.rs @@ -66,6 +66,7 @@ pub enum PgfAction { /// MASP tx action. #[derive(Clone, Debug, BorshDeserialize, BorshSerialize)] pub struct MaspAction { + /// The hash of the masp [`Section`] pub masp_section_ref: Hash, } @@ -117,7 +118,9 @@ fn storage_key() -> storage::Key { .expect("Cannot obtain a storage key") } -/// Helper function to get the optional masp section reference from the [`Actions`]. If more than one [`MaspAction`] has been found we return the first one +/// Helper function to get the optional masp section reference from the +/// [`Actions`]. If more than one [`MaspAction`] has been found we return the +/// first one pub fn get_masp_section_ref( reader: &T, ) -> Result, ::Err> { diff --git a/crates/tx/src/data/mod.rs b/crates/tx/src/data/mod.rs index e2100ce509..20c4019fc2 100644 --- a/crates/tx/src/data/mod.rs +++ b/crates/tx/src/data/mod.rs @@ -21,7 +21,7 @@ use namada_core::borsh::{ BorshDeserialize, BorshSchema, BorshSerialize, BorshSerializeExt, }; use namada_core::hash::Hash; -use namada_core::masp::BatchMaspTxRefs; +use namada_core::masp::MaspTxRefs; use namada_core::storage; use namada_events::Event; use namada_gas::{Gas, VpsGas}; @@ -242,8 +242,10 @@ impl<'de, T: Deserialize<'de>> serde::Deserialize<'de> for BatchResults { /// The extended transaction result, containing the references to masp /// sections (if any) pub struct ExtendedTxResult { + /// The transaction result pub tx_result: TxResult, - pub masp_tx_refs: BatchMaspTxRefs, + /// The optional references to masp sections + pub masp_tx_refs: MaspTxRefs, } impl Default for ExtendedTxResult { @@ -300,7 +302,7 @@ impl TxResult { /// Converts this result to [`ExtendedTxResult`] pub fn to_extended_result( self, - masp_tx_refs: Option, + masp_tx_refs: Option, ) -> ExtendedTxResult { ExtendedTxResult { tx_result: self, diff --git a/crates/tx/src/types.rs b/crates/tx/src/types.rs index c783ce6076..3156b584d5 100644 --- a/crates/tx/src/types.rs +++ b/crates/tx/src/types.rs @@ -1730,8 +1730,8 @@ impl<'tx> Tx { } } -/// Represents the pointers of an indexed tx, which are the block height, the -/// index inside that block and the commitment inside the tx bundle +/// Represents the pointers to a indexed tx, which are the block height and the +/// index inside that block #[derive( Debug, Clone, @@ -1749,9 +1749,6 @@ pub struct IndexedTx { pub height: BlockHeight, /// The index in the block of the tx pub index: TxIndex, - /// This is a pointer to the inner tx inside the batch - //FIXME: do we really need this? Probably not for the masp - pub inner_tx: TxCommitments, } impl Default for IndexedTx { @@ -1759,7 +1756,6 @@ impl Default for IndexedTx { Self { height: BlockHeight::first(), index: TxIndex(0), - inner_tx: TxCommitments::default(), } } } diff --git a/crates/vp_env/src/lib.rs b/crates/vp_env/src/lib.rs index 642d2a7fc9..7751632299 100644 --- a/crates/vp_env/src/lib.rs +++ b/crates/vp_env/src/lib.rs @@ -24,7 +24,6 @@ use namada_core::address::Address; use namada_core::borsh::BorshDeserialize; use namada_core::hash::Hash; use namada_core::storage::{BlockHeight, Epoch, Epochs, Header, Key, TxIndex}; -use namada_core::token::Transfer; use namada_events::{Event, EventType}; use namada_storage::StorageRead; use namada_tx::BatchedTxRef; diff --git a/wasm/tx_ibc/src/lib.rs b/wasm/tx_ibc/src/lib.rs index f7c27f9eb9..a91ef16f91 100644 --- a/wasm/tx_ibc/src/lib.rs +++ b/wasm/tx_ibc/src/lib.rs @@ -12,28 +12,25 @@ fn apply_tx(ctx: &mut Ctx, tx_data: BatchedTx) -> TxResult { let transfer = ibc::ibc_actions(ctx).execute(&data).into_storage_result()?; - if let Some(transfer) = transfer { - if let Some(masp_section_ref) = transfer.shielded { - let shielded = signed - .get_section(&masp_section_ref) - .and_then(|x| x.as_ref().masp_tx()) - .ok_or_err_msg( - "Unable to find required shielded section in tx data", - ) - .map_err(|err| { - ctx.set_commitment_sentinel(); - err - })?; - token::utils::handle_masp_tx( - ctx, - &shielded, - transfer.key.as_deref(), + if let Some(masp_section_ref) = + transfer.and_then(|transfer| transfer.shielded) + { + let shielded = tx_data + .tx + .get_section(&masp_section_ref) + .and_then(|x| x.as_ref().masp_tx()) + .ok_or_err_msg( + "Unable to find required shielded section in tx data", ) + .map_err(|err| { + ctx.set_commitment_sentinel(); + err + })?; + token::utils::handle_masp_tx(ctx, &shielded) .wrap_err("Encountered error while handling MASP transaction")?; - update_masp_note_commitment_tree(&shielded) - .wrap_err("Failed to update the MASP commitment tree")?; - ctx.push_action(Action::Masp(MaspAction { masp_section_ref }))?; - } + update_masp_note_commitment_tree(&shielded) + .wrap_err("Failed to update the MASP commitment tree")?; + ctx.push_action(Action::Masp(MaspAction { masp_section_ref }))?; } Ok(()) diff --git a/wasm/tx_transfer/src/lib.rs b/wasm/tx_transfer/src/lib.rs index 871cb836fc..62e7adebac 100644 --- a/wasm/tx_transfer/src/lib.rs +++ b/wasm/tx_transfer/src/lib.rs @@ -22,7 +22,8 @@ fn apply_tx(ctx: &mut Ctx, tx_data: BatchedTx) -> TxResult { .wrap_err("Token transfer failed")?; if let Some(masp_section_ref) = transfer.shielded { - let shielded = signed + let shielded = tx_data + .tx .get_section(&masp_section_ref) .and_then(|x| x.as_ref().masp_tx()) .ok_or_err_msg( @@ -32,7 +33,7 @@ fn apply_tx(ctx: &mut Ctx, tx_data: BatchedTx) -> TxResult { ctx.set_commitment_sentinel(); err })?; - token::utils::handle_masp_tx(ctx, &shielded, transfer.key.as_deref()) + token::utils::handle_masp_tx(ctx, &shielded) .wrap_err("Encountered error while handling MASP transaction")?; update_masp_note_commitment_tree(&shielded) .wrap_err("Failed to update the MASP commitment tree")?; From 0b709e72212320a243c64d32e438044eeac3a1d7 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Thu, 23 May 2024 17:32:01 +0200 Subject: [PATCH 44/70] Fixes broken doc link --- crates/tx/src/action.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/tx/src/action.rs b/crates/tx/src/action.rs index c43820c019..6748e181aa 100644 --- a/crates/tx/src/action.rs +++ b/crates/tx/src/action.rs @@ -66,7 +66,7 @@ pub enum PgfAction { /// MASP tx action. #[derive(Clone, Debug, BorshDeserialize, BorshSerialize)] pub struct MaspAction { - /// The hash of the masp [`Section`] + /// The hash of the masp [`crate::types::Section`] pub masp_section_ref: Hash, } From 4bf8fcc3716b20a9b60c83fd1bd65a4a8a891f62 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Thu, 23 May 2024 17:15:32 +0200 Subject: [PATCH 45/70] Changelog #3232 --- .changelog/unreleased/improvements/3232-masp-no-transfer-dep.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/3232-masp-no-transfer-dep.md diff --git a/.changelog/unreleased/improvements/3232-masp-no-transfer-dep.md b/.changelog/unreleased/improvements/3232-masp-no-transfer-dep.md new file mode 100644 index 0000000000..359a4d4651 --- /dev/null +++ b/.changelog/unreleased/improvements/3232-masp-no-transfer-dep.md @@ -0,0 +1,2 @@ +- Removed any dependency on the specific transaction data from the masp vp. + ([\#3232](https://github.com/anoma/namada/pull/3232)) \ No newline at end of file From 3e7fde85fe636170d49d36c6a4713290f56236eb Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 17 May 2024 12:36:14 +0100 Subject: [PATCH 46/70] Move all wasmer deps to workspace --- Cargo.toml | 3 +++ crates/namada/Cargo.toml | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0d1f58a577..7f89a6bc98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -190,8 +190,11 @@ tracing-subscriber = {version = "0.3.7", default-features = false, features = [" wasmparser = "0.107.0" wasm-instrument = {version = "0.4.0", features = ["sign_ext"]} wasmer = {git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b"} +wasmer-cache = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b" } wasmer-compiler-singlepass = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b" } +wasmer-engine-dylib = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b" } wasmer-engine-universal = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b" } +wasmer-vm = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b" } winapi = "0.3.9" yansi = "0.5.1" zeroize = { version = "1.5.5", features = ["zeroize_derive"] } diff --git a/crates/namada/Cargo.toml b/crates/namada/Cargo.toml index 3f500eb42c..db2f4e460c 100644 --- a/crates/namada/Cargo.toml +++ b/crates/namada/Cargo.toml @@ -152,11 +152,11 @@ tracing.workspace = true uint = "0.9.5" wasm-instrument = { workspace = true, optional = true } wasmer = { workspace = true, optional = true } -wasmer-cache = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b", optional = true } +wasmer-cache = { workspace = true, optional = true } wasmer-compiler-singlepass = { workspace = true, optional = true } -wasmer-engine-dylib = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b", optional = true } +wasmer-engine-dylib = { workspace = true, optional = true } wasmer-engine-universal = { workspace = true, optional = true } -wasmer-vm = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b", optional = true } +wasmer-vm = { workspace = true, optional = true } # Greater versions break in `test_tx_stack_limiter` and `test_vp_stack_limiter` wat = "=1.0.71" wasmparser.workspace = true From 9d9cb529736f0874157454c7dfbe6f9bb3d01217 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 17 May 2024 13:18:20 +0100 Subject: [PATCH 47/70] Upgrade to wasmer 4.3.1 --- Cargo.lock | 912 +++++++++++------- Cargo.toml | 10 +- crates/benches/Cargo.toml | 1 - crates/benches/wasm_opcodes.rs | 31 +- crates/namada/Cargo.toml | 6 - crates/namada/src/vm/host_env.rs | 21 +- .../src/vm/wasm/compilation_cache/common.rs | 45 +- crates/namada/src/vm/wasm/host_env.rs | 447 +++++++-- crates/namada/src/vm/wasm/memory.rs | 187 ++-- crates/namada/src/vm/wasm/run.rs | 195 ++-- wasm/Cargo.lock | 814 ++++++++++------ wasm/Cargo.toml | 2 +- wasm/tx_bond/Cargo.toml | 2 +- .../tx_change_validator_commission/Cargo.toml | 2 +- wasm/tx_redelegate/Cargo.toml | 2 +- wasm/tx_unbond/Cargo.toml | 2 +- wasm/tx_withdraw/Cargo.toml | 2 +- wasm/vp_implicit/Cargo.toml | 2 +- wasm/vp_user/Cargo.toml | 2 +- wasm_for_tests/Cargo.lock | 800 +++++++++------ wasm_for_tests/Cargo.toml | 2 +- 21 files changed, 2251 insertions(+), 1236 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a9d914fe1..3ce2c8055a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,7 +54,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "once_cell", "version_check", ] @@ -349,7 +349,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustversion", - "serde 1.0.193", + "serde 1.0.202", "sync_wrapper", "tower", "tower-layer", @@ -384,7 +384,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object 0.32.1", + "object", "rustc-demangle", ] @@ -433,7 +433,7 @@ dependencies = [ "displaydoc", "ics23", "prost 0.12.3", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "sha2 0.10.8", "tendermint 0.35.0", @@ -479,7 +479,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -488,7 +488,7 @@ version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -552,7 +552,7 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -765,7 +765,7 @@ version = "4.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da78b32057b8fdfc352504708feeba7216dcd65a2c9ab02978cbd288d1279b6c" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", "utf8-width", ] @@ -803,7 +803,16 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", +] + +[[package]] +name = "bytesize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" +dependencies = [ + "serde 1.0.202", ] [[package]] @@ -823,7 +832,7 @@ version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -832,7 +841,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -844,7 +853,7 @@ dependencies = [ "camino", "cargo-platform", "semver 1.0.20", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "thiserror", ] @@ -935,29 +944,29 @@ dependencies = [ [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", - "half", + "half 2.4.1", ] [[package]] @@ -998,6 +1007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" dependencies = [ "clap_builder", + "clap_derive", ] [[package]] @@ -1012,6 +1022,18 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "clap_lex" version = "0.6.0" @@ -1034,7 +1056,7 @@ dependencies = [ "digest 0.10.7", "hmac 0.12.1", "k256", - "serde 1.0.193", + "serde 1.0.202", "sha2 0.10.8", "thiserror", ] @@ -1068,7 +1090,7 @@ dependencies = [ "generic-array", "hex", "ripemd", - "serde 1.0.193", + "serde 1.0.202", "serde_derive", "sha2 0.10.8", "sha3", @@ -1127,7 +1149,7 @@ dependencies = [ "lazy_static", "nom 5.1.3", "rust-ini", - "serde 1.0.193", + "serde 1.0.202", "serde-hjson", "serde_json", "toml 0.5.11", @@ -1153,7 +1175,7 @@ dependencies = [ "cpufeatures", "hex", "proptest", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -1245,7 +1267,7 @@ checksum = "7879036156092ad1c22fe0d7316efc5a5eceec2bc3906462a2560215f2a2f929" dependencies = [ "cosmwasm-schema-derive", "schemars", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "thiserror", ] @@ -1276,7 +1298,7 @@ dependencies = [ "forward_ref", "hex", "schemars", - "serde 1.0.193", + "serde 1.0.202", "serde-json-wasm 0.5.2", "sha2 0.10.8", "static_assertions", @@ -1294,56 +1316,74 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38faa2a16616c8e78a18d37b4726b98bfd2de192f2fdc8a39ddf568a408a0f75" +checksum = "2a2ab4512dfd3a6f4be184403a195f76e81a8a9f9e6c898e19d2dc3ce20e0115" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f192472a3ba23860afd07d2b0217dc628f21fcc72617aa1336d98e1671f33b" +checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc" dependencies = [ + "arrayvec 0.7.4", + "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", + "cranelift-egraph", "cranelift-entity", + "cranelift-isle", "gimli 0.26.2", "log", - "regalloc", + "regalloc2", "smallvec", "target-lexicon", ] [[package]] name = "cranelift-codegen-meta" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32ddb89e9b89d3d9b36a5b7d7ea3261c98235a76ac95ba46826b8ec40b1a24" +checksum = "639307b45434ad112a98f8300c0f0ab085cbefcd767efcdef9ef19d4c0756e74" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.82.3" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "278e52e29c53fcf32431ef08406c295699a70306d05a0715c5b1bf50e33a9ab7" + +[[package]] +name = "cranelift-egraph" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01fd0d9f288cc1b42d9333b7a776b17e278fc888c28e6a0f09b5573d45a150bc" +checksum = "624b54323b06e675293939311943ba82d323bb340468ce1889be5da7932c8d73" +dependencies = [ + "cranelift-entity", + "fxhash", + "hashbrown 0.12.3", + "indexmap 1.9.3", + "log", + "smallvec", +] [[package]] name = "cranelift-entity" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3bfe172b83167604601faf9dc60453e0d0a93415b57a9c4d1a7ae6849185cf" +checksum = "9a59bcbca89c3f1b70b93ab3cbba5e5e0cbf3e63dadb23c7525cb142e21a9d4c" [[package]] name = "cranelift-frontend" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a006e3e32d80ce0e4ba7f1f9ddf66066d052a8c884a110b91d05404d6ce26dce" +checksum = "0d70abacb8cfef3dc8ff7e8836e9c1d70f7967dfdac824a4cd5e30223415aca6" dependencies = [ "cranelift-codegen", "log", @@ -1351,6 +1391,12 @@ dependencies = [ "target-lexicon", ] +[[package]] +name = "cranelift-isle" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" + [[package]] name = "crc32fast" version = "1.3.2" @@ -1379,7 +1425,7 @@ dependencies = [ "plotters", "rayon", "regex", - "serde 1.0.193", + "serde 1.0.202", "serde_derive", "serde_json", "tinytemplate", @@ -1429,6 +1475,15 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.19" @@ -1556,7 +1611,17 @@ checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" dependencies = [ "cosmwasm-std", "schemars", - "serde 1.0.193", + "serde 1.0.202", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", ] [[package]] @@ -1565,8 +1630,22 @@ version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.3", + "darling_macro 0.20.3", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", ] [[package]] @@ -1582,17 +1661,41 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ - "darling_core", + "darling_core 0.20.3", "quote", "syn 2.0.52", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.3", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "data-encoding" version = "2.5.0" @@ -1635,6 +1738,37 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_builder" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" +dependencies = [ + "darling 0.14.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -1716,6 +1850,15 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "document-features" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +dependencies = [ + "litrs", +] + [[package]] name = "drain_filter_polyfill" version = "0.1.3" @@ -1742,7 +1885,7 @@ checksum = "7c1a2e028bbf7921549873b291ddc0cfe08b673d9489da81ac28898cd5a0e6e0" dependencies = [ "chrono", "rust_decimal", - "serde 1.0.193", + "serde 1.0.202", "thiserror", "time", "winnow 0.6.8", @@ -1777,7 +1920,7 @@ checksum = "64fba5a42bd76a17cad4bfa00de168ee1cbfa06a5e8ce992ae880218c05641a9" dependencies = [ "byteorder", "dynasm", - "memmap2", + "memmap2 0.5.10", ] [[package]] @@ -1814,7 +1957,7 @@ dependencies = [ "curve25519-dalek-ng", "hex", "rand_core 0.6.4", - "serde 1.0.193", + "serde 1.0.202", "sha2 0.9.9", "thiserror", "zeroize", @@ -1828,7 +1971,7 @@ checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" dependencies = [ "curve25519-dalek 4.1.2", "ed25519", - "serde 1.0.193", + "serde 1.0.202", "sha2 0.10.8", "subtle", "zeroize", @@ -1844,7 +1987,7 @@ dependencies = [ "hashbrown 0.12.3", "hex", "rand_core 0.6.4", - "serde 1.0.193", + "serde 1.0.202", "sha2 0.9.9", "zeroize", ] @@ -1897,7 +2040,7 @@ dependencies = [ "log", "rand 0.8.5", "rlp", - "serde 1.0.193", + "serde 1.0.202", "sha3", "zeroize", ] @@ -1937,7 +2080,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" dependencies = [ - "darling", + "darling 0.20.3", "proc-macro2", "quote", "syn 2.0.52", @@ -1967,7 +2110,7 @@ checksum = "768064bd3a0e2bedcba91dc87ace90beea91acc41b6a01a3ca8e9aa8827461bf" dependencies = [ "log", "once_cell", - "serde 1.0.193", + "serde 1.0.202", "serde_json", ] @@ -1985,7 +2128,7 @@ dependencies = [ "pbkdf2 0.11.0", "rand 0.8.5", "scrypt", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "sha2 0.10.8", "sha3", @@ -2003,7 +2146,7 @@ dependencies = [ "hex", "once_cell", "regex", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "sha3", "thiserror", @@ -2105,7 +2248,7 @@ checksum = "8c405f24ea3a517899ba7985385c43dc4a7eb1209af3b1e0a1a32d7dcc7f8d09" dependencies = [ "ethers-core", "once_cell", - "serde 1.0.193", + "serde 1.0.202", "serde_json", ] @@ -2123,7 +2266,7 @@ dependencies = [ "futures-util", "once_cell", "pin-project", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "thiserror", ] @@ -2143,7 +2286,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "syn 2.0.52", "toml 0.8.2", @@ -2186,7 +2329,7 @@ dependencies = [ "open-fastrlp", "rand 0.8.5", "rlp", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "strum 0.25.0", "syn 2.0.52", @@ -2206,7 +2349,7 @@ dependencies = [ "ethers-core", "reqwest", "semver 1.0.20", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "thiserror", "tracing", @@ -2229,7 +2372,7 @@ dependencies = [ "futures-util", "instant", "reqwest", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "thiserror", "tokio", @@ -2261,7 +2404,7 @@ dependencies = [ "once_cell", "pin-project", "reqwest", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "thiserror", "tokio", @@ -2610,9 +2753,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "js-sys", @@ -2713,7 +2856,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.11", - "indexmap 2.1.0", + "indexmap 2.2.6", "slab", "tokio", "tokio-util 0.7.10", @@ -2727,12 +2870,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] -name = "hashbrown" -version = "0.11.2" +name = "half" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ - "ahash", + "cfg-if", + "crunchy", ] [[package]] @@ -3031,7 +3175,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde 1.0.202", "serde-json-wasm 1.0.1", ] @@ -3061,7 +3205,7 @@ dependencies = [ "primitive-types", "scale-info", "schemars", - "serde 1.0.193", + "serde 1.0.202", "uint", ] @@ -3088,7 +3232,7 @@ dependencies = [ "ibc-client-wasm-types", "ibc-core", "prost 0.12.3", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -3104,7 +3248,7 @@ dependencies = [ "ibc-core-handler-types", "ibc-core-host", "ibc-primitives", - "serde 1.0.193", + "serde 1.0.202", "tendermint 0.36.0", "tendermint-light-client-verifier", ] @@ -3133,7 +3277,7 @@ dependencies = [ "ibc-core-host-types", "ibc-primitives", "ibc-proto", - "serde 1.0.193", + "serde 1.0.202", "tendermint 0.36.0", "tendermint-light-client-verifier", "tendermint-proto 0.36.0", @@ -3152,7 +3296,7 @@ dependencies = [ "ibc-core-host-types", "ibc-primitives", "ibc-proto", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -3216,7 +3360,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde 1.0.202", "sha2 0.10.8", "subtle-encoding", "tendermint 0.36.0", @@ -3269,7 +3413,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde 1.0.202", "subtle-encoding", "tendermint 0.36.0", ] @@ -3289,7 +3433,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde 1.0.202", "subtle-encoding", ] @@ -3323,7 +3467,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde 1.0.202", "subtle-encoding", "tendermint 0.36.0", ] @@ -3364,7 +3508,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde 1.0.202", "subtle-encoding", "tendermint 0.36.0", ] @@ -3406,7 +3550,7 @@ dependencies = [ "ibc-core-host-types", "ibc-primitives", "ibc-proto", - "serde 1.0.193", + "serde 1.0.202", "sha2 0.10.8", "subtle-encoding", "tendermint 0.36.0", @@ -3425,7 +3569,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -3458,7 +3602,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "schemars", - "serde 1.0.193", + "serde 1.0.202", "subtle-encoding", "tendermint 0.36.0", ] @@ -3488,7 +3632,7 @@ dependencies = [ "prost 0.12.3", "scale-info", "schemars", - "serde 1.0.193", + "serde 1.0.202", "tendermint 0.36.0", "time", ] @@ -3509,7 +3653,7 @@ dependencies = [ "prost 0.12.3", "scale-info", "schemars", - "serde 1.0.193", + "serde 1.0.202", "subtle-encoding", "tendermint-proto 0.36.0", "tonic", @@ -3561,7 +3705,7 @@ dependencies = [ "informalsystems-pbjson 0.6.0", "prost 0.12.3", "ripemd", - "serde 1.0.193", + "serde 1.0.202", "sha2 0.10.8", "sha3", ] @@ -3617,7 +3761,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -3637,7 +3781,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5ad43a3f5795945459d577f6589cf62a476e92c79b75e70cd954364e14ce17b" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -3652,7 +3796,7 @@ version = "0.8.0" source = "git+https://github.com/heliaxdev/index-set?tag=v0.8.1#b0d928f83cf0d465ccda299d131e8df2859b5184" dependencies = [ "borsh 1.2.1", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -3663,28 +3807,29 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] name = "indexmap" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +version = "2.2.4" +source = "git+https://github.com/heliaxdev/indexmap?tag=2.2.4-heliax-1#b5b5b547bd6ab04bbb16e060326a50ddaeb6c909" dependencies = [ + "borsh 1.2.1", "equivalent", "hashbrown 0.14.3", + "serde 1.0.202", ] [[package]] name = "indexmap" -version = "2.2.4" -source = "git+https://github.com/heliaxdev/indexmap?tag=2.2.4-heliax-1#b5b5b547bd6ab04bbb16e060326a50ddaeb6c909" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ - "borsh 1.2.1", "equivalent", "hashbrown 0.14.3", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -3694,7 +3839,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4eecd90f87bea412eac91c6ef94f6b1e390128290898cbe14f2b926787ae1fb" dependencies = [ "base64 0.13.1", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -3704,7 +3849,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aa4a0980c8379295100d70854354e78df2ee1c6ca0f96ffe89afeb3140e3a3d" dependencies = [ "base64 0.21.7", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -3742,13 +3887,13 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ "hermit-abi", - "rustix", - "windows-sys 0.48.0", + "libc", + "windows-sys 0.52.0", ] [[package]] @@ -3811,7 +3956,7 @@ dependencies = [ "base64 0.21.7", "pem", "ring 0.16.20", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "simple_asn1", ] @@ -3954,7 +4099,7 @@ checksum = "02036c84eab9c48e85bc568d269221ba4f5e1cfbc785c3c2c2f6bb8c131f9287" dependencies = [ "async-trait", "ledger-transport", - "serde 1.0.193", + "serde 1.0.202", "thiserror", ] @@ -3973,9 +4118,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.150" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libgit2-sys" @@ -4049,7 +4194,7 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -4078,6 +4223,12 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + [[package]] name = "lock_api" version = "0.4.11" @@ -4094,27 +4245,6 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -[[package]] -name = "loupe" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6a72dfa44fe15b5e76b94307eeb2ff995a8c5b283b55008940c02e0c5b634d" -dependencies = [ - "indexmap 1.9.3", - "loupe-derive", - "rustversion", -] - -[[package]] -name = "loupe-derive" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fbfc88337168279f2e9ae06e157cfed4efd3316e14dc96ed074d4f2e6c5952" -dependencies = [ - "quote", - "syn 1.0.109", -] - [[package]] name = "mach" version = "0.3.2" @@ -4133,9 +4263,9 @@ dependencies = [ "indexmap 1.9.3", "linked-hash-map", "regex", - "serde 1.0.193", + "serde 1.0.202", "serde_derive", - "serde_yaml", + "serde_yaml 0.7.5", ] [[package]] @@ -4192,7 +4322,7 @@ dependencies = [ "blake2b_simd", "bls12_381", "directories", - "getrandom 0.2.11", + "getrandom 0.2.15", "group", "itertools 0.11.0", "jubjub", @@ -4235,12 +4365,12 @@ dependencies = [ ] [[package]] -name = "memoffset" -version = "0.6.5" +name = "memmap2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" dependencies = [ - "autocfg", + "libc", ] [[package]] @@ -4383,7 +4513,6 @@ dependencies = [ "k256", "konst", "linkme", - "loupe", "masp_primitives", "masp_proofs", "namada_account", @@ -4420,7 +4549,7 @@ dependencies = [ "rayon", "regex", "ripemd", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "sha2 0.9.9", "slip10_ed25519", @@ -4440,8 +4569,6 @@ dependencies = [ "wasmer", "wasmer-cache", "wasmer-compiler-singlepass", - "wasmer-engine-dylib", - "wasmer-engine-universal", "wasmer-vm", "wasmparser 0.107.0", "wasmtimer", @@ -4460,7 +4587,7 @@ dependencies = [ "namada_migrations", "namada_storage", "proptest", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -4528,7 +4655,7 @@ dependencies = [ "rand_core 0.6.4", "reqwest", "rpassword", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "sha2 0.9.9", "tar", @@ -4568,7 +4695,6 @@ dependencies = [ "wasm-instrument", "wasmer", "wasmer-compiler-singlepass", - "wasmer-engine-universal", ] [[package]] @@ -4615,7 +4741,7 @@ dependencies = [ "prost-types 0.12.3", "rand 0.8.5", "rand_core 0.6.4", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "sha2 0.9.9", "smooth-operator", @@ -4669,7 +4795,7 @@ dependencies = [ "namada_tx", "namada_vote_ext", "rand 0.8.5", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "tendermint 0.36.0", "tendermint-proto 0.36.0", @@ -4687,7 +4813,7 @@ dependencies = [ "namada_core", "namada_macros", "namada_migrations", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "thiserror", "tracing", @@ -4725,7 +4851,7 @@ dependencies = [ "namada_macros", "namada_migrations", "proptest", - "serde 1.0.193", + "serde 1.0.202", "thiserror", ] @@ -4745,7 +4871,7 @@ dependencies = [ "namada_storage", "namada_trans_token", "proptest", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "smooth-operator", "thiserror", @@ -4778,7 +4904,7 @@ dependencies = [ "primitive-types", "proptest", "prost 0.12.3", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "sha2 0.9.9", "thiserror", @@ -4938,7 +5064,7 @@ dependencies = [ "pretty_assertions", "proptest", "proptest-state-machine", - "serde 1.0.193", + "serde 1.0.202", "smooth-operator", "test-log", "thiserror", @@ -5009,7 +5135,7 @@ dependencies = [ "rand_core 0.6.4", "regex", "ripemd", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "sha2 0.9.9", "slip10_ed25519", @@ -5041,7 +5167,7 @@ dependencies = [ "namada_tx", "proptest", "rayon", - "serde 1.0.193", + "serde 1.0.202", "smooth-operator", "test-log", "tracing", @@ -5092,7 +5218,7 @@ dependencies = [ "namada_migrations", "namada_replay_protection", "regex", - "serde 1.0.193", + "serde 1.0.202", "smooth-operator", "thiserror", "tracing", @@ -5148,7 +5274,7 @@ dependencies = [ "prost 0.12.3", "rand 0.8.5", "regex", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "sha2 0.9.9", "tar", @@ -5206,7 +5332,7 @@ dependencies = [ "prost 0.12.3", "prost-types 0.12.3", "rand 0.8.5", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "sha2 0.9.9", "thiserror", @@ -5265,7 +5391,7 @@ dependencies = [ "namada_macros", "namada_migrations", "namada_tx", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -5514,7 +5640,7 @@ dependencies = [ "num", "num-derive 0.3.3", "num-traits 0.2.17", - "serde 1.0.193", + "serde 1.0.202", "serde_derive", ] @@ -5549,18 +5675,6 @@ dependencies = [ "syn 2.0.52", ] -[[package]] -name = "object" -version = "0.28.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" -dependencies = [ - "crc32fast", - "hashbrown 0.11.2", - "indexmap 1.9.3", - "memchr", -] - [[package]] name = "object" version = "0.32.1" @@ -5664,7 +5778,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6624905ddd92e460ff0685567539ed1ac985b2dee4c92c7edcd64fce905b00c" dependencies = [ "ct-codecs", - "getrandom 0.2.11", + "getrandom 0.2.15", "subtle", "zeroize", ] @@ -5701,7 +5815,7 @@ dependencies = [ "byte-slice-cast", "impl-trait-for-tuples", "parity-scale-codec-derive", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -5873,7 +5987,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.1.0", + "indexmap 2.2.6", ] [[package]] @@ -5942,9 +6056,9 @@ checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" dependencies = [ "num-traits 0.2.17", "plotters-backend", @@ -5955,15 +6069,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" dependencies = [ "plotters-backend", ] @@ -6344,7 +6458,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", ] [[package]] @@ -6400,7 +6514,7 @@ dependencies = [ "jubjub", "pasta_curves", "rand_core 0.6.4", - "serde 1.0.193", + "serde 1.0.202", "thiserror", "zeroize", ] @@ -6413,7 +6527,7 @@ checksum = "7a60db2c3bc9c6fd1e8631fee75abc008841d27144be744951d6b9b75f9b569c" dependencies = [ "rand_core 0.6.4", "reddsa", - "serde 1.0.193", + "serde 1.0.202", "thiserror", "zeroize", ] @@ -6433,19 +6547,20 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "libredox", "thiserror", ] [[package]] -name = "regalloc" -version = "0.0.34" +name = "regalloc2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62446b1d3ebf980bdc68837700af1d77b37bc430e524bf95319c6eada2a4cc02" +checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c" dependencies = [ + "fxhash", "log", - "rustc-hash", + "slice-group-by", "smallvec", ] @@ -6542,7 +6657,7 @@ dependencies = [ "rustls", "rustls-native-certs", "rustls-pemfile", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "serde_urlencoded", "system-configuration", @@ -6589,7 +6704,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", - "getrandom 0.2.11", + "getrandom 0.2.15", "libc", "spin 0.9.8", "untrusted 0.9.0", @@ -6614,6 +6729,7 @@ dependencies = [ "bitvec", "bytecheck", "hashbrown 0.12.3", + "indexmap 1.9.3", "ptr_meta", "rend", "rkyv_derive", @@ -6874,8 +6990,9 @@ checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" dependencies = [ "dyn-clone", "schemars_derive", - "serde 1.0.193", + "serde 1.0.202", "serde_json", + "url", ] [[package]] @@ -6968,6 +7085,12 @@ dependencies = [ "libc", ] +[[package]] +name = "self_cell" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" + [[package]] name = "semver" version = "0.11.0" @@ -6983,7 +7106,7 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -7015,9 +7138,9 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] @@ -7040,7 +7163,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -7049,7 +7172,18 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f05da0d153dd4595bdffd5099dc0e9ce425b205ee648eb93437ff7302af8c9a5" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" +dependencies = [ + "js-sys", + "serde 1.0.202", + "wasm-bindgen", ] [[package]] @@ -7058,7 +7192,7 @@ version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -7067,15 +7201,15 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ - "half", - "serde 1.0.193", + "half 1.8.2", + "serde 1.0.202", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", @@ -7101,7 +7235,7 @@ checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -7121,7 +7255,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -7133,7 +7267,7 @@ dependencies = [ "form_urlencoded", "itoa", "ryu", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -7144,10 +7278,23 @@ checksum = "ef8099d3df28273c99a1728190c7a9f19d444c941044f64adf986bee7ec53051" dependencies = [ "dtoa", "linked-hash-map", - "serde 1.0.193", + "serde 1.0.202", "yaml-rust", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.2.6", + "itoa", + "ryu", + "serde 1.0.202", + "unsafe-libyaml", +] + [[package]] name = "serdect" version = "0.2.0" @@ -7155,7 +7302,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" dependencies = [ "base16ct", - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -7212,6 +7359,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared-buffer" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" +dependencies = [ + "bytes", + "memmap2 0.6.2", +] + [[package]] name = "shlex" version = "1.3.0" @@ -7270,6 +7427,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + [[package]] name = "slip10_ed25519" version = "0.1.3" @@ -7595,7 +7758,7 @@ dependencies = [ "once_cell", "prost 0.12.3", "prost-types 0.12.3", - "serde 1.0.193", + "serde 1.0.202", "serde_bytes", "serde_json", "serde_repr", @@ -7625,7 +7788,7 @@ dependencies = [ "prost 0.12.3", "prost-types 0.12.3", "ripemd", - "serde 1.0.193", + "serde 1.0.202", "serde_bytes", "serde_json", "serde_repr", @@ -7645,7 +7808,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e07b383dc8780ebbec04cfb603f3fdaba6ea6663d8dd861425b1ffa7761fe90d" dependencies = [ "flex-error", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "tendermint 0.36.0", "toml 0.8.2", @@ -7664,7 +7827,7 @@ dependencies = [ "flex-error", "futures", "regex", - "serde 1.0.193", + "serde 1.0.202", "serde_cbor", "serde_derive", "serde_json", @@ -7685,7 +7848,7 @@ checksum = "4216e487165e5dbd7af79952eaa0d5f06c5bde861eb76c690acd7f2d2a19395c" dependencies = [ "derive_more", "flex-error", - "serde 1.0.193", + "serde 1.0.202", "tendermint 0.36.0", "time", ] @@ -7702,7 +7865,7 @@ dependencies = [ "num-traits 0.2.17", "prost 0.12.3", "prost-types 0.12.3", - "serde 1.0.193", + "serde 1.0.202", "serde_bytes", "subtle-encoding", "time", @@ -7718,7 +7881,7 @@ dependencies = [ "flex-error", "prost 0.12.3", "prost-types 0.12.3", - "serde 1.0.193", + "serde 1.0.202", "serde_bytes", "subtle-encoding", "time", @@ -7734,13 +7897,13 @@ dependencies = [ "bytes", "flex-error", "futures", - "getrandom 0.2.11", + "getrandom 0.2.15", "peg", "pin-project", "rand 0.8.5", "reqwest", "semver 1.0.20", - "serde 1.0.193", + "serde 1.0.202", "serde_bytes", "serde_json", "subtle", @@ -7765,7 +7928,7 @@ checksum = "b233cec83c56c413ccc346af866cb9206a14d468fcecf0255080107bc9b103c0" dependencies = [ "ed25519-consensus", "gumdrop", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "simple-error", "tempfile", @@ -7882,7 +8045,7 @@ dependencies = [ "deranged", "itoa", "powerfmt", - "serde 1.0.193", + "serde 1.0.202", "time-core", "time-macros", ] @@ -7947,7 +8110,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", "serde_json", ] @@ -8096,7 +8259,19 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", +] + +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde 1.0.202", + "serde_spanned", + "toml_datetime", + "toml_edit 0.19.15", ] [[package]] @@ -8105,7 +8280,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", "serde_spanned", "toml_datetime", "toml_edit 0.20.2", @@ -8117,7 +8292,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", ] [[package]] @@ -8126,7 +8301,9 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.6", + "serde 1.0.202", + "serde_spanned", "toml_datetime", "winnow 0.5.25", ] @@ -8137,8 +8314,8 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.1.0", - "serde 1.0.193", + "indexmap 2.2.6", + "serde 1.0.202", "serde_spanned", "toml_datetime", "winnow 0.5.25", @@ -8318,7 +8495,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" dependencies = [ - "serde 1.0.193", + "serde 1.0.202", "tracing-core", ] @@ -8332,7 +8509,7 @@ dependencies = [ "nu-ansi-term", "once_cell", "regex", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "sharded-slab", "thread_local", @@ -8490,6 +8667,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.7.1" @@ -8511,6 +8694,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde 1.0.202", ] [[package]] @@ -8537,8 +8721,8 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.11", - "serde 1.0.193", + "getrandom 0.2.15", + "serde 1.0.202", ] [[package]] @@ -8613,7 +8797,7 @@ dependencies = [ "pin-project", "rustls-pemfile", "scoped-tls", - "serde 1.0.193", + "serde 1.0.202", "serde_json", "serde_urlencoded", "tokio", @@ -8722,46 +8906,38 @@ dependencies = [ [[package]] name = "wasmer" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce4a267a570e121c9375136adefa2c48810273907de9c6817bc19db4d6144bc" dependencies = [ + "bytes", "cfg-if", + "derivative", "indexmap 1.9.3", "js-sys", - "loupe", "more-asserts", + "rustc-demangle", + "serde 1.0.202", + "serde-wasm-bindgen", + "shared-buffer", "target-lexicon", "thiserror", + "tracing", "wasm-bindgen", - "wasmer-artifact", "wasmer-compiler", "wasmer-compiler-cranelift", "wasmer-derive", - "wasmer-engine", - "wasmer-engine-dylib", - "wasmer-engine-universal", "wasmer-types", "wasmer-vm", "wat", "winapi", ] -[[package]] -name = "wasmer-artifact" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "enumset", - "loupe", - "thiserror", - "wasmer-compiler", - "wasmer-types", -] - [[package]] name = "wasmer-cache" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a40804bcc2567f112003182fc5edc29584da5199c4a1f5a8d6a6e4b65feff0" dependencies = [ "blake3", "hex", @@ -8771,31 +8947,42 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9c23098e86ef1038155684fe50f0c1079a0e2a2e70f115b789df17e6ba98d20" dependencies = [ + "backtrace", + "bytes", + "cfg-if", + "enum-iterator", "enumset", - "loupe", + "lazy_static", + "leb128", + "memmap2 0.5.10", + "more-asserts", + "region", "rkyv", - "serde 1.0.193", - "serde_bytes", + "self_cell", + "shared-buffer", "smallvec", - "target-lexicon", "thiserror", "wasmer-types", - "wasmparser 0.83.0", + "wasmer-vm", + "wasmparser 0.121.2", + "winapi", + "xxhash-rust", ] [[package]] name = "wasmer-compiler-cranelift" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95287b79973ad5f485215733ef9f0d4bb951a6b7e655585d2bd3d4a4ba1253c9" dependencies = [ "cranelift-codegen", "cranelift-entity", "cranelift-frontend", "gimli 0.26.2", - "loupe", "more-asserts", "rayon", "smallvec", @@ -8803,185 +8990,128 @@ dependencies = [ "tracing", "wasmer-compiler", "wasmer-types", - "wasmer-vm", ] [[package]] name = "wasmer-compiler-singlepass" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00d78d59be3ce78ad859e176b88f0d5bec0120ece0684922d7c5da1289e251b1" dependencies = [ "byteorder", "dynasm", "dynasmrt", + "enumset", "gimli 0.26.2", "lazy_static", - "loupe", "more-asserts", "rayon", "smallvec", "wasmer-compiler", "wasmer-types", - "wasmer-vm", ] [[package]] -name = "wasmer-derive" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "wasmer-engine" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "backtrace", - "enumset", - "lazy_static", - "loupe", - "memmap2", - "more-asserts", - "rustc-demangle", - "serde 1.0.193", - "serde_bytes", - "target-lexicon", - "thiserror", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-types", - "wasmer-vm", -] - -[[package]] -name = "wasmer-engine-dylib" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "cfg-if", - "enum-iterator", - "enumset", - "leb128", - "libloading", - "loupe", - "object 0.28.4", - "rkyv", - "serde 1.0.193", - "tempfile", - "tracing", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-engine", - "wasmer-object", - "wasmer-types", - "wasmer-vm", - "which", -] - -[[package]] -name = "wasmer-engine-universal" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "cfg-if", - "enumset", - "leb128", - "loupe", - "region", - "rkyv", - "wasmer-compiler", - "wasmer-engine", - "wasmer-engine-universal-artifact", - "wasmer-types", - "wasmer-vm", - "winapi", -] - -[[package]] -name = "wasmer-engine-universal-artifact" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +name = "wasmer-config" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a0f70c177b1c5062cfe0f5308c3317751796fef9403c22a0cd7b4cacd4ccd8" dependencies = [ - "enum-iterator", - "enumset", - "loupe", - "rkyv", + "anyhow", + "bytesize", + "derive_builder", + "hex", + "indexmap 2.2.6", + "schemars", + "semver 1.0.20", + "serde 1.0.202", + "serde_cbor", + "serde_json", + "serde_yaml 0.9.34+deprecated", "thiserror", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-types", + "toml 0.8.2", + "url", ] [[package]] -name = "wasmer-object" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +name = "wasmer-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48f36aeeecb655f15fdd358bdf6e4cec27df181468fa4226084157e8462bd5e" dependencies = [ - "object 0.28.4", - "thiserror", - "wasmer-compiler", - "wasmer-types", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] name = "wasmer-types" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83cb97b6b20084757a2a8d548dc0d4179c3fe9e2d711740423a1e6aa3f8b9091" dependencies = [ - "backtrace", + "bytecheck", "enum-iterator", + "enumset", + "getrandom 0.2.15", + "hex", "indexmap 1.9.3", - "loupe", + "more-asserts", "rkyv", - "serde 1.0.193", + "sha2 0.10.8", + "target-lexicon", "thiserror", + "webc", + "xxhash-rust", ] [[package]] name = "wasmer-vm" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc1e19d986844b17b927ec8b0c7f3da6a7a2c2cb3b0f8ca5d4cb1a1f71bfb124" dependencies = [ "backtrace", "cc", "cfg-if", "corosensei", + "crossbeam-queue", + "dashmap", + "derivative", "enum-iterator", + "fnv", "indexmap 1.9.3", "lazy_static", "libc", - "loupe", "mach", - "memoffset 0.6.5", + "memoffset 0.9.0", "more-asserts", "region", - "rkyv", "scopeguard", - "serde 1.0.193", "thiserror", - "wasmer-artifact", "wasmer-types", "winapi", ] [[package]] name = "wasmparser" -version = "0.83.0" +version = "0.107.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" +checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" +dependencies = [ + "indexmap 1.9.3", + "semver 1.0.20", +] [[package]] name = "wasmparser" -version = "0.107.0" +version = "0.121.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" +checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" dependencies = [ - "indexmap 1.9.3", + "bitflags 2.5.0", + "indexmap 2.2.6", "semver 1.0.20", ] @@ -9030,6 +9160,36 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webc" +version = "6.0.0-alpha9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b4e8dd987046eede4348d660404ff990412631b7d493f9e547adcf2862cd5" +dependencies = [ + "anyhow", + "base64 0.21.7", + "bytes", + "cfg-if", + "clap", + "document-features", + "flate2", + "indexmap 1.9.3", + "libc", + "once_cell", + "semver 1.0.20", + "serde 1.0.202", + "serde_cbor", + "serde_json", + "sha2 0.10.8", + "shared-buffer", + "tar", + "tempfile", + "thiserror", + "toml 0.7.8", + "url", + "wasmer-config", +] + [[package]] name = "webpki-roots" version = "0.25.3" @@ -9394,6 +9554,12 @@ dependencies = [ "libc", ] +[[package]] +name = "xxhash-rust" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" + [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/Cargo.toml b/Cargo.toml index 7f89a6bc98..f5ebc0b9f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -189,12 +189,10 @@ tracing-log = "0.2.0" tracing-subscriber = {version = "0.3.7", default-features = false, features = ["env-filter", "fmt"]} wasmparser = "0.107.0" wasm-instrument = {version = "0.4.0", features = ["sign_ext"]} -wasmer = {git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b"} -wasmer-cache = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b" } -wasmer-compiler-singlepass = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b" } -wasmer-engine-dylib = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b" } -wasmer-engine-universal = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b" } -wasmer-vm = { git = "https://github.com/heliaxdev/wasmer", rev = "255054f7f58b7b4a525f2fee6b9b86422d1ca15b" } +wasmer = "4.3.1" +wasmer-cache = "4.3.1" +wasmer-compiler-singlepass = "4.3.1" +wasmer-vm = "4.3.1" winapi = "0.3.9" yansi = "0.5.1" zeroize = { version = "1.5.5", features = ["zeroize_derive"] } diff --git a/crates/benches/Cargo.toml b/crates/benches/Cargo.toml index ca308f9100..541dd07138 100644 --- a/crates/benches/Cargo.toml +++ b/crates/benches/Cargo.toml @@ -57,5 +57,4 @@ tempfile.workspace = true sha2.workspace = true wasm-instrument.workspace = true wasmer-compiler-singlepass.workspace = true -wasmer-engine-universal.workspace = true wasmer.workspace = true diff --git a/crates/benches/wasm_opcodes.rs b/crates/benches/wasm_opcodes.rs index b9ce3bfdb2..ceae69bc51 100644 --- a/crates/benches/wasm_opcodes.rs +++ b/crates/benches/wasm_opcodes.rs @@ -410,12 +410,11 @@ impl Display for WatBuilder { // optimizations that would compile out the benchmarks since most of them are // trivial operations fn get_wasm_store() -> Store { - wasmer::Store::new( - &wasmer_engine_universal::Universal::new( - wasmer_compiler_singlepass::Singlepass::default(), - ) - .engine(), - ) + Store::new(::new( + Box::new(wasmer_compiler_singlepass::Singlepass::default()), + wasmer::Target::default(), + wasmer::sys::Features::default(), + )) } // An empty wasm module to serve as the base reference for all the other @@ -428,12 +427,13 @@ fn empty_module(c: &mut Criterion) { ) "#, ); - let module = Module::new(&get_wasm_store(), module_wat).unwrap(); - let instance = Instance::new(&module, &imports! {}).unwrap(); + let mut store = get_wasm_store(); + let module = Module::new(&store, module_wat).unwrap(); + let instance = Instance::new(&mut store, &module, &imports! {}).unwrap(); let function = instance.exports.get_function(ENTRY_POINT).unwrap(); c.bench_function("empty_module", |b| { - b.iter(|| function.call(&[Value::I32(0)]).unwrap()); + b.iter(|| function.call(&mut store, &[Value::I32(0)]).unwrap()); }); } @@ -441,16 +441,19 @@ fn ops(c: &mut Criterion) { let mut group = c.benchmark_group("wasm_opts"); for builder in bench_functions() { - let module = - Module::new(&get_wasm_store(), builder.to_string()).unwrap(); - let instance = Instance::new(&module, &imports! {}).unwrap(); + let mut store = get_wasm_store(); + let module = Module::new(&store, builder.to_string()).unwrap(); + let instance = + Instance::new(&mut store, &module, &imports! {}).unwrap(); let function = instance.exports.get_function(ENTRY_POINT).unwrap(); group.bench_function(format!("{}", builder.instruction), |b| { if let Unreachable = builder.instruction { - b.iter(|| function.call(&[Value::I32(0)]).unwrap_err()); + b.iter(|| { + function.call(&mut store, &[Value::I32(0)]).unwrap_err() + }); } else { - b.iter(|| function.call(&[Value::I32(0)]).unwrap()); + b.iter(|| function.call(&mut store, &[Value::I32(0)]).unwrap()); } }); } diff --git a/crates/namada/Cargo.toml b/crates/namada/Cargo.toml index db2f4e460c..6e4f940dd4 100644 --- a/crates/namada/Cargo.toml +++ b/crates/namada/Cargo.toml @@ -19,14 +19,11 @@ default = ["wasm-runtime"] mainnet = ["namada_core/mainnet"] std = ["namada_sdk/std"] wasm-runtime = [ - "loupe", "parity-wasm", "rayon", "wasm-instrument", "wasmer-cache", "wasmer-compiler-singlepass", - "wasmer-engine-dylib", - "wasmer-engine-universal", "wasmer-vm", "wasmer", ] @@ -121,7 +118,6 @@ futures.workspace = true itertools.workspace = true konst.workspace = true linkme = {workspace = true, optional = true} -loupe = { version = "0.1.3", optional = true } masp_primitives.workspace = true masp_proofs.workspace = true num256.workspace = true @@ -154,8 +150,6 @@ wasm-instrument = { workspace = true, optional = true } wasmer = { workspace = true, optional = true } wasmer-cache = { workspace = true, optional = true } wasmer-compiler-singlepass = { workspace = true, optional = true } -wasmer-engine-dylib = { workspace = true, optional = true } -wasmer-engine-universal = { workspace = true, optional = true } wasmer-vm = { workspace = true, optional = true } # Greater versions break in `test_tx_stack_limiter` and `test_vp_stack_limiter` wat = "=1.0.71" diff --git a/crates/namada/src/vm/host_env.rs b/crates/namada/src/vm/host_env.rs index ed09242f16..cce172bc6f 100644 --- a/crates/namada/src/vm/host_env.rs +++ b/crates/namada/src/vm/host_env.rs @@ -1,5 +1,6 @@ //! Virtual machine's host environment exposes functions that may be called from //! within a virtual machine. + use std::cell::RefCell; use std::collections::BTreeSet; use std::fmt::Debug; @@ -2385,6 +2386,8 @@ where /// A helper module for testing #[cfg(feature = "testing")] pub mod testing { + use std::rc::Rc; + use super::*; use crate::vm::memory::testing::NativeMemory; use crate::vm::wasm::memory::WasmMemory; @@ -2451,15 +2454,14 @@ pub mod testing { S: State, CA: WasmCacheAccess, { - let store = crate::vm::wasm::compilation_cache::common::store(); - let initial_memory = - crate::vm::wasm::memory::prepare_tx_memory(&store).unwrap(); - let mut wasm_memory = WasmMemory::default(); - wasm_memory.inner.initialize(initial_memory); + let mut store = crate::vm::wasm::compilation_cache::common::store(); + + let wasm_memory = + crate::vm::wasm::memory::prepare_tx_memory(&mut store).unwrap(); let (write_log, in_mem, db) = state.split_borrow(); - TxVmEnv::new( - wasm_memory, + let mut env = TxVmEnv::new( + WasmMemory::new(Rc::new(RefCell::new(store))), write_log, in_mem, db, @@ -2476,7 +2478,10 @@ pub mod testing { vp_wasm_cache, #[cfg(feature = "wasm-runtime")] tx_wasm_cache, - ) + ); + + env.memory.init_from(&wasm_memory); + env } /// Setup a validity predicate environment diff --git a/crates/namada/src/vm/wasm/compilation_cache/common.rs b/crates/namada/src/vm/wasm/compilation_cache/common.rs index b23d79e50c..146d03df3a 100644 --- a/crates/namada/src/vm/wasm/compilation_cache/common.rs +++ b/crates/namada/src/vm/wasm/compilation_cache/common.rs @@ -1,8 +1,7 @@ //! WASM compilation cache. +//! //! The cache is backed by in-memory LRU cache with configurable size -//! limit and a file system cache of compiled modules (either to dynamic libs -//! compiled via the `dylib` module, or serialized modules compiled via the -//! `universal` module). +//! limit and a file system cache of serialized modules. use std::collections::hash_map::RandomState; use std::fs; @@ -496,9 +495,6 @@ fn hash_of_code(code: impl AsRef<[u8]>) -> Hash { fn compile( code: impl AsRef<[u8]>, ) -> Result<(Module, Store), wasm::run::Error> { - // There's an issue with dylib compiler on mac in linker and on linux - // with the dylib's store loading the dylib from a file, so we're caching a - // module serialized to bytes instead for now. universal::compile(code).map_err(wasm::run::Error::CompileError) } @@ -581,39 +577,6 @@ mod universal { } } -/// A dynamic library engine compilation. -mod dylib { - use super::*; - - #[allow(dead_code)] - #[cfg(windows)] - pub const FILE_EXT: &str = "dll"; - #[allow(dead_code)] - #[cfg(all(not(unix), target_os = "macos"))] - pub const FILE_EXT: &str = "dylib"; - #[allow(dead_code)] - #[cfg(all(unix, not(target_os = "macos")))] - pub const FILE_EXT: &str = "so"; - - /// Compile wasm to a dynamic library - #[allow(dead_code)] - pub fn compile( - code: impl AsRef<[u8]>, - ) -> Result<(Module, Store), wasmer::CompileError> { - let store = store(); - let module = Module::new(&store, code.as_ref())?; - Ok((module, store)) - } - - /// Dylib WASM store - #[allow(dead_code)] - pub fn store() -> Store { - let compiler = wasmer_compiler_singlepass::Singlepass::default(); - let engine = wasmer_engine_dylib::Dylib::new(compiler).engine(); - Store::new_with_tunables(&engine, memory::vp_limit()) - } -} - /// Testing helpers #[cfg(any(test, feature = "testing"))] pub mod testing { @@ -1063,10 +1026,6 @@ mod test { /// Get the WASM code bytes, its hash and find the compiled module's size fn load_wasm(file: impl AsRef) -> WasmWithMeta { - // When `WeightScale` calls `loupe::size_of_val` in the cache, for some - // reason it returns 8 bytes more than the same call in here. - let _extra_bytes = 8; - let file = file.as_ref(); let code = fs::read(file).unwrap(); let hash = hash_of_code(&code); diff --git a/crates/namada/src/vm/wasm/host_env.rs b/crates/namada/src/vm/wasm/host_env.rs index 1dc86a9a09..20e968067a 100644 --- a/crates/namada/src/vm/wasm/host_env.rs +++ b/crates/namada/src/vm/wasm/host_env.rs @@ -4,86 +4,58 @@ //! imports, so they can be called from inside the wasm. use namada_state::{DBIter, StorageHasher, DB}; -use wasmer::{ - Function, HostEnvInitError, ImportObject, Instance, Store, WasmerEnv, -}; +use wasmer::{Function, FunctionEnv, Imports}; use crate::vm::host_env::{TxVmEnv, VpEvaluator, VpVmEnv}; use crate::vm::wasm::memory::WasmMemory; use crate::vm::{host_env, WasmCacheAccess}; -impl WasmerEnv for TxVmEnv -where - D: DB + for<'iter> DBIter<'iter> + 'static, - H: StorageHasher + 'static, - CA: WasmCacheAccess + 'static, -{ - fn init_with_instance( - &mut self, - instance: &Instance, - ) -> std::result::Result<(), HostEnvInitError> { - self.memory.init_env_memory(&instance.exports) - } -} - -impl WasmerEnv for VpVmEnv -where - D: DB + for<'iter> DBIter<'iter> + 'static, - H: StorageHasher + 'static, - EVAL: VpEvaluator + 'static, - CA: WasmCacheAccess + 'static, -{ - fn init_with_instance( - &mut self, - instance: &Instance, - ) -> std::result::Result<(), HostEnvInitError> { - self.memory.init_env_memory(&instance.exports) - } -} - /// Prepare imports (memory and host functions) exposed to the vm guest running /// transaction code #[allow(clippy::too_many_arguments)] pub fn tx_imports( - wasm_store: &Store, + wasm_store: &mut impl wasmer::AsStoreMut, env: TxVmEnv, -) -> ImportObject +) -> Imports where D: DB + for<'iter> DBIter<'iter> + 'static, H: StorageHasher + 'static, CA: WasmCacheAccess + 'static, { + let env = FunctionEnv::new(wasm_store, env); + wasmer::imports! { - // default namespace + // Default namespace "env" => { - // Wasm middleware gas injection hook - "gas" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_charge_gas), - "namada_tx_read" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_read), - "namada_tx_read_temp" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_read_temp), - "namada_tx_result_buffer" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_result_buffer), - "namada_tx_has_key" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_has_key), - "namada_tx_write" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_write), - "namada_tx_write_temp" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_write_temp), - "namada_tx_delete" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_delete), - "namada_tx_iter_prefix" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_iter_prefix), - "namada_tx_iter_next" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_iter_next), - "namada_tx_insert_verifier" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_insert_verifier), - "namada_tx_update_validity_predicate" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_update_validity_predicate), - "namada_tx_init_account" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_init_account), - "namada_tx_emit_event" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_emit_event), - "namada_tx_get_events" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_events), - "namada_tx_get_chain_id" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_chain_id), - "namada_tx_get_tx_index" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_tx_index), - "namada_tx_get_block_height" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_block_height), - "namada_tx_get_block_header" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_block_header), - "namada_tx_get_block_epoch" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_block_epoch), - "namada_tx_get_pred_epochs" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_pred_epochs), - "namada_tx_get_native_token" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_native_token), - "namada_tx_log_string" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_log_string), - "namada_tx_set_commitment_sentinel" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_set_commitment_sentinel), - "namada_tx_verify_tx_section_signature" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_verify_tx_section_signature), - "namada_tx_update_masp_note_commitment_tree" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_update_masp_note_commitment_tree), - "namada_tx_yield_value" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_yield_value), + // Gas injection hook + "gas" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_1(host_env::tx_charge_gas)), + // Tx Host functions + "namada_tx_delete" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_2(host_env::tx_delete)), + "namada_tx_emit_event" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_2(host_env::tx_emit_event)), + "namada_tx_get_block_epoch" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_0(host_env::tx_get_block_epoch)), + "namada_tx_get_block_header" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_1(host_env::tx_get_block_header)), + "namada_tx_get_block_height" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_0(host_env::tx_get_block_height)), + "namada_tx_get_chain_id" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_1(host_env::tx_get_chain_id)), + "namada_tx_get_events" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_2(host_env::tx_get_events)), + "namada_tx_get_native_token" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_1(host_env::tx_get_native_token)), + "namada_tx_get_pred_epochs" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_0(host_env::tx_get_pred_epochs)), + "namada_tx_get_tx_index" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_0(host_env::tx_get_tx_index)), + "namada_tx_has_key" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_2(host_env::tx_has_key)), + "namada_tx_init_account" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_7(host_env::tx_init_account)), + "namada_tx_insert_verifier" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_2(host_env::tx_insert_verifier)), + "namada_tx_iter_next" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_1(host_env::tx_iter_next)), + "namada_tx_iter_prefix" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_2(host_env::tx_iter_prefix)), + "namada_tx_log_string" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_2(host_env::tx_log_string)), + "namada_tx_read" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_2(host_env::tx_read)), + "namada_tx_read_temp" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_2(host_env::tx_read_temp)), + "namada_tx_result_buffer" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_1(host_env::tx_result_buffer)), + "namada_tx_set_commitment_sentinel" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_0(host_env::tx_set_commitment_sentinel)), + "namada_tx_update_masp_note_commitment_tree" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_2(host_env::tx_update_masp_note_commitment_tree)), + "namada_tx_update_validity_predicate" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_6(host_env::tx_update_validity_predicate)), + "namada_tx_verify_tx_section_signature" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_7(host_env::tx_verify_tx_section_signature)), + "namada_tx_write" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_4(host_env::tx_write)), + "namada_tx_write_temp" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_4(host_env::tx_write_temp)), + "namada_tx_yield_value" => Function::new_typed_with_env(wasm_store, &env, wrap_tx::_2(host_env::tx_yield_value)), }, } } @@ -91,42 +63,337 @@ where /// Prepare imports (memory and host functions) exposed to the vm guest running /// validity predicate code pub fn vp_imports( - wasm_store: &Store, + wasm_store: &mut impl wasmer::AsStoreMut, env: VpVmEnv, -) -> ImportObject +) -> Imports where D: DB + for<'iter> DBIter<'iter> + 'static, H: StorageHasher + 'static, EVAL: VpEvaluator + 'static, CA: WasmCacheAccess + 'static, { + let env = FunctionEnv::new(wasm_store, env); + wasmer::imports! { - // default namespace + // Default namespace "env" => { - // Wasm middleware gas injection hook - "gas" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_charge_gas), - "namada_vp_read_pre" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_read_pre), - "namada_vp_read_post" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_read_post), - "namada_vp_read_temp" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_read_temp), - "namada_vp_result_buffer" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_result_buffer), - "namada_vp_has_key_pre" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_has_key_pre), - "namada_vp_has_key_post" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_has_key_post), - "namada_vp_iter_prefix_pre" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_iter_prefix_pre), - "namada_vp_iter_prefix_post" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_iter_prefix_pre), - "namada_vp_iter_next" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_iter_next), - "namada_vp_get_chain_id" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_chain_id), - "namada_vp_get_tx_index" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_tx_index), - "namada_vp_get_block_height" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_block_height), - "namada_vp_get_block_header" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_block_header), - "namada_vp_get_tx_code_hash" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_tx_code_hash), - "namada_vp_get_block_epoch" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_block_epoch), - "namada_vp_get_pred_epochs" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_pred_epochs), - "namada_vp_get_events" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_events), - "namada_vp_yield_value" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_yield_value), - "namada_vp_verify_tx_section_signature" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_verify_tx_section_signature), - "namada_vp_eval" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_eval), - "namada_vp_get_native_token" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_native_token), - "namada_vp_log_string" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_log_string), + // Gas injection hook + "gas" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_1(host_env::vp_charge_gas)), + // VP Host functions + "namada_vp_eval" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_4(host_env::vp_eval)), + "namada_vp_get_block_header" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_1(host_env::vp_get_block_header)), + "namada_vp_get_block_height" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_0(host_env::vp_get_block_height)), + "namada_vp_get_chain_id" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_1(host_env::vp_get_chain_id)), + "namada_vp_get_events" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_2(host_env::vp_get_events)), + "namada_vp_get_native_token" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_1(host_env::vp_get_native_token)), + "namada_vp_get_pred_epochs" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_0(host_env::vp_get_pred_epochs)), + "namada_vp_get_tx_code_hash" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_1(host_env::vp_get_tx_code_hash)), + "namada_vp_get_tx_index" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_0(host_env::vp_get_tx_index)), + "namada_vp_has_key_post" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_2(host_env::vp_has_key_post)), + "namada_vp_has_key_pre" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_2(host_env::vp_has_key_pre)), + "namada_vp_iter_next" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_1(host_env::vp_iter_next)), + "namada_vp_iter_prefix_post" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_2(host_env::vp_iter_prefix_post)), + "namada_vp_iter_prefix_pre" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_2(host_env::vp_iter_prefix_pre)), + "namada_vp_log_string" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_2(host_env::vp_log_string)), + "namada_vp_read_post" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_2(host_env::vp_read_post)), + "namada_vp_read_pre" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_2(host_env::vp_read_pre)), + "namada_vp_read_temp" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_2(host_env::vp_read_temp)), + "namada_vp_result_buffer" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_1(host_env::vp_result_buffer)), + "namada_vp_verify_tx_section_signature" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_9(host_env::vp_verify_tx_section_signature)), + "namada_vp_yield_value" => Function::new_typed_with_env(wasm_store, &env, wrap_vp::_2(host_env::vp_yield_value)), }, } } + +// TODO: Attempt to reduce the boilerplate of this module with macros, traits +// or something of this sort... +mod wrap_tx { + //! Wrap tx host functions with any number of arguments in a callback + //! that can be passed to [`wasmer`], to be used by the guest wasm code. + + #![allow(missing_docs)] + + use namada_state::{DBIter, StorageHasher, DB}; + use wasmer::FunctionEnvMut; + + use crate::vm::host_env::TxVmEnv; + use crate::vm::wasm::memory::WasmMemory; + use crate::vm::WasmCacheAccess; + + pub(super) fn _0( + f: F, + ) -> impl Fn(FunctionEnvMut<'_, TxVmEnv>) -> RET + where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, + CA: WasmCacheAccess + 'static, + F: Fn(&TxVmEnv) -> RET, + { + move |env| f(env.data()) + } + + pub(super) fn _1( + f: F, + ) -> impl Fn(FunctionEnvMut<'_, TxVmEnv>, ARG0) -> RET + where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, + CA: WasmCacheAccess + 'static, + F: Fn(&TxVmEnv, ARG0) -> RET, + { + move |env, arg0| f(env.data(), arg0) + } + + pub(super) fn _2( + f: F, + ) -> impl Fn(FunctionEnvMut<'_, TxVmEnv>, ARG0, ARG1) -> RET + where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, + CA: WasmCacheAccess + 'static, + F: Fn(&TxVmEnv, ARG0, ARG1) -> RET, + { + move |env, arg0, arg1| f(env.data(), arg0, arg1) + } + + pub(super) fn _4( + f: F, + ) -> impl Fn( + FunctionEnvMut<'_, TxVmEnv>, + ARG0, + ARG1, + ARG2, + ARG3, + ) -> RET + where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, + CA: WasmCacheAccess + 'static, + F: Fn(&TxVmEnv, ARG0, ARG1, ARG2, ARG3) -> RET, + { + move |env, arg0, arg1, arg2, arg3| f(env.data(), arg0, arg1, arg2, arg3) + } + + pub(super) fn _6( + f: F, + ) -> impl Fn( + FunctionEnvMut<'_, TxVmEnv>, + ARG0, + ARG1, + ARG2, + ARG3, + ARG4, + ARG5, + ) -> RET + where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, + CA: WasmCacheAccess + 'static, + F: Fn( + &TxVmEnv, + ARG0, + ARG1, + ARG2, + ARG3, + ARG4, + ARG5, + ) -> RET, + { + move |env, arg0, arg1, arg2, arg3, arg4, arg5| { + f(env.data(), arg0, arg1, arg2, arg3, arg4, arg5) + } + } + + pub(super) fn _7< + F, + ARG0, + ARG1, + ARG2, + ARG3, + ARG4, + ARG5, + ARG6, + RET, + D, + H, + CA, + >( + f: F, + ) -> impl Fn( + FunctionEnvMut<'_, TxVmEnv>, + ARG0, + ARG1, + ARG2, + ARG3, + ARG4, + ARG5, + ARG6, + ) -> RET + where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, + CA: WasmCacheAccess + 'static, + F: Fn( + &TxVmEnv, + ARG0, + ARG1, + ARG2, + ARG3, + ARG4, + ARG5, + ARG6, + ) -> RET, + { + move |env, arg0, arg1, arg2, arg3, arg4, arg5, arg6| { + f(env.data(), arg0, arg1, arg2, arg3, arg4, arg5, arg6) + } + } +} + +// TODO: Attempt to reduce the boilerplate of this module with macros, traits +// or something of this sort... +mod wrap_vp { + //! Wrap vp host functions with any number of arguments in a callback + //! that can be passed to [`wasmer`], to be used by the guest wasm code. + + #![allow(missing_docs)] + + use namada_state::{DBIter, StorageHasher, DB}; + use wasmer::FunctionEnvMut; + + use crate::vm::host_env::{VpEvaluator, VpVmEnv}; + use crate::vm::wasm::memory::WasmMemory; + use crate::vm::WasmCacheAccess; + + pub(super) fn _0( + f: F, + ) -> impl Fn(FunctionEnvMut<'_, VpVmEnv>) -> RET + where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, + CA: WasmCacheAccess + 'static, + EVAL: VpEvaluator + 'static, + F: Fn(&VpVmEnv) -> RET, + { + move |env| f(env.data()) + } + + pub(super) fn _1( + f: F, + ) -> impl Fn(FunctionEnvMut<'_, VpVmEnv>, ARG0) -> RET + where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, + CA: WasmCacheAccess + 'static, + EVAL: VpEvaluator + 'static, + F: Fn(&VpVmEnv, ARG0) -> RET, + { + move |env, arg0| f(env.data(), arg0) + } + + pub(super) fn _2( + f: F, + ) -> impl Fn( + FunctionEnvMut<'_, VpVmEnv>, + ARG0, + ARG1, + ) -> RET + where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, + CA: WasmCacheAccess + 'static, + EVAL: VpEvaluator + 'static, + F: Fn(&VpVmEnv, ARG0, ARG1) -> RET, + { + move |env, arg0, arg1| f(env.data(), arg0, arg1) + } + + pub(super) fn _4( + f: F, + ) -> impl Fn( + FunctionEnvMut<'_, VpVmEnv>, + ARG0, + ARG1, + ARG2, + ARG3, + ) -> RET + where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, + CA: WasmCacheAccess + 'static, + EVAL: VpEvaluator + 'static, + F: Fn( + &VpVmEnv, + ARG0, + ARG1, + ARG2, + ARG3, + ) -> RET, + { + move |env, arg0, arg1, arg2, arg3| f(env.data(), arg0, arg1, arg2, arg3) + } + + pub(super) fn _9< + F, + ARG0, + ARG1, + ARG2, + ARG3, + ARG4, + ARG5, + ARG6, + ARG7, + ARG8, + RET, + D, + H, + EVAL, + CA, + >( + f: F, + ) -> impl Fn( + FunctionEnvMut<'_, VpVmEnv>, + ARG0, + ARG1, + ARG2, + ARG3, + ARG4, + ARG5, + ARG6, + ARG7, + ARG8, + ) -> RET + where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, + CA: WasmCacheAccess + 'static, + EVAL: VpEvaluator + 'static, + F: Fn( + &VpVmEnv, + ARG0, + ARG1, + ARG2, + ARG3, + ARG4, + ARG5, + ARG6, + ARG7, + ARG8, + ) -> RET, + { + move |env, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8| { + f( + env.data(), + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + ) + } + } +} diff --git a/crates/namada/src/vm/wasm/memory.rs b/crates/namada/src/vm/wasm/memory.rs index 451301ec9b..89ebcd037f 100644 --- a/crates/namada/src/vm/wasm/memory.rs +++ b/crates/namada/src/vm/wasm/memory.rs @@ -1,18 +1,20 @@ //! Wasm memory is used for bi-directionally passing data between the host and a //! wasm instance. +use std::cell::RefCell; use std::ptr::NonNull; +use std::rc::Rc; use std::str::Utf8Error; -use std::sync::Arc; use borsh_ext::BorshSerializeExt; use namada_gas::MEMORY_ACCESS_GAS_PER_BYTE; use namada_sdk::arith::{self, checked}; use namada_tx::BatchedTxRef; use thiserror::Error; +use wasmer::sys::BaseTunables; use wasmer::{ - vm, BaseTunables, HostEnvInitError, LazyInit, Memory, MemoryError, - MemoryType, Pages, TableType, Target, Tunables, WASM_PAGE_SIZE, + vm, Memory, MemoryError, MemoryType, Pages, Store, TableType, Target, + Tunables, WASM_PAGE_SIZE, }; use wasmer_vm::{ MemoryStyle, TableStyle, VMMemoryDefinition, VMTableDefinition, @@ -28,8 +30,10 @@ pub enum Error { OverflowingOffset(u64, usize), #[error("Failed initializing the memory: {0}")] InitMemoryError(wasmer::MemoryError), - #[error("Memory ouf of bounds: {0}")] - MemoryOutOfBounds(wasmer::MemoryError), + #[error("Failed to grow memory: {0}")] + Grow(wasmer::MemoryError), + #[error("Wasm memory access error: {0}")] + Access(#[from] wasmer::MemoryAccessError), #[error("Encoding error: {0}")] EncodingError(std::io::Error), #[error("Memory is not initialized")] @@ -58,7 +62,9 @@ pub const VP_MEMORY_INIT_PAGES: u32 = 100; // 6.4 MiB pub const VP_MEMORY_MAX_PAGES: u32 = 200; // 12.8 MiB /// Prepare memory for instantiating a transaction module -pub fn prepare_tx_memory(store: &wasmer::Store) -> Result { +pub fn prepare_tx_memory( + store: &mut impl wasmer::AsStoreMut, +) -> Result { let mem_type = wasmer::MemoryType::new( TX_MEMORY_INIT_PAGES, Some(TX_MEMORY_MAX_PAGES), @@ -68,7 +74,9 @@ pub fn prepare_tx_memory(store: &wasmer::Store) -> Result { } /// Prepare memory for instantiating a validity predicate module -pub fn prepare_vp_memory(store: &wasmer::Store) -> Result { +pub fn prepare_vp_memory( + store: &mut impl wasmer::AsStoreMut, +) -> Result { let mem_type = wasmer::MemoryType::new( VP_MEMORY_INIT_PAGES, Some(VP_MEMORY_MAX_PAGES), @@ -89,6 +97,7 @@ pub struct TxCallInput { /// Write transaction inputs into wasm memory pub fn write_tx_inputs( + store: &mut impl wasmer::AsStoreMut, memory: &wasmer::Memory, tx_data: &BatchedTxRef<'_>, ) -> Result { @@ -96,7 +105,7 @@ pub fn write_tx_inputs( let tx_data_bytes = tx_data.serialize_to_vec(); let tx_data_len = tx_data_bytes.len() as _; - write_memory_bytes(memory, tx_data_ptr, tx_data_bytes)?; + write_memory_bytes(store, memory, tx_data_ptr, tx_data_bytes)?; Ok(TxCallInput { tx_data_ptr, @@ -127,6 +136,7 @@ pub struct VpCallInput { /// Write validity predicate inputs into wasm memory pub fn write_vp_inputs( + store: &mut impl wasmer::AsStoreMut, memory: &wasmer::Memory, VpInput { addr, @@ -158,7 +168,7 @@ pub fn write_vp_inputs( &verifiers_bytes[..], ] .concat(); - write_memory_bytes(memory, addr_ptr, bytes)?; + write_memory_bytes(store, memory, addr_ptr, bytes)?; Ok(VpCallInput { addr_ptr, @@ -174,12 +184,22 @@ pub fn write_vp_inputs( /// Check that the given offset and length fits into the memory bounds. If not, /// it will try to grow the memory. -fn check_bounds(memory: &Memory, base_addr: u64, offset: usize) -> Result<()> { +// TODO: avoid growing memory if we're only performing reads; return an Err +// instead +fn check_bounds( + store: &mut impl wasmer::AsStoreMut, + memory: &Memory, + base_addr: u64, + offset: usize, +) -> Result<()> { + let store_mut = store.as_store_mut(); + let memview = memory.view(&store_mut); + tracing::debug!( "check_bounds pages {}, data_size {}, base_addr {base_addr}, offset \ {offset}", - memory.size().0, - memory.data_size(), + memview.size().0, + memview.data_size(), ); let desired_offset = base_addr .checked_add(offset as u64) @@ -193,8 +213,8 @@ fn check_bounds(memory: &Memory, base_addr: u64, offset: usize) -> Result<()> { } }) .ok_or(Error::OverflowingOffset(base_addr, offset))?; - if memory.data_size() < desired_offset { - let cur_pages = memory.size().0 as usize; + if memview.data_size() < desired_offset { + let cur_pages = memview.size().0 as usize; let capacity = checked!(cur_pages * WASM_PAGE_SIZE)?; // usizes should be at least 32 bits wide on most architectures, // so this cast shouldn't cause panics, given the invariant that @@ -209,9 +229,9 @@ fn check_bounds(memory: &Memory, base_addr: u64, offset: usize) -> Result<()> { checked!((missing + WASM_PAGE_SIZE - 1) / WASM_PAGE_SIZE)?; let req_pages: u32 = u32::try_from(req_pages)?; tracing::debug!(req_pages, "Attempting to grow wasm memory"); - memory.grow(req_pages).map_err(Error::MemoryOutOfBounds)?; + memory.grow(store, req_pages).map_err(Error::Grow)?; tracing::debug!( - mem_size = memory.data_size(), + mem_size = memory.view(&store.as_store_mut()).data_size(), "Wasm memory size has been successfully extended" ); } @@ -220,62 +240,69 @@ fn check_bounds(memory: &Memory, base_addr: u64, offset: usize) -> Result<()> { /// Read bytes from memory at the given offset and length fn read_memory_bytes( + store: &mut impl wasmer::AsStoreMut, memory: &Memory, offset: u64, len: usize, ) -> Result> { - check_bounds(memory, offset, len)?; - let offset = usize::try_from(offset)?; - let vec: Vec<_> = memory.view()[offset..checked!(offset + len)?] - .iter() - .map(|cell| cell.get()) - .collect(); - Ok(vec) + check_bounds(store, memory, offset, len)?; + let mut buf = vec![0; len]; + memory.view(&store.as_store_mut()).read(offset, &mut buf)?; + Ok(buf) } /// Write bytes into memory at the given offset fn write_memory_bytes( + store: &mut impl wasmer::AsStoreMut, memory: &Memory, offset: u64, bytes: impl AsRef<[u8]>, ) -> Result<()> { - let slice = bytes.as_ref(); - let len = slice.len(); - check_bounds(memory, offset, len as _)?; - let offset = usize::try_from(offset)?; - memory.view()[offset..checked!(offset + len)?] - .iter() - .zip(slice.iter()) - .for_each(|(cell, v)| cell.set(*v)); + let buf = bytes.as_ref(); + check_bounds(store, memory, offset, buf.len() as _)?; + memory.view(&store.as_store_mut()).write(offset, buf)?; Ok(()) } /// The wasm memory -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone)] pub struct WasmMemory { - pub(crate) inner: LazyInit, + store: Rc>, + memory: Rc>>, } +// TODO: Wasm memory is neither `Send` nor `Sync`, but we must implement +// it for now for the code to compile. +unsafe impl Send for WasmMemory {} +unsafe impl Sync for WasmMemory {} + impl WasmMemory { - /// Initialize the memory from the given exports, used to implement - /// [`wasmer::WasmerEnv`]. - pub fn init_env_memory( - &mut self, - exports: &wasmer::Exports, - ) -> std::result::Result<(), HostEnvInitError> { - // "`TxEnv` holds a reference to the Wasm `Memory`, which itself - // internally holds a reference to the instance which owns that - // memory. However the instance itself also holds a reference to - // the `TxEnv` when it is instantiated, thus creating a circular - // reference. - // You can work around this by using `get_with_generics_weak` which - // creates a weak reference to the `Instance` internally." - // - let memory = exports.get_with_generics_weak("memory")?; - if !self.inner.initialize(memory) { + /// Build a new wasm memory. + pub fn new(store: Rc>) -> Self { + Self { + store, + memory: Rc::new(RefCell::new(None)), + } + } + + /// Initialize the host memory with a pointer to the given memory. + pub fn init_from(&mut self, memory: &Memory) { + if self.memory.borrow().is_some() { tracing::error!("wasm memory is already initialized"); + return; } - Ok(()) + *self.memory.borrow_mut() = Some(memory.clone()); + } + + /// Access the inner [`Memory`]. + #[inline] + fn access(&self, f: F) -> Result + where + F: FnOnce(&Memory) -> Result, + { + let borrow = self.memory.borrow(); + let memory = borrow.as_ref().ok_or(Error::UninitializedMemory)?; + f(memory) } } @@ -285,23 +312,27 @@ impl VmMemory for WasmMemory { /// Read bytes from memory at the given offset and length, return the bytes /// and the gas cost fn read_bytes(&self, offset: u64, len: usize) -> Result<(Vec, u64)> { - let memory = self.inner.get_ref().ok_or(Error::UninitializedMemory)?; - let bytes = read_memory_bytes(memory, offset, len)?; - let len = bytes.len() as u64; - let gas = checked!(len * MEMORY_ACCESS_GAS_PER_BYTE)?; - Ok((bytes, gas)) + self.access(|memory| { + let mut store = self.store.borrow_mut(); + let bytes = read_memory_bytes(&mut *store, memory, offset, len)?; + let len = bytes.len() as u64; + let gas = checked!(len * MEMORY_ACCESS_GAS_PER_BYTE)?; + Ok((bytes, gas)) + }) } /// Write bytes into memory at the given offset and return the gas cost fn write_bytes(&self, offset: u64, bytes: impl AsRef<[u8]>) -> Result { - // No need for a separate gas multiplier for writes since we are only - // writing to memory and we already charge gas for every memory page - // allocated - let len = bytes.as_ref().len() as u64; - let gas = checked!(len * MEMORY_ACCESS_GAS_PER_BYTE)?; - let memory = self.inner.get_ref().ok_or(Error::UninitializedMemory)?; - write_memory_bytes(memory, offset, bytes)?; - Ok(gas) + self.access(|memory| { + // No need for a separate gas multiplier for writes since we are + // only writing to memory and we already charge gas for + // every memory page allocated + let len = bytes.as_ref().len() as u64; + let gas = checked!(len * MEMORY_ACCESS_GAS_PER_BYTE)?; + let mut store = self.store.borrow_mut(); + write_memory_bytes(&mut *store, memory, offset, bytes)?; + Ok(gas) + }) } /// Read string from memory at the given offset and bytes length, and return @@ -321,7 +352,6 @@ impl VmMemory for WasmMemory { } } -#[derive(loupe::MemoryUsage)] /// A custom [`Tunables`] to set a WASM memory limits. /// /// Adapted from . @@ -341,6 +371,7 @@ pub fn vp_limit() -> Limit { let limit = Pages(VP_MEMORY_MAX_PAGES); Limit { limit, base } } + /// A [`Limit`] with memory limit setup for transaction WASM execution. pub fn tx_limit() -> Limit { let base = BaseTunables::for_target(&Target::default()); @@ -412,7 +443,7 @@ impl Tunables for Limit { &self, ty: &MemoryType, style: &MemoryStyle, - ) -> std::result::Result, MemoryError> { + ) -> std::result::Result { let adjusted = self.adjust_memory(ty); self.validate_memory(&adjusted)?; self.base.create_host_memory(&adjusted, style) @@ -427,7 +458,7 @@ impl Tunables for Limit { ty: &MemoryType, style: &MemoryStyle, vm_definition_location: NonNull, - ) -> std::result::Result, MemoryError> { + ) -> std::result::Result { let adjusted = self.adjust_memory(ty); self.validate_memory(&adjusted)?; self.base @@ -442,7 +473,7 @@ impl Tunables for Limit { &self, ty: &TableType, style: &TableStyle, - ) -> std::result::Result, String> { + ) -> std::result::Result { self.base.create_host_table(ty, style) } @@ -455,14 +486,18 @@ impl Tunables for Limit { ty: &TableType, style: &TableStyle, vm_definition_location: NonNull, - ) -> std::result::Result, String> { + ) -> std::result::Result { self.base.create_vm_table(ty, style, vm_definition_location) } } #[cfg(test)] pub mod tests { - use wasmer::{wat2wasm, Cranelift, Instance, Module, Store}; + use wasmer::sys::Features; + use wasmer::{ + wat2wasm, Cranelift, Engine, Instance, Module, NativeEngineExt, Store, + Target, + }; use super::*; @@ -479,14 +514,19 @@ pub mod tests { // Any compiler and any engine do the job here let compiler = Cranelift::default(); - let engine = wasmer_engine_universal::Universal::new(compiler).engine(); + let mut engine = ::new( + Box::new(compiler), + Target::default(), + Features::default(), + ); let base = BaseTunables::for_target(&Target::default()); let limit = Pages(24); let tunables = Limit { limit, base }; + engine.set_tunables(tunables); // Create a store, that holds the engine and our custom tunables - let store = Store::new_with_tunables(&engine, tunables); + let mut store = Store::new(engine); println!("Compiling module..."); let module = Module::new(&store, wasm_bytes).unwrap(); @@ -495,7 +535,8 @@ pub mod tests { let import_object = wasmer::imports! {}; // Now at this point, our custom tunables are used - let instance = Instance::new(&module, &import_object).unwrap(); + let instance = + Instance::new(&mut store, &module, &import_object).unwrap(); // Check what happened let mut memories: Vec = instance @@ -508,6 +549,6 @@ pub mod tests { let first_memory = memories.pop().unwrap(); println!("Memory of this instance: {:?}", first_memory); - assert_eq!(first_memory.ty().maximum.unwrap(), limit); + assert_eq!(first_memory.ty(&store).maximum.unwrap(), limit); } } diff --git a/crates/namada/src/vm/wasm/run.rs b/crates/namada/src/vm/wasm/run.rs index 002081a288..53adc441d3 100644 --- a/crates/namada/src/vm/wasm/run.rs +++ b/crates/namada/src/vm/wasm/run.rs @@ -6,6 +6,7 @@ use std::error::Error as _; use std::fmt::Debug; use std::marker::PhantomData; use std::num::NonZeroU32; +use std::rc::Rc; use borsh::BorshDeserialize; use namada_core::validity_predicate::VpError; @@ -16,7 +17,8 @@ use namada_tx::{BatchedTxRef, Commitment, Section, Tx, TxCommitments}; use parity_wasm::elements::Instruction::*; use parity_wasm::elements::{self, SignExtInstruction}; use thiserror::Error; -use wasmer::{BaseTunables, Module, Store}; +use wasmer::sys::{BaseTunables, Features}; +use wasmer::{Engine, Module, NativeEngineExt, Store, Target}; use super::memory::{Limit, WasmMemory}; use super::TxCache; @@ -191,6 +193,7 @@ where let (module, store) = fetch_or_compile(tx_wasm_cache, &tx_code.code, state, gas_meter)?; + let store = Rc::new(RefCell::new(store)); let mut iterators: PrefixIterators<'_, ::D> = PrefixIterators::default(); @@ -200,8 +203,8 @@ where let sentinel = RefCell::new(TxSentinel::default()); let (write_log, in_mem, db) = state.split_borrow(); - let env = TxVmEnv::new( - WasmMemory::default(), + let mut env = TxVmEnv::new( + WasmMemory::new(Rc::clone(&store)), write_log, in_mem, db, @@ -218,51 +221,69 @@ where tx_wasm_cache, ); - let imports = tx_imports(&store, env); - // Instantiate the wasm module - let instance = wasmer::Instance::new(&module, &imports) - .map_err(|e| Error::InstantiationError(Box::new(e)))?; + let instance = { + let mut store = store.borrow_mut(); + let imports = tx_imports(&mut *store, env.clone()); + wasmer::Instance::new(&mut *store, &module, &imports) + .map_err(|e| Error::InstantiationError(Box::new(e)))? + }; - // We need to write the inputs in the memory exported from the wasm - // module - let memory = instance + // Fetch guest's main memory + let guest_memory = instance .exports .get_memory("memory") .map_err(Error::MissingModuleMemory)?; + + env.memory.init_from(guest_memory); + + // Write the inputs in the memory exported from the wasm + // module let memory::TxCallInput { tx_data_ptr, tx_data_len, - } = memory::write_tx_inputs(memory, &batched_tx) - .map_err(Error::MemoryError)?; + } = { + let mut store = store.borrow_mut(); + memory::write_tx_inputs(&mut *store, guest_memory, &batched_tx) + .map_err(Error::MemoryError)? + }; + // Get the module's entrypoint to be called - let apply_tx = instance - .exports - .get_function(TX_ENTRYPOINT) - .map_err(Error::MissingModuleEntrypoint)? - .native::<(u64, u64), u64>() - .map_err(|error| Error::UnexpectedModuleEntrypointInterface { - entrypoint: TX_ENTRYPOINT, - error, - })?; - let ok = apply_tx.call(tx_data_ptr, tx_data_len).map_err(|err| { - tracing::debug!("Tx WASM failed with {}", err); - match *sentinel.borrow() { - TxSentinel::None => Error::RuntimeError(err), - TxSentinel::OutOfGas => Error::GasError(err.to_string()), - TxSentinel::InvalidCommitment => { - Error::MissingSection(err.to_string()) + let apply_tx = { + let store = store.borrow(); + instance + .exports + .get_function(TX_ENTRYPOINT) + .map_err(Error::MissingModuleEntrypoint)? + .typed::<(u64, u64), u64>(&*store) + .map_err(|error| Error::UnexpectedModuleEntrypointInterface { + entrypoint: TX_ENTRYPOINT, + error, + })? + }; + let ok = apply_tx + .call( + unsafe { &mut *RefCell::as_ptr(&*store) }, + tx_data_ptr, + tx_data_len, + ) + .map_err(|err| { + tracing::debug!("Tx WASM failed with {}", err); + match *sentinel.borrow() { + TxSentinel::None => Error::RuntimeError(err), + TxSentinel::OutOfGas => Error::GasError(err.to_string()), + TxSentinel::InvalidCommitment => { + Error::MissingSection(err.to_string()) + } } - } - })?; + })?; + + // NB: early drop this data to avoid memory errors + _ = (instance, env); if ok == 1 { Ok(verifiers) } else { - // NB: drop imports so we can safely access the - // `&mut` ptrs we shared with the guest - _ = (instance, imports); - let err = yielded_value.take().map_or_else( || Ok("Execution ended abruptly with an unknown error".to_owned()), |borsh_encoded_err| { @@ -306,6 +327,7 @@ where state, gas_meter, )?; + let store = Rc::new(RefCell::new(store)); let mut iterators: PrefixIterators<'_, ::D> = PrefixIterators::default(); @@ -318,8 +340,8 @@ where cache_access: PhantomData, }; let BatchedTxRef { tx, cmt } = batched_tx; - let env = VpVmEnv::new( - WasmMemory::default(), + let mut env = VpVmEnv::new( + WasmMemory::new(Rc::clone(&store)), address, state.write_log(), state.in_mem(), @@ -338,9 +360,14 @@ where ); let yielded_value_borrow = env.ctx.yielded_value; - let imports = vp_imports(&store, env); + + let imports = { + let mut store = store.borrow_mut(); + vp_imports(&mut *store, env.clone()) + }; run_vp( + store, module, imports, &vp_code_hash, @@ -349,20 +376,26 @@ where keys_changed, verifiers, yielded_value_borrow, + |guest_memory| env.memory.init_from(guest_memory), ) } #[allow(clippy::too_many_arguments)] -fn run_vp( +fn run_vp( + store: Rc>, module: wasmer::Module, - vp_imports: wasmer::ImportObject, + vp_imports: wasmer::Imports, vp_code_hash: &Hash, input_data: &BatchedTxRef<'_>, address: &Address, keys_changed: &BTreeSet, verifiers: &BTreeSet
, yielded_value: HostRef>>, -) -> Result<()> { + mut init_memory_callback: F, +) -> Result<()> +where + F: FnMut(&wasmer::Memory), +{ let input: VpInput<'_> = VpInput { addr: address, data: input_data, @@ -371,15 +404,22 @@ fn run_vp( }; // Instantiate the wasm module - let instance = wasmer::Instance::new(&module, &vp_imports) - .map_err(|e| Error::InstantiationError(Box::new(e)))?; + let instance = { + let mut store = store.borrow_mut(); + wasmer::Instance::new(&mut *store, &module, &vp_imports) + .map_err(|e| Error::InstantiationError(Box::new(e)))? + }; - // We need to write the inputs in the memory exported from the wasm - // module - let memory = instance + // Fetch guest's main memory + let guest_memory = instance .exports .get_memory("memory") .map_err(Error::MissingModuleMemory)?; + + init_memory_callback(guest_memory); + + // Write the inputs in the memory exported from the wasm + // module let memory::VpCallInput { addr_ptr, addr_len, @@ -389,20 +429,28 @@ fn run_vp( keys_changed_len, verifiers_ptr, verifiers_len, - } = memory::write_vp_inputs(memory, input).map_err(Error::MemoryError)?; + } = { + let mut store = store.borrow_mut(); + memory::write_vp_inputs(&mut *store, guest_memory, input) + .map_err(Error::MemoryError)? + }; // Get the module's entrypoint to be called - let validate_tx = instance - .exports - .get_function(VP_ENTRYPOINT) - .map_err(Error::MissingModuleEntrypoint)? - .native::<(u64, u64, u64, u64, u64, u64, u64, u64), u64>() - .map_err(|error| Error::UnexpectedModuleEntrypointInterface { - entrypoint: VP_ENTRYPOINT, - error, - })?; + let validate_tx = { + let store = store.borrow(); + instance + .exports + .get_function(VP_ENTRYPOINT) + .map_err(Error::MissingModuleEntrypoint)? + .typed::<(u64, u64, u64, u64, u64, u64, u64, u64), u64>(&*store) + .map_err(|error| Error::UnexpectedModuleEntrypointInterface { + entrypoint: VP_ENTRYPOINT, + error, + })? + }; let is_valid = validate_tx .call( + unsafe { &mut *RefCell::as_ptr(&*store) }, addr_ptr, addr_len, data_ptr, @@ -438,13 +486,12 @@ fn run_vp( "wasm vp" ); + // NB: early drop this data to avoid memory errors + _ = (instance, vp_imports); + if is_valid == 1 { Ok(()) } else { - // NB: drop imports so we can safely access the - // `&mut` ptrs we shared with the guest - _ = (instance, vp_imports); - unsafe { yielded_value.get_mut() }.take().map_or_else( || Err(Error::VpError(VpError::Unspecified)), |borsh_encoded_err| { @@ -526,15 +573,20 @@ where &ctx.state(), gas_meter, )?; + let store = Rc::new(RefCell::new(store)); - let env = VpVmEnv { - memory: WasmMemory::default(), + let mut env = VpVmEnv { + memory: WasmMemory::new(Rc::clone(&store)), ctx, }; let yielded_value_borrow = env.ctx.yielded_value; - let imports = vp_imports(&store, env); + let imports = { + let mut store = store.borrow_mut(); + vp_imports(&mut *store, env.clone()) + }; run_vp( + store, module, imports, &vp_code_hash, @@ -543,6 +595,7 @@ where keys_changed, verifiers, yielded_value_borrow, + |guest_memory| env.memory.init_from(guest_memory), ) } } @@ -551,10 +604,16 @@ where pub fn untrusted_wasm_store(limit: Limit) -> wasmer::Store { // Use Singlepass compiler with the default settings let compiler = wasmer_compiler_singlepass::Singlepass::default(); - wasmer::Store::new_with_tunables( - &wasmer_engine_universal::Universal::new(compiler).engine(), - limit, - ) + let mut engine = ::new( + Box::new(compiler), + // NB: The default target corresponds to the host's triplet + Target::default(), + // NB: WASM features are validated via `validate_untrusted_wasm`, + // so we can use the default features here + Features::default(), + ); + engine.set_tunables(limit); + wasmer::Store::new(engine) } /// Inject gas counter and stack-height limiter into the given wasm code @@ -1288,7 +1347,7 @@ mod tests { // of memory match result { // Dylib engine error (used anywhere except mac) - Err(Error::MemoryError(memory::Error::MemoryOutOfBounds( + Err(Error::MemoryError(memory::Error::Grow( wasmer::MemoryError::CouldNotGrow { .. }, ))) => {} Err(error) => { @@ -1352,7 +1411,7 @@ mod tests { // of memory match result { // Dylib engine error (used anywhere except mac) - Err(Error::MemoryError(memory::Error::MemoryOutOfBounds( + Err(Error::MemoryError(memory::Error::Grow( wasmer::MemoryError::CouldNotGrow { .. }, ))) => { // as expected diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 2a00208e8a..58cef7625d 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -54,7 +54,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "once_cell", "version_check", ] @@ -83,6 +83,55 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "anyhow" version = "1.0.75" @@ -304,7 +353,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "miniz_oxide", - "object 0.32.1", + "object", "rustc-demangle", ] @@ -661,6 +710,15 @@ dependencies = [ "serde", ] +[[package]] +name = "bytesize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" +dependencies = [ + "serde", +] + [[package]] name = "camino" version = "1.1.6" @@ -787,6 +845,46 @@ dependencies = [ "version_check", ] +[[package]] +name = "clap" +version = "4.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + [[package]] name = "clru" version = "0.5.0" @@ -844,6 +942,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + [[package]] name = "concat-idents" version = "1.1.5" @@ -994,56 +1098,74 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38faa2a16616c8e78a18d37b4726b98bfd2de192f2fdc8a39ddf568a408a0f75" +checksum = "2a2ab4512dfd3a6f4be184403a195f76e81a8a9f9e6c898e19d2dc3ce20e0115" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f192472a3ba23860afd07d2b0217dc628f21fcc72617aa1336d98e1671f33b" +checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc" dependencies = [ + "arrayvec", + "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", + "cranelift-egraph", "cranelift-entity", + "cranelift-isle", "gimli 0.26.2", "log", - "regalloc", + "regalloc2", "smallvec", "target-lexicon", ] [[package]] name = "cranelift-codegen-meta" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32ddb89e9b89d3d9b36a5b7d7ea3261c98235a76ac95ba46826b8ec40b1a24" +checksum = "639307b45434ad112a98f8300c0f0ab085cbefcd767efcdef9ef19d4c0756e74" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.82.3" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "278e52e29c53fcf32431ef08406c295699a70306d05a0715c5b1bf50e33a9ab7" + +[[package]] +name = "cranelift-egraph" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01fd0d9f288cc1b42d9333b7a776b17e278fc888c28e6a0f09b5573d45a150bc" +checksum = "624b54323b06e675293939311943ba82d323bb340468ce1889be5da7932c8d73" +dependencies = [ + "cranelift-entity", + "fxhash", + "hashbrown 0.12.3", + "indexmap 1.9.3", + "log", + "smallvec", +] [[package]] name = "cranelift-entity" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3bfe172b83167604601faf9dc60453e0d0a93415b57a9c4d1a7ae6849185cf" +checksum = "9a59bcbca89c3f1b70b93ab3cbba5e5e0cbf3e63dadb23c7525cb142e21a9d4c" [[package]] name = "cranelift-frontend" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a006e3e32d80ce0e4ba7f1f9ddf66066d052a8c884a110b91d05404d6ce26dce" +checksum = "0d70abacb8cfef3dc8ff7e8836e9c1d70f7967dfdac824a4cd5e30223415aca6" dependencies = [ "cranelift-codegen", "log", @@ -1051,6 +1173,12 @@ dependencies = [ "target-lexicon", ] +[[package]] +name = "cranelift-isle" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" + [[package]] name = "crc32fast" version = "1.3.2" @@ -1080,10 +1208,19 @@ dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset 0.9.0", + "memoffset", "scopeguard", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.19" @@ -1180,14 +1317,38 @@ dependencies = [ "serde", ] +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + [[package]] name = "darling" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.3", + "darling_macro 0.20.3", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", ] [[package]] @@ -1203,17 +1364,41 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ - "darling_core", + "darling_core 0.20.3", "quote", "syn 2.0.52", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if 1.0.0", + "hashbrown 0.14.3", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "data-encoding" version = "2.5.0" @@ -1256,6 +1441,37 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_builder" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" +dependencies = [ + "darling 0.14.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -1319,6 +1535,15 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "document-features" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +dependencies = [ + "litrs", +] + [[package]] name = "dunce" version = "1.0.4" @@ -1368,7 +1593,7 @@ checksum = "64fba5a42bd76a17cad4bfa00de168ee1cbfa06a5e8ce992ae880218c05641a9" dependencies = [ "byteorder", "dynasm", - "memmap2", + "memmap2 0.5.10", ] [[package]] @@ -1514,7 +1739,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" dependencies = [ - "darling", + "darling 0.20.3", "proc-macro2", "quote", "syn 2.0.52", @@ -2127,9 +2352,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -2211,7 +2436,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.11", - "indexmap 2.1.0", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -2219,13 +2444,10 @@ dependencies = [ ] [[package]] -name = "hashbrown" -version = "0.11.2" +name = "half" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" [[package]] name = "hashbrown" @@ -3087,20 +3309,21 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +version = "2.2.4" +source = "git+https://github.com/heliaxdev/indexmap?tag=2.2.4-heliax-1#b5b5b547bd6ab04bbb16e060326a50ddaeb6c909" dependencies = [ + "borsh 1.4.0", "equivalent", "hashbrown 0.14.3", + "serde", ] [[package]] name = "indexmap" -version = "2.2.4" -source = "git+https://github.com/heliaxdev/indexmap?tag=2.2.4-heliax-1#b5b5b547bd6ab04bbb16e060326a50ddaeb6c909" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ - "borsh 1.4.0", "equivalent", "hashbrown 0.14.3", "serde", @@ -3159,6 +3382,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.11.0" @@ -3282,16 +3511,6 @@ version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if 1.0.0", - "winapi", -] - [[package]] name = "libm" version = "0.2.8" @@ -3335,6 +3554,12 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + [[package]] name = "lock_api" version = "0.4.11" @@ -3351,27 +3576,6 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -[[package]] -name = "loupe" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6a72dfa44fe15b5e76b94307eeb2ff995a8c5b283b55008940c02e0c5b634d" -dependencies = [ - "indexmap 1.9.3", - "loupe-derive", - "rustversion", -] - -[[package]] -name = "loupe-derive" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fbfc88337168279f2e9ae06e157cfed4efd3316e14dc96ed074d4f2e6c5952" -dependencies = [ - "quote", - "syn 1.0.109", -] - [[package]] name = "mach" version = "0.3.2" @@ -3435,7 +3639,7 @@ dependencies = [ "blake2b_simd", "bls12_381", "directories", - "getrandom 0.2.11", + "getrandom 0.2.15", "group", "itertools 0.11.0", "jubjub", @@ -3478,12 +3682,12 @@ dependencies = [ ] [[package]] -name = "memoffset" -version = "0.6.5" +name = "memmap2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" dependencies = [ - "autocfg", + "libc", ] [[package]] @@ -3584,7 +3788,6 @@ dependencies = [ "itertools 0.12.1", "konst", "linkme", - "loupe", "masp_primitives", "masp_proofs", "namada_account", @@ -3636,8 +3839,6 @@ dependencies = [ "wasmer", "wasmer-cache", "wasmer-compiler-singlepass", - "wasmer-engine-dylib", - "wasmer-engine-universal", "wasmer-vm", "wasmparser 0.107.0", "wasmtimer", @@ -4384,18 +4585,6 @@ dependencies = [ "syn 2.0.52", ] -[[package]] -name = "object" -version = "0.28.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" -dependencies = [ - "crc32fast", - "hashbrown 0.11.2", - "indexmap 1.9.3", - "memchr", -] - [[package]] name = "object" version = "0.32.1" @@ -4449,7 +4638,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6624905ddd92e460ff0685567539ed1ac985b2dee4c92c7edcd64fce905b00c" dependencies = [ "ct-codecs", - "getrandom 0.2.11", + "getrandom 0.2.15", "subtle", "zeroize", ] @@ -4652,7 +4841,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.1.0", + "indexmap 2.2.6", ] [[package]] @@ -4998,7 +5187,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", ] [[package]] @@ -5087,19 +5276,20 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "libredox", "thiserror", ] [[package]] -name = "regalloc" -version = "0.0.34" +name = "regalloc2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62446b1d3ebf980bdc68837700af1d77b37bc430e524bf95319c6eada2a4cc02" +checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c" dependencies = [ + "fxhash", "log", - "rustc-hash", + "slice-group-by", "smallvec", ] @@ -5235,7 +5425,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", - "getrandom 0.2.11", + "getrandom 0.2.15", "libc", "spin 0.9.8", "untrusted 0.9.0", @@ -5260,6 +5450,7 @@ dependencies = [ "bitvec", "bytecheck", "hashbrown 0.12.3", + "indexmap 1.9.3", "ptr_meta", "rend", "rkyv_derive", @@ -5458,6 +5649,7 @@ dependencies = [ "schemars_derive", "serde", "serde_json", + "url", ] [[package]] @@ -5521,6 +5713,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "self_cell" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" + [[package]] name = "semver" version = "0.11.0" @@ -5562,9 +5760,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] @@ -5587,6 +5785,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_bytes" version = "0.11.12" @@ -5596,11 +5805,21 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", @@ -5661,6 +5880,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.2.6", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "serdect" version = "0.2.0" @@ -5714,6 +5946,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared-buffer" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" +dependencies = [ + "bytes", + "memmap2 0.6.2", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -5766,6 +6008,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + [[package]] name = "slip10_ed25519" version = "0.1.3" @@ -5865,6 +6113,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" version = "0.24.1" @@ -6155,7 +6409,7 @@ dependencies = [ "async-trait", "bytes", "flex-error", - "getrandom 0.2.11", + "getrandom 0.2.15", "peg", "pin-project", "rand 0.8.5", @@ -6399,6 +6653,18 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.19.15", +] + [[package]] name = "toml" version = "0.8.2" @@ -6426,7 +6692,9 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.6", + "serde", + "serde_spanned", "toml_datetime", "winnow 0.5.25", ] @@ -6437,7 +6705,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -6450,7 +6718,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.6", "toml_datetime", "winnow 0.5.25", ] @@ -6533,7 +6801,6 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -6594,7 +6861,7 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" name = "tx_become_validator" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6603,7 +6870,7 @@ dependencies = [ name = "tx_bond" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada", "namada_test_utils", "namada_tests", @@ -6620,7 +6887,7 @@ dependencies = [ name = "tx_bridge_pool" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6629,7 +6896,7 @@ dependencies = [ name = "tx_change_consensus_key" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6638,7 +6905,7 @@ dependencies = [ name = "tx_change_validator_commission" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada", "namada_test_utils", "namada_tests", @@ -6655,7 +6922,7 @@ dependencies = [ name = "tx_change_validator_metadata" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6664,7 +6931,7 @@ dependencies = [ name = "tx_claim_rewards" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6673,7 +6940,7 @@ dependencies = [ name = "tx_deactivate_validator" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6682,7 +6949,7 @@ dependencies = [ name = "tx_ibc" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6691,7 +6958,7 @@ dependencies = [ name = "tx_init_account" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6700,7 +6967,7 @@ dependencies = [ name = "tx_init_proposal" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6709,7 +6976,7 @@ dependencies = [ name = "tx_reactivate_validator" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6718,7 +6985,7 @@ dependencies = [ name = "tx_redelegate" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada", "namada_test_utils", "namada_tests", @@ -6735,7 +7002,7 @@ dependencies = [ name = "tx_resign_steward" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6744,7 +7011,7 @@ dependencies = [ name = "tx_reveal_pk" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6753,7 +7020,7 @@ dependencies = [ name = "tx_transfer" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6762,7 +7029,7 @@ dependencies = [ name = "tx_unbond" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada", "namada_test_utils", "namada_tests", @@ -6779,7 +7046,7 @@ dependencies = [ name = "tx_unjail_validator" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6788,7 +7055,7 @@ dependencies = [ name = "tx_update_account" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6797,7 +7064,7 @@ dependencies = [ name = "tx_update_steward_commission" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6806,7 +7073,7 @@ dependencies = [ name = "tx_vote_proposal" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_tx_prelude", "wee_alloc", ] @@ -6815,7 +7082,7 @@ dependencies = [ name = "tx_withdraw" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada", "namada_test_utils", "namada_tests", @@ -6936,6 +7203,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.7.1" @@ -6957,15 +7230,22 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "uuid" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "serde", ] @@ -6985,7 +7265,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" name = "vp_implicit" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada", "namada_test_utils", "namada_tests", @@ -7002,7 +7282,7 @@ dependencies = [ name = "vp_user" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada", "namada_test_utils", "namada_tests", @@ -7141,46 +7421,38 @@ dependencies = [ [[package]] name = "wasmer" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce4a267a570e121c9375136adefa2c48810273907de9c6817bc19db4d6144bc" dependencies = [ + "bytes", "cfg-if 1.0.0", + "derivative", "indexmap 1.9.3", "js-sys", - "loupe", "more-asserts", + "rustc-demangle", + "serde", + "serde-wasm-bindgen", + "shared-buffer", "target-lexicon", "thiserror", + "tracing", "wasm-bindgen", - "wasmer-artifact", "wasmer-compiler", "wasmer-compiler-cranelift", "wasmer-derive", - "wasmer-engine", - "wasmer-engine-dylib", - "wasmer-engine-universal", "wasmer-types", "wasmer-vm", "wat", "winapi", ] -[[package]] -name = "wasmer-artifact" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "enumset", - "loupe", - "thiserror", - "wasmer-compiler", - "wasmer-types", -] - [[package]] name = "wasmer-cache" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a40804bcc2567f112003182fc5edc29584da5199c4a1f5a8d6a6e4b65feff0" dependencies = [ "blake3", "hex", @@ -7190,31 +7462,42 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9c23098e86ef1038155684fe50f0c1079a0e2a2e70f115b789df17e6ba98d20" dependencies = [ + "backtrace", + "bytes", + "cfg-if 1.0.0", + "enum-iterator", "enumset", - "loupe", + "lazy_static", + "leb128", + "memmap2 0.5.10", + "more-asserts", + "region", "rkyv", - "serde", - "serde_bytes", + "self_cell", + "shared-buffer", "smallvec", - "target-lexicon", "thiserror", "wasmer-types", - "wasmparser 0.83.0", + "wasmer-vm", + "wasmparser 0.121.2", + "winapi", + "xxhash-rust", ] [[package]] name = "wasmer-compiler-cranelift" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95287b79973ad5f485215733ef9f0d4bb951a6b7e655585d2bd3d4a4ba1253c9" dependencies = [ "cranelift-codegen", "cranelift-entity", "cranelift-frontend", "gimli 0.26.2", - "loupe", "more-asserts", "rayon", "smallvec", @@ -7222,185 +7505,128 @@ dependencies = [ "tracing", "wasmer-compiler", "wasmer-types", - "wasmer-vm", ] [[package]] name = "wasmer-compiler-singlepass" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00d78d59be3ce78ad859e176b88f0d5bec0120ece0684922d7c5da1289e251b1" dependencies = [ "byteorder", "dynasm", "dynasmrt", + "enumset", "gimli 0.26.2", "lazy_static", - "loupe", "more-asserts", "rayon", "smallvec", "wasmer-compiler", "wasmer-types", - "wasmer-vm", ] [[package]] -name = "wasmer-derive" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "wasmer-engine" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "backtrace", - "enumset", - "lazy_static", - "loupe", - "memmap2", - "more-asserts", - "rustc-demangle", - "serde", - "serde_bytes", - "target-lexicon", - "thiserror", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-types", - "wasmer-vm", -] - -[[package]] -name = "wasmer-engine-dylib" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +name = "wasmer-config" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a0f70c177b1c5062cfe0f5308c3317751796fef9403c22a0cd7b4cacd4ccd8" dependencies = [ - "cfg-if 1.0.0", - "enum-iterator", - "enumset", - "leb128", - "libloading", - "loupe", - "object 0.28.4", - "rkyv", + "anyhow", + "bytesize", + "derive_builder", + "hex", + "indexmap 2.2.6", + "schemars", + "semver 1.0.20", "serde", - "tempfile", - "tracing", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-engine", - "wasmer-object", - "wasmer-types", - "wasmer-vm", - "which", -] - -[[package]] -name = "wasmer-engine-universal" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "cfg-if 1.0.0", - "enumset", - "leb128", - "loupe", - "region", - "rkyv", - "wasmer-compiler", - "wasmer-engine", - "wasmer-engine-universal-artifact", - "wasmer-types", - "wasmer-vm", - "winapi", -] - -[[package]] -name = "wasmer-engine-universal-artifact" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "enum-iterator", - "enumset", - "loupe", - "rkyv", + "serde_cbor", + "serde_json", + "serde_yaml", "thiserror", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-types", + "toml 0.8.2", + "url", ] [[package]] -name = "wasmer-object" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +name = "wasmer-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48f36aeeecb655f15fdd358bdf6e4cec27df181468fa4226084157e8462bd5e" dependencies = [ - "object 0.28.4", - "thiserror", - "wasmer-compiler", - "wasmer-types", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] name = "wasmer-types" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83cb97b6b20084757a2a8d548dc0d4179c3fe9e2d711740423a1e6aa3f8b9091" dependencies = [ - "backtrace", + "bytecheck", "enum-iterator", + "enumset", + "getrandom 0.2.15", + "hex", "indexmap 1.9.3", - "loupe", + "more-asserts", "rkyv", - "serde", + "sha2 0.10.8", + "target-lexicon", "thiserror", + "webc", + "xxhash-rust", ] [[package]] name = "wasmer-vm" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc1e19d986844b17b927ec8b0c7f3da6a7a2c2cb3b0f8ca5d4cb1a1f71bfb124" dependencies = [ "backtrace", "cc", "cfg-if 1.0.0", "corosensei", + "crossbeam-queue", + "dashmap", + "derivative", "enum-iterator", + "fnv", "indexmap 1.9.3", "lazy_static", "libc", - "loupe", "mach", - "memoffset 0.6.5", + "memoffset", "more-asserts", "region", - "rkyv", "scopeguard", - "serde", "thiserror", - "wasmer-artifact", "wasmer-types", "winapi", ] [[package]] name = "wasmparser" -version = "0.83.0" +version = "0.107.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" +checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" +dependencies = [ + "indexmap 1.9.3", + "semver 1.0.20", +] [[package]] name = "wasmparser" -version = "0.107.0" +version = "0.121.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" +checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" dependencies = [ - "indexmap 1.9.3", + "bitflags 2.5.0", + "indexmap 2.2.6", "semver 1.0.20", ] @@ -7449,6 +7675,36 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webc" +version = "6.0.0-alpha9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b4e8dd987046eede4348d660404ff990412631b7d493f9e547adcf2862cd5" +dependencies = [ + "anyhow", + "base64 0.21.7", + "bytes", + "cfg-if 1.0.0", + "clap", + "document-features", + "flate2", + "indexmap 1.9.3", + "libc", + "once_cell", + "semver 1.0.20", + "serde", + "serde_cbor", + "serde_json", + "sha2 0.10.8", + "shared-buffer", + "tar", + "tempfile", + "thiserror", + "toml 0.7.8", + "url", + "wasmer-config", +] + [[package]] name = "webpki-roots" version = "0.25.3" @@ -7761,6 +8017,12 @@ dependencies = [ "rustix", ] +[[package]] +name = "xxhash-rust" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" + [[package]] name = "zcash_encoding" version = "0.2.0" diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index 890a3b6c61..ad76e0cf0f 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -40,7 +40,7 @@ namada_vp_prelude = { path = "../crates/vp_prelude" } once_cell = { version = "1.8.0" } wee_alloc = "0.4.5" -getrandom = { version = "0.2", features = ["custom"] } +getrandom = { version = "0.2.15", features = ["custom"] } [profile.release] # smaller and faster wasm (https://rustwasm.github.io/book/reference/code-size.html#compiling-with-link-time-optimizations-lto) diff --git a/wasm/tx_bond/Cargo.toml b/wasm/tx_bond/Cargo.toml index 7c4a73c733..df1dd9a5f4 100644 --- a/wasm/tx_bond/Cargo.toml +++ b/wasm/tx_bond/Cargo.toml @@ -14,7 +14,7 @@ wee_alloc.workspace = true getrandom.workspace = true [dev-dependencies] -namada = {path = "../../crates/namada"} +namada = {path = "../../crates/namada", default-features = false} namada_tests = {path = "../../crates/tests"} namada_test_utils = {path = "../../crates/test_utils"} namada_tx_prelude = { workspace = true, features = ["testing"] } diff --git a/wasm/tx_change_validator_commission/Cargo.toml b/wasm/tx_change_validator_commission/Cargo.toml index d2905316ff..87815504b3 100644 --- a/wasm/tx_change_validator_commission/Cargo.toml +++ b/wasm/tx_change_validator_commission/Cargo.toml @@ -14,7 +14,7 @@ wee_alloc.workspace = true getrandom.workspace = true [dev-dependencies] -namada = {path = "../../crates/namada"} +namada = {path = "../../crates/namada", default-features = false} namada_tests = {path = "../../crates/tests"} namada_test_utils = {path = "../../crates/test_utils"} namada_vp_prelude = {path = "../../crates/vp_prelude"} diff --git a/wasm/tx_redelegate/Cargo.toml b/wasm/tx_redelegate/Cargo.toml index cd3e662f75..1c567420b2 100644 --- a/wasm/tx_redelegate/Cargo.toml +++ b/wasm/tx_redelegate/Cargo.toml @@ -14,7 +14,7 @@ wee_alloc.workspace = true getrandom.workspace = true [dev-dependencies] -namada = {path = "../../crates/namada"} +namada = {path = "../../crates/namada", default-features = false} namada_tests = {path = "../../crates/tests"} namada_test_utils = {path = "../../crates/test_utils"} namada_tx_prelude = { workspace = true, features = ["testing"] } diff --git a/wasm/tx_unbond/Cargo.toml b/wasm/tx_unbond/Cargo.toml index 75cc46c9f8..a8918cddf2 100644 --- a/wasm/tx_unbond/Cargo.toml +++ b/wasm/tx_unbond/Cargo.toml @@ -14,7 +14,7 @@ wee_alloc.workspace = true getrandom.workspace = true [dev-dependencies] -namada = {path = "../../crates/namada"} +namada = {path = "../../crates/namada", default-features = false} namada_tests = {path = "../../crates/tests"} namada_test_utils = {path = "../../crates/test_utils"} namada_tx_prelude = { workspace = true, features = ["testing"] } diff --git a/wasm/tx_withdraw/Cargo.toml b/wasm/tx_withdraw/Cargo.toml index f447b81cc0..62d5daa30d 100644 --- a/wasm/tx_withdraw/Cargo.toml +++ b/wasm/tx_withdraw/Cargo.toml @@ -14,7 +14,7 @@ wee_alloc.workspace = true getrandom.workspace = true [dev-dependencies] -namada = {path = "../../crates/namada"} +namada = {path = "../../crates/namada", default-features = false} namada_tests = {path = "../../crates/tests"} namada_test_utils = {path = "../../crates/test_utils"} namada_tx_prelude = { workspace = true, features = ["testing"] } diff --git a/wasm/vp_implicit/Cargo.toml b/wasm/vp_implicit/Cargo.toml index 6a3487b74d..e237b39337 100644 --- a/wasm/vp_implicit/Cargo.toml +++ b/wasm/vp_implicit/Cargo.toml @@ -15,7 +15,7 @@ wee_alloc.workspace = true getrandom.workspace = true [dev-dependencies] -namada = {path = "../../crates/namada"} +namada = {path = "../../crates/namada", default-features = false} namada_tests = {path = "../../crates/tests"} namada_test_utils = {path = "../../crates/test_utils"} namada_vp_prelude = {path = "../../crates/vp_prelude"} diff --git a/wasm/vp_user/Cargo.toml b/wasm/vp_user/Cargo.toml index fdcc100666..e10d44d4c7 100644 --- a/wasm/vp_user/Cargo.toml +++ b/wasm/vp_user/Cargo.toml @@ -15,7 +15,7 @@ wee_alloc.workspace = true getrandom.workspace = true [dev-dependencies] -namada = {path = "../../crates/namada"} +namada = {path = "../../crates/namada", default-features = false} namada_tests = {path = "../../crates/tests"} namada_test_utils = {path = "../../crates/test_utils"} namada_vp_prelude = {path = "../../crates/vp_prelude"} diff --git a/wasm_for_tests/Cargo.lock b/wasm_for_tests/Cargo.lock index 59aa30e730..e0e31f40eb 100644 --- a/wasm_for_tests/Cargo.lock +++ b/wasm_for_tests/Cargo.lock @@ -54,7 +54,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "once_cell", "version_check", ] @@ -83,6 +83,55 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "anyhow" version = "1.0.75" @@ -304,7 +353,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "miniz_oxide", - "object 0.32.1", + "object", "rustc-demangle", ] @@ -661,6 +710,15 @@ dependencies = [ "serde", ] +[[package]] +name = "bytesize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" +dependencies = [ + "serde", +] + [[package]] name = "camino" version = "1.1.6" @@ -787,6 +845,46 @@ dependencies = [ "version_check", ] +[[package]] +name = "clap" +version = "4.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + [[package]] name = "clru" version = "0.5.0" @@ -844,6 +942,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + [[package]] name = "concat-idents" version = "1.1.5" @@ -994,56 +1098,74 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38faa2a16616c8e78a18d37b4726b98bfd2de192f2fdc8a39ddf568a408a0f75" +checksum = "2a2ab4512dfd3a6f4be184403a195f76e81a8a9f9e6c898e19d2dc3ce20e0115" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f192472a3ba23860afd07d2b0217dc628f21fcc72617aa1336d98e1671f33b" +checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc" dependencies = [ + "arrayvec", + "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", + "cranelift-egraph", "cranelift-entity", + "cranelift-isle", "gimli 0.26.2", "log", - "regalloc", + "regalloc2", "smallvec", "target-lexicon", ] [[package]] name = "cranelift-codegen-meta" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32ddb89e9b89d3d9b36a5b7d7ea3261c98235a76ac95ba46826b8ec40b1a24" +checksum = "639307b45434ad112a98f8300c0f0ab085cbefcd767efcdef9ef19d4c0756e74" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.82.3" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "278e52e29c53fcf32431ef08406c295699a70306d05a0715c5b1bf50e33a9ab7" + +[[package]] +name = "cranelift-egraph" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01fd0d9f288cc1b42d9333b7a776b17e278fc888c28e6a0f09b5573d45a150bc" +checksum = "624b54323b06e675293939311943ba82d323bb340468ce1889be5da7932c8d73" +dependencies = [ + "cranelift-entity", + "fxhash", + "hashbrown 0.12.3", + "indexmap 1.9.3", + "log", + "smallvec", +] [[package]] name = "cranelift-entity" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3bfe172b83167604601faf9dc60453e0d0a93415b57a9c4d1a7ae6849185cf" +checksum = "9a59bcbca89c3f1b70b93ab3cbba5e5e0cbf3e63dadb23c7525cb142e21a9d4c" [[package]] name = "cranelift-frontend" -version = "0.82.3" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a006e3e32d80ce0e4ba7f1f9ddf66066d052a8c884a110b91d05404d6ce26dce" +checksum = "0d70abacb8cfef3dc8ff7e8836e9c1d70f7967dfdac824a4cd5e30223415aca6" dependencies = [ "cranelift-codegen", "log", @@ -1051,6 +1173,12 @@ dependencies = [ "target-lexicon", ] +[[package]] +name = "cranelift-isle" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" + [[package]] name = "crc32fast" version = "1.3.2" @@ -1080,10 +1208,19 @@ dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset 0.9.0", + "memoffset", "scopeguard", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.19" @@ -1180,14 +1317,38 @@ dependencies = [ "serde", ] +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + [[package]] name = "darling" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.3", + "darling_macro 0.20.3", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", ] [[package]] @@ -1203,17 +1364,41 @@ dependencies = [ "syn 2.0.65", ] +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ - "darling_core", + "darling_core 0.20.3", "quote", "syn 2.0.65", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if 1.0.0", + "hashbrown 0.14.3", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "data-encoding" version = "2.5.0" @@ -1256,6 +1441,37 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_builder" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" +dependencies = [ + "darling 0.14.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -1319,6 +1535,15 @@ dependencies = [ "syn 2.0.65", ] +[[package]] +name = "document-features" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +dependencies = [ + "litrs", +] + [[package]] name = "dunce" version = "1.0.4" @@ -1368,7 +1593,7 @@ checksum = "64fba5a42bd76a17cad4bfa00de168ee1cbfa06a5e8ce992ae880218c05641a9" dependencies = [ "byteorder", "dynasm", - "memmap2", + "memmap2 0.5.10", ] [[package]] @@ -1514,7 +1739,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" dependencies = [ - "darling", + "darling 0.20.3", "proc-macro2", "quote", "syn 2.0.65", @@ -2127,9 +2352,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -2211,7 +2436,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.11", - "indexmap 2.1.0", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -2219,13 +2444,10 @@ dependencies = [ ] [[package]] -name = "hashbrown" -version = "0.11.2" +name = "half" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" [[package]] name = "hashbrown" @@ -3087,20 +3309,21 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +version = "2.2.4" +source = "git+https://github.com/heliaxdev/indexmap?tag=2.2.4-heliax-1#b5b5b547bd6ab04bbb16e060326a50ddaeb6c909" dependencies = [ + "borsh 1.2.1", "equivalent", "hashbrown 0.14.3", + "serde", ] [[package]] name = "indexmap" -version = "2.2.4" -source = "git+https://github.com/heliaxdev/indexmap?tag=2.2.4-heliax-1#b5b5b547bd6ab04bbb16e060326a50ddaeb6c909" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ - "borsh 1.2.1", "equivalent", "hashbrown 0.14.3", "serde", @@ -3159,6 +3382,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.11.0" @@ -3282,16 +3511,6 @@ version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if 1.0.0", - "winapi", -] - [[package]] name = "libm" version = "0.2.8" @@ -3315,6 +3534,12 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + [[package]] name = "lock_api" version = "0.4.11" @@ -3331,27 +3556,6 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -[[package]] -name = "loupe" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6a72dfa44fe15b5e76b94307eeb2ff995a8c5b283b55008940c02e0c5b634d" -dependencies = [ - "indexmap 1.9.3", - "loupe-derive", - "rustversion", -] - -[[package]] -name = "loupe-derive" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fbfc88337168279f2e9ae06e157cfed4efd3316e14dc96ed074d4f2e6c5952" -dependencies = [ - "quote", - "syn 1.0.109", -] - [[package]] name = "mach" version = "0.3.2" @@ -3415,7 +3619,7 @@ dependencies = [ "blake2b_simd", "bls12_381", "directories", - "getrandom 0.2.11", + "getrandom 0.2.15", "group", "itertools 0.11.0", "jubjub", @@ -3458,12 +3662,12 @@ dependencies = [ ] [[package]] -name = "memoffset" -version = "0.6.5" +name = "memmap2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" dependencies = [ - "autocfg", + "libc", ] [[package]] @@ -3563,7 +3767,6 @@ dependencies = [ "futures", "itertools 0.12.1", "konst", - "loupe", "masp_primitives", "masp_proofs", "namada_account", @@ -3614,8 +3817,6 @@ dependencies = [ "wasmer", "wasmer-cache", "wasmer-compiler-singlepass", - "wasmer-engine-dylib", - "wasmer-engine-universal", "wasmer-vm", "wasmparser 0.107.0", "wasmtimer", @@ -4329,18 +4530,6 @@ dependencies = [ "syn 2.0.65", ] -[[package]] -name = "object" -version = "0.28.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" -dependencies = [ - "crc32fast", - "hashbrown 0.11.2", - "indexmap 1.9.3", - "memchr", -] - [[package]] name = "object" version = "0.32.1" @@ -4394,7 +4583,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6624905ddd92e460ff0685567539ed1ac985b2dee4c92c7edcd64fce905b00c" dependencies = [ "ct-codecs", - "getrandom 0.2.11", + "getrandom 0.2.15", "subtle", "zeroize", ] @@ -4597,7 +4786,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.1.0", + "indexmap 2.2.6", ] [[package]] @@ -4935,7 +5124,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", ] [[package]] @@ -5024,19 +5213,20 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "libredox", "thiserror", ] [[package]] -name = "regalloc" -version = "0.0.34" +name = "regalloc2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62446b1d3ebf980bdc68837700af1d77b37bc430e524bf95319c6eada2a4cc02" +checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c" dependencies = [ + "fxhash", "log", - "rustc-hash", + "slice-group-by", "smallvec", ] @@ -5172,7 +5362,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", - "getrandom 0.2.11", + "getrandom 0.2.15", "libc", "spin 0.9.8", "untrusted 0.9.0", @@ -5197,6 +5387,7 @@ dependencies = [ "bitvec", "bytecheck", "hashbrown 0.12.3", + "indexmap 1.9.3", "ptr_meta", "rend", "rkyv_derive", @@ -5395,6 +5586,7 @@ dependencies = [ "schemars_derive", "serde", "serde_json", + "url", ] [[package]] @@ -5458,6 +5650,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "self_cell" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" + [[package]] name = "semver" version = "0.11.0" @@ -5499,9 +5697,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] @@ -5524,6 +5722,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_bytes" version = "0.11.12" @@ -5533,11 +5742,21 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", @@ -5598,6 +5817,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.2.6", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "serdect" version = "0.2.0" @@ -5651,6 +5883,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared-buffer" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" +dependencies = [ + "bytes", + "memmap2 0.6.2", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -5703,6 +5945,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + [[package]] name = "slip10_ed25519" version = "0.1.3" @@ -5802,6 +6050,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" version = "0.24.1" @@ -6092,7 +6346,7 @@ dependencies = [ "async-trait", "bytes", "flex-error", - "getrandom 0.2.11", + "getrandom 0.2.15", "peg", "pin-project", "rand 0.8.5", @@ -6336,6 +6590,18 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.19.15", +] + [[package]] name = "toml" version = "0.8.2" @@ -6363,7 +6629,9 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.6", + "serde", + "serde_spanned", "toml_datetime", "winnow 0.5.25", ] @@ -6374,7 +6642,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -6459,7 +6727,6 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -6520,7 +6787,7 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" name = "tx_fail" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6536,7 +6803,7 @@ dependencies = [ name = "tx_infinite_guest_gas" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6552,7 +6819,7 @@ dependencies = [ name = "tx_infinite_host_gas" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6568,7 +6835,7 @@ dependencies = [ name = "tx_invalid_data" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6584,7 +6851,7 @@ dependencies = [ name = "tx_memory_limit" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6600,7 +6867,7 @@ dependencies = [ name = "tx_no_op" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6616,7 +6883,7 @@ dependencies = [ name = "tx_proposal_code" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6632,7 +6899,7 @@ dependencies = [ name = "tx_proposal_ibc_token_inflation" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6648,7 +6915,7 @@ dependencies = [ name = "tx_proposal_masp_reward" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6664,7 +6931,7 @@ dependencies = [ name = "tx_read_storage_key" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6680,7 +6947,7 @@ dependencies = [ name = "tx_write" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6800,6 +7067,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.7.1" @@ -6821,15 +7094,22 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "uuid" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "serde", ] @@ -6849,7 +7129,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" name = "vp_always_false" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6865,7 +7145,7 @@ dependencies = [ name = "vp_always_true" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6881,7 +7161,7 @@ dependencies = [ name = "vp_eval" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6897,7 +7177,7 @@ dependencies = [ name = "vp_infinite_guest_gas" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6913,7 +7193,7 @@ dependencies = [ name = "vp_infinite_host_gas" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6929,7 +7209,7 @@ dependencies = [ name = "vp_memory_limit" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -6945,7 +7225,7 @@ dependencies = [ name = "vp_read_storage_key" version = "0.37.0" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", "namada_test_utils", "namada_tests", "namada_tx_prelude", @@ -7083,46 +7363,38 @@ dependencies = [ [[package]] name = "wasmer" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce4a267a570e121c9375136adefa2c48810273907de9c6817bc19db4d6144bc" dependencies = [ + "bytes", "cfg-if 1.0.0", + "derivative", "indexmap 1.9.3", "js-sys", - "loupe", "more-asserts", + "rustc-demangle", + "serde", + "serde-wasm-bindgen", + "shared-buffer", "target-lexicon", "thiserror", + "tracing", "wasm-bindgen", - "wasmer-artifact", "wasmer-compiler", "wasmer-compiler-cranelift", "wasmer-derive", - "wasmer-engine", - "wasmer-engine-dylib", - "wasmer-engine-universal", "wasmer-types", "wasmer-vm", "wat", "winapi", ] -[[package]] -name = "wasmer-artifact" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "enumset", - "loupe", - "thiserror", - "wasmer-compiler", - "wasmer-types", -] - [[package]] name = "wasmer-cache" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a40804bcc2567f112003182fc5edc29584da5199c4a1f5a8d6a6e4b65feff0" dependencies = [ "blake3", "hex", @@ -7132,31 +7404,42 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9c23098e86ef1038155684fe50f0c1079a0e2a2e70f115b789df17e6ba98d20" dependencies = [ + "backtrace", + "bytes", + "cfg-if 1.0.0", + "enum-iterator", "enumset", - "loupe", + "lazy_static", + "leb128", + "memmap2 0.5.10", + "more-asserts", + "region", "rkyv", - "serde", - "serde_bytes", + "self_cell", + "shared-buffer", "smallvec", - "target-lexicon", "thiserror", "wasmer-types", - "wasmparser 0.83.0", + "wasmer-vm", + "wasmparser 0.121.2", + "winapi", + "xxhash-rust", ] [[package]] name = "wasmer-compiler-cranelift" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95287b79973ad5f485215733ef9f0d4bb951a6b7e655585d2bd3d4a4ba1253c9" dependencies = [ "cranelift-codegen", "cranelift-entity", "cranelift-frontend", "gimli 0.26.2", - "loupe", "more-asserts", "rayon", "smallvec", @@ -7164,185 +7447,128 @@ dependencies = [ "tracing", "wasmer-compiler", "wasmer-types", - "wasmer-vm", ] [[package]] name = "wasmer-compiler-singlepass" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00d78d59be3ce78ad859e176b88f0d5bec0120ece0684922d7c5da1289e251b1" dependencies = [ "byteorder", "dynasm", "dynasmrt", + "enumset", "gimli 0.26.2", "lazy_static", - "loupe", "more-asserts", "rayon", "smallvec", "wasmer-compiler", "wasmer-types", - "wasmer-vm", -] - -[[package]] -name = "wasmer-derive" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "wasmer-engine" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "backtrace", - "enumset", - "lazy_static", - "loupe", - "memmap2", - "more-asserts", - "rustc-demangle", - "serde", - "serde_bytes", - "target-lexicon", - "thiserror", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-types", - "wasmer-vm", ] [[package]] -name = "wasmer-engine-dylib" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +name = "wasmer-config" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a0f70c177b1c5062cfe0f5308c3317751796fef9403c22a0cd7b4cacd4ccd8" dependencies = [ - "cfg-if 1.0.0", - "enum-iterator", - "enumset", - "leb128", - "libloading", - "loupe", - "object 0.28.4", - "rkyv", + "anyhow", + "bytesize", + "derive_builder", + "hex", + "indexmap 2.2.6", + "schemars", + "semver 1.0.20", "serde", - "tempfile", - "tracing", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-engine", - "wasmer-object", - "wasmer-types", - "wasmer-vm", - "which", -] - -[[package]] -name = "wasmer-engine-universal" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "cfg-if 1.0.0", - "enumset", - "leb128", - "loupe", - "region", - "rkyv", - "wasmer-compiler", - "wasmer-engine", - "wasmer-engine-universal-artifact", - "wasmer-types", - "wasmer-vm", - "winapi", -] - -[[package]] -name = "wasmer-engine-universal-artifact" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" -dependencies = [ - "enum-iterator", - "enumset", - "loupe", - "rkyv", + "serde_cbor", + "serde_json", + "serde_yaml", "thiserror", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-types", + "toml 0.8.2", + "url", ] [[package]] -name = "wasmer-object" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +name = "wasmer-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48f36aeeecb655f15fdd358bdf6e4cec27df181468fa4226084157e8462bd5e" dependencies = [ - "object 0.28.4", - "thiserror", - "wasmer-compiler", - "wasmer-types", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] name = "wasmer-types" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83cb97b6b20084757a2a8d548dc0d4179c3fe9e2d711740423a1e6aa3f8b9091" dependencies = [ - "backtrace", + "bytecheck", "enum-iterator", + "enumset", + "getrandom 0.2.15", + "hex", "indexmap 1.9.3", - "loupe", + "more-asserts", "rkyv", - "serde", + "sha2 0.10.8", + "target-lexicon", "thiserror", + "webc", + "xxhash-rust", ] [[package]] name = "wasmer-vm" -version = "2.3.0" -source = "git+https://github.com/heliaxdev/wasmer?rev=255054f7f58b7b4a525f2fee6b9b86422d1ca15b#255054f7f58b7b4a525f2fee6b9b86422d1ca15b" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc1e19d986844b17b927ec8b0c7f3da6a7a2c2cb3b0f8ca5d4cb1a1f71bfb124" dependencies = [ "backtrace", "cc", "cfg-if 1.0.0", "corosensei", + "crossbeam-queue", + "dashmap", + "derivative", "enum-iterator", + "fnv", "indexmap 1.9.3", "lazy_static", "libc", - "loupe", "mach", - "memoffset 0.6.5", + "memoffset", "more-asserts", "region", - "rkyv", "scopeguard", - "serde", "thiserror", - "wasmer-artifact", "wasmer-types", "winapi", ] [[package]] name = "wasmparser" -version = "0.83.0" +version = "0.107.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" +checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" +dependencies = [ + "indexmap 1.9.3", + "semver 1.0.20", +] [[package]] name = "wasmparser" -version = "0.107.0" +version = "0.121.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" +checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" dependencies = [ - "indexmap 1.9.3", + "bitflags 2.5.0", + "indexmap 2.2.6", "semver 1.0.20", ] @@ -7391,6 +7617,36 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webc" +version = "6.0.0-alpha9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b4e8dd987046eede4348d660404ff990412631b7d493f9e547adcf2862cd5" +dependencies = [ + "anyhow", + "base64 0.21.7", + "bytes", + "cfg-if 1.0.0", + "clap", + "document-features", + "flate2", + "indexmap 1.9.3", + "libc", + "once_cell", + "semver 1.0.20", + "serde", + "serde_cbor", + "serde_json", + "sha2 0.10.8", + "shared-buffer", + "tar", + "tempfile", + "thiserror", + "toml 0.7.8", + "url", + "wasmer-config", +] + [[package]] name = "webpki-roots" version = "0.25.3" @@ -7703,6 +7959,12 @@ dependencies = [ "rustix", ] +[[package]] +name = "xxhash-rust" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" + [[package]] name = "zcash_encoding" version = "0.2.0" diff --git a/wasm_for_tests/Cargo.toml b/wasm_for_tests/Cargo.toml index 4aa5b90290..def83e389f 100644 --- a/wasm_for_tests/Cargo.toml +++ b/wasm_for_tests/Cargo.toml @@ -33,7 +33,7 @@ namada_test_utils = { path = "../crates/test_utils" } namada_tx_prelude = { path = "../crates/tx_prelude" } namada_vp_prelude = { path = "../crates/vp_prelude" } wee_alloc = "0.4.5" -getrandom = { version = "0.2", features = ["custom"] } +getrandom = { version = "0.2.15", features = ["custom"] } [profile.release] # smaller and faster wasm (https://rustwasm.github.io/book/reference/code-size.html#compiling-with-link-time-optimizations-lto) From ef33d6289d91689ab67d8f61dd0f5b2641f0f9fd Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Fri, 24 May 2024 10:44:54 +0200 Subject: [PATCH 48/70] Fmt --- crates/node/src/shell/finalize_block.rs | 424 ++++++++++++++---------- 1 file changed, 252 insertions(+), 172 deletions(-) diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 0fac63841d..07413be068 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -2801,21 +2801,25 @@ mod test_finalize_block { assert_eq!(root_pre.0, root_post.0); // Check transaction's hash in storage - assert!(shell - .shell - .state - .write_log() - .has_replay_protection_entry(&wrapper_tx.raw_header_hash())); + assert!( + shell + .shell + .state + .write_log() + .has_replay_protection_entry(&wrapper_tx.raw_header_hash()) + ); // Check that the hash is not present in the merkle tree shell.state.commit_block().unwrap(); - assert!(!shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&wrapper_hash_key) - .unwrap()); + assert!( + !shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&wrapper_hash_key) + .unwrap() + ); // test that a commitment to replay protection gets added. let reprot_key = replay_protection::commitment_key(); @@ -2862,22 +2866,26 @@ mod test_finalize_block { assert_eq!(root_pre.0, root_post.0); // Check that the hashes are present in the merkle tree shell.state.commit_block().unwrap(); - assert!(shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&convert_key) - .unwrap()); - assert!(shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&commitment_key) - .unwrap()); + assert!( + shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&convert_key) + .unwrap() + ); + assert!( + shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&commitment_key) + .unwrap() + ); } /// Test that a tx that has already been applied in the same block @@ -2955,26 +2963,34 @@ mod test_finalize_block { assert_eq!(code, ResultCode::WasmRuntimeError); for wrapper in [&wrapper, &new_wrapper] { - assert!(shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.raw_header_hash())); - assert!(!shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.header_hash())); + assert!( + shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.raw_header_hash()) + ); + assert!( + !shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.header_hash()) + ); } // Commit to check the hashes from storage shell.commit(); for wrapper in [&wrapper, &new_wrapper] { - assert!(shell - .state - .has_replay_protection_entry(&wrapper.raw_header_hash()) - .unwrap()); - assert!(!shell - .state - .has_replay_protection_entry(&wrapper.header_hash()) - .unwrap()); + assert!( + shell + .state + .has_replay_protection_entry(&wrapper.raw_header_hash()) + .unwrap() + ); + assert!( + !shell + .state + .has_replay_protection_entry(&wrapper.header_hash()) + .unwrap() + ); } } @@ -3257,23 +3273,29 @@ mod test_finalize_block { &unsigned_wrapper, &wrong_commitment_wrapper, ] { - assert!(!shell - .state - .write_log() - .has_replay_protection_entry(&valid_wrapper.raw_header_hash())); - assert!(shell + assert!( + !shell.state.write_log().has_replay_protection_entry( + &valid_wrapper.raw_header_hash() + ) + ); + assert!( + shell + .state + .write_log() + .has_replay_protection_entry(&valid_wrapper.header_hash()) + ); + } + assert!( + shell.state.write_log().has_replay_protection_entry( + &failing_wrapper.raw_header_hash() + ) + ); + assert!( + !shell .state .write_log() - .has_replay_protection_entry(&valid_wrapper.header_hash())); - } - assert!(shell - .state - .write_log() - .has_replay_protection_entry(&failing_wrapper.raw_header_hash())); - assert!(!shell - .state - .write_log() - .has_replay_protection_entry(&failing_wrapper.header_hash())); + .has_replay_protection_entry(&failing_wrapper.header_hash()) + ); // Commit to check the hashes from storage shell.commit(); @@ -3282,23 +3304,33 @@ mod test_finalize_block { unsigned_wrapper, wrong_commitment_wrapper, ] { - assert!(!shell + assert!( + !shell + .state + .has_replay_protection_entry( + &valid_wrapper.raw_header_hash() + ) + .unwrap() + ); + assert!( + shell + .state + .has_replay_protection_entry(&valid_wrapper.header_hash()) + .unwrap() + ); + } + assert!( + shell .state - .has_replay_protection_entry(&valid_wrapper.raw_header_hash()) - .unwrap()); - assert!(shell + .has_replay_protection_entry(&failing_wrapper.raw_header_hash()) + .unwrap() + ); + assert!( + !shell .state - .has_replay_protection_entry(&valid_wrapper.header_hash()) - .unwrap()); - } - assert!(shell - .state - .has_replay_protection_entry(&failing_wrapper.raw_header_hash()) - .unwrap()); - assert!(!shell - .state - .has_replay_protection_entry(&failing_wrapper.header_hash()) - .unwrap()); + .has_replay_protection_entry(&failing_wrapper.header_hash()) + .unwrap() + ); } #[test] @@ -3358,14 +3390,18 @@ mod test_finalize_block { let code = event[0].read_attribute::().expect("Test failed"); assert_eq!(code, ResultCode::InvalidTx); - assert!(shell - .state - .write_log() - .has_replay_protection_entry(&wrapper_hash)); - assert!(!shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.raw_header_hash())); + assert!( + shell + .state + .write_log() + .has_replay_protection_entry(&wrapper_hash) + ); + assert!( + !shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.raw_header_hash()) + ); } // Test that the fees are paid even if the inner transaction fails and its @@ -3763,9 +3799,11 @@ mod test_finalize_block { .unwrap(), Some(ValidatorState::Consensus) ); - assert!(enqueued_slashes_handle() - .at(&Epoch::default()) - .is_empty(&shell.state)?); + assert!( + enqueued_slashes_handle() + .at(&Epoch::default()) + .is_empty(&shell.state)? + ); assert_eq!( get_num_consensus_validators(&shell.state, Epoch::default()) .unwrap(), @@ -3784,17 +3822,21 @@ mod test_finalize_block { .unwrap(), Some(ValidatorState::Jailed) ); - assert!(enqueued_slashes_handle() - .at(&epoch) - .is_empty(&shell.state)?); + assert!( + enqueued_slashes_handle() + .at(&epoch) + .is_empty(&shell.state)? + ); assert_eq!( get_num_consensus_validators(&shell.state, epoch).unwrap(), 5_u64 ); } - assert!(!enqueued_slashes_handle() - .at(&processing_epoch) - .is_empty(&shell.state)?); + assert!( + !enqueued_slashes_handle() + .at(&processing_epoch) + .is_empty(&shell.state)? + ); // Advance to the processing epoch loop { @@ -3817,9 +3859,11 @@ mod test_finalize_block { // println!("Reached processing epoch"); break; } else { - assert!(enqueued_slashes_handle() - .at(&shell.state.in_mem().block.epoch) - .is_empty(&shell.state)?); + assert!( + enqueued_slashes_handle() + .at(&shell.state.in_mem().block.epoch) + .is_empty(&shell.state)? + ); let stake1 = read_validator_stake( &shell.state, ¶ms, @@ -4303,11 +4347,13 @@ mod test_finalize_block { ) .unwrap(); assert_eq!(last_slash, Some(misbehavior_epoch)); - assert!(namada_proof_of_stake::storage::validator_slashes_handle( - &val1.address - ) - .is_empty(&shell.state) - .unwrap()); + assert!( + namada_proof_of_stake::storage::validator_slashes_handle( + &val1.address + ) + .is_empty(&shell.state) + .unwrap() + ); tracing::debug!("Advancing to epoch 7"); @@ -4372,18 +4418,22 @@ mod test_finalize_block { ) .unwrap(); assert_eq!(last_slash, Some(Epoch(4))); - assert!(namada_proof_of_stake::is_validator_frozen( - &shell.state, - &val1.address, - current_epoch, - ¶ms - ) - .unwrap()); - assert!(namada_proof_of_stake::storage::validator_slashes_handle( - &val1.address - ) - .is_empty(&shell.state) - .unwrap()); + assert!( + namada_proof_of_stake::is_validator_frozen( + &shell.state, + &val1.address, + current_epoch, + ¶ms + ) + .unwrap() + ); + assert!( + namada_proof_of_stake::storage::validator_slashes_handle( + &val1.address + ) + .is_empty(&shell.state) + .unwrap() + ); let pre_stake_10 = namada_proof_of_stake::storage::read_validator_stake( @@ -5261,9 +5311,11 @@ mod test_finalize_block { shell.vp_wasm_cache.clone(), ); let parameters = ParametersVp { ctx }; - assert!(parameters - .validate_tx(&batched_tx, &keys_changed, &verifiers) - .is_ok()); + assert!( + parameters + .validate_tx(&batched_tx, &keys_changed, &verifiers) + .is_ok() + ); // we advance forward to the next epoch let mut req = FinalizeBlock::default(); @@ -5336,11 +5388,13 @@ mod test_finalize_block { let inner_results = inner_tx_result.batch_results.0; for cmt in batch.commitments() { - assert!(inner_results - .get(&cmt.get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); + assert!( + inner_results + .get(&cmt.get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); } // Check storage modifications @@ -5378,18 +5432,24 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!(inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); - assert!(inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err()); + assert!( + inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); + assert!( + inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err() + ); // Assert that the last tx didn't run - assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); + assert!( + !inner_results.contains_key(&batch.commitments()[2].get_hash()) + ); // Check storage modifications are missing for key in ["random_key_1", "random_key_2", "random_key_3"] { @@ -5420,21 +5480,27 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!(inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); - assert!(inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err()); - assert!(inner_results - .get(&batch.commitments()[2].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); + assert!( + inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); + assert!( + inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err() + ); + assert!( + inner_results + .get(&batch.commitments()[2].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); // Check storage modifications assert_eq!( @@ -5445,10 +5511,12 @@ mod test_finalize_block { .unwrap(), STORAGE_VALUE ); - assert!(!shell - .state - .has_key(&"random_key_2".parse().unwrap()) - .unwrap()); + assert!( + !shell + .state + .has_key(&"random_key_2".parse().unwrap()) + .unwrap() + ); assert_eq!( shell .state @@ -5480,18 +5548,24 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!(inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); - assert!(inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err()); + assert!( + inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); + assert!( + inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err() + ); // Assert that the last tx didn't run - assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); + assert!( + !inner_results.contains_key(&batch.commitments()[2].get_hash()) + ); // Check storage modifications are missing for key in ["random_key_1", "random_key_2", "random_key_3"] { @@ -5521,18 +5595,24 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!(inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); - assert!(inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err()); + assert!( + inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); + assert!( + inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err() + ); // Assert that the last tx didn't run - assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); + assert!( + !inner_results.contains_key(&batch.commitments()[2].get_hash()) + ); // Check storage modifications assert_eq!( From fb3351c6c52aee8988a6d6f75ddd7b14bb3b6fd7 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 24 May 2024 10:18:05 +0100 Subject: [PATCH 49/70] Restrict bounds on wasm memory --- crates/namada/src/vm/host_env.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/crates/namada/src/vm/host_env.rs b/crates/namada/src/vm/host_env.rs index cce172bc6f..af5adc4ce3 100644 --- a/crates/namada/src/vm/host_env.rs +++ b/crates/namada/src/vm/host_env.rs @@ -93,7 +93,6 @@ pub type TxResult = std::result::Result; /// A transaction's host environment pub struct TxVmEnv where - MEM: VmMemory, D: DB + for<'iter> DBIter<'iter>, H: StorageHasher, CA: WasmCacheAccess, @@ -151,7 +150,6 @@ where impl TxVmEnv where - MEM: VmMemory, D: DB + for<'iter> DBIter<'iter>, H: StorageHasher, CA: WasmCacheAccess, @@ -229,7 +227,7 @@ where impl Clone for TxVmEnv where - MEM: VmMemory, + MEM: Clone, D: DB + for<'iter> DBIter<'iter>, H: StorageHasher, CA: WasmCacheAccess, @@ -307,7 +305,6 @@ where /// A validity predicate's host environment pub struct VpVmEnv where - MEM: VmMemory, D: DB + for<'iter> DBIter<'iter>, H: StorageHasher, EVAL: VpEvaluator, @@ -393,7 +390,6 @@ impl VpVmEnv where D: DB + for<'iter> DBIter<'iter>, H: StorageHasher, - MEM: VmMemory, EVAL: VpEvaluator, CA: WasmCacheAccess, { @@ -453,7 +449,7 @@ where impl Clone for VpVmEnv where - MEM: VmMemory, + MEM: Clone, D: DB + for<'iter> DBIter<'iter>, H: StorageHasher, EVAL: VpEvaluator, From 134fbc037ef104d04790e1709d6032d44da85137 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 24 May 2024 10:47:01 +0100 Subject: [PATCH 50/70] Pass mutable refs to wasm host env --- crates/namada/src/vm/host_env.rs | 119 ++++++++++++++------------ crates/namada/src/vm/wasm/host_env.rs | 60 +++++++------ crates/tests/src/vm_host_env/tx.rs | 56 ++++++------ crates/tests/src/vm_host_env/vp.rs | 8 +- 4 files changed, 135 insertions(+), 108 deletions(-) diff --git a/crates/namada/src/vm/host_env.rs b/crates/namada/src/vm/host_env.rs index af5adc4ce3..5a31ec09fe 100644 --- a/crates/namada/src/vm/host_env.rs +++ b/crates/namada/src/vm/host_env.rs @@ -587,7 +587,7 @@ where /// Add a gas cost incured in a transaction pub fn tx_charge_gas( - env: &TxVmEnv, + env: &mut TxVmEnv, used_gas: u64, ) -> TxResult<()> where @@ -611,7 +611,7 @@ where /// Called from VP wasm to request to use the given gas amount pub fn vp_charge_gas( - env: &VpVmEnv, + env: &mut VpVmEnv, used_gas: u64, ) -> vp_host_fns::EnvResult<()> where @@ -628,7 +628,7 @@ where /// Storage `has_key` function exposed to the wasm VM Tx environment. It will /// try to check the write log first and if no entry found then the storage. pub fn tx_has_key( - env: &TxVmEnv, + env: &mut TxVmEnv, key_ptr: u64, key_len: u64, ) -> TxResult @@ -660,7 +660,7 @@ where /// Returns `-1` when the key is not present, or the length of the data when /// the key is present (the length may be `0`). pub fn tx_read( - env: &TxVmEnv, + env: &mut TxVmEnv, key_ptr: u64, key_len: u64, ) -> TxResult @@ -703,7 +703,7 @@ where /// Returns `-1` when the key is not present, or the length of the data when /// the key is present (the length may be `0`). pub fn tx_read_temp( - env: &TxVmEnv, + env: &mut TxVmEnv, key_ptr: u64, key_len: u64, ) -> TxResult @@ -749,7 +749,7 @@ where /// any) back to the guest, the second step reads the value from cache into a /// pre-allocated buffer with the obtained size. pub fn tx_result_buffer( - env: &TxVmEnv, + env: &mut TxVmEnv, result_ptr: u64, ) -> TxResult<()> where @@ -773,7 +773,7 @@ where /// It will try to get an iterator from the storage and return the corresponding /// ID of the iterator, ordered by storage keys. pub fn tx_iter_prefix( - env: &TxVmEnv, + env: &mut TxVmEnv, prefix_ptr: u64, prefix_len: u64, ) -> TxResult @@ -813,7 +813,7 @@ where /// Returns `-1` when the key is not present, or the length of the data when /// the key is present (the length may be `0`). pub fn tx_iter_next( - env: &TxVmEnv, + env: &mut TxVmEnv, iter_id: u64, ) -> TxResult where @@ -824,7 +824,11 @@ where { tracing::debug!("tx_iter_next iter_id {}", iter_id,); - let state = env.state(); + // NB: an env clone is required to avoid an immutable + // borrow while a mutable borrow is taking place + let env2 = env.clone(); + let state = env2.state(); + let iterators = unsafe { env.ctx.iterators.get_mut() }; let iter_id = PrefixIteratorId::new(iter_id); while let Some((key, val, iter_gas)) = iterators.next(iter_id) { @@ -878,7 +882,7 @@ where /// Storage write function exposed to the wasm VM Tx environment. The given /// key/value will be written to the write log. pub fn tx_write( - env: &TxVmEnv, + env: &mut TxVmEnv, key_ptr: u64, key_len: u64, val_ptr: u64, @@ -920,7 +924,7 @@ where /// given key/value will be written only to the write log. It will be never /// written to the storage. pub fn tx_write_temp( - env: &TxVmEnv, + env: &mut TxVmEnv, key_ptr: u64, key_len: u64, val_ptr: u64, @@ -958,7 +962,7 @@ where } fn check_address_existence( - env: &TxVmEnv, + env: &mut TxVmEnv, key: &Key, ) -> TxResult<()> where @@ -1005,7 +1009,7 @@ where /// Storage delete function exposed to the wasm VM Tx environment. The given /// key/value will be written as deleted to the write log. pub fn tx_delete( - env: &TxVmEnv, + env: &mut TxVmEnv, key_ptr: u64, key_len: u64, ) -> TxResult<()> @@ -1035,7 +1039,7 @@ where /// Expose the functionality to emit events to the wasm VM's Tx environment. /// An emitted event will land in the write log. pub fn tx_emit_event( - env: &TxVmEnv, + env: &mut TxVmEnv, event_ptr: u64, event_len: u64, ) -> TxResult<()> @@ -1062,7 +1066,7 @@ where /// Expose the functionality to query events from the wasm VM's Tx environment. pub fn tx_get_events( - env: &TxVmEnv, + env: &mut TxVmEnv, event_type_ptr: u64, event_type_len: u64, ) -> TxResult @@ -1103,7 +1107,7 @@ where /// Returns `-1` when the key is not present, or the length of the data when /// the key is present (the length may be `0`). pub fn vp_read_pre( - env: &VpVmEnv, + env: &mut VpVmEnv, key_ptr: u64, key_len: u64, ) -> vp_host_fns::EnvResult @@ -1153,7 +1157,7 @@ where /// Returns `-1` when the key is not present, or the length of the data when /// the key is present (the length may be `0`). pub fn vp_read_post( - env: &VpVmEnv, + env: &mut VpVmEnv, key_ptr: u64, key_len: u64, ) -> vp_host_fns::EnvResult @@ -1198,7 +1202,7 @@ where /// Returns `-1` when the key is not present, or the length of the data when /// the key is present (the length may be `0`). pub fn vp_read_temp( - env: &VpVmEnv, + env: &mut VpVmEnv, key_ptr: u64, key_len: u64, ) -> vp_host_fns::EnvResult @@ -1246,7 +1250,7 @@ where /// any) back to the guest, the second step reads the value from cache into a /// pre-allocated buffer with the obtained size. pub fn vp_result_buffer( - env: &VpVmEnv, + env: &mut VpVmEnv, result_ptr: u64, ) -> vp_host_fns::EnvResult<()> where @@ -1271,7 +1275,7 @@ where /// Storage `has_key` in prior state (before tx execution) function exposed to /// the wasm VM VP environment. It will try to read from the storage. pub fn vp_has_key_pre( - env: &VpVmEnv, + env: &mut VpVmEnv, key_ptr: u64, key_len: u64, ) -> vp_host_fns::EnvResult @@ -1302,7 +1306,7 @@ where /// to the wasm VM VP environment. It will try to check the write log first and /// if no entry found then the storage. pub fn vp_has_key_post( - env: &VpVmEnv, + env: &mut VpVmEnv, key_ptr: u64, key_len: u64, ) -> vp_host_fns::EnvResult @@ -1334,7 +1338,7 @@ where /// the storage and return the corresponding ID of the iterator, ordered by /// storage keys. pub fn vp_iter_prefix_pre( - env: &VpVmEnv, + env: &mut VpVmEnv, prefix_ptr: u64, prefix_len: u64, ) -> vp_host_fns::EnvResult @@ -1373,7 +1377,7 @@ where /// the storage and return the corresponding ID of the iterator, ordered by /// storage keys. pub fn vp_iter_prefix_post( - env: &VpVmEnv, + env: &mut VpVmEnv, prefix_ptr: u64, prefix_len: u64, ) -> vp_host_fns::EnvResult @@ -1414,7 +1418,7 @@ where /// Returns `-1` when the key is not present, or the length of the data when /// the key is present (the length may be `0`). pub fn vp_iter_next( - env: &VpVmEnv, + env: &mut VpVmEnv, iter_id: u64, ) -> vp_host_fns::EnvResult where @@ -1447,7 +1451,7 @@ where /// Verifier insertion function exposed to the wasm VM Tx environment. pub fn tx_insert_verifier( - env: &TxVmEnv, + env: &mut TxVmEnv, addr_ptr: u64, addr_len: u64, ) -> TxResult<()> @@ -1481,7 +1485,7 @@ where /// Update a validity predicate function exposed to the wasm VM Tx environment pub fn tx_update_validity_predicate( - env: &TxVmEnv, + env: &mut TxVmEnv, addr_ptr: u64, addr_len: u64, code_hash_ptr: u64, @@ -1532,7 +1536,7 @@ where /// Initialize a new account established address. #[allow(clippy::too_many_arguments)] pub fn tx_init_account( - env: &TxVmEnv, + env: &mut TxVmEnv, code_hash_ptr: u64, code_hash_len: u64, code_tag_ptr: u64, @@ -1588,7 +1592,7 @@ where /// Getting the chain ID function exposed to the wasm VM Tx environment. pub fn tx_get_chain_id( - env: &TxVmEnv, + env: &mut TxVmEnv, result_ptr: u64, ) -> TxResult<()> where @@ -1611,7 +1615,7 @@ where /// environment. The height is that of the block to which the current /// transaction is being applied. pub fn tx_get_block_height( - env: &TxVmEnv, + env: &mut TxVmEnv, ) -> TxResult where MEM: VmMemory, @@ -1629,7 +1633,7 @@ where /// environment. The index is that of the transaction being applied /// in the current block. pub fn tx_get_tx_index( - env: &TxVmEnv, + env: &mut TxVmEnv, ) -> TxResult where MEM: VmMemory, @@ -1651,7 +1655,7 @@ where /// environment. The height is that of the block to which the current /// transaction is being applied. pub fn vp_get_tx_index( - env: &VpVmEnv, + env: &mut VpVmEnv, ) -> vp_host_fns::EnvResult where MEM: VmMemory, @@ -1670,7 +1674,7 @@ where /// environment. The epoch is that of the block to which the current /// transaction is being applied. pub fn tx_get_block_epoch( - env: &TxVmEnv, + env: &mut TxVmEnv, ) -> TxResult where MEM: VmMemory, @@ -1686,7 +1690,7 @@ where /// Get predecessor epochs function exposed to the wasm VM Tx environment. pub fn tx_get_pred_epochs( - env: &TxVmEnv, + env: &mut TxVmEnv, ) -> TxResult where MEM: VmMemory, @@ -1713,7 +1717,7 @@ where /// Get the native token's address pub fn tx_get_native_token( - env: &TxVmEnv, + env: &mut TxVmEnv, result_ptr: u64, ) -> TxResult<()> where @@ -1741,7 +1745,7 @@ where /// Getting the block header function exposed to the wasm VM Tx environment. pub fn tx_get_block_header( - env: &TxVmEnv, + env: &mut TxVmEnv, height: u64, ) -> TxResult where @@ -1773,7 +1777,7 @@ where /// Getting the chain ID function exposed to the wasm VM VP environment. pub fn vp_get_chain_id( - env: &VpVmEnv, + env: &mut VpVmEnv, result_ptr: u64, ) -> vp_host_fns::EnvResult<()> where @@ -1797,7 +1801,7 @@ where /// environment. The height is that of the block to which the current /// transaction is being applied. pub fn vp_get_block_height( - env: &VpVmEnv, + env: &mut VpVmEnv, ) -> vp_host_fns::EnvResult where MEM: VmMemory, @@ -1814,7 +1818,7 @@ where /// Getting the block header function exposed to the wasm VM VP environment. pub fn vp_get_block_header( - env: &VpVmEnv, + env: &mut VpVmEnv, height: u64, ) -> vp_host_fns::EnvResult where @@ -1847,7 +1851,7 @@ where /// Getting the transaction hash function exposed to the wasm VM VP environment. pub fn vp_get_tx_code_hash( - env: &VpVmEnv, + env: &mut VpVmEnv, result_ptr: u64, ) -> vp_host_fns::EnvResult<()> where @@ -1880,7 +1884,7 @@ where /// environment. The epoch is that of the block to which the current /// transaction is being applied. pub fn vp_get_block_epoch( - env: &VpVmEnv, + env: &mut VpVmEnv, ) -> vp_host_fns::EnvResult where MEM: VmMemory, @@ -1897,7 +1901,7 @@ where /// Get predecessor epochs function exposed to the wasm VM VP environment. pub fn vp_get_pred_epochs( - env: &VpVmEnv, + env: &mut VpVmEnv, ) -> vp_host_fns::EnvResult where MEM: VmMemory, @@ -1921,7 +1925,7 @@ where /// Expose the functionality to query events from the wasm VM's VP environment. pub fn vp_get_events( - env: &VpVmEnv, + env: &mut VpVmEnv, event_type_ptr: u64, event_type_len: u64, ) -> vp_host_fns::EnvResult @@ -1955,7 +1959,7 @@ where /// performance #[allow(clippy::too_many_arguments)] pub fn vp_verify_tx_section_signature( - env: &VpVmEnv, + env: &mut VpVmEnv, hash_list_ptr: u64, hash_list_len: u64, public_keys_map_ptr: u64, @@ -2037,7 +2041,7 @@ where /// printed at the [`tracing::Level::INFO`]. This function is for development /// only. pub fn tx_log_string( - env: &TxVmEnv, + env: &mut TxVmEnv, str_ptr: u64, str_len: u64, ) -> TxResult<()> @@ -2057,7 +2061,7 @@ where /// Validate a VP WASM code hash in a tx environment. fn tx_validate_vp_code_hash( - env: &TxVmEnv, + env: &mut TxVmEnv, code_hash: &[u8], code_tag: &Option, ) -> TxResult<()> @@ -2069,7 +2073,11 @@ where { let code_hash = Hash::try_from(code_hash) .map_err(|e| TxRuntimeError::InvalidVpCodeHash(e.to_string()))?; - let state = env.state(); + + // NB: an env clone is required to avoid an immutable + // borrow while a mutable borrow is taking place + let env2 = env.clone(); + let state = env2.state(); // First check that code hash corresponds to the code tag if it is present if let Some(tag) = code_tag { @@ -2115,8 +2123,9 @@ where } /// Set the sentinel for an invalid tx section commitment -pub fn tx_set_commitment_sentinel(env: &TxVmEnv) -where +pub fn tx_set_commitment_sentinel( + env: &mut TxVmEnv, +) where D: 'static + DB + for<'iter> DBIter<'iter>, H: 'static + StorageHasher, MEM: VmMemory, @@ -2129,7 +2138,7 @@ where /// Verify a transaction signature #[allow(clippy::too_many_arguments)] pub fn tx_verify_tx_section_signature( - env: &TxVmEnv, + env: &mut TxVmEnv, hash_list_ptr: u64, hash_list_len: u64, public_keys_map_ptr: u64, @@ -2201,7 +2210,7 @@ where /// Appends the new note commitments to the tree in storage pub fn tx_update_masp_note_commitment_tree( - env: &TxVmEnv, + env: &mut TxVmEnv, transaction_ptr: u64, transaction_len: u64, ) -> TxResult @@ -2238,7 +2247,7 @@ where /// Yield a byte array value from the guest. pub fn tx_yield_value( - env: &TxVmEnv, + env: &mut TxVmEnv, buf_ptr: u64, buf_len: u64, ) -> TxResult<()> @@ -2260,7 +2269,7 @@ where /// Evaluate a validity predicate with the given input data. pub fn vp_eval( - env: &VpVmEnv, + env: &mut VpVmEnv, vp_code_hash_ptr: u64, vp_code_hash_len: u64, input_data_ptr: u64, @@ -2312,7 +2321,7 @@ where /// Get the native token's address pub fn vp_get_native_token( - env: &VpVmEnv, + env: &mut VpVmEnv, result_ptr: u64, ) -> vp_host_fns::EnvResult<()> where @@ -2337,7 +2346,7 @@ where /// printed at the [`tracing::Level::INFO`]. This function is for development /// only. pub fn vp_log_string( - env: &VpVmEnv, + env: &mut VpVmEnv, str_ptr: u64, str_len: u64, ) -> vp_host_fns::EnvResult<()> @@ -2358,7 +2367,7 @@ where /// Yield a byte array value from the guest. pub fn vp_yield_value( - env: &VpVmEnv, + env: &mut VpVmEnv, buf_ptr: u64, buf_len: u64, ) -> vp_host_fns::EnvResult<()> diff --git a/crates/namada/src/vm/wasm/host_env.rs b/crates/namada/src/vm/wasm/host_env.rs index 20e968067a..fa5eea43b8 100644 --- a/crates/namada/src/vm/wasm/host_env.rs +++ b/crates/namada/src/vm/wasm/host_env.rs @@ -127,9 +127,9 @@ mod wrap_tx { D: DB + for<'iter> DBIter<'iter> + 'static, H: StorageHasher + 'static, CA: WasmCacheAccess + 'static, - F: Fn(&TxVmEnv) -> RET, + F: Fn(&mut TxVmEnv) -> RET, { - move |env| f(env.data()) + move |mut env| f(env.data_mut()) } pub(super) fn _1( @@ -139,9 +139,9 @@ mod wrap_tx { D: DB + for<'iter> DBIter<'iter> + 'static, H: StorageHasher + 'static, CA: WasmCacheAccess + 'static, - F: Fn(&TxVmEnv, ARG0) -> RET, + F: Fn(&mut TxVmEnv, ARG0) -> RET, { - move |env, arg0| f(env.data(), arg0) + move |mut env, arg0| f(env.data_mut(), arg0) } pub(super) fn _2( @@ -151,9 +151,9 @@ mod wrap_tx { D: DB + for<'iter> DBIter<'iter> + 'static, H: StorageHasher + 'static, CA: WasmCacheAccess + 'static, - F: Fn(&TxVmEnv, ARG0, ARG1) -> RET, + F: Fn(&mut TxVmEnv, ARG0, ARG1) -> RET, { - move |env, arg0, arg1| f(env.data(), arg0, arg1) + move |mut env, arg0, arg1| f(env.data_mut(), arg0, arg1) } pub(super) fn _4( @@ -169,9 +169,17 @@ mod wrap_tx { D: DB + for<'iter> DBIter<'iter> + 'static, H: StorageHasher + 'static, CA: WasmCacheAccess + 'static, - F: Fn(&TxVmEnv, ARG0, ARG1, ARG2, ARG3) -> RET, + F: Fn( + &mut TxVmEnv, + ARG0, + ARG1, + ARG2, + ARG3, + ) -> RET, { - move |env, arg0, arg1, arg2, arg3| f(env.data(), arg0, arg1, arg2, arg3) + move |mut env, arg0, arg1, arg2, arg3| { + f(env.data_mut(), arg0, arg1, arg2, arg3) + } } pub(super) fn _6( @@ -190,7 +198,7 @@ mod wrap_tx { H: StorageHasher + 'static, CA: WasmCacheAccess + 'static, F: Fn( - &TxVmEnv, + &mut TxVmEnv, ARG0, ARG1, ARG2, @@ -199,8 +207,8 @@ mod wrap_tx { ARG5, ) -> RET, { - move |env, arg0, arg1, arg2, arg3, arg4, arg5| { - f(env.data(), arg0, arg1, arg2, arg3, arg4, arg5) + move |mut env, arg0, arg1, arg2, arg3, arg4, arg5| { + f(env.data_mut(), arg0, arg1, arg2, arg3, arg4, arg5) } } @@ -234,7 +242,7 @@ mod wrap_tx { H: StorageHasher + 'static, CA: WasmCacheAccess + 'static, F: Fn( - &TxVmEnv, + &mut TxVmEnv, ARG0, ARG1, ARG2, @@ -244,8 +252,8 @@ mod wrap_tx { ARG6, ) -> RET, { - move |env, arg0, arg1, arg2, arg3, arg4, arg5, arg6| { - f(env.data(), arg0, arg1, arg2, arg3, arg4, arg5, arg6) + move |mut env, arg0, arg1, arg2, arg3, arg4, arg5, arg6| { + f(env.data_mut(), arg0, arg1, arg2, arg3, arg4, arg5, arg6) } } } @@ -273,9 +281,9 @@ mod wrap_vp { H: StorageHasher + 'static, CA: WasmCacheAccess + 'static, EVAL: VpEvaluator + 'static, - F: Fn(&VpVmEnv) -> RET, + F: Fn(&mut VpVmEnv) -> RET, { - move |env| f(env.data()) + move |mut env| f(env.data_mut()) } pub(super) fn _1( @@ -286,9 +294,9 @@ mod wrap_vp { H: StorageHasher + 'static, CA: WasmCacheAccess + 'static, EVAL: VpEvaluator + 'static, - F: Fn(&VpVmEnv, ARG0) -> RET, + F: Fn(&mut VpVmEnv, ARG0) -> RET, { - move |env, arg0| f(env.data(), arg0) + move |mut env, arg0| f(env.data_mut(), arg0) } pub(super) fn _2( @@ -303,9 +311,9 @@ mod wrap_vp { H: StorageHasher + 'static, CA: WasmCacheAccess + 'static, EVAL: VpEvaluator + 'static, - F: Fn(&VpVmEnv, ARG0, ARG1) -> RET, + F: Fn(&mut VpVmEnv, ARG0, ARG1) -> RET, { - move |env, arg0, arg1| f(env.data(), arg0, arg1) + move |mut env, arg0, arg1| f(env.data_mut(), arg0, arg1) } pub(super) fn _4( @@ -323,14 +331,16 @@ mod wrap_vp { CA: WasmCacheAccess + 'static, EVAL: VpEvaluator + 'static, F: Fn( - &VpVmEnv, + &mut VpVmEnv, ARG0, ARG1, ARG2, ARG3, ) -> RET, { - move |env, arg0, arg1, arg2, arg3| f(env.data(), arg0, arg1, arg2, arg3) + move |mut env, arg0, arg1, arg2, arg3| { + f(env.data_mut(), arg0, arg1, arg2, arg3) + } } pub(super) fn _9< @@ -369,7 +379,7 @@ mod wrap_vp { CA: WasmCacheAccess + 'static, EVAL: VpEvaluator + 'static, F: Fn( - &VpVmEnv, + &mut VpVmEnv, ARG0, ARG1, ARG2, @@ -381,9 +391,9 @@ mod wrap_vp { ARG8, ) -> RET, { - move |env, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8| { + move |mut env, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8| { f( - env.data(), + env.data_mut(), arg0, arg1, arg2, diff --git a/crates/tests/src/vm_host_env/tx.rs b/crates/tests/src/vm_host_env/tx.rs index f6f0ff580f..7df8beb282 100644 --- a/crates/tests/src/vm_host_env/tx.rs +++ b/crates/tests/src/vm_host_env/tx.rs @@ -354,7 +354,7 @@ mod native_tx_host_env { batched_tx, }: &mut TestTxEnv| { - let tx_env = vm::host_env::testing::tx_env( + let mut tx_env = vm::host_env::testing::tx_env( state, iterators, verifiers, @@ -371,7 +371,7 @@ mod native_tx_host_env { // Call the `host_env` function and unwrap any // runtime errors - $fn( &tx_env, $($arg),* ).unwrap() + $fn( &mut tx_env, $($arg),* ).unwrap() }) } }); @@ -398,7 +398,7 @@ mod native_tx_host_env { batched_tx }: &mut TestTxEnv| { - let tx_env = vm::host_env::testing::tx_env( + let mut tx_env = vm::host_env::testing::tx_env( state, iterators, verifiers, @@ -415,7 +415,7 @@ mod native_tx_host_env { // Call the `host_env` function and unwrap any // runtime errors - $fn( &tx_env, $($arg),* ).unwrap() + $fn( &mut tx_env, $($arg),* ).unwrap() }) } }); @@ -442,7 +442,7 @@ mod native_tx_host_env { batched_tx, }: &mut TestTxEnv| { - let tx_env = vm::host_env::testing::tx_env( + let mut tx_env = vm::host_env::testing::tx_env( state, iterators, verifiers, @@ -458,7 +458,7 @@ mod native_tx_host_env { ); // Call the `host_env` function - $fn( &tx_env, $($arg),* ) + $fn( &mut tx_env, $($arg),* ) }) } }); @@ -582,13 +582,18 @@ mod tests { // dbg!(&setup); let mut test_env = TestTxEnv::default(); - let tx_env = setup_host_env(&setup, &mut test_env); + let mut tx_env = setup_host_env(&setup, &mut test_env); // Can fail, but must not panic - let _res = - host_env::tx_read(&tx_env, setup.key_memory_ptr, setup.key_len()); - let _res = - host_env::tx_result_buffer(&tx_env, setup.read_buffer_memory_ptr); + let _res = host_env::tx_read( + &mut tx_env, + setup.key_memory_ptr, + setup.key_len(), + ); + let _res = host_env::tx_result_buffer( + &mut tx_env, + setup.read_buffer_memory_ptr, + ); } proptest! { @@ -603,10 +608,10 @@ mod tests { fn test_tx_charge_gas_cannot_panic_aux(setup: TestSetup, gas: u64) { let mut test_env = TestTxEnv::default(); - let tx_env = setup_host_env(&setup, &mut test_env); + let mut tx_env = setup_host_env(&setup, &mut test_env); // Can fail, but must not panic - let _res = host_env::tx_charge_gas(&tx_env, gas); + let _res = host_env::tx_charge_gas(&mut tx_env, gas); } proptest! { @@ -622,11 +627,11 @@ mod tests { // dbg!(&setup); let mut test_env = TestTxEnv::default(); - let tx_env = setup_host_env(&setup, &mut test_env); + let mut tx_env = setup_host_env(&setup, &mut test_env); // Can fail, but must not panic let _res = host_env::tx_has_key( - &tx_env, + &mut tx_env, setup.key_memory_ptr, setup.key_len(), ); @@ -645,18 +650,18 @@ mod tests { // dbg!(&setup); let mut test_env = TestTxEnv::default(); - let tx_env = setup_host_env(&setup, &mut test_env); + let mut tx_env = setup_host_env(&setup, &mut test_env); // Can fail, but must not panic let _res = host_env::tx_write( - &tx_env, + &mut tx_env, setup.key_memory_ptr, setup.key_len(), setup.val_memory_ptr, setup.val_len(), ); let _res = host_env::tx_write_temp( - &tx_env, + &mut tx_env, setup.key_memory_ptr, setup.key_len(), setup.val_memory_ptr, @@ -677,11 +682,14 @@ mod tests { // dbg!(&setup); let mut test_env = TestTxEnv::default(); - let tx_env = setup_host_env(&setup, &mut test_env); + let mut tx_env = setup_host_env(&setup, &mut test_env); // Can fail, but must not panic - let _res = - host_env::tx_delete(&tx_env, setup.key_memory_ptr, setup.key_len()); + let _res = host_env::tx_delete( + &mut tx_env, + setup.key_memory_ptr, + setup.key_len(), + ); } proptest! { @@ -697,16 +705,16 @@ mod tests { // dbg!(&setup); let mut test_env = TestTxEnv::default(); - let tx_env = setup_host_env(&setup, &mut test_env); + let mut tx_env = setup_host_env(&setup, &mut test_env); // Can fail, but must not panic let _res = host_env::tx_iter_prefix( - &tx_env, + &mut tx_env, setup.key_memory_ptr, setup.key_len(), ); let _res = host_env::tx_iter_next( - &tx_env, + &mut tx_env, // This field is not used for anything else in this test setup.val_memory_ptr, ); diff --git a/crates/tests/src/vm_host_env/vp.rs b/crates/tests/src/vm_host_env/vp.rs index 4444310a39..10a7bda496 100644 --- a/crates/tests/src/vm_host_env/vp.rs +++ b/crates/tests/src/vm_host_env/vp.rs @@ -267,7 +267,7 @@ mod native_vp_host_env { vp_cache_dir: _, }: &mut TestVpEnv| { - let env = vm::host_env::testing::vp_env( + let mut env = vm::host_env::testing::vp_env( addr, state, iterators, @@ -285,7 +285,7 @@ mod native_vp_host_env { // Call the `host_env` function and unwrap any // runtime errors - $fn( &env, $($arg),* ).unwrap() + $fn( &mut env, $($arg),* ).unwrap() }) } }); @@ -312,7 +312,7 @@ mod native_vp_host_env { vp_cache_dir: _, }: &mut TestVpEnv| { - let env = vm::host_env::testing::vp_env( + let mut env = vm::host_env::testing::vp_env( addr, state, iterators, @@ -330,7 +330,7 @@ mod native_vp_host_env { // Call the `host_env` function and unwrap any // runtime errors - $fn( &env, $($arg),* ).unwrap() + $fn( &mut env, $($arg),* ).unwrap() }) } }); From 339e17d044b44f9a5899824f90243bc78a71d0fe Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 24 May 2024 10:59:14 +0100 Subject: [PATCH 51/70] Allow exclusive access to vm memory --- crates/namada/src/vm/memory.rs | 16 ++++++++-------- crates/namada/src/vm/wasm/memory.rs | 20 ++++++++++++++++---- crates/tests/src/vm_host_env/tx.rs | 2 +- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/crates/namada/src/vm/memory.rs b/crates/namada/src/vm/memory.rs index e55117726c..fe53a6c832 100644 --- a/crates/namada/src/vm/memory.rs +++ b/crates/namada/src/vm/memory.rs @@ -9,28 +9,28 @@ pub trait VmMemory: Clone + Send + Sync { /// Returns bytes read from memory together with the associated gas cost. fn read_bytes( - &self, + &mut self, offset: u64, len: usize, ) -> Result<(Vec, u64), Self::Error>; /// Write bytes to memory. Returns the gas cost. fn write_bytes( - &self, + &mut self, offset: u64, bytes: impl AsRef<[u8]>, ) -> Result; /// Returns string read from memory together with the associated gas cost. fn read_string( - &self, + &mut self, offset: u64, len: usize, ) -> Result<(String, u64), Self::Error>; /// Write string to memory. Returns the gas cost. fn write_string( - &self, + &mut self, offset: u64, string: String, ) -> Result; @@ -55,7 +55,7 @@ pub mod testing { type Error = Infallible; fn read_bytes( - &self, + &mut self, offset: u64, len: usize, ) -> Result<(Vec, u64)> { @@ -64,7 +64,7 @@ pub mod testing { } fn write_bytes( - &self, + &mut self, offset: u64, bytes: impl AsRef<[u8]>, ) -> Result { @@ -77,7 +77,7 @@ pub mod testing { } fn read_string( - &self, + &mut self, offset: u64, len: usize, ) -> Result<(String, u64)> { @@ -88,7 +88,7 @@ pub mod testing { Ok((string, 0)) } - fn write_string(&self, offset: u64, string: String) -> Result { + fn write_string(&mut self, offset: u64, string: String) -> Result { let bytes = string.as_bytes(); let len = bytes.len(); let target = diff --git a/crates/namada/src/vm/wasm/memory.rs b/crates/namada/src/vm/wasm/memory.rs index 89ebcd037f..6cd7bbf924 100644 --- a/crates/namada/src/vm/wasm/memory.rs +++ b/crates/namada/src/vm/wasm/memory.rs @@ -311,7 +311,11 @@ impl VmMemory for WasmMemory { /// Read bytes from memory at the given offset and length, return the bytes /// and the gas cost - fn read_bytes(&self, offset: u64, len: usize) -> Result<(Vec, u64)> { + fn read_bytes( + &mut self, + offset: u64, + len: usize, + ) -> Result<(Vec, u64)> { self.access(|memory| { let mut store = self.store.borrow_mut(); let bytes = read_memory_bytes(&mut *store, memory, offset, len)?; @@ -322,7 +326,11 @@ impl VmMemory for WasmMemory { } /// Write bytes into memory at the given offset and return the gas cost - fn write_bytes(&self, offset: u64, bytes: impl AsRef<[u8]>) -> Result { + fn write_bytes( + &mut self, + offset: u64, + bytes: impl AsRef<[u8]>, + ) -> Result { self.access(|memory| { // No need for a separate gas multiplier for writes since we are // only writing to memory and we already charge gas for @@ -337,7 +345,11 @@ impl VmMemory for WasmMemory { /// Read string from memory at the given offset and bytes length, and return /// the gas cost - fn read_string(&self, offset: u64, len: usize) -> Result<(String, u64)> { + fn read_string( + &mut self, + offset: u64, + len: usize, + ) -> Result<(String, u64)> { let (bytes, gas) = self.read_bytes(offset, len)?; let string = std::str::from_utf8(&bytes) .map_err(Error::InvalidUtf8String)? @@ -347,7 +359,7 @@ impl VmMemory for WasmMemory { /// Write string into memory at the given offset and return the gas cost #[allow(dead_code)] - fn write_string(&self, offset: u64, string: String) -> Result { + fn write_string(&mut self, offset: u64, string: String) -> Result { self.write_bytes(offset, string.as_bytes()) } } diff --git a/crates/tests/src/vm_host_env/tx.rs b/crates/tests/src/vm_host_env/tx.rs index 7df8beb282..594391024d 100644 --- a/crates/tests/src/vm_host_env/tx.rs +++ b/crates/tests/src/vm_host_env/tx.rs @@ -759,7 +759,7 @@ mod tests { batched_tx, } = test_env; - let tx_env = vm::host_env::testing::tx_env_with_wasm_memory( + let mut tx_env = vm::host_env::testing::tx_env_with_wasm_memory( state, iterators, verifiers, From 19e78990d7fb0c5e0b6edb449c1d990f949b2b3b Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Fri, 24 May 2024 12:37:15 +0200 Subject: [PATCH 52/70] fixup! Merge branch 'grarco/masp-no-transfer-dep' (#3232) evil 3232 --- crates/namada/src/ledger/protocol/mod.rs | 53 ++- crates/node/src/shell/finalize_block.rs | 440 +++++++++++++---------- 2 files changed, 283 insertions(+), 210 deletions(-) diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index 0d995c4e7d..3b481da6a6 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -18,8 +18,8 @@ use namada_state::StorageWrite; use namada_token::event::{TokenEvent, TokenOperation, UserAccount}; use namada_tx::data::protocol::{ProtocolTx, ProtocolTxType}; use namada_tx::data::{ - BatchResults, BatchedTxResult, ExtendedTxResult, TxResult, - VpStatusFlags, VpsResult, WrapperTx, + BatchResults, BatchedTxResult, ExtendedTxResult, TxResult, VpStatusFlags, + VpsResult, WrapperTx, }; use namada_tx::{BatchedTxRef, Tx}; use namada_vote_ext::EthereumTxData; @@ -225,31 +225,29 @@ where vp_wasm_cache, tx_wasm_cache, } => { - if let Some(mut tx_result) = wrapper_tx_result { + if let Some(tx_result) = wrapper_tx_result { // TODO(namada#2597): handle masp fee payment in the first inner // tx if necessary - // Replay protection check on the batch - let tx_hash = tx.raw_header_hash(); - if state.write_log().has_replay_protection_entry(&tx_hash) { - // If the same batch has already been committed in - // this block, skip execution and return - return Err(DispatchError { - error: Error::ReplayAttempt(tx_hash), - tx_result: None, - }); - } - - dispatch_inner_txs( - tx, - tx_result, - tx_index, - tx_gas_meter, - state, - vp_wasm_cache, - tx_wasm_cache, - ) - + // Replay protection check on the batch + let tx_hash = tx.raw_header_hash(); + if state.write_log().has_replay_protection_entry(&tx_hash) { + // If the same batch has already been committed in + // this block, skip execution and return + return Err(DispatchError { + error: Error::ReplayAttempt(tx_hash), + tx_result: None, + }); + } + dispatch_inner_txs( + tx, + tx_result, + tx_index, + tx_gas_meter, + state, + vp_wasm_cache, + tx_wasm_cache, + ) } else { // Governance proposal. We don't allow tx batches in this case, // just take the first one @@ -273,8 +271,7 @@ where .collect(), ), } - .to_extended_result(None)) - ) + .to_extended_result(None)) } } DispatchArgs::Protocol(protocol_tx) => { @@ -308,13 +305,13 @@ where ) .map_err(|e| Error::WrapperRunnerError(e.to_string()))?; - Ok(tx_result) + Ok(tx_result.to_extended_result(None)) } } } fn dispatch_inner_txs<'a, D, H, CA>( - tx: Tx, + tx: &Tx, tx_result: TxResult, tx_index: TxIndex, tx_gas_meter: &'a RefCell, diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 9bf02356fc..0d26854544 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -15,7 +15,7 @@ use namada::ledger::events::EmitEvents; use namada::ledger::gas::GasMetering; use namada::ledger::ibc; use namada::ledger::pos::namada_proof_of_stake; -use namada::ledger::protocol::DispatchArgs; +use namada::ledger::protocol::{DispatchArgs, DispatchError}; use namada::masp::MaspTxRefs; use namada::proof_of_stake; use namada::proof_of_stake::storage::{ @@ -353,8 +353,8 @@ where tx_data: TxData<'_>, mut tx_logs: TxLogs<'_>, ) -> Option { - match dispatch_result { - Ok(tx_result) => match tx_data.tx.header.tx_type { + match extended_dispatch_result { + Ok(extended_tx_result) => match tx_data.tx.header.tx_type { TxType::Wrapper(_) => { // Return withouth emitting any events return Some(WrapperCache { @@ -362,12 +362,12 @@ where tx_index: tx_data.tx_index, gas_meter: tx_data.tx_gas_meter, event: tx_logs.tx_event, - tx_result, + tx_result: extended_tx_result.tx_result, }); } _ => self.handle_inner_tx_results( response, - tx_result, + extended_tx_result, tx_data, &mut tx_logs, ), @@ -1354,11 +1354,7 @@ mod test_finalize_block { .enumerate() .find_map( |(idx, tx_hash)| { - if tx_hash == &hash { - Some(idx) - } else { - None - } + if tx_hash == &hash { Some(idx) } else { None } }, ) .unwrap(); @@ -2952,21 +2948,25 @@ mod test_finalize_block { assert_eq!(root_pre.0, root_post.0); // Check transaction's hash in storage - assert!(shell - .shell - .state - .write_log() - .has_replay_protection_entry(&wrapper_tx.raw_header_hash())); + assert!( + shell + .shell + .state + .write_log() + .has_replay_protection_entry(&wrapper_tx.raw_header_hash()) + ); // Check that the hash is not present in the merkle tree shell.state.commit_block().unwrap(); - assert!(!shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&wrapper_hash_key) - .unwrap()); + assert!( + !shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&wrapper_hash_key) + .unwrap() + ); // test that a commitment to replay protection gets added. let reprot_key = replay_protection::commitment_key(); @@ -3013,22 +3013,26 @@ mod test_finalize_block { assert_eq!(root_pre.0, root_post.0); // Check that the hashes are present in the merkle tree shell.state.commit_block().unwrap(); - assert!(shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&convert_key) - .unwrap()); - assert!(shell - .shell - .state - .in_mem() - .block - .tree - .has_key(&commitment_key) - .unwrap()); + assert!( + shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&convert_key) + .unwrap() + ); + assert!( + shell + .shell + .state + .in_mem() + .block + .tree + .has_key(&commitment_key) + .unwrap() + ); } /// Test that a tx that has already been applied in the same block @@ -3106,26 +3110,34 @@ mod test_finalize_block { assert_eq!(code, ResultCode::WasmRuntimeError); for wrapper in [&wrapper, &new_wrapper] { - assert!(shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.raw_header_hash())); - assert!(!shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.header_hash())); + assert!( + shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.raw_header_hash()) + ); + assert!( + !shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.header_hash()) + ); } // Commit to check the hashes from storage shell.commit(); for wrapper in [&wrapper, &new_wrapper] { - assert!(shell - .state - .has_replay_protection_entry(&wrapper.raw_header_hash()) - .unwrap()); - assert!(!shell - .state - .has_replay_protection_entry(&wrapper.header_hash()) - .unwrap()); + assert!( + shell + .state + .has_replay_protection_entry(&wrapper.raw_header_hash()) + .unwrap() + ); + assert!( + !shell + .state + .has_replay_protection_entry(&wrapper.header_hash()) + .unwrap() + ); } } @@ -3408,23 +3420,29 @@ mod test_finalize_block { &unsigned_wrapper, &wrong_commitment_wrapper, ] { - assert!(!shell - .state - .write_log() - .has_replay_protection_entry(&valid_wrapper.raw_header_hash())); - assert!(shell + assert!( + !shell.state.write_log().has_replay_protection_entry( + &valid_wrapper.raw_header_hash() + ) + ); + assert!( + shell + .state + .write_log() + .has_replay_protection_entry(&valid_wrapper.header_hash()) + ); + } + assert!( + shell.state.write_log().has_replay_protection_entry( + &failing_wrapper.raw_header_hash() + ) + ); + assert!( + !shell .state .write_log() - .has_replay_protection_entry(&valid_wrapper.header_hash())); - } - assert!(shell - .state - .write_log() - .has_replay_protection_entry(&failing_wrapper.raw_header_hash())); - assert!(!shell - .state - .write_log() - .has_replay_protection_entry(&failing_wrapper.header_hash())); + .has_replay_protection_entry(&failing_wrapper.header_hash()) + ); // Commit to check the hashes from storage shell.commit(); @@ -3433,23 +3451,33 @@ mod test_finalize_block { unsigned_wrapper, wrong_commitment_wrapper, ] { - assert!(!shell + assert!( + !shell + .state + .has_replay_protection_entry( + &valid_wrapper.raw_header_hash() + ) + .unwrap() + ); + assert!( + shell + .state + .has_replay_protection_entry(&valid_wrapper.header_hash()) + .unwrap() + ); + } + assert!( + shell .state - .has_replay_protection_entry(&valid_wrapper.raw_header_hash()) - .unwrap()); - assert!(shell + .has_replay_protection_entry(&failing_wrapper.raw_header_hash()) + .unwrap() + ); + assert!( + !shell .state - .has_replay_protection_entry(&valid_wrapper.header_hash()) - .unwrap()); - } - assert!(shell - .state - .has_replay_protection_entry(&failing_wrapper.raw_header_hash()) - .unwrap()); - assert!(!shell - .state - .has_replay_protection_entry(&failing_wrapper.header_hash()) - .unwrap()); + .has_replay_protection_entry(&failing_wrapper.header_hash()) + .unwrap() + ); } #[test] @@ -3509,14 +3537,18 @@ mod test_finalize_block { let code = event[0].read_attribute::().expect("Test failed"); assert_eq!(code, ResultCode::InvalidTx); - assert!(shell - .state - .write_log() - .has_replay_protection_entry(&wrapper_hash)); - assert!(!shell - .state - .write_log() - .has_replay_protection_entry(&wrapper.raw_header_hash())); + assert!( + shell + .state + .write_log() + .has_replay_protection_entry(&wrapper_hash) + ); + assert!( + !shell + .state + .write_log() + .has_replay_protection_entry(&wrapper.raw_header_hash()) + ); } // Test that the fees are paid even if the inner transaction fails and its @@ -3914,9 +3946,11 @@ mod test_finalize_block { .unwrap(), Some(ValidatorState::Consensus) ); - assert!(enqueued_slashes_handle() - .at(&Epoch::default()) - .is_empty(&shell.state)?); + assert!( + enqueued_slashes_handle() + .at(&Epoch::default()) + .is_empty(&shell.state)? + ); assert_eq!( get_num_consensus_validators(&shell.state, Epoch::default()) .unwrap(), @@ -3935,17 +3969,21 @@ mod test_finalize_block { .unwrap(), Some(ValidatorState::Jailed) ); - assert!(enqueued_slashes_handle() - .at(&epoch) - .is_empty(&shell.state)?); + assert!( + enqueued_slashes_handle() + .at(&epoch) + .is_empty(&shell.state)? + ); assert_eq!( get_num_consensus_validators(&shell.state, epoch).unwrap(), 5_u64 ); } - assert!(!enqueued_slashes_handle() - .at(&processing_epoch) - .is_empty(&shell.state)?); + assert!( + !enqueued_slashes_handle() + .at(&processing_epoch) + .is_empty(&shell.state)? + ); // Advance to the processing epoch loop { @@ -3968,9 +4006,11 @@ mod test_finalize_block { // println!("Reached processing epoch"); break; } else { - assert!(enqueued_slashes_handle() - .at(&shell.state.in_mem().block.epoch) - .is_empty(&shell.state)?); + assert!( + enqueued_slashes_handle() + .at(&shell.state.in_mem().block.epoch) + .is_empty(&shell.state)? + ); let stake1 = read_validator_stake( &shell.state, ¶ms, @@ -4454,11 +4494,13 @@ mod test_finalize_block { ) .unwrap(); assert_eq!(last_slash, Some(misbehavior_epoch)); - assert!(namada_proof_of_stake::storage::validator_slashes_handle( - &val1.address - ) - .is_empty(&shell.state) - .unwrap()); + assert!( + namada_proof_of_stake::storage::validator_slashes_handle( + &val1.address + ) + .is_empty(&shell.state) + .unwrap() + ); tracing::debug!("Advancing to epoch 7"); @@ -4523,18 +4565,22 @@ mod test_finalize_block { ) .unwrap(); assert_eq!(last_slash, Some(Epoch(4))); - assert!(namada_proof_of_stake::is_validator_frozen( - &shell.state, - &val1.address, - current_epoch, - ¶ms - ) - .unwrap()); - assert!(namada_proof_of_stake::storage::validator_slashes_handle( - &val1.address - ) - .is_empty(&shell.state) - .unwrap()); + assert!( + namada_proof_of_stake::is_validator_frozen( + &shell.state, + &val1.address, + current_epoch, + ¶ms + ) + .unwrap() + ); + assert!( + namada_proof_of_stake::storage::validator_slashes_handle( + &val1.address + ) + .is_empty(&shell.state) + .unwrap() + ); let pre_stake_10 = namada_proof_of_stake::storage::read_validator_stake( @@ -5412,9 +5458,11 @@ mod test_finalize_block { shell.vp_wasm_cache.clone(), ); let parameters = ParametersVp { ctx }; - assert!(parameters - .validate_tx(&batched_tx, &keys_changed, &verifiers) - .is_ok()); + assert!( + parameters + .validate_tx(&batched_tx, &keys_changed, &verifiers) + .is_ok() + ); // we advance forward to the next epoch let mut req = FinalizeBlock::default(); @@ -5487,11 +5535,13 @@ mod test_finalize_block { let inner_results = inner_tx_result.batch_results.0; for cmt in batch.commitments() { - assert!(inner_results - .get(&cmt.get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); + assert!( + inner_results + .get(&cmt.get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); } // Check storage modifications @@ -5529,18 +5579,24 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!(inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); - assert!(inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err()); + assert!( + inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); + assert!( + inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err() + ); // Assert that the last tx didn't run - assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); + assert!( + !inner_results.contains_key(&batch.commitments()[2].get_hash()) + ); // Check storage modifications are missing for key in ["random_key_1", "random_key_2", "random_key_3"] { @@ -5571,21 +5627,27 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!(inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); - assert!(inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err()); - assert!(inner_results - .get(&batch.commitments()[2].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); + assert!( + inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); + assert!( + inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err() + ); + assert!( + inner_results + .get(&batch.commitments()[2].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); // Check storage modifications assert_eq!( @@ -5596,10 +5658,12 @@ mod test_finalize_block { .unwrap(), STORAGE_VALUE ); - assert!(!shell - .state - .has_key(&"random_key_2".parse().unwrap()) - .unwrap()); + assert!( + !shell + .state + .has_key(&"random_key_2".parse().unwrap()) + .unwrap() + ); assert_eq!( shell .state @@ -5631,18 +5695,24 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!(inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); - assert!(inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err()); + assert!( + inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); + assert!( + inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err() + ); // Assert that the last tx didn't run - assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); + assert!( + !inner_results.contains_key(&batch.commitments()[2].get_hash()) + ); // Check storage modifications are missing for key in ["random_key_1", "random_key_2", "random_key_3"] { @@ -5672,18 +5742,24 @@ mod test_finalize_block { let inner_tx_result = event[0].read_attribute::>().unwrap(); let inner_results = inner_tx_result.batch_results.0; - assert!(inner_results - .get(&batch.commitments()[0].get_hash()) - .unwrap() - .clone() - .is_ok_and(|res| res.is_accepted())); - assert!(inner_results - .get(&batch.commitments()[1].get_hash()) - .unwrap() - .clone() - .is_err()); + assert!( + inner_results + .get(&batch.commitments()[0].get_hash()) + .unwrap() + .clone() + .is_ok_and(|res| res.is_accepted()) + ); + assert!( + inner_results + .get(&batch.commitments()[1].get_hash()) + .unwrap() + .clone() + .is_err() + ); // Assert that the last tx didn't run - assert!(!inner_results.contains_key(&batch.commitments()[2].get_hash())); + assert!( + !inner_results.contains_key(&batch.commitments()[2].get_hash()) + ); // Check storage modifications assert_eq!( From 0e73311509f991f4085ad8d10fb3540667b4a133 Mon Sep 17 00:00:00 2001 From: satan Date: Fri, 24 May 2024 16:25:36 +0200 Subject: [PATCH 53/70] [feat]: Allow nodes to schedule a migrations json to be read and run to facilitate hard-forking --- crates/apps/src/bin/namada-node/cli.rs | 21 +++- crates/apps_lib/src/cli.rs | 48 ++++++++- crates/node/src/bench_utils.rs | 1 + crates/node/src/lib.rs | 42 ++++---- crates/node/src/shell/mod.rs | 26 ++++- crates/node/src/shims/abcipp_shim.rs | 3 + crates/node/src/storage/rocksdb.rs | 29 +++++- crates/sdk/src/migrations.rs | 136 +++++++++++++++++++++++-- crates/storage/src/db.rs | 20 ++++ crates/storage/src/mockdb.rs | 1 + crates/tests/src/integration/setup.rs | 1 + 11 files changed, 290 insertions(+), 38 deletions(-) diff --git a/crates/apps/src/bin/namada-node/cli.rs b/crates/apps/src/bin/namada-node/cli.rs index eb941e0d62..bca121ac6b 100644 --- a/crates/apps/src/bin/namada-node/cli.rs +++ b/crates/apps/src/bin/namada-node/cli.rs @@ -2,6 +2,7 @@ use eyre::{Context, Result}; use namada::core::time::{DateTimeUtc, Utc}; +use namada::sdk::migrations::ScheduledMigration; use namada_apps_lib::cli::cmds::TestGenesis; use namada_apps_lib::cli::{self, cmds}; use namada_apps_lib::config::{Action, ActionAtHeight, ValidatorLocalConfig}; @@ -17,7 +18,21 @@ pub fn main() -> Result<()> { let chain_ctx = ctx.take_chain_or_exit(); let wasm_dir = chain_ctx.wasm_dir(); sleep_until(args.start_time); - node::run(chain_ctx.config.ledger, wasm_dir); + let scheduled_migration = args.migration_path.map(|p| { + let hash = args.migration_hash.expect( + "Expected a hash to be provided along with the \ + migrations file.", + ); + let height = args.migration_height.expect( + "Expected a block height for the scheduled migration.", + ); + ScheduledMigration::from_path(p, hash, height).unwrap() + }); + node::run( + chain_ctx.config.ledger, + wasm_dir, + scheduled_migration, + ); } cmds::Ledger::RunUntil(cmds::LedgerRunUntil(args)) => { let mut chain_ctx = ctx.take_chain_or_exit(); @@ -25,7 +40,7 @@ pub fn main() -> Result<()> { sleep_until(args.time); chain_ctx.config.ledger.shell.action_at_height = Some(args.action_at_height); - node::run(chain_ctx.config.ledger, wasm_dir); + node::run(chain_ctx.config.ledger, wasm_dir, None); } cmds::Ledger::Reset(_) => { let chain_ctx = ctx.take_chain_or_exit(); @@ -69,7 +84,7 @@ pub fn main() -> Result<()> { ); // don't stop on panics let handle = std::thread::spawn(|| { - node::run(chain_ctx.config.ledger, wasm_dir) + node::run(chain_ctx.config.ledger, wasm_dir, None) }); _ = handle.join(); std::env::remove_var("NAMADA_INITIAL_HEIGHT"); diff --git a/crates/apps_lib/src/cli.rs b/crates/apps_lib/src/cli.rs index bef722d042..b853d34b10 100644 --- a/crates/apps_lib/src/cli.rs +++ b/crates/apps_lib/src/cli.rs @@ -862,6 +862,9 @@ pub mod cmds { // The `run` command is the default if no sub-command given .or(Some(Self::Run(LedgerRun(args::LedgerRun { start_time: None, + migration_path: None, + migration_hash: None, + migration_height: None, })))) }) } @@ -2984,6 +2987,7 @@ pub mod args { use namada::core::time::DateTimeUtc; use namada::core::token; use namada::core::token::NATIVE_MAX_DECIMAL_PLACES; + use namada::hash::Hash; use namada::ibc::core::host::types::identifiers::{ChannelId, PortId}; use namada::tx::data::GasLimit; pub use namada_sdk::args::*; @@ -3135,6 +3139,7 @@ pub mod args { arg("validator"); pub const HALT_ACTION: ArgFlag = flag("halt"); pub const HASH: Arg = arg("hash"); + pub const HASH_OPT: ArgOpt = arg_opt("hash"); pub const HASH_LIST: Arg = arg("hash-list"); pub const HD_DERIVATION_PATH: ArgDefault = arg_default("hd-path", DefaultFn(|| "default".to_string())); @@ -3164,6 +3169,7 @@ pub mod args { arg("max-commission-rate-change"); pub const MAX_ETH_GAS: ArgOpt = arg_opt("max_eth-gas"); pub const MEMO_OPT: ArgOpt = arg_opt("memo"); + pub const MIGRATION_PATH: ArgOpt = arg_opt("migration-path"); pub const MODE: ArgOpt = arg_opt("mode"); pub const NET_ADDRESS: Arg = arg("net-address"); pub const NAMADA_START_TIME: ArgOpt = arg_opt("time"); @@ -3177,6 +3183,7 @@ pub mod args { pub const OWNER: Arg = arg("owner"); pub const OWNER_OPT: ArgOpt = OWNER.opt(); pub const PATH: Arg = arg("path"); + pub const PATH_OPT: ArgOpt = arg_opt("path"); pub const PORT_ID: ArgDefault = arg_default( "port-id", DefaultFn(|| PortId::from_str("transfer").unwrap()), @@ -3339,12 +3346,24 @@ pub mod args { #[derive(Clone, Debug)] pub struct LedgerRun { pub start_time: Option, + pub migration_path: Option, + pub migration_hash: Option, + pub migration_height: Option, } impl Args for LedgerRun { fn parse(matches: &ArgMatches) -> Self { let start_time = NAMADA_START_TIME.parse(matches); - Self { start_time } + let migration_path = PATH_OPT.parse(matches); + let migration_hash = HASH_OPT.parse(matches); + let migration_height = BLOCK_HEIGHT_OPT.parse(matches); + Self { + start_time, + migration_path, + migration_hash: migration_hash + .map(|h| Hash::try_from(h).unwrap()), + migration_height, + } } fn def(app: App) -> App { @@ -3356,6 +3375,33 @@ pub mod args { equivalent:\n2023-01-20T12:12:12Z\n2023-01-20 \ 12:12:12Z\n2023- 01-20T12: 12:12Z" ))) + .arg( + PATH_OPT + .def() + .requires(HASH_OPT.name) + .requires(BLOCK_HEIGHT_OPT.name) + .help(wrap!("Optional path to a migrations JSON file.")), + ) + .arg( + HASH_OPT + .def() + .requires(PATH_OPT.name) + .requires(BLOCK_HEIGHT_OPT.name) + .help(wrap!( + "Hash to verify contents of optinally provided \ + migrations file." + )), + ) + .arg( + BLOCK_HEIGHT_OPT + .def() + .requires(PATH_OPT.name) + .requires(HASH_OPT.name) + .help(wrap!( + "Height for which the optionally provided migration \ + should be executed." + )), + ) } } diff --git a/crates/node/src/bench_utils.rs b/crates/node/src/bench_utils.rs index da0828ecc7..4b1853b0e8 100644 --- a/crates/node/src/bench_utils.rs +++ b/crates/node/src/bench_utils.rs @@ -180,6 +180,7 @@ impl Default for BenchShell { sender, None, None, + None, 50 * 1024 * 1024, // 50 kiB 50 * 1024 * 1024, // 50 kiB ); diff --git a/crates/node/src/lib.rs b/crates/node/src/lib.rs index bac9eb2062..f210bb8a71 100644 --- a/crates/node/src/lib.rs +++ b/crates/node/src/lib.rs @@ -43,6 +43,7 @@ use namada_apps_lib::config::utils::{ convert_tm_addr_to_socket_addr, num_of_threads, }; use namada_apps_lib::{config, wasm_loader}; +use namada_sdk::migrations::ScheduledMigration; use namada_sdk::state::StateRead; use once_cell::unsync::Lazy; use sysinfo::{RefreshKind, System, SystemExt}; @@ -196,7 +197,11 @@ fn emit_warning_on_non_64bit_cpu() { } /// Run the ledger with an async runtime -pub fn run(config: config::Ledger, wasm_dir: PathBuf) { +pub fn run( + config: config::Ledger, + wasm_dir: PathBuf, + scheduled_migration: Option, +) { emit_warning_on_non_64bit_cpu(); let logical_cores = num_cpus::get(); @@ -232,7 +237,7 @@ pub fn run(config: config::Ledger, wasm_dir: PathBuf) { .enable_all() .build() .unwrap() - .block_on(run_aux(config, wasm_dir)); + .block_on(run_aux(config, wasm_dir, scheduled_migration)); } /// Resets the tendermint_node state and removes database files @@ -311,25 +316,9 @@ pub fn update_db_keys(config: config::Ledger, updates: PathBuf, dry_run: bool) { let db_path = config.shell.db_dir(&chain_id); let db = storage::PersistentDB::open(db_path, None); - let mut db_visitor = storage::RocksDBUpdateVisitor::new(&db); - - for change in &updates.changes { - match change.update(&mut db_visitor) { - Ok(status) => { - tracing::info!("{}", status); - } - e => { - tracing::error!( - "Attempt to write to key/pattern <{}> failed.", - change.pattern() - ); - e.unwrap(); - } - } - } + let batch = db.apply_migration_to_batch(updates.changes).unwrap(); if !dry_run { tracing::info!("Persisting DB changes..."); - let batch = db_visitor.take_batch(); db.exec_batch(batch).expect("Failed to execute write batch"); db.flush(true).expect("Failed to flush data to disk"); @@ -357,8 +346,13 @@ pub fn rollback(config: config::Ledger) -> Result<(), shell::Error> { /// them to the ledger. /// /// All must be alive for correct functioning. -async fn run_aux(config: config::Ledger, wasm_dir: PathBuf) { - let setup_data = run_aux_setup(&config, &wasm_dir).await; +async fn run_aux( + config: config::Ledger, + wasm_dir: PathBuf, + scheduled_migration: Option, +) { + let setup_data = + run_aux_setup(&config, &wasm_dir, scheduled_migration).await; // Create an `AbortableSpawner` for signalling shut down from the shell or // from Tendermint @@ -431,12 +425,14 @@ struct RunAuxSetup { vp_wasm_compilation_cache: u64, tx_wasm_compilation_cache: u64, db_block_cache_size_bytes: u64, + scheduled_migration: Option, } /// Return some variables used to start child processes of the ledger. async fn run_aux_setup( config: &config::Ledger, wasm_dir: &PathBuf, + scheduled_migration: Option, ) -> RunAuxSetup { // Prefetch needed wasm artifacts wasm_loader::pre_fetch_wasm(wasm_dir).await; @@ -523,6 +519,7 @@ async fn run_aux_setup( vp_wasm_compilation_cache, tx_wasm_compilation_cache, db_block_cache_size_bytes, + scheduled_migration, } } @@ -546,6 +543,7 @@ fn start_abci_broadcaster_shell( vp_wasm_compilation_cache, tx_wasm_compilation_cache, db_block_cache_size_bytes, + scheduled_migration, } = setup_data; // Channels for validators to send protocol txs to be broadcast to the @@ -596,6 +594,7 @@ fn start_abci_broadcaster_shell( broadcaster_sender, eth_oracle, &db_cache, + scheduled_migration, vp_wasm_compilation_cache, tx_wasm_compilation_cache, ); @@ -888,6 +887,7 @@ pub fn test_genesis_files( broadcast_sender, None, None, + None, 50 * 1024 * 1024, 50 * 1024 * 1024, ); diff --git a/crates/node/src/shell/mod.rs b/crates/node/src/shell/mod.rs index cecdb51eca..7bbf4a711b 100644 --- a/crates/node/src/shell/mod.rs +++ b/crates/node/src/shell/mod.rs @@ -64,6 +64,8 @@ use namada::vm::{WasmCacheAccess, WasmCacheRwAccess}; use namada::vote_ext::EthereumTxData; use namada_apps_lib::wallet::{self, ValidatorData, ValidatorKeys}; use namada_sdk::eth_bridge::{EthBridgeQueries, EthereumOracleConfig}; +use namada_sdk::migrations; +use namada_sdk::migrations::ScheduledMigration; use namada_sdk::tendermint::AppHash; use thiserror::Error; use tokio::sync::mpsc::{Receiver, UnboundedSender}; @@ -351,6 +353,7 @@ where storage_read_past_height_limit: Option, /// Log of events emitted by `FinalizeBlock` ABCI calls. event_log: EventLog, + scheduled_migration: Option>, } /// Storage key filter to store the diffs into the storage. Return `false` for @@ -401,6 +404,7 @@ where broadcast_sender: UnboundedSender>, eth_oracle: Option, db_cache: Option<&D::Cache>, + scheduled_migration: Option>, vp_wasm_compilation_cache: u64, tx_wasm_compilation_cache: u64, ) -> Self { @@ -510,6 +514,17 @@ where TendermintMode::Seed => ShellMode::Seed, }; + if let Some(schedule_migration) = scheduled_migration.as_ref() { + let current = state.get_block_height().unwrap_or_default(); + if schedule_migration.height < current { + panic!( + "Cannot schedule a migration earlier than the latest \ + block height({})", + current + ); + } + } + let mut shell = Self { chain_id, state, @@ -531,6 +546,7 @@ where storage_read_past_height_limit, // TODO(namada#3237): config event log params event_log: EventLog::default(), + scheduled_migration, }; shell.update_eth_oracle(&Default::default()); shell @@ -648,9 +664,14 @@ where self.state .commit_block() .expect("Encountered a storage error while committing a block"); - - let merkle_root = self.state.in_mem().merkle_root(); let committed_height = self.state.in_mem().get_last_block_height(); + self.scheduled_migration = migrations::commit( + self.state.db(), + committed_height, + self.scheduled_migration.take(), + ); + let merkle_root = self.state.in_mem().merkle_root(); + tracing::info!( "Committed block hash: {merkle_root}, height: {committed_height}", ); @@ -1513,6 +1534,7 @@ mod test_utils { sender, Some(eth_oracle), None, + None, vp_wasm_compilation_cache, tx_wasm_compilation_cache, ); diff --git a/crates/node/src/shims/abcipp_shim.rs b/crates/node/src/shims/abcipp_shim.rs index 4583666472..1ba7b2c50f 100644 --- a/crates/node/src/shims/abcipp_shim.rs +++ b/crates/node/src/shims/abcipp_shim.rs @@ -10,6 +10,7 @@ use namada::core::storage::BlockHeight; use namada::proof_of_stake::storage::find_validator_by_raw_hash; use namada::time::{DateTimeUtc, Utc}; use namada::tx::data::hash_tx; +use namada_sdk::migrations::ScheduledMigration; use tokio::sync::broadcast; use tokio::sync::mpsc::UnboundedSender; use tower::Service; @@ -48,6 +49,7 @@ impl AbcippShim { broadcast_sender: UnboundedSender>, eth_oracle: Option, db_cache: &rocksdb::Cache, + scheduled_migration: Option, vp_wasm_compilation_cache: u64, tx_wasm_compilation_cache: u64, ) -> (Self, AbciService, broadcast::Sender<()>) { @@ -65,6 +67,7 @@ impl AbcippShim { broadcast_sender, eth_oracle, Some(db_cache), + scheduled_migration, vp_wasm_compilation_cache, tx_wasm_compilation_cache, ), diff --git a/crates/node/src/storage/rocksdb.rs b/crates/node/src/storage/rocksdb.rs index c5b91e95c8..36a527fa18 100644 --- a/crates/node/src/storage/rocksdb.rs +++ b/crates/node/src/storage/rocksdb.rs @@ -72,7 +72,7 @@ use namada::storage::{ SUBSPACE_CF, }; use namada_sdk::arith::checked; -use namada_sdk::migrations::DBUpdateVisitor; +use namada_sdk::migrations::{DBUpdateVisitor, DbUpdateType}; use rayon::prelude::*; use regex::Regex; use rocksdb::{ @@ -82,6 +82,7 @@ use rocksdb::{ }; use crate::config::utils::num_of_threads; +use crate::storage; // TODO the DB schema will probably need some kind of versioning @@ -695,6 +696,7 @@ impl RocksDB { impl DB for RocksDB { type Cache = rocksdb::Cache; + type Migrator = DbUpdateType; type WriteBatch = RocksDBWriteBatch; fn open( @@ -1402,6 +1404,31 @@ impl DB for RocksDB { Ok(()) } + + #[inline] + fn apply_migration_to_batch( + &self, + updates: impl IntoIterator, + ) -> Result { + let mut db_visitor = storage::RocksDBUpdateVisitor::new(self); + for change in updates.into_iter() { + match change.update(&mut db_visitor) { + Ok(status) => { + tracing::info!("{}", status); + } + Err(e) => { + let error = format!( + "Attempt to write to key/pattern <{}> failed:\n{}.", + change.pattern(), + e + ); + tracing::error!(error); + return Err(Error::DBError(error)); + } + } + } + Ok(db_visitor.take_batch()) + } } /// A struct that can visit a set of updates, diff --git a/crates/sdk/src/migrations.rs b/crates/sdk/src/migrations.rs index 0e2eb1a8c1..172928722c 100644 --- a/crates/sdk/src/migrations.rs +++ b/crates/sdk/src/migrations.rs @@ -6,11 +6,16 @@ use core::fmt::Formatter; use core::fmt::{Display, Formatter}; #[cfg(feature = "migrations")] use core::str::FromStr; +use std::io::Read; +use std::marker::PhantomData; +use std::path::{Path, PathBuf}; use borsh::{BorshDeserialize, BorshSerialize}; use borsh_ext::BorshSerializeExt; use data_encoding::HEXUPPER; -use namada_core::storage::Key; +use eyre::eyre; +use namada_core::hash::Hash; +use namada_core::storage::{BlockHeight, Key}; #[cfg(feature = "migrations")] use namada_macros::derive_borshdeserializer; #[cfg(feature = "migrations")] @@ -19,9 +24,9 @@ use namada_macros::typehash; use namada_migrations::TypeHash; #[cfg(feature = "migrations")] use namada_migrations::*; -use namada_storage::DbColFam; +use namada_storage::{DbColFam, DbMigration, DB}; use regex::Regex; -use serde::de::{Error, Visitor}; +use serde::de::{DeserializeOwned, Error, Visitor}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "migrations")] @@ -35,7 +40,7 @@ pub trait DBUpdateVisitor { fn get_pattern(&self, pattern: Regex) -> Vec<(String, Vec)>; } -#[derive(Clone, BorshSerialize, BorshDeserialize)] +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)] enum UpdateBytes { Raw { to_write: Vec, @@ -46,7 +51,7 @@ enum UpdateBytes { }, } -#[derive(Clone, BorshSerialize, BorshDeserialize)] +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)] /// A value to be added to the database that can be /// validated. pub struct UpdateValue { @@ -171,7 +176,7 @@ impl<'de> Deserialize<'de> for UpdateValue { deserializer.deserialize_any(UpdateValueVisitor) } } -#[derive(Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] /// An update to the database pub enum DbUpdateType { Add { @@ -190,6 +195,8 @@ pub enum DbUpdateType { RepeatDelete(String, DbColFam), } +impl DbMigration for DbUpdateType {} + #[cfg(feature = "migrations")] impl DbUpdateType { /// Get the key or pattern being modified as string @@ -280,7 +287,6 @@ impl DbUpdateType { /// Validate a DB change and persist it if so. The debug representation of /// the new value is returned for logging purposes. - #[allow(dead_code)] pub fn update( &self, db: &mut DB, @@ -352,11 +358,81 @@ impl DbUpdateType { } } -#[derive(Serialize, Deserialize)] -pub struct DbChanges { - pub changes: Vec, +/// A set of key-value changes to be applied to +/// the db at a specified height. +#[derive(Debug, Clone)] +pub struct ScheduledMigration { + /// The height at which to perform the changes + pub height: BlockHeight, + /// The actual set of changes + pub path: PathBuf, + /// A hash of the expected contents in the file + pub hash: Hash, + /// For keeping track of what data type we deserialize the + /// contents of the file to. + phantom: PhantomData, } +impl ScheduledMigration +where + D: DbMigration + DeserializeOwned, +{ + /// Read in a migrations json and a hash to verify the contents + /// against. Also needs a height for which the changes are scheduled. + pub fn from_path( + path: impl AsRef, + hash: Hash, + height: BlockHeight, + ) -> eyre::Result { + let scheduled_migration = Self { + height, + path: path.as_ref().to_path_buf(), + hash, + phantom: Default::default(), + }; + scheduled_migration.validate()?; + Ok(scheduled_migration) + } + + fn load(&self) -> eyre::Result> { + let update_json = self.validate()?; + serde_json::from_str(&update_json) + .map_err(|_| eyre!("Could not parse the updates file as json")) + } + + fn validate(&self) -> eyre::Result { + let mut update_json = String::new(); + let mut file = std::fs::File::open(&self.path).map_err(|_| { + eyre!("Could not fine updates file at the specified path.") + })?; + _ = file + .read_to_string(&mut update_json) + .map_err(|e| eyre!("{}", e))?; + // validate contents against provided hash + if Hash::sha256(update_json.as_bytes()) != self.hash { + Err(eyre!( + "Provided hash did not match the contents at the specified \ + path." + )) + } else { + Ok(update_json) + } + } +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct DbChanges { + pub changes: Vec, +} + +impl IntoIterator for DbChanges { + type IntoIter = std::vec::IntoIter; + type Item = D; + + fn into_iter(self) -> Self::IntoIter { + self.changes.into_iter() + } +} #[cfg(feature = "migrations")] impl Display for DbUpdateType { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { @@ -431,6 +507,46 @@ impl Display for UpdateStatus { } } +/// Check if a scheduled migration should take place at this block height. +/// If so, apply it to the DB. +pub fn commit( + db: &D, + height: BlockHeight, + mut migration: Option>, +) -> Option> +where + D::Migrator: DeserializeOwned, +{ + let maybe_migration = migration.take(); + if let Some(migration) = maybe_migration.as_ref() { + if height != migration.height { + return maybe_migration; + } + } else { + return None; + } + tracing::info!( + "A migration is scheduled to take place at this block height. \ + Starting..." + ); + let migration = maybe_migration.unwrap().load().unwrap(); + + match db.apply_migration_to_batch(migration) { + Ok(batch) => { + tracing::info!("Persisting DB changes..."); + db.exec_batch(batch).expect("Failed to execute write batch"); + } + Err(e) => { + panic!( + "Failed to execute migration, no changes persisted. \ + Encountered error: {}", + e + ); + } + } + None +} + #[cfg(feature = "migrations")] derive_borshdeserializer!(Vec::); #[cfg(feature = "migrations")] diff --git a/crates/storage/src/db.rs b/crates/storage/src/db.rs index afaec5d230..676c497e24 100644 --- a/crates/storage/src/db.rs +++ b/crates/storage/src/db.rs @@ -14,6 +14,8 @@ use namada_merkle_tree::{ StoreType, }; use regex::Regex; +use serde::de::DeserializeOwned; +use serde::Serialize; use thiserror::Error; use crate::conversion_state::ConversionState; @@ -122,6 +124,10 @@ pub trait DB: Debug { /// A handle for batch writes type WriteBatch: DBWriteBatch; + /// A type that can apply a key-value + /// change to DB. + type Migrator: DbMigration + DeserializeOwned; + /// Open the database from provided path fn open( db_path: impl AsRef, @@ -277,6 +283,15 @@ pub trait DB: Debug { key: &Key, new_value: impl AsRef<[u8]>, ) -> Result<()>; + + /// Apply a series of key-value changes + /// to the DB. + fn apply_migration_to_batch( + &self, + _updates: impl IntoIterator, + ) -> Result { + unimplemented!() + } } /// A database prefix iterator. @@ -329,3 +344,8 @@ pub trait DBIter<'iter> { /// Atomic batch write. pub trait DBWriteBatch {} + +/// A type that can apply a key-value change to a DB +pub trait DbMigration: Debug + Clone + Serialize {} + +impl DbMigration for () {} diff --git a/crates/storage/src/mockdb.rs b/crates/storage/src/mockdb.rs index 20432d37ff..1de9122307 100644 --- a/crates/storage/src/mockdb.rs +++ b/crates/storage/src/mockdb.rs @@ -91,6 +91,7 @@ impl MockDB { impl DB for MockDB { /// There is no cache for MockDB type Cache = (); + type Migrator = (); type WriteBatch = MockDBWriteBatch; fn open(_db_path: impl AsRef, _cache: Option<&Self::Cache>) -> Self { diff --git a/crates/tests/src/integration/setup.rs b/crates/tests/src/integration/setup.rs index 448ef59c08..441273e71e 100644 --- a/crates/tests/src/integration/setup.rs +++ b/crates/tests/src/integration/setup.rs @@ -211,6 +211,7 @@ fn create_node( shell_handlers.tx_broadcaster, shell_handlers.eth_oracle_channels, None, + None, 50 * 1024 * 1024, // 50 kiB 50 * 1024 * 1024, // 50 kiB ))), From 1d828e01ec416d0085abf38c56ee0da227766c68 Mon Sep 17 00:00:00 2001 From: satan Date: Fri, 24 May 2024 16:30:59 +0200 Subject: [PATCH 54/70] changelog --- .../unreleased/improvements/3310-scheduled-migrations.md | 3 +++ crates/storage/src/db.rs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .changelog/unreleased/improvements/3310-scheduled-migrations.md diff --git a/.changelog/unreleased/improvements/3310-scheduled-migrations.md b/.changelog/unreleased/improvements/3310-scheduled-migrations.md new file mode 100644 index 0000000000..20c5dbb41d --- /dev/null +++ b/.changelog/unreleased/improvements/3310-scheduled-migrations.md @@ -0,0 +1,3 @@ +- Allow nodes to schedule a migrations json to be read and run to facilitate hard-forking. This is done by + taking a migrations json and passing the path, a hash of the contents, and a block height to the node when + starting the ledger. ([\#3310](https://github.com/anoma/namada/pull/3310)) \ No newline at end of file diff --git a/crates/storage/src/db.rs b/crates/storage/src/db.rs index 676c497e24..2483ee850d 100644 --- a/crates/storage/src/db.rs +++ b/crates/storage/src/db.rs @@ -153,7 +153,7 @@ pub trait DB: Debug { fn read_block_header(&self, height: BlockHeight) -> Result>; /// Read the merkle tree stores with the given epoch. If a store_type is - /// given, it reads only the the specified tree. Otherwise, it reads all + /// given, it reads only the specified tree. Otherwise, it reads all /// trees. fn read_merkle_tree_stores( &self, From 540e8533be86345c122c8f46b0ec9862aa986ffd Mon Sep 17 00:00:00 2001 From: satan Date: Fri, 24 May 2024 16:43:22 +0200 Subject: [PATCH 55/70] Fix typo --- crates/apps_lib/src/cli.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/apps_lib/src/cli.rs b/crates/apps_lib/src/cli.rs index b853d34b10..62ebb3afa6 100644 --- a/crates/apps_lib/src/cli.rs +++ b/crates/apps_lib/src/cli.rs @@ -3388,7 +3388,7 @@ pub mod args { .requires(PATH_OPT.name) .requires(BLOCK_HEIGHT_OPT.name) .help(wrap!( - "Hash to verify contents of optinally provided \ + "Hash to verify contents of optionally provided \ migrations file." )), ) From eff67bb878ea960c205df621f990f3da77029ee0 Mon Sep 17 00:00:00 2001 From: Murisi Tarusenga Date: Wed, 22 May 2024 18:24:34 +0200 Subject: [PATCH 56/70] Start including MASP randomness in the test vectors. --- Cargo.lock | 7 ++++--- Cargo.toml | 4 ++-- crates/sdk/src/lib.rs | 8 ++++++-- crates/sdk/src/masp.rs | 22 +++++++++++++--------- examples/Cargo.toml | 1 + examples/tx_schema.rs | 2 ++ wasm/Cargo.lock | 6 +++--- wasm_for_tests/Cargo.lock | 6 +++--- 8 files changed, 34 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 49188b7254..d04ce78bd1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4141,7 +4141,7 @@ dependencies = [ [[package]] name = "masp_note_encryption" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=4ede1c42d76d6348af8224bc8bfac4404321fe82#4ede1c42d76d6348af8224bc8bfac4404321fe82" dependencies = [ "borsh 1.2.1", "chacha20", @@ -4154,7 +4154,7 @@ dependencies = [ [[package]] name = "masp_primitives" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=4ede1c42d76d6348af8224bc8bfac4404321fe82#4ede1c42d76d6348af8224bc8bfac4404321fe82" dependencies = [ "aes", "bip0039", @@ -4186,7 +4186,7 @@ dependencies = [ [[package]] name = "masp_proofs" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=4ede1c42d76d6348af8224bc8bfac4404321fe82#4ede1c42d76d6348af8224bc8bfac4404321fe82" dependencies = [ "bellman", "blake2b_simd", @@ -4699,6 +4699,7 @@ version = "0.36.1" dependencies = [ "borsh 1.2.1", "data-encoding", + "masp_primitives", "masp_proofs", "namada_apps_lib", "namada_macros", diff --git a/Cargo.toml b/Cargo.toml index eef45461eb..1f9c58f492 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -125,8 +125,8 @@ libc = "0.2.97" libloading = "0.7.2" linkme = "0.3.24" # branch = "main" -masp_primitives = { git = "https://github.com/anoma/masp", rev = "3aacc707c5948e7423589ac617305448bead9842" } -masp_proofs = { git = "https://github.com/anoma/masp", rev = "3aacc707c5948e7423589ac617305448bead9842", default-features = false, features = ["local-prover"] } +masp_primitives = { git = "https://github.com/anoma/masp", rev = "4ede1c42d76d6348af8224bc8bfac4404321fe82" } +masp_proofs = { git = "https://github.com/anoma/masp", rev = "4ede1c42d76d6348af8224bc8bfac4404321fe82", default-features = false, features = ["local-prover"] } num256 = "0.3.5" num_cpus = "1.13.0" num-derive = "0.4" diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs index f1d6d672ee..2d6c060c4d 100644 --- a/crates/sdk/src/lib.rs +++ b/crates/sdk/src/lib.rs @@ -801,6 +801,7 @@ pub mod testing { use borsh_ext::BorshSerializeExt; use governance::ProposalType; use ibc::primitives::proto::Any; + use masp_primitives::transaction::components::sapling::builder::StoredBuildParams; use masp_primitives::transaction::TransparentAddress; use namada_account::{InitAccount, UpdateAccount}; use namada_core::address::testing::{ @@ -870,6 +871,7 @@ pub mod testing { VoteProposal(VoteProposalData), Withdraw(Withdraw), Transfer(Transfer), + MaspTransfer(Transfer, (StoredBuildParams, String)), Bond(Bond), Redelegation(Redelegation), UpdateStewardCommission(UpdateStewardCommission), @@ -1067,7 +1069,7 @@ pub mod testing { mut header in arb_header(), wrapper in arb_wrapper_tx(), code_hash in arb_hash(), - (masp_tx_type, (shielded_transfer, asset_types)) in prop_oneof![ + (masp_tx_type, (shielded_transfer, asset_types, build_params)) in prop_oneof![ (Just(MaspTxType::Shielded), arb_shielded_transfer(0..MAX_ASSETS)), (Just(MaspTxType::Shielding), arb_shielding_transfer(encode_address(&transfer.source), 1)), (Just(MaspTxType::Deshielding), arb_deshielding_transfer(encode_address(&transfer.target), 1)), @@ -1116,7 +1118,9 @@ pub mod testing { // Link the Builder to the Transaction by hash code target: masp_tx_hash, }); - (tx, TxData::Transfer(transfer)) + let build_param_bytes = + data_encoding::HEXLOWER.encode(&build_params.serialize_to_vec()); + (tx, TxData::MaspTransfer(transfer, (build_params, build_param_bytes))) } } diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 7247d3e2c5..9b10163a24 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -2219,6 +2219,7 @@ pub mod testing { use masp_primitives::sapling::prover::TxProver; use masp_primitives::sapling::redjubjub::Signature; use masp_primitives::sapling::{ProofGenerationKey, Rseed}; + use masp_primitives::transaction::components::sapling::builder::StoredBuildParams; use masp_primitives::transaction::components::GROTH_PROOF_SIZE; use masp_proofs::bellman::groth16::Proof; use proptest::prelude::*; @@ -2990,19 +2991,20 @@ pub mod testing { prover_rng in arb_rng().prop_map(TestCsprng), mut rng in arb_rng().prop_map(TestCsprng), bparams_rng in arb_rng().prop_map(TestCsprng), - ) -> (ShieldedTransfer, HashMap) { + ) -> (ShieldedTransfer, HashMap, StoredBuildParams) { + let mut rng_build_params = RngBuildParams::new(bparams_rng); let (masp_tx, metadata) = builder.clone().build( &MockTxProver(Mutex::new(prover_rng)), &FeeRule::non_standard(U64Sum::zero()), &mut rng, - &mut RngBuildParams::new(bparams_rng), + &mut rng_build_params, ).unwrap(); (ShieldedTransfer { builder: builder.map_builder(WalletMap), metadata, masp_tx, epoch, - }, asset_types) + }, asset_types, rng_build_params.to_stored().unwrap()) } } @@ -3020,19 +3022,20 @@ pub mod testing { prover_rng in arb_rng().prop_map(TestCsprng), mut rng in arb_rng().prop_map(TestCsprng), bparams_rng in arb_rng().prop_map(TestCsprng), - ) -> (ShieldedTransfer, HashMap) { + ) -> (ShieldedTransfer, HashMap, StoredBuildParams) { + let mut rng_build_params = RngBuildParams::new(bparams_rng); let (masp_tx, metadata) = builder.clone().build( &MockTxProver(Mutex::new(prover_rng)), &FeeRule::non_standard(U64Sum::zero()), &mut rng, - &mut RngBuildParams::new(bparams_rng), + &mut rng_build_params, ).unwrap(); (ShieldedTransfer { builder: builder.map_builder(WalletMap), metadata, masp_tx, epoch, - }, asset_types) + }, asset_types, rng_build_params.to_stored().unwrap()) } } @@ -3050,19 +3053,20 @@ pub mod testing { prover_rng in arb_rng().prop_map(TestCsprng), mut rng in arb_rng().prop_map(TestCsprng), bparams_rng in arb_rng().prop_map(TestCsprng), - ) -> (ShieldedTransfer, HashMap) { + ) -> (ShieldedTransfer, HashMap, StoredBuildParams) { + let mut rng_build_params = RngBuildParams::new(bparams_rng); let (masp_tx, metadata) = builder.clone().build( &MockTxProver(Mutex::new(prover_rng)), &FeeRule::non_standard(U64Sum::zero()), &mut rng, - &mut RngBuildParams::new(bparams_rng), + &mut rng_build_params, ).unwrap(); (ShieldedTransfer { builder: builder.map_builder(WalletMap), metadata, masp_tx, epoch, - }, asset_types) + }, asset_types, rng_build_params.to_stored().unwrap()) } } } diff --git a/examples/Cargo.toml b/examples/Cargo.toml index a95700f17a..d5303d31fd 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -28,6 +28,7 @@ path = "make-db-migration.rs" namada-eth-bridge = ["namada_sdk/namada-eth-bridge"] [dev-dependencies] +masp_primitives = { workspace = true, features = ["transparent-inputs"] } masp_proofs = { workspace = true, default-features = false, features = ["local-prover", "download-params"] } namada_apps_lib = {path = "../crates/apps_lib", features = ["migrations"]} namada_macros = {path = "../crates/macros"} diff --git a/examples/tx_schema.rs b/examples/tx_schema.rs index e3d678eefe..1fcf24e162 100644 --- a/examples/tx_schema.rs +++ b/examples/tx_schema.rs @@ -1,6 +1,7 @@ use std::collections::BTreeMap; use std::error::Error; +use masp_primitives::transaction::components::sapling::builder::StoredBuildParams; use namada_sdk::borsh::BorshSchema; use namada_sdk::tx::Tx; @@ -12,6 +13,7 @@ fn main() -> Result<(), Box> { } let mut definitions = BTreeMap::new(); Tx::add_definitions_recursively(&mut definitions); + StoredBuildParams::add_definitions_recursively(&mut definitions); std::fs::write(&args[1], format!("{:#?}", definitions)) .expect("unable to save schema"); Ok(()) diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 71e195bbf1..0c8c434430 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -3384,7 +3384,7 @@ dependencies = [ [[package]] name = "masp_note_encryption" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=4ede1c42d76d6348af8224bc8bfac4404321fe82#4ede1c42d76d6348af8224bc8bfac4404321fe82" dependencies = [ "borsh 1.4.0", "chacha20", @@ -3397,7 +3397,7 @@ dependencies = [ [[package]] name = "masp_primitives" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=4ede1c42d76d6348af8224bc8bfac4404321fe82#4ede1c42d76d6348af8224bc8bfac4404321fe82" dependencies = [ "aes", "bip0039", @@ -3429,7 +3429,7 @@ dependencies = [ [[package]] name = "masp_proofs" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=4ede1c42d76d6348af8224bc8bfac4404321fe82#4ede1c42d76d6348af8224bc8bfac4404321fe82" dependencies = [ "bellman", "blake2b_simd", diff --git a/wasm_for_tests/Cargo.lock b/wasm_for_tests/Cargo.lock index aacadf28d1..2403064f78 100644 --- a/wasm_for_tests/Cargo.lock +++ b/wasm_for_tests/Cargo.lock @@ -3364,7 +3364,7 @@ dependencies = [ [[package]] name = "masp_note_encryption" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=4ede1c42d76d6348af8224bc8bfac4404321fe82#4ede1c42d76d6348af8224bc8bfac4404321fe82" dependencies = [ "borsh 1.2.1", "chacha20", @@ -3377,7 +3377,7 @@ dependencies = [ [[package]] name = "masp_primitives" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=4ede1c42d76d6348af8224bc8bfac4404321fe82#4ede1c42d76d6348af8224bc8bfac4404321fe82" dependencies = [ "aes", "bip0039", @@ -3409,7 +3409,7 @@ dependencies = [ [[package]] name = "masp_proofs" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=3aacc707c5948e7423589ac617305448bead9842#3aacc707c5948e7423589ac617305448bead9842" +source = "git+https://github.com/anoma/masp?rev=4ede1c42d76d6348af8224bc8bfac4404321fe82#4ede1c42d76d6348af8224bc8bfac4404321fe82" dependencies = [ "bellman", "blake2b_simd", From 1a0f24d2f081ee287cbf8f518c0781a9a4f74dc3 Mon Sep 17 00:00:00 2001 From: Murisi Tarusenga Date: Mon, 27 May 2024 11:08:59 +0200 Subject: [PATCH 57/70] Added a changelog entry. --- .../improvements/3296-test-vectors-with-randomness2.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/3296-test-vectors-with-randomness2.md diff --git a/.changelog/unreleased/improvements/3296-test-vectors-with-randomness2.md b/.changelog/unreleased/improvements/3296-test-vectors-with-randomness2.md new file mode 100644 index 0000000000..48ae627d24 --- /dev/null +++ b/.changelog/unreleased/improvements/3296-test-vectors-with-randomness2.md @@ -0,0 +1,2 @@ +- Include the used MASP randomness parameters in the test vectors. + ([\#3296](https://github.com/anoma/namada/pull/3296)) \ No newline at end of file From c75f3e253314b90a53b85a81a7ceba68c2fef122 Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli Date: Mon, 27 May 2024 12:39:28 +0200 Subject: [PATCH 58/70] export more ibc storage keys to wasm --- crates/tx_prelude/src/ibc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/tx_prelude/src/ibc.rs b/crates/tx_prelude/src/ibc.rs index a52f10038e..14a289f23a 100644 --- a/crates/tx_prelude/src/ibc.rs +++ b/crates/tx_prelude/src/ibc.rs @@ -9,7 +9,7 @@ use namada_core::token::Amount; use namada_events::EventTypeBuilder; pub use namada_ibc::event::{IbcEvent, IbcEventType}; pub use namada_ibc::storage::{ - burn_tokens, ibc_token, is_ibc_key, mint_tokens, + burn_tokens, ibc_token, is_ibc_key, mint_tokens, mint_limit_key, throughput_limit_key }; pub use namada_ibc::{ IbcActions, IbcCommonContext, IbcStorageContext, NftTransferModule, From 54c555d06bbf604425a7165fa10964a843defc93 Mon Sep 17 00:00:00 2001 From: yito88 Date: Mon, 27 May 2024 13:07:15 +0200 Subject: [PATCH 59/70] store ibc traces when minting --- crates/ibc/src/actions.rs | 19 +-- crates/ibc/src/context/nft_transfer.rs | 24 +++ crates/ibc/src/context/storage.rs | 6 - crates/ibc/src/context/token_transfer.rs | 30 ++++ crates/ibc/src/event.rs | 59 +------ crates/ibc/src/lib.rs | 159 +----------------- .../src/ledger/native_vp/ibc/context.rs | 32 +--- crates/tx_prelude/src/ibc.rs | 15 -- 8 files changed, 60 insertions(+), 284 deletions(-) diff --git a/crates/ibc/src/actions.rs b/crates/ibc/src/actions.rs index 24a13a35bf..4676721c49 100644 --- a/crates/ibc/src/actions.rs +++ b/crates/ibc/src/actions.rs @@ -13,7 +13,7 @@ use namada_core::ibc::core::channel::types::timeout::TimeoutHeight; use namada_core::ibc::MsgTransfer; use namada_core::tendermint::Time as TmTime; use namada_core::token::Amount; -use namada_events::{EmitEvents, EventTypeBuilder}; +use namada_events::EmitEvents; use namada_governance::storage::proposal::PGFIbcTarget; use namada_parameters::read_epoch_duration_parameter; use namada_state::{ @@ -124,23 +124,6 @@ where Ok(()) } - /// Get IBC events - fn get_ibc_events( - &self, - event_type: impl AsRef, - ) -> Result, StorageError> { - let event_type = EventTypeBuilder::new_of::() - .with_segment(event_type) - .build(); - - Ok(self - .state - .write_log() - .lookup_events_with_prefix(&event_type) - .filter_map(|event| IbcEvent::try_from(event).ok()) - .collect()) - } - /// Transfer token fn transfer_token( &mut self, diff --git a/crates/ibc/src/context/nft_transfer.rs b/crates/ibc/src/context/nft_transfer.rs index ef06b05ed7..2ac019bf6f 100644 --- a/crates/ibc/src/context/nft_transfer.rs +++ b/crates/ibc/src/context/nft_transfer.rs @@ -89,6 +89,26 @@ where .store_withdraw(token, added_withdraw) .map_err(NftTransferError::from) } + + fn store_ibc_trace( + &self, + owner: &Address, + class_id: &PrefixedClassId, + token_id: &TokenId, + ) -> Result<(), NftTransferError> { + let ibc_trace = format!("{class_id}/{token_id}"); + let trace_hash = storage::calc_hash(&ibc_trace); + + self.inner + .borrow_mut() + .store_ibc_trace(owner.to_string(), &trace_hash, &ibc_trace) + .map_err(NftTransferError::from)?; + + self.inner + .borrow_mut() + .store_ibc_trace(token_id, &trace_hash, &ibc_trace) + .map_err(NftTransferError::from) + } } impl NftTransferValidationContext for NftTransferContext @@ -342,6 +362,10 @@ where self.update_mint_amount(&ibc_token, true)?; self.add_deposit(&ibc_token)?; + // Store the IBC trace with the token hash to be able to retrieve it + // later + self.store_ibc_trace(account, class_id, token_id)?; + self.inner .borrow_mut() .mint_token(account, &ibc_token, Amount::from_u64(1)) diff --git a/crates/ibc/src/context/storage.rs b/crates/ibc/src/context/storage.rs index 4db283e567..a33b2621fd 100644 --- a/crates/ibc/src/context/storage.rs +++ b/crates/ibc/src/context/storage.rs @@ -12,12 +12,6 @@ pub trait IbcStorageContext: StorageRead + StorageWrite { /// Emit an IBC event fn emit_ibc_event(&mut self, event: IbcEvent) -> Result<(), Error>; - /// Get IBC events - fn get_ibc_events( - &self, - event_type: impl AsRef, - ) -> Result, Error>; - /// Transfer token fn transfer_token( &mut self, diff --git a/crates/ibc/src/context/token_transfer.rs b/crates/ibc/src/context/token_transfer.rs index 94410c5673..be37122e57 100644 --- a/crates/ibc/src/context/token_transfer.rs +++ b/crates/ibc/src/context/token_transfer.rs @@ -141,6 +141,32 @@ where .store_withdraw(token, added_withdraw) .map_err(TokenTransferError::from) } + + fn store_ibc_denom( + &self, + owner: &Address, + coin: &PrefixedCoin, + ) -> Result<(), TokenTransferError> { + if coin.denom.trace_path.is_empty() { + // It isn't an IBC denom + return Ok(()); + } + let ibc_denom = coin.denom.to_string(); + let trace_hash = storage::calc_hash(&ibc_denom); + + self.inner + .borrow_mut() + .store_ibc_trace(owner.to_string(), &trace_hash, &ibc_denom) + .map_err(TokenTransferError::from)?; + + let base_token = Address::decode(coin.denom.base_denom.as_str()) + .map(|a| a.to_string()) + .unwrap_or(coin.denom.base_denom.to_string()); + self.inner + .borrow_mut() + .store_ibc_trace(base_token, &trace_hash, &ibc_denom) + .map_err(TokenTransferError::from) + } } impl TokenTransferValidationContext for TokenTransferContext @@ -277,6 +303,10 @@ where self.insert_verifier(&ibc_token); } + // Store the IBC denom with the token hash to be able to retrieve it + // later + self.store_ibc_denom(account, coin)?; + self.inner .borrow_mut() .mint_token(account, &ibc_token, amount) diff --git a/crates/ibc/src/event.rs b/crates/ibc/src/event.rs index 7bd613e881..5e19292686 100644 --- a/crates/ibc/src/event.rs +++ b/crates/ibc/src/event.rs @@ -19,7 +19,7 @@ use namada_core::ibc::core::host::types::identifiers::{ use namada_core::ibc::primitives::Timestamp; use namada_core::tendermint::abci::Event as AbciEvent; use namada_events::extend::{ - event_domain_of, AttributesMap, EventAttributeEntry, ExtendAttributesMap, + event_domain_of, AttributesMap, EventAttributeEntry, ReadFromEventAttributes as _, }; use namada_events::{ @@ -140,63 +140,6 @@ pub struct IbcEvent { pub attributes: HashMap, } -fn validate_ibc_event_type( - namada_event: &Event, -) -> Result { - if namada_event.kind().domain() != IbcEvent::DOMAIN { - return Err(EventError::InvalidEventType); - } - - let event_type = namada_event.kind().sub_domain(); - - // TODO(namada#3229): validate IBC event types. eg: - // - // ```ignore - // if !matches!( - // event_type, - // "update_client" | "send_packet" | "write_acknowledgement" - // ) { - // return Err(EventError::InvalidEventType); - // } - // ``` - - Ok(IbcEventType(event_type.to_owned())) -} - -impl TryFrom<&Event> for IbcEvent { - type Error = EventError; - - fn try_from( - namada_event: &Event, - ) -> std::result::Result { - Ok(Self { - event_type: validate_ibc_event_type(namada_event)?, - #[allow(deprecated)] - attributes: namada_event - .attributes() - .iter() - .map(|(k, v)| (k.clone(), v.clone())) - .collect(), - }) - } -} - -impl TryFrom for IbcEvent { - type Error = EventError; - - fn try_from(namada_event: Event) -> std::result::Result { - Ok(Self { - event_type: validate_ibc_event_type(&namada_event)?, - attributes: { - let mut attrs: HashMap<_, _> = - namada_event.into_attributes().into_iter().collect(); - attrs.with_attribute(event_domain_of::()); - attrs - }, - }) - } -} - impl std::cmp::PartialOrd for IbcEvent { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index fc79cfd566..7500d7ccda 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -39,12 +39,11 @@ pub use context::token_transfer::TokenTransferContext; pub use context::transfer_mod::{ModuleWrapper, TransferModule}; use context::IbcContext; pub use context::ValidationParams; -use namada_core::address::{Address, MASP}; +use namada_core::address::Address; use namada_core::ibc::apps::nft_transfer::handler::{ send_nft_transfer_execute, send_nft_transfer_validate, }; use namada_core::ibc::apps::nft_transfer::types::error::NftTransferError; -use namada_core::ibc::apps::nft_transfer::types::packet::PacketData as NftPacketData; use namada_core::ibc::apps::nft_transfer::types::{ is_receiver_chain_source as is_nft_receiver_chain_source, PrefixedClassId, TokenId, TracePrefix as NftTracePrefix, @@ -53,16 +52,13 @@ use namada_core::ibc::apps::transfer::handler::{ send_transfer_execute, send_transfer_validate, }; use namada_core::ibc::apps::transfer::types::error::TokenTransferError; -use namada_core::ibc::apps::transfer::types::packet::PacketData; use namada_core::ibc::apps::transfer::types::{ is_receiver_chain_source, TracePrefix, }; use namada_core::ibc::core::channel::types::acknowledgement::{ Acknowledgement, AcknowledgementStatus, }; -use namada_core::ibc::core::channel::types::msgs::{ - MsgRecvPacket as IbcMsgRecvPacket, PacketMsg, -}; +use namada_core::ibc::core::channel::types::msgs::PacketMsg; use namada_core::ibc::core::entrypoint::{execute, validate}; use namada_core::ibc::core::handler::types::error::ContextError; use namada_core::ibc::core::handler::types::events::Error as RawIbcEventError; @@ -72,8 +68,6 @@ use namada_core::ibc::core::host::types::identifiers::{ChannelId, PortId}; use namada_core::ibc::core::router::types::error::RouterError; use namada_core::ibc::primitives::proto::Any; pub use namada_core::ibc::*; -use namada_core::masp::PaymentAddress; -use namada_events::extend::{ReadFromEventAttributes, Success as SuccessAttr}; use namada_token::Transfer; use prost::Message; use thiserror::Error; @@ -175,16 +169,7 @@ where MsgEnvelope::Packet(PacketMsg::Recv(msg.message.clone())); execute(&mut self.ctx, &mut self.router, envelope) .map_err(|e| Error::Context(Box::new(e)))?; - let transfer = if self.is_receiving_success()? { - // the current ibc-rs execution doesn't store the denom - // for the token hash when transfer with MsgRecvPacket - self.store_trace(&msg.message)?; - // For receiving the token to a shielded address - msg.transfer.clone() - } else { - None - }; - Ok(transfer) + Ok(msg.transfer.clone()) } IbcMessage::AckPacket(msg) => { let envelope = @@ -211,149 +196,11 @@ where IbcMessage::Envelope(envelope) => { execute(&mut self.ctx, &mut self.router, *envelope.clone()) .map_err(|e| Error::Context(Box::new(e)))?; - if let MsgEnvelope::Packet(PacketMsg::Recv(msg)) = &**envelope { - if self.is_receiving_success()? { - // the current ibc-rs execution doesn't store the denom - // for the token hash when transfer with MsgRecvPacket - self.store_trace(msg)?; - } - } Ok(None) } } } - /// Store the trace path when transfer with MsgRecvPacket - fn store_trace(&mut self, msg: &IbcMsgRecvPacket) -> Result<(), Error> { - // Get the IBC trace, and the receiver from the packet data - let minted_token_info = if let Ok(data) = - serde_json::from_slice::(&msg.packet.data) - { - let ibc_denom = received_ibc_trace( - data.token.denom.to_string(), - &msg.packet.port_id_on_a, - &msg.packet.chan_id_on_a, - &msg.packet.port_id_on_b, - &msg.packet.chan_id_on_b, - )?; - if !ibc_denom.contains('/') { - // Skip to store it because the token has been redeemed - return Ok(()); - } - let receiver = - if data.receiver.as_ref().parse::().is_ok() { - MASP.to_string() - } else { - data.receiver.to_string() - }; - Some((vec![ibc_denom], receiver)) - } else if let Ok(data) = - serde_json::from_slice::(&msg.packet.data) - { - let ibc_traces: Result, _> = data - .token_ids - .0 - .iter() - .map(|id| { - let trace = format!("{}/{id}", data.class_id); - received_ibc_trace( - trace, - &msg.packet.port_id_on_a, - &msg.packet.chan_id_on_a, - &msg.packet.port_id_on_b, - &msg.packet.chan_id_on_b, - ) - }) - .collect(); - let receiver = - if data.receiver.as_ref().parse::().is_ok() { - MASP.to_string() - } else { - data.receiver.to_string() - }; - Some((ibc_traces?, receiver)) - } else { - None - }; - - if let Some((ibc_traces, receiver)) = minted_token_info { - // If the trace event has the trace hash and the IBC denom or NFT - // IDs, a token has been minted. The raw IBC trace including the - // port ID, the channel ID and the base token is stored to be - // restored from the trace hash. - for ibc_trace in ibc_traces { - let trace_hash = storage::calc_hash(&ibc_trace); - self.ctx - .inner - .borrow_mut() - .store_ibc_trace(&receiver, &trace_hash, &ibc_trace) - .map_err(|e| { - Error::Trace(format!( - "Writing the IBC trace failed: {}", - e - )) - })?; - let base_token = if let Some((_, base_token)) = - is_ibc_denom(&ibc_trace) - { - base_token - } else if let Some((_, _, token_id)) = is_nft_trace(&ibc_trace) - { - token_id - } else { - // non-prefixed denom - continue; - }; - self.ctx - .inner - .borrow_mut() - .store_ibc_trace(base_token, trace_hash, &ibc_trace) - .map_err(|e| { - Error::Trace(format!( - "Writing the IBC trace failed: {}", - e - )) - })?; - } - } - Ok(()) - } - - /// Check the result of receiving the packet from IBC events - fn is_receiving_success(&self) -> Result { - let mut receive_event = self - .ctx - .inner - .borrow() - .get_ibc_events(EVENT_TYPE_PACKET) - .map_err(|_| { - Error::Trace("Reading the IBC event failed".to_string()) - })?; - if receive_event.is_empty() { - // check the packet is for an NFT - receive_event = self - .ctx - .inner - .borrow() - .get_ibc_events(EVENT_TYPE_NFT_PACKET) - .map_err(|_| { - Error::Trace("Reading the IBC event failed".to_string()) - })?; - } - receive_event.first().as_ref().map_or_else( - || Ok(false), - |event| { - let success = SuccessAttr::read_opt_from_event_attributes( - &event.attributes, - ) - .map_err(|err| { - Error::Trace(format!("Reading the IBC event failed: {err}")) - })?; - Ok(success.unwrap_or(false)) - }, - ) - } - /// Validate according to the message in IBC VP pub fn validate(&self, tx_data: &[u8]) -> Result<(), Error> { // Use an empty verifiers set placeholder for validation, this is only diff --git a/crates/namada/src/ledger/native_vp/ibc/context.rs b/crates/namada/src/ledger/native_vp/ibc/context.rs index ab6832c92e..0baaad84c1 100644 --- a/crates/namada/src/ledger/native_vp/ibc/context.rs +++ b/crates/namada/src/ledger/native_vp/ibc/context.rs @@ -9,8 +9,7 @@ use namada_core::storage::Epochs; use namada_gas::MEMORY_ACCESS_GAS_PER_BYTE; use namada_ibc::event::IbcEvent; use namada_ibc::{IbcCommonContext, IbcStorageContext}; -use namada_sdk::events::log::dumb_queries; -use namada_sdk::events::{Event, EventTypeBuilder}; +use namada_sdk::events::Event; use namada_state::{StateRead, StorageError, StorageRead, StorageWrite}; use namada_vp_env::VpEnv; @@ -195,28 +194,6 @@ where Ok(()) } - fn get_ibc_events( - &self, - event_type: impl AsRef, - ) -> Result> { - let matcher = dumb_queries::QueryMatcher::with_prefix( - EventTypeBuilder::new_of::() - .with_segment(event_type) - .build(), - ); - Ok(self - .event - .iter() - .filter_map(|event| { - if matcher.matches(event) { - IbcEvent::try_from(event).ok() - } else { - None - } - }) - .collect()) - } - fn transfer_token( &mut self, src: &Address, @@ -376,13 +353,6 @@ where unimplemented!("Validation doesn't emit an event") } - fn get_ibc_events( - &self, - _event_type: impl AsRef, - ) -> Result> { - unimplemented!("Validation doesn't get an event") - } - fn transfer_token( &mut self, _src: &Address, diff --git a/crates/tx_prelude/src/ibc.rs b/crates/tx_prelude/src/ibc.rs index a52f10038e..5b773e54d6 100644 --- a/crates/tx_prelude/src/ibc.rs +++ b/crates/tx_prelude/src/ibc.rs @@ -6,7 +6,6 @@ use std::rc::Rc; use namada_core::address::Address; use namada_core::token::Amount; -use namada_events::EventTypeBuilder; pub use namada_ibc::event::{IbcEvent, IbcEventType}; pub use namada_ibc::storage::{ burn_tokens, ibc_token, is_ibc_key, mint_tokens, @@ -42,20 +41,6 @@ impl IbcStorageContext for Ctx { ::emit_event(self, event) } - fn get_ibc_events( - &self, - event_type: impl AsRef, - ) -> Result, Error> { - let event_type = EventTypeBuilder::new_of::() - .with_segment(event_type.as_ref()) - .build(); - - Ok(::get_events(self, &event_type)? - .into_iter() - .filter_map(|event| IbcEvent::try_from(event).ok()) - .collect()) - } - fn transfer_token( &mut self, src: &Address, From 98bf4e43105e87f4a7a89fa7b8d04e96d472eb1b Mon Sep 17 00:00:00 2001 From: yito88 Date: Mon, 27 May 2024 21:14:33 +0200 Subject: [PATCH 60/70] new is_receiving_success --- crates/ibc/src/lib.rs | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index 7500d7ccda..65be208679 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -53,12 +53,15 @@ use namada_core::ibc::apps::transfer::handler::{ }; use namada_core::ibc::apps::transfer::types::error::TokenTransferError; use namada_core::ibc::apps::transfer::types::{ - is_receiver_chain_source, TracePrefix, + ack_success_b64, is_receiver_chain_source, TracePrefix, }; use namada_core::ibc::core::channel::types::acknowledgement::{ Acknowledgement, AcknowledgementStatus, }; -use namada_core::ibc::core::channel::types::msgs::PacketMsg; +use namada_core::ibc::core::channel::types::commitment::compute_ack_commitment; +use namada_core::ibc::core::channel::types::msgs::{ + MsgRecvPacket as IbcMsgRecvPacket, PacketMsg, +}; use namada_core::ibc::core::entrypoint::{execute, validate}; use namada_core::ibc::core::handler::types::error::ContextError; use namada_core::ibc::core::handler::types::events::Error as RawIbcEventError; @@ -169,7 +172,13 @@ where MsgEnvelope::Packet(PacketMsg::Recv(msg.message.clone())); execute(&mut self.ctx, &mut self.router, envelope) .map_err(|e| Error::Context(Box::new(e)))?; - Ok(msg.transfer.clone()) + let transfer = if self.is_receiving_success(&msg.message)? { + // For receiving the token to a shielded address + msg.transfer.clone() + } else { + None + }; + Ok(transfer) } IbcMessage::AckPacket(msg) => { let envelope = @@ -201,6 +210,28 @@ where } } + /// Check the result of receiving the packet by checking the packet + /// acknowledgement + fn is_receiving_success( + &self, + msg: &IbcMsgRecvPacket, + ) -> Result { + let packet_ack = self + .ctx + .inner + .borrow() + .packet_ack( + &msg.packet.port_id_on_b, + &msg.packet.chan_id_on_b, + msg.packet.seq_on_a, + ) + .map_err(|e| Error::Context(Box::new(e)))?; + let success_ack_commitment = compute_ack_commitment( + &AcknowledgementStatus::success(ack_success_b64()).into(), + ); + Ok(packet_ack == success_ack_commitment) + } + /// Validate according to the message in IBC VP pub fn validate(&self, tx_data: &[u8]) -> Result<(), Error> { // Use an empty verifiers set placeholder for validation, this is only From 53b208b68559d161893ae55dd365e4ecf21eeece Mon Sep 17 00:00:00 2001 From: yito88 Date: Mon, 27 May 2024 21:52:01 +0200 Subject: [PATCH 61/70] add changelog --- .../improvements/3317-store-ibc-trace-when-minting.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/3317-store-ibc-trace-when-minting.md diff --git a/.changelog/unreleased/improvements/3317-store-ibc-trace-when-minting.md b/.changelog/unreleased/improvements/3317-store-ibc-trace-when-minting.md new file mode 100644 index 0000000000..7622b65086 --- /dev/null +++ b/.changelog/unreleased/improvements/3317-store-ibc-trace-when-minting.md @@ -0,0 +1,2 @@ +- Store IBC denom when minting the IBC token + ([\#3317](https://github.com/anoma/namada/issues/3317)) \ No newline at end of file From 777d40d646f6f551526df491108cd7d2ec3cbe39 Mon Sep 17 00:00:00 2001 From: satan Date: Tue, 28 May 2024 10:37:13 +0200 Subject: [PATCH 62/70] Added tests --- crates/node/src/shell/mod.rs | 3 +- crates/node/src/shell/testing/node.rs | 9 +++ crates/sdk/src/migrations.rs | 32 ++++++++ crates/tests/src/integration/ledger_tests.rs | 85 +++++++++++++++++++- 4 files changed, 126 insertions(+), 3 deletions(-) diff --git a/crates/node/src/shell/mod.rs b/crates/node/src/shell/mod.rs index 7bbf4a711b..8eb42f5881 100644 --- a/crates/node/src/shell/mod.rs +++ b/crates/node/src/shell/mod.rs @@ -353,7 +353,8 @@ where storage_read_past_height_limit: Option, /// Log of events emitted by `FinalizeBlock` ABCI calls. event_log: EventLog, - scheduled_migration: Option>, + /// A migration that can be scheduled at a given block height + pub scheduled_migration: Option>, } /// Storage key filter to store the diffs into the storage. Return `false` for diff --git a/crates/node/src/shell/testing/node.rs b/crates/node/src/shell/testing/node.rs index 279c7ba433..9e74e6689c 100644 --- a/crates/node/src/shell/testing/node.rs +++ b/crates/node/src/shell/testing/node.rs @@ -333,6 +333,15 @@ impl MockNode { self.genesis_dir().join("wallet.toml") } + pub fn block_height(&self) -> BlockHeight { + self.shell + .lock() + .unwrap() + .state + .get_block_height() + .unwrap_or_default() + } + pub fn current_epoch(&self) -> Epoch { self.shell.lock().unwrap().state.in_mem().last_epoch } diff --git a/crates/sdk/src/migrations.rs b/crates/sdk/src/migrations.rs index 172928722c..964e16c7be 100644 --- a/crates/sdk/src/migrations.rs +++ b/crates/sdk/src/migrations.rs @@ -583,3 +583,35 @@ static BTREEMAP_STRING_ADDRESS: fn() = || { }, ); }; + +#[cfg(test)] +mod test_migrations { + use namada_core::token::Amount; + + use super::*; + + /// Check that if the hash of the file is wrong, the scheduled + /// migration will not load. + #[test] + fn test_scheduled_migration_validate() { + let file = tempfile::Builder::new().tempfile().expect("Test failed"); + let updates = [DbUpdateType::Add { + key: Key::parse("bing/fucking/bong").expect("Test failed"), + cf: DbColFam::SUBSPACE, + value: Amount::native_whole(1337).into(), + force: false, + }]; + let changes = DbChanges { + changes: updates.into_iter().collect(), + }; + let json = serde_json::to_string(&changes).expect("Test failed"); + let hash = Hash::sha256("derpy derp".as_bytes()); + std::fs::write(file.path(), json).expect("Test failed"); + let migration = ScheduledMigration::::from_path( + file.path(), + hash, + Default::default(), + ); + assert!(migration.is_err()); + } +} diff --git a/crates/tests/src/integration/ledger_tests.rs b/crates/tests/src/integration/ledger_tests.rs index 40816bdf67..12747bc872 100644 --- a/crates/tests/src/integration/ledger_tests.rs +++ b/crates/tests/src/integration/ledger_tests.rs @@ -2,6 +2,7 @@ use std::collections::BTreeSet; use std::str::FromStr; use assert_matches::assert_matches; +use borsh::BorshDeserialize; use borsh_ext::BorshSerializeExt; use color_eyre::eyre::Result; use data_encoding::HEXLOWER; @@ -9,10 +10,13 @@ use namada::core::collections::HashMap; use namada::token; use namada_apps_lib::wallet::defaults; use namada_core::dec::Dec; -use namada_core::storage::Epoch; -use namada_core::token::NATIVE_MAX_DECIMAL_PLACES; +use namada_core::hash::Hash; +use namada_core::storage::{DbColFam, Epoch, Key}; +use namada_core::token::{Amount, NATIVE_MAX_DECIMAL_PLACES}; use namada_node::shell::testing::client::run; use namada_node::shell::testing::utils::{Bin, CapturedOutput}; +use namada_sdk::migrations; +use namada_sdk::queries::RPC; use namada_sdk::tx::{TX_TRANSFER_WASM, VP_USER_WASM}; use namada_test_utils::TestWasms; use test_log::test; @@ -1578,3 +1582,80 @@ fn change_validator_metadata() -> Result<()> { Ok(()) } + +/// Test that a scheduled migration actually makes changes +/// to storage at the scheduled height. +#[test] +fn scheduled_migration() -> Result<()> { + let (node, _services) = setup::setup()?; + + // schedule a migration + let (hash, migrations_file) = make_migration_json(); + let scheduled_migration = migrations::ScheduledMigration::from_path( + migrations_file.path(), + hash, + 5.into(), + ) + .expect("Test failed"); + { + let mut locked = node.shell.lock().unwrap(); + locked.scheduled_migration = Some(scheduled_migration); + } + + while node.block_height().0 != 4 { + node.finalize_and_commit() + } + // check that the key doesn't exist before the scheduled block + let rt = tokio::runtime::Runtime::new().unwrap(); + let bytes = rt + .block_on(RPC.shell().storage_value( + &&node, + None, + None, + false, + &Key::parse("bing/fucking/bong").expect("Test failed"), + )) + .expect("Test failed") + .data; + assert!(bytes.is_empty()); + + // check that the key now exists and has the expected value + node.finalize_and_commit(); + let rt = tokio::runtime::Runtime::new().unwrap(); + let bytes = rt + .block_on(RPC.shell().storage_value( + &&node, + None, + None, + false, + &Key::parse("bing/fucking/bong").expect("Test failed"), + )) + .expect("Test failed") + .data; + let amount = Amount::try_from_slice(&bytes).expect("Test failed"); + assert_eq!(amount, Amount::native_whole(1337)); + + // check that no migration is scheduled + { + let locked = node.shell.lock().unwrap(); + assert!(locked.scheduled_migration.is_none()); + } + Ok(()) +} + +fn make_migration_json() -> (Hash, tempfile::NamedTempFile) { + let file = tempfile::Builder::new().tempfile().expect("Test failed"); + let updates = [migrations::DbUpdateType::Add { + key: Key::parse("bing/fucking/bong").expect("Test failed"), + cf: DbColFam::SUBSPACE, + value: Amount::native_whole(1337).into(), + force: false, + }]; + let changes = migrations::DbChanges { + changes: updates.into_iter().collect(), + }; + let json = serde_json::to_string(&changes).expect("Test failed"); + let hash = Hash::sha256(json.as_bytes()); + std::fs::write(file.path(), json).expect("Test failed"); + (hash, file) +} From 10e371394dcb8d69c653d903a2727baa9c3e18e2 Mon Sep 17 00:00:00 2001 From: Jacob Turner Date: Tue, 28 May 2024 15:10:56 +0200 Subject: [PATCH 63/70] Update crates/sdk/src/migrations.rs Co-authored-by: Tomas Zemanovic --- crates/sdk/src/migrations.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/crates/sdk/src/migrations.rs b/crates/sdk/src/migrations.rs index 964e16c7be..07c915129a 100644 --- a/crates/sdk/src/migrations.rs +++ b/crates/sdk/src/migrations.rs @@ -401,13 +401,9 @@ where } fn validate(&self) -> eyre::Result { - let mut update_json = String::new(); - let mut file = std::fs::File::open(&self.path).map_err(|_| { - eyre!("Could not fine updates file at the specified path.") + let update_json = std::fs::read_to_string(&self.path).map_err(|_| { + eyre!("Could not find or read updates file at the specified path.") })?; - _ = file - .read_to_string(&mut update_json) - .map_err(|e| eyre!("{}", e))?; // validate contents against provided hash if Hash::sha256(update_json.as_bytes()) != self.hash { Err(eyre!( From da45f99d4d08827914d1102d26a377584ad4927a Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 27 May 2024 09:01:47 +0100 Subject: [PATCH 64/70] Associate issues with TODOs --- crates/namada/src/vm/wasm/host_env.rs | 8 ++++---- crates/namada/src/vm/wasm/memory.rs | 12 +++++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/crates/namada/src/vm/wasm/host_env.rs b/crates/namada/src/vm/wasm/host_env.rs index fa5eea43b8..0d8d740693 100644 --- a/crates/namada/src/vm/wasm/host_env.rs +++ b/crates/namada/src/vm/wasm/host_env.rs @@ -105,8 +105,8 @@ where } } -// TODO: Attempt to reduce the boilerplate of this module with macros, traits -// or something of this sort... +// TODO(namada#3313): Attempt to reduce the boilerplate of this module with +// macros, traits or something of this sort... mod wrap_tx { //! Wrap tx host functions with any number of arguments in a callback //! that can be passed to [`wasmer`], to be used by the guest wasm code. @@ -258,8 +258,8 @@ mod wrap_tx { } } -// TODO: Attempt to reduce the boilerplate of this module with macros, traits -// or something of this sort... +// TODO(namada#3313): Attempt to reduce the boilerplate of this module with +// macros, traits or something of this sort... mod wrap_vp { //! Wrap vp host functions with any number of arguments in a callback //! that can be passed to [`wasmer`], to be used by the guest wasm code. diff --git a/crates/namada/src/vm/wasm/memory.rs b/crates/namada/src/vm/wasm/memory.rs index 6cd7bbf924..894e4efc44 100644 --- a/crates/namada/src/vm/wasm/memory.rs +++ b/crates/namada/src/vm/wasm/memory.rs @@ -51,7 +51,9 @@ pub type Result = std::result::Result; // The bounds are set in number of pages, the actual size is multiplied by // `wasmer::WASM_PAGE_SIZE = 64kiB`. -// TODO set bounds to accommodate for wasm env size +// +// TODO: set bounds to accommodate for wasm env size +// /// Initial pages in tx memory pub const TX_MEMORY_INIT_PAGES: u32 = 100; // 6.4 MiB /// Mamixmum pages in tx memory @@ -184,8 +186,8 @@ pub fn write_vp_inputs( /// Check that the given offset and length fits into the memory bounds. If not, /// it will try to grow the memory. -// TODO: avoid growing memory if we're only performing reads; return an Err -// instead +// TODO(namada#3314): avoid growing memory if we're only performing reads; +// return an Err instead fn check_bounds( store: &mut impl wasmer::AsStoreMut, memory: &Memory, @@ -271,8 +273,8 @@ pub struct WasmMemory { memory: Rc>>, } -// TODO: Wasm memory is neither `Send` nor `Sync`, but we must implement -// it for now for the code to compile. +// TODO(namada#3313): Wasm memory is neither `Send` nor `Sync`, but we must +// implement it for now for the code to compile. unsafe impl Send for WasmMemory {} unsafe impl Sync for WasmMemory {} From 83b33e3c4d94f1d92e165fcff9d37474804cfa2a Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Tue, 28 May 2024 14:30:11 +0100 Subject: [PATCH 65/70] Avoid cloning tx env in some host fns --- crates/namada/src/vm/host_env.rs | 42 +++++++++++++------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/crates/namada/src/vm/host_env.rs b/crates/namada/src/vm/host_env.rs index 5a31ec09fe..8984b4ac5f 100644 --- a/crates/namada/src/vm/host_env.rs +++ b/crates/namada/src/vm/host_env.rs @@ -824,29 +824,25 @@ where { tracing::debug!("tx_iter_next iter_id {}", iter_id,); - // NB: an env clone is required to avoid an immutable - // borrow while a mutable borrow is taking place - let env2 = env.clone(); - let state = env2.state(); - let iterators = unsafe { env.ctx.iterators.get_mut() }; let iter_id = PrefixIteratorId::new(iter_id); while let Some((key, val, iter_gas)) = iterators.next(iter_id) { - let (log_val, log_gas) = state - .write_log() - .read( - &Key::parse(key.clone()) - .map_err(TxRuntimeError::StorageDataError)?, - ) - .into_storage_result()?; + let (log_val, log_gas) = { + let state = env.state(); + let (log_val, log_gas) = state + .write_log() + .read( + &Key::parse(key.clone()) + .map_err(TxRuntimeError::StorageDataError)?, + ) + .into_storage_result()?; + (log_val.cloned(), log_gas) + }; tx_charge_gas::(env, checked!(iter_gas + log_gas)?)?; match log_val { - Some(write_log::StorageModification::Write { ref value }) => { - let key_val = borsh::to_vec(&KeyVal { - key, - val: value.clone(), - }) - .map_err(TxRuntimeError::EncodingError)?; + Some(write_log::StorageModification::Write { value }) => { + let key_val = borsh::to_vec(&KeyVal { key, val: value }) + .map_err(TxRuntimeError::EncodingError)?; let len: i64 = key_val .len() .try_into() @@ -2074,15 +2070,11 @@ where let code_hash = Hash::try_from(code_hash) .map_err(|e| TxRuntimeError::InvalidVpCodeHash(e.to_string()))?; - // NB: an env clone is required to avoid an immutable - // borrow while a mutable borrow is taking place - let env2 = env.clone(); - let state = env2.state(); - // First check that code hash corresponds to the code tag if it is present if let Some(tag) = code_tag { let hash_key = Key::wasm_hash(tag); - let (result, gas) = state + let (result, gas) = env + .state() .db_read(&hash_key) .map_err(TxRuntimeError::StateError)?; tx_charge_gas::(env, gas)?; @@ -2113,7 +2105,7 @@ where // Then check that the corresponding VP code does indeed exist let code_key = Key::wasm_code(&code_hash); - let is_present = state.has_key(&code_key)?; + let is_present = env.state().has_key(&code_key)?; if !is_present { return Err(TxRuntimeError::InvalidVpCodeHash( "The corresponding VP code doesn't exist".to_string(), From edc2e24de8106d1b7c52bca62cf18e867937eaa8 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 27 May 2024 09:05:45 +0100 Subject: [PATCH 66/70] Changelog for #3308 --- .changelog/unreleased/improvements/3308-wasmer-upgrade.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .changelog/unreleased/improvements/3308-wasmer-upgrade.md diff --git a/.changelog/unreleased/improvements/3308-wasmer-upgrade.md b/.changelog/unreleased/improvements/3308-wasmer-upgrade.md new file mode 100644 index 0000000000..b7f43144a2 --- /dev/null +++ b/.changelog/unreleased/improvements/3308-wasmer-upgrade.md @@ -0,0 +1,4 @@ +- Upgrade `wasmer` vm to upstream version `4.3.1`, + moving away from the [forked code based on version + `2.3.0`](https://github.com/heliaxdev/wasmer/tree/255054f7f58b7b4a525f2fee6b9b86422d1ca15b). + ([\#3308](https://github.com/anoma/namada/pull/3308)) \ No newline at end of file From 657b9165fb74b1ff7cc2d278eb8e4863ae76e032 Mon Sep 17 00:00:00 2001 From: brentstone Date: Tue, 28 May 2024 13:25:11 -0700 Subject: [PATCH 67/70] fix clippy + fmt --- crates/sdk/src/migrations.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crates/sdk/src/migrations.rs b/crates/sdk/src/migrations.rs index 07c915129a..d5538214dd 100644 --- a/crates/sdk/src/migrations.rs +++ b/crates/sdk/src/migrations.rs @@ -6,7 +6,6 @@ use core::fmt::Formatter; use core::fmt::{Display, Formatter}; #[cfg(feature = "migrations")] use core::str::FromStr; -use std::io::Read; use std::marker::PhantomData; use std::path::{Path, PathBuf}; @@ -401,9 +400,13 @@ where } fn validate(&self) -> eyre::Result { - let update_json = std::fs::read_to_string(&self.path).map_err(|_| { - eyre!("Could not find or read updates file at the specified path.") - })?; + let update_json = + std::fs::read_to_string(&self.path).map_err(|_| { + eyre!( + "Could not find or read updates file at the specified \ + path." + ) + })?; // validate contents against provided hash if Hash::sha256(update_json.as_bytes()) != self.hash { Err(eyre!( From 5a0432aa80decb4ffb3c4b8dec1b898bd3c50fab Mon Sep 17 00:00:00 2001 From: brentstone Date: Tue, 28 May 2024 13:29:18 -0700 Subject: [PATCH 68/70] fmt --- crates/tx_prelude/src/ibc.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/tx_prelude/src/ibc.rs b/crates/tx_prelude/src/ibc.rs index 14a289f23a..2a5ca7b1ca 100644 --- a/crates/tx_prelude/src/ibc.rs +++ b/crates/tx_prelude/src/ibc.rs @@ -9,7 +9,8 @@ use namada_core::token::Amount; use namada_events::EventTypeBuilder; pub use namada_ibc::event::{IbcEvent, IbcEventType}; pub use namada_ibc::storage::{ - burn_tokens, ibc_token, is_ibc_key, mint_tokens, mint_limit_key, throughput_limit_key + burn_tokens, ibc_token, is_ibc_key, mint_limit_key, mint_tokens, + throughput_limit_key, }; pub use namada_ibc::{ IbcActions, IbcCommonContext, IbcStorageContext, NftTransferModule, From 6d7803e7b79a2a36827f2d964eb1b1ce258b01af Mon Sep 17 00:00:00 2001 From: brentstone Date: Tue, 28 May 2024 14:14:35 -0700 Subject: [PATCH 69/70] evil: fix imports --- Cargo.lock | 1 + crates/storage/Cargo.toml | 1 + crates/tests/src/integration/ledger_tests.rs | 2 +- wasm/Cargo.lock | 1 + wasm_for_tests/Cargo.lock | 1 + 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 5b543ef638..81feb55cae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5245,6 +5245,7 @@ dependencies = [ "namada_migrations", "namada_replay_protection", "regex", + "serde", "smooth-operator", "thiserror", "tracing", diff --git a/crates/storage/Cargo.toml b/crates/storage/Cargo.toml index 6612b42dbb..470c72caf8 100644 --- a/crates/storage/Cargo.toml +++ b/crates/storage/Cargo.toml @@ -33,6 +33,7 @@ borsh.workspace = true itertools.workspace = true linkme = {workspace = true, optional = true} regex.workspace = true +serde.workspace = true smooth-operator.workspace = true thiserror.workspace = true tracing.workspace = true diff --git a/crates/tests/src/integration/ledger_tests.rs b/crates/tests/src/integration/ledger_tests.rs index ca3b081d14..23e8acf5a5 100644 --- a/crates/tests/src/integration/ledger_tests.rs +++ b/crates/tests/src/integration/ledger_tests.rs @@ -13,7 +13,7 @@ use namada_apps_lib::wallet::defaults::{self, albert_keypair}; use namada_core::dec::Dec; use namada_core::hash::Hash; use namada_core::storage::{DbColFam, Epoch, Key}; -use namada_core::token::{Amount, NATIVE_MAX_DECIMAL_PLACES}; +use namada_core::token::NATIVE_MAX_DECIMAL_PLACES; use namada_node::shell::testing::client::run; use namada_node::shell::testing::node::NodeResults; use namada_node::shell::testing::utils::{Bin, CapturedOutput}; diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index fc3cfdfce6..fe08f81667 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -3976,6 +3976,7 @@ dependencies = [ "namada_migrations", "namada_replay_protection", "regex", + "serde", "smooth-operator", "thiserror", "tracing", diff --git a/wasm_for_tests/Cargo.lock b/wasm_for_tests/Cargo.lock index c37b4ab2e0..cc34f08061 100644 --- a/wasm_for_tests/Cargo.lock +++ b/wasm_for_tests/Cargo.lock @@ -3925,6 +3925,7 @@ dependencies = [ "namada_merkle_tree", "namada_replay_protection", "regex", + "serde", "smooth-operator", "thiserror", "tracing", From bc40dd25a3e09e3aa2e81f6a713085bbc79ff650 Mon Sep 17 00:00:00 2001 From: yito88 Date: Wed, 29 May 2024 17:07:29 +0200 Subject: [PATCH 70/70] fix func name --- crates/ibc/src/context/token_transfer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ibc/src/context/token_transfer.rs b/crates/ibc/src/context/token_transfer.rs index be37122e57..1fc9700f93 100644 --- a/crates/ibc/src/context/token_transfer.rs +++ b/crates/ibc/src/context/token_transfer.rs @@ -142,7 +142,7 @@ where .map_err(TokenTransferError::from) } - fn store_ibc_denom( + fn maybe_store_ibc_denom( &self, owner: &Address, coin: &PrefixedCoin, @@ -305,7 +305,7 @@ where // Store the IBC denom with the token hash to be able to retrieve it // later - self.store_ibc_denom(account, coin)?; + self.maybe_store_ibc_denom(account, coin)?; self.inner .borrow_mut()