Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test: System Fuzzer Updates #1605

Merged
merged 7 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
101 changes: 76 additions & 25 deletions fuzz-tests/src/bin/system.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![cfg_attr(feature = "libfuzzer-sys", no_main)]

use arbitrary::Arbitrary;
use fuzz_tests::fuzz_template;
use native_sdk::modules::metadata::Metadata;
Expand All @@ -7,40 +8,39 @@ use radix_engine::errors::RuntimeError;
use radix_engine::kernel::kernel_api::{KernelNodeApi, KernelSubstateApi};
use radix_engine::system::system_callback::SystemLockData;
use radix_engine::vm::{OverridePackageCode, VmInvoke};
use radix_engine_common::manifest_args;
use radix_engine_common::{manifest_args, ManifestSbor};
use serde::{Deserialize, Serialize};

use radix_engine::prelude::ManifestArgs;
use radix_engine::types::ScryptoSbor;
use radix_engine_common::prelude::{scrypto_encode, NodeId, Own, ScryptoCustomTypeKind};
use radix_engine_common::prelude::{
scrypto_encode, GlobalAddress, NodeId, Own, ScryptoCustomTypeKind,
};
use radix_engine_common::types::ComponentAddress;
use radix_engine_interface::api::{
FieldValue, KeyValueStoreDataSchema, LockFlags, ACTOR_STATE_SELF,
};
use radix_engine_interface::blueprints::package::PackageDefinition;
use radix_engine_interface::prelude::{AttachedModuleId, ClientApi, OwnerRole};
use radix_engine_interface::types::IndexedScryptoValue;
use radix_engine_interface::types::{IndexedScryptoValue, Level};
use sbor::basic_well_known_types::ANY_TYPE;
use sbor::{generate_full_schema, LocalTypeId, TypeAggregator};
use scrypto_unit::{InjectSystemCostingError, TestRunnerBuilder};
use scrypto_unit::{InjectSystemCostingError, TestRunnerBuilder, TestRunnerSnapshot};
use transaction::builder::ManifestBuilder;
use utils::indexmap;
use utils::prelude::{index_set_new, IndexSet};

fuzz_template!(|actions: SystemActions| { fuzz_system(actions) });

// Fuzzer entry points
fn fuzz_system(actions: SystemActions) {
let mut test_runner = TestRunnerBuilder::new()
.with_custom_extension(OverridePackageCode::new(
CUSTOM_PACKAGE_CODE_ID,
FuzzSystem(actions.clone()),
))
.skip_receipt_check()
.build();

let component_address = {
let package_address = test_runner.publish_native_package(
CUSTOM_PACKAGE_CODE_ID,
lazy_static::lazy_static! {
static ref TEST_RUNNER_SNAPSHOT: (TestRunnerSnapshot, ComponentAddress) = {
let mut test_runner = TestRunnerBuilder::new()
.with_custom_extension(OverridePackageCode::new(CUSTOM_PACKAGE_CODE_ID, FuzzSystem))
.without_trace()
.skip_receipt_check()
.build();
let package_address = test_runner
.publish_native_package(CUSTOM_PACKAGE_CODE_ID,
PackageDefinition::new_with_fields_test_definition(
BLUEPRINT_NAME,
2,
Expand All @@ -54,12 +54,25 @@ fn fuzz_system(actions: SystemActions) {
.build(),
vec![],
);
receipt.expect_commit_success().new_component_addresses()[0]
let component_address = receipt.expect_commit_success().new_component_addresses()[0];
(test_runner.create_snapshot(), component_address)
};
}

// Fuzzer entry points
fn fuzz_system(actions: SystemActions) {
let mut test_runner = TestRunnerBuilder::new()
.with_custom_extension(OverridePackageCode::new(CUSTOM_PACKAGE_CODE_ID, FuzzSystem))
.without_trace()
.skip_receipt_check()
.build_from_snapshot(TEST_RUNNER_SNAPSHOT.0.clone());

// Setup
let component_address = TEST_RUNNER_SNAPSHOT.1.clone();

let manifest = ManifestBuilder::new()
.lock_fee(test_runner.faucet_component(), 500u32)
.call_method(component_address, "test", manifest_args!())
.call_method(component_address, "test", manifest_args!(actions.actions))
.build();

test_runner
Expand All @@ -69,7 +82,7 @@ fn fuzz_system(actions: SystemActions) {
actions.inject_err_after_count,
);

test_runner.check_database()
test_runner.check_database();
}

#[derive(Debug, Clone, Arbitrary, Serialize, Deserialize)]
Expand All @@ -78,13 +91,13 @@ struct SystemActions {
pub actions: Vec<SystemAction>,
}

#[derive(Debug, Clone, Arbitrary, Serialize, Deserialize)]
#[derive(Debug, Clone, Arbitrary, Serialize, Deserialize, ScryptoSbor, ManifestSbor)]
enum NodeValue {
Own,
Ref,
}

#[derive(Debug, Clone, Arbitrary, Serialize, Deserialize)]
#[derive(Debug, Clone, Arbitrary, Serialize, Deserialize, ScryptoSbor, ManifestSbor)]
enum SystemAction {
FieldOpen(u8, u32),
FieldRead(usize),
Expand All @@ -99,6 +112,11 @@ enum SystemAction {
KeyValueEntryRemove(usize),
KeyValueEntryClose(usize),
KeyValueEntryLock(usize),
SysLog(Level, String),
SysBech32EncodeAddress(GlobalAddress),
SysGetTransactionHash,
SysGenerateRuid,
SysPanic(String),
}

#[derive(Debug, Clone, ScryptoSbor)]
Expand Down Expand Up @@ -244,6 +262,21 @@ impl SystemAction {
api.key_value_entry_lock(handle)?;
}
}
SystemAction::SysLog(level, message) => {
api.emit_log(level.clone(), message.clone())?;
}
SystemAction::SysBech32EncodeAddress(address) => {
api.bech32_encode_address(address.clone())?;
}
SystemAction::SysGetTransactionHash => {
api.get_transaction_hash()?;
}
SystemAction::SysPanic(message) => {
api.panic(message.clone())?;
}
SystemAction::SysGenerateRuid => {
api.generate_ruid()?;
}
}

Ok(())
Expand All @@ -253,12 +286,12 @@ impl SystemAction {
const BLUEPRINT_NAME: &str = "MyBlueprint";
const CUSTOM_PACKAGE_CODE_ID: u64 = 1024;
#[derive(Clone)]
struct FuzzSystem(SystemActions);
struct FuzzSystem;
impl VmInvoke for FuzzSystem {
fn invoke<Y>(
&mut self,
export_name: &str,
_input: &IndexedScryptoValue,
input: &IndexedScryptoValue,
api: &mut Y,
) -> Result<IndexedScryptoValue, RuntimeError>
where
Expand All @@ -270,7 +303,8 @@ impl VmInvoke for FuzzSystem {
handles: index_set_new(),
nodes: index_set_new(),
};
for action in &self.0.actions {
let actions: (Vec<SystemAction>,) = input.as_typed().unwrap();
for action in &actions.0 {
action.act(api, &mut state)?;
}
}
Expand Down Expand Up @@ -356,4 +390,21 @@ fn test_system_generate_fuzz_input_data() {
let serialized = serialize(&actions).unwrap();
fs::write(format!("system_{:03?}.raw", idx), serialized).expect("Unable to write file");
}

{
let idx = 2;
let actions = SystemActions {
inject_err_after_count: 32u64,
actions: vec![
SystemAction::SysPanic("panic".to_string()),
SystemAction::SysGetTransactionHash,
SystemAction::SysLog(Level::Error, "error".to_string()),
SystemAction::SysBech32EncodeAddress(XRD.into()),
SystemAction::SysGenerateRuid,
],
};

let serialized = serialize(&actions).unwrap();
fs::write(format!("system_{:03?}.raw", idx), serialized).expect("Unable to write file");
}
}
4 changes: 4 additions & 0 deletions radix-engine-common/src/types/addresses/global_address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ use sbor::*;
use utils::{copy_u8_array, ContextualDisplay};

/// Address to a global entity
#[cfg_attr(
feature = "radix_engine_fuzzing",
derive(serde::Serialize, serde::Deserialize)
)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct GlobalAddress(NodeId); // private to ensure entity type check

Expand Down
6 changes: 6 additions & 0 deletions radix-engine-interface/src/types/level.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
use crate::*;
#[cfg(feature = "radix_engine_fuzzing")]
use arbitrary::Arbitrary;
use core::str::FromStr;
use sbor::rust::prelude::*;

/// Represents the level of a log message.
#[cfg_attr(
feature = "radix_engine_fuzzing",
derive(Arbitrary, serde::Serialize, serde::Deserialize)
)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Sbor, Ord, PartialOrd, Default)]
pub enum Level {
Error,
Expand Down