Skip to content

Commit

Permalink
Merge pull request #3445 from anoma/tomas/fuzz-tx
Browse files Browse the repository at this point in the history
fuzz test txs
  • Loading branch information
mergify[bot] authored Aug 16, 2024
2 parents d5fbd97 + a47bfa7 commit f1df925
Show file tree
Hide file tree
Showing 56 changed files with 1,223 additions and 186 deletions.
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

0 comments on commit f1df925

Please sign in to comment.