Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
15bdc41
init a fuzz target with cargo-fuzz
tzemanovic Jun 26, 2024
9ed51c1
tx: impl Arbitrary for Tx
tzemanovic Jun 26, 2024
49fcca7
fuzz mempool with arb txs
tzemanovic Jun 26, 2024
b226786
Makefile: add `cargo-fuzz` dep and `fuzz-txs-mempool` recipe
tzemanovic Jun 28, 2024
a04b45f
node/init_chain: no wasm pre-compile for fuzzing
tzemanovic Jul 1, 2024
44c1d71
fuzz: set dev opt-level = 3
tzemanovic Jul 1, 2024
b5c0a2c
fuzz_txs_mempool: re-use TestShell between runs
tzemanovic Jul 1, 2024
0c5e9cb
core/key: fix arbitrary impls
tzemanovic Jul 2, 2024
3206ad7
tx: fix manual impl Arbitrary for Section
tzemanovic Jul 2, 2024
4a57fff
shell/mempool: skip chain ID check for fuzzing
tzemanovic Jul 3, 2024
6bfa43c
make/fuzz-txs-mempool: run with `--dev` to avoid OOM
tzemanovic Jul 12, 2024
864a7bd
tx: add arbitrary masp tx section
tzemanovic Jul 12, 2024
2f1818e
tx: add non-panicking serialization method
tzemanovic Jul 12, 2024
6eae64c
fuzz_txs_mempool: use non-panicking tx serialization method
tzemanovic Jul 12, 2024
0bbfef3
fuzz_txs_mempool: catch panics in serialization
tzemanovic Jul 12, 2024
2aa37ae
use updated jubjub that prevents invalid arb ExtendedPoint
tzemanovic Jul 12, 2024
671be7d
impl Arbitrary for MaspBuilder to derive tx sections
tzemanovic Jul 16, 2024
b8fc3ae
fuzz_txs_mempool: rm unused import
tzemanovic Jul 16, 2024
9de44c4
tx: prevent overflow in arbitrary masp builder
tzemanovic Jul 16, 2024
72ec0d5
fix clippy
tzemanovic Jul 16, 2024
dd25917
fuzz: use a shorter target name
tzemanovic Jul 16, 2024
8748322
fuzz: add txs_prepare_proposal
tzemanovic Jul 16, 2024
4b5971c
prepare_proposal: make tx fee checks pass for fuzzing
tzemanovic Jul 17, 2024
62d63cc
token: avoid trying to read denom when fuzzing
tzemanovic Jul 18, 2024
5e9a8be
fuzz: add README.md
tzemanovic Jul 18, 2024
54571e0
fuzz: add txs_process_proposal
tzemanovic Jul 18, 2024
422e2af
add conditional fuzzing sig acceptance at lower level
tzemanovic Jul 23, 2024
b18507a
fuzz: add txs_finalize_block target
tzemanovic Jul 24, 2024
19793ea
fuzz: add txs_wasm_run
tzemanovic Jul 30, 2024
a47bfa7
changelog: add #3445
tzemanovic Aug 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .changelog/unreleased/testing/3445-fuzz-tx.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Added fuzz testing targets for txs in mempool, block proposals and finalize
block. ([\#3445](https://github.com/anoma/namada/pull/3445))
173 changes: 133 additions & 40 deletions Cargo.lock

Large diffs are not rendered by default.

20 changes: 13 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ members = [
"crates/vp_env",
"crates/vp_prelude",
"examples",
"fuzz",
]

# wasm packages have to be built separately
Expand All @@ -62,6 +63,7 @@ repository = "https://github.com/anoma/namada"
version = "0.42.0"

[workspace.dependencies]
arbitrary = {version = "1.3", features = ["derive"]}
ark-bls12-381 = {version = "0.3"}
ark-serialize = {version = "0.3"}
ark-std = "0.3.0"
Expand Down Expand Up @@ -113,15 +115,16 @@ flume = "0.11.0"
fs_extra = "1.2.0"
futures = "0.3"
git2 = { version = "0.18.1", default-features = false }
ibc = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b", features = ["serde"] }
ibc-derive = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" }
ibc-testkit = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b", default-features = false }
ibc = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "0c3b3c0ab598e1e627089d06941efe0e39b61cd7", features = ["serde"] }
ibc-derive = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "0c3b3c0ab598e1e627089d06941efe0e39b61cd7" }
ibc-testkit = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "0c3b3c0ab598e1e627089d06941efe0e39b61cd7", default-features = false }
ics23 = "0.11.0"
index-set = { git = "https://github.com/heliaxdev/index-set", tag = "v0.8.1", features = ["serialize-borsh", "serialize-serde"] }
indexmap = { git = "https://github.com/heliaxdev/indexmap", tag = "2.2.4-heliax-1", features = ["borsh-schema", "serde"] }
init-once = "0.6.0"
itertools = "0.12.1"
jubjub = "0.10"
# branch "tomas/arbitrary"
jubjub = { git = "https://github.com/heliaxdev/jubjub.git", rev = "a373686962f4e9d0edb3b4716f86ff6bbd9aa86c" }
k256 = { version = "0.13.0", default-features = false, features = ["ecdsa", "pkcs8", "precomputed-tables", "serde", "std"]}
kdam = "0.5.2"
konst = { version = "0.3.8", default-features = false }
Expand All @@ -134,9 +137,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 = "8d83b172698098fba393006016072bc201ed9ab7" }
masp_proofs = { git = "https://github.com/anoma/masp", rev = "8d83b172698098fba393006016072bc201ed9ab7", default-features = false, features = ["local-prover"] }
# branch = "tomas/arbitrary"
masp_primitives = { git = "https://github.com/anoma/masp", rev = "12ed8b060b295c06502a2ff8468e4a941cb7cca4" }
masp_proofs = { git = "https://github.com/anoma/masp", rev = "12ed8b060b295c06502a2ff8468e4a941cb7cca4", default-features = false, features = ["local-prover"] }
num256 = "0.3.5"
num_cpus = "1.13.0"
num-derive = "0.4"
Expand Down Expand Up @@ -221,3 +224,6 @@ lto = true
opt-level = 3
panic = "unwind"
overflow-checks = true

[profile.dev.package.namada_fuzz]
opt-level = 3
23 changes: 20 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ clippy-wasm = $(cargo) +$(nightly) clippy --manifest-path $(wasm)/Cargo.toml --a

# Need a separate command for benchmarks to prevent the "testing" feature flag from being activated
clippy:
$(cargo) +$(nightly) clippy $(jobs) --all-targets --workspace --exclude namada_benchmarks -- -D warnings && \
$(cargo) +$(nightly) clippy $(jobs) --all-targets --package namada_benchmarks -- -D warnings && \
$(cargo) +$(nightly) clippy $(jobs) --all-targets --workspace --exclude namada_benchmarks -- -D warnings --check-cfg 'cfg(fuzzing)' && \
$(cargo) +$(nightly) clippy $(jobs) --all-targets --package namada_benchmarks -- -D warnings --check-cfg 'cfg(fuzzing)' && \
make -C $(wasms) clippy && \
make -C $(wasms_for_tests) clippy

Expand Down Expand Up @@ -273,6 +273,23 @@ clean:
bench:
$(cargo) bench --package namada_benchmarks

# NOTE: running in `--dev` as release build takes over 64GB memory, but
# dev is still configured for opt-level=3
fuzz-txs-mempool:
$(cargo) +$(nightly) fuzz run txs_mempool --dev -- -rss_limit_mb=4096

fuzz-txs-prepare-proposal:
$(cargo) +$(nightly) fuzz run txs_prepare_proposal --dev -- -rss_limit_mb=4096

fuzz-txs-process-proposal:
$(cargo) +$(nightly) fuzz run txs_process_proposal --dev -- -rss_limit_mb=4096

fuzz-txs-finalize-block:
$(cargo) +$(nightly) fuzz run txs_finalize_block --dev -- -rss_limit_mb=4096

fuzz-txs-wasm-run:
$(cargo) +$(nightly) fuzz run txs_wasm_run --dev -- -rss_limit_mb=4096 --sanitizer=none

build-doc:
$(cargo) doc --no-deps

Expand Down Expand Up @@ -351,7 +368,7 @@ dev-deps:
$(rustup) toolchain install $(nightly)
$(rustup) target add wasm32-unknown-unknown
$(rustup) component add rustfmt clippy miri --toolchain $(nightly)
$(cargo) install cargo-watch unclog wasm-opt
$(cargo) install cargo-watch unclog wasm-opt cargo-fuzz

test-miri:
$(cargo) +$(nightly) miri setup
Expand Down
2 changes: 2 additions & 0 deletions crates/account/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ version.workspace = true
[features]
default = []
testing = ["namada_core/testing", "proptest"]
arbitrary = ["dep:arbitrary", "namada_core/arbitrary"]
migrations = ["namada_migrations", "linkme"]

[dependencies]
Expand All @@ -23,6 +24,7 @@ namada_macros = { path = "../macros" }
namada_migrations = { path = "../migrations", optional = true }
namada_storage = { path = "../storage" }

arbitrary = { workspace = true, optional = true }
borsh.workspace = true
linkme = {workspace = true, optional = true }
proptest = { workspace = true, optional = true }
Expand Down
2 changes: 2 additions & 0 deletions crates/account/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use namada_migrations::*;
use serde::{Deserialize, Serialize};

/// A tx data type to initialize a new established account
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Debug,
Clone,
Expand All @@ -31,6 +32,7 @@ pub struct InitAccount {
}

/// A tx data type to update an account's validity predicate
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Debug,
Clone,
Expand Down
8 changes: 8 additions & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,19 @@ migrations = [
]
benches = ["proptest"]
control_flow = ["futures", "lazy_static", "tokio", "wasmtimer"]
arbitrary = [
"dep:arbitrary",
"chrono/arbitrary",
"ibc/arbitrary",
"indexmap/arbitrary",
"masp_primitives/arbitrary",
]

[dependencies]
namada_macros = {path = "../macros"}
namada_migrations = {path = "../migrations", optional = true}

arbitrary = { workspace = true, optional = true }
arse-merkle-tree.workspace = true
bech32.workspace = true
borsh.workspace = true
Expand Down
4 changes: 4 additions & 0 deletions crates/core/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub type DecodeError = string_encoding::DecodeError;
pub type Result<T> = std::result::Result<T, DecodeError>;

/// An account's address
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Clone,
BorshSerialize,
Expand Down Expand Up @@ -412,6 +413,7 @@ impl TryFrom<Signer> for Address {
}

/// An established address is generated on-chain
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Debug,
Clone,
Expand Down Expand Up @@ -512,6 +514,7 @@ impl EstablishedAddressGen {
}

/// An implicit address is derived from a cryptographic key
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Debug,
Clone,
Expand Down Expand Up @@ -543,6 +546,7 @@ impl From<&key::common::PublicKey> for Address {
}

/// An internal address represents a module with a native VP
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Debug,
Clone,
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ impl ProposalBytes {
pub const DEFAULT_CHAIN_ID: &str = "namada-internal.00000000000000";

/// Chain ID
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Debug,
Clone,
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/dec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub type Result<T> = std::result::Result<T, Error>;
///
/// To be precise, an instance X of this type should be
/// interpreted as the Dec X * 10 ^ (-[`POS_DECIMAL_PRECISION`])
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Clone,
Copy,
Expand Down
4 changes: 4 additions & 0 deletions crates/core/src/eth_bridge_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const VERSION: u8 = 1;
const NAMESPACE: &str = "transfer";

/// Transfer to Ethereum kinds.
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Copy,
Clone,
Expand Down Expand Up @@ -170,6 +171,7 @@ impl<'transfer> PendingTransferAppendix<'transfer> {

/// A transfer message to be submitted to Ethereum
/// to move assets from Namada across the bridge.
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Debug,
Clone,
Expand Down Expand Up @@ -200,6 +202,7 @@ pub struct TransferToEthereum {

/// A transfer message to Ethereum sitting in the
/// bridge pool, waiting to be relayed
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Debug,
Clone,
Expand Down Expand Up @@ -338,6 +341,7 @@ impl From<&PendingTransfer> for Key {
/// The amount of fees to be paid, in Namada, to the relayer
/// of a transfer across the Ethereum Bridge, compensating
/// for Ethereum gas costs.
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Debug,
Clone,
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/ethereum_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ impl From<u64> for Uint {

/// Representation of address on Ethereum. The inner value is the last 20 bytes
/// of the public key that controls the account.
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Copy,
Clone,
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub enum Error {
/// Result for functions that may fail
pub type HashResult<T> = std::result::Result<T, Error>;

#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Clone,
Copy,
Expand Down
2 changes: 2 additions & 0 deletions crates/core/src/ibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::hash::Hash;
use crate::token;

/// IBC token hash derived from a denomination.
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Debug,
Clone,
Expand Down Expand Up @@ -75,6 +76,7 @@ impl FromStr for IbcTxDataRefs {
}

/// The target of a PGF payment
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Debug,
Clone,
Expand Down
2 changes: 2 additions & 0 deletions crates/core/src/key/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::key::{SignableBytes, StorageHasher};
use crate::{impl_display_and_from_str_via_format, string_encoding};

/// Public key
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Clone,
Debug,
Expand Down Expand Up @@ -299,6 +300,7 @@ impl FromStr for SecretKey {
}

/// Signature
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Clone,
Debug,
Expand Down
45 changes: 43 additions & 2 deletions crates/core/src/key/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,48 @@ impl super::SigScheme for SigScheme {
where
H: 'static + StorageHasher,
{
pk.0.verify(&sig.0, &data.signable_hash::<H>())
.map_err(|err| VerifySigError::SigVerifyError(err.to_string()))
#[cfg(not(fuzzing))]
{
pk.0.verify(&sig.0, &data.signable_hash::<H>())
.map_err(|err| VerifySigError::SigVerifyError(err.to_string()))
}

#[cfg(fuzzing)]
{
let _ = (pk, data, sig);
Ok(())
}
}
}

#[cfg(feature = "arbitrary")]
impl arbitrary::Arbitrary<'_> for PublicKey {
fn arbitrary(
u: &mut arbitrary::Unstructured<'_>,
) -> arbitrary::Result<Self> {
let seed: [u8; 32] = arbitrary::Arbitrary::arbitrary(u)?;
let sk = ed25519_consensus::SigningKey::from(seed);
Ok(Self(sk.verification_key()))
}

fn size_hint(_depth: usize) -> (usize, Option<usize>) {
// Signing key seed size
(32, Some(32))
}
}

#[cfg(feature = "arbitrary")]
impl arbitrary::Arbitrary<'_> for Signature {
fn arbitrary(
u: &mut arbitrary::Unstructured<'_>,
) -> arbitrary::Result<Self> {
let seed: [u8; 32] = arbitrary::Arbitrary::arbitrary(u)?;
let sk = ed25519_consensus::SigningKey::from(seed);
Ok(Self(sk.sign(&[0_u8])))
}

fn size_hint(_depth: usize) -> (usize, Option<usize>) {
// Signing key seed size
(32, Some(32))
}
}
1 change: 1 addition & 0 deletions crates/core/src/key/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ pub trait SigScheme: Eq + Ord + Debug + Serialize + Default {

/// Public key hash derived from `common::Key` borsh encoded bytes (hex string
/// of the first 40 chars of sha256 hash)
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(
Debug,
Clone,
Expand Down
Loading