bitcoin-fuzz 0.1.16-alpha.0

contains the bitcoin fuzz tests
Documentation
crate::ix!();

//-------------------------------------------[.cpp/bitcoin/src/test/fuzz/rpc.cpp]

pub struct RPCFuzzTestingSetup {
    base: TestingSetup,
}

impl RPCFuzzTestingSetup {

    pub fn new(
        chain_name: &String,
        extra_args: &Vec<*const u8>) -> Self {
    
        todo!();
        /*
            : TestingSetup{chain_name, extra_args}
        */
    }
    
    pub fn callrpc(&mut self, 
        rpc_method: &str,
        arguments:  &Vec<&str>) -> UniValue {
        
        todo!();
        /*
            JSONRPCRequest request;
            request.context = &m_node;
            request.strMethod = rpc_method;
            request.params = RPCConvertValues(rpc_method, arguments);
            return tableRPC.execute(request);
        */
    }
    
    pub fn get_rpc_commands(&self) -> Vec<String> {
        
        todo!();
        /*
            return tableRPC.listCommands();
        */
    }
}

lazy_static!{
    /*
    RPCFuzzTestingSetup* rpc_testing_setup = nullptr;
    std::string g_limit_to_rpc_command;
    */
}

/**
  | RPC commands which are not appropriate for
  | fuzzing: such as RPC commands reading or
  | writing to a filename passed as an RPC
  | parameter, RPC commands resulting in network
  | activity, etc.
  */
lazy_static!{
    /*
    const std::vector<std::string> RPC_COMMANDS_NOT_SAFE_FOR_FUZZING{
        "addconnection",  // avoid DNS lookups
        "addnode",        // avoid DNS lookups
        "addpeeraddress", // avoid DNS lookups
        "analyzepsbt",    // avoid signed integer overflow in CFeeRate::GetFee(unsigned long) (https://github.com/bitcoin/bitcoin/issues/20607)
        "dumptxoutset",   // avoid writing to disk
        "dumpwallet", // avoid writing to disk
        "echoipc",              // avoid assertion failure (Assertion `"EnsureAnyNodeContext(request.context).init" && check' failed.)
        "generatetoaddress",    // avoid prohibitively slow execution (when `num_blocks` is large)
        "generatetodescriptor", // avoid prohibitively slow execution (when `nblocks` is large)
        "gettxoutproof",        // avoid prohibitively slow execution
        "importwallet", // avoid reading from disk
        "loadwallet",   // avoid reading from disk
        "prioritisetransaction", // avoid signed integer overflow in CTxMemPool::PrioritiseTransaction(uint256 const&, long const&) (https://github.com/bitcoin/bitcoin/issues/20626)
        "savemempool",           // disabled as a precautionary measure: may take a file path argument in the future
        "setban",                // avoid DNS lookups
        "stop",                  // avoid shutdown state
    };
    */
}

/**
  | RPC commands which are safe for fuzzing.
  |
  */
lazy_static!{
    static ref RPC_COMMANDS_SAFE_FOR_FUZZING: Vec<&'static str> = vec!{
        "clearbanned",
        "combinepsbt",
        "combinerawtransaction",
        "converttopsbt",
        "createmultisig",
        "createpsbt",
        "createrawtransaction",
        "decodepsbt",
        "decoderawtransaction",
        "decodescript",
        "deriveaddresses",
        "disconnectnode",
        "echo",
        "echojson",
        "estimaterawfee",
        "estimatesmartfee",
        "finalizepsbt",
        "generate",
        "generateblock",
        "getaddednodeinfo",
        "getbestblockhash",
        "getblock",
        "getblockchaininfo",
        "getblockcount",
        "getblockfilter",
        "getblockhash",
        "getblockheader",
        "getblockstats",
        "getblocktemplate",
        "getchaintips",
        "getchaintxstats",
        "getconnectioncount",
        "getdescriptorinfo",
        "getdifficulty",
        "getindexinfo",
        "getmemoryinfo",
        "getmempoolancestors",
        "getmempooldescendants",
        "getmempoolentry",
        "getmempoolinfo",
        "getmininginfo",
        "getnettotals",
        "getnetworkhashps",
        "getnetworkinfo",
        "getnodeaddresses",
        "getpeerinfo",
        "getrawmempool",
        "getrawtransaction",
        "getrpcinfo",
        "gettxout",
        "gettxoutsetinfo",
        "help",
        "invalidateblock",
        "joinpsbts",
        "listbanned",
        "logging",
        "mockscheduler",
        "ping",
        "preciousblock",
        "pruneblockchain",
        "reconsiderblock",
        "scantxoutset",
        "sendrawtransaction",
        "setmocktime",
        "setnetworkactive",
        "signmessagewithprivkey",
        "signrawtransactionwithkey",
        "submitblock",
        "submitheader",
        "syncwithvalidationinterfacequeue",
        "testmempoolaccept",
        "uptime",
        "utxoupdatepsbt",
        "validateaddress",
        "verifychain",
        "verifymessage",
        "verifytxoutproof",
        "waitforblock",
        "waitforblockheight",
        "waitfornewblock",
    };
}

pub fn consume_scalar_rpc_argument(fuzzed_data_provider: &mut FuzzedDataProvider) -> String {
    
    todo!();
        /*
            const size_t max_string_length = 4096;
        const size_t max_base58_bytes_length{64};
        std::string r;
        CallOneOf(
            fuzzed_data_provider,
            [&] {
                // string argument
                r = fuzzed_data_provider.ConsumeRandomLengthString(max_string_length);
            },
            [&] {
                // base64 argument
                r = EncodeBase64(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length));
            },
            [&] {
                // hex argument
                r = HexStr(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length));
            },
            [&] {
                // bool argument
                r = fuzzed_data_provider.ConsumeBool() ? "true" : "false";
            },
            [&] {
                // range argument
                r = "[" + ToString(fuzzed_data_provider.ConsumeIntegral<int64_t>()) + "," + ToString(fuzzed_data_provider.ConsumeIntegral<int64_t>()) + "]";
            },
            [&] {
                // integral argument (int64_t)
                r = ToString(fuzzed_data_provider.ConsumeIntegral<int64_t>());
            },
            [&] {
                // integral argument (uint64_t)
                r = ToString(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
            },
            [&] {
                // floating point argument
                r = strprintf("%f", fuzzed_data_provider.ConsumeFloatingPoint<double>());
            },
            [&] {
                // tx destination argument
                r = EncodeDestination(ConsumeTxDestination(fuzzed_data_provider));
            },
            [&] {
                // u160 argument
                r = ConsumeUInt160(fuzzed_data_provider).ToString();
            },
            [&] {
                // uint256 argument
                r = ConsumeUInt256(fuzzed_data_provider).ToString();
            },
            [&] {
                // base32 argument
                r = EncodeBase32(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length));
            },
            [&] {
                // base58 argument
                r = EncodeBase58(MakeUCharSpan(fuzzed_data_provider.ConsumeRandomLengthString(max_base58_bytes_length)));
            },
            [&] {
                // base58 argument with checksum
                r = EncodeBase58Check(MakeUCharSpan(fuzzed_data_provider.ConsumeRandomLengthString(max_base58_bytes_length)));
            },
            [&] {
                // hex encoded block
                std::optional<CBlock> opt_block = ConsumeDeserializable<CBlock>(fuzzed_data_provider);
                if (!opt_block) {
                    return;
                }
                DataStream data_stream{SER_NETWORK, PROTOCOL_VERSION};
                data_stream << *opt_block;
                r = HexStr(data_stream);
            },
            [&] {
                // hex encoded block header
                std::optional<CBlockHeader> opt_block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
                if (!opt_block_header) {
                    return;
                }
                DataStream data_stream{SER_NETWORK, PROTOCOL_VERSION};
                data_stream << *opt_block_header;
                r = HexStr(data_stream);
            },
            [&] {
                // hex encoded tx
                std::optional<CMutableTransaction> opt_tx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
                if (!opt_tx) {
                    return;
                }
                DataStream data_stream{SER_NETWORK, fuzzed_data_provider.ConsumeBool() ? PROTOCOL_VERSION : (PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS)};
                data_stream << *opt_tx;
                r = HexStr(data_stream);
            },
            [&] {
                // base64 encoded psbt
                std::optional<PartiallySignedTransaction> opt_psbt = ConsumeDeserializable<PartiallySignedTransaction>(fuzzed_data_provider);
                if (!opt_psbt) {
                    return;
                }
                DataStream data_stream{SER_NETWORK, PROTOCOL_VERSION};
                data_stream << *opt_psbt;
                r = EncodeBase64({data_stream.begin(), data_stream.end()});
            },
            [&] {
                // base58 encoded key
                const std::vector<uint8_t> random_bytes = fuzzed_data_provider.ConsumeBytes<uint8_t>(32);
                CKey key;
                key.Set(random_bytes.begin(), random_bytes.end(), fuzzed_data_provider.ConsumeBool());
                if (!key.IsValid()) {
                    return;
                }
                r = EncodeSecret(key);
            },
            [&] {
                // hex encoded pubkey
                const std::vector<uint8_t> random_bytes = fuzzed_data_provider.ConsumeBytes<uint8_t>(32);
                CKey key;
                key.Set(random_bytes.begin(), random_bytes.end(), fuzzed_data_provider.ConsumeBool());
                if (!key.IsValid()) {
                    return;
                }
                r = HexStr(key.GetPubKey());
            });
        return r;
        */
}

pub fn consume_array_rpc_argument(fuzzed_data_provider: &mut FuzzedDataProvider) -> String {
    
    todo!();
        /*
            std::vector<std::string> scalar_arguments;
        while (fuzzed_data_provider.ConsumeBool()) {
            scalar_arguments.push_back(ConsumeScalarRPCArgument(fuzzed_data_provider));
        }
        return "[\"" + Join(scalar_arguments, "\",\"") + "\"]";
        */
}

pub fn consume_rpc_argument(fuzzed_data_provider: &mut FuzzedDataProvider) -> String {
    
    todo!();
        /*
            return fuzzed_data_provider.ConsumeBool() ? ConsumeScalarRPCArgument(fuzzed_data_provider) : ConsumeArrayRPCArgument(fuzzed_data_provider);
        */
}

pub fn initialize_rpc_fuzz_testing_setup() -> *mut RPCFuzzTestingSetup {
    
    todo!();
        /*
            static const auto setup = MakeNoLogFileContext<RPCFuzzTestingSetup>();
        SetRPCWarmupFinished();
        return setup.get();
        */
}

pub fn initialize_rpc()  {
    
    todo!();
        /*
            rpc_testing_setup = InitializeRPCFuzzTestingSetup();
        const std::vector<std::string> supported_rpc_commands = rpc_testing_setup->GetRPCCommands();
        for (const std::string& rpc_command : supported_rpc_commands) {
            const bool safe_for_fuzzing = std::find(RPC_COMMANDS_SAFE_FOR_FUZZING.begin(), RPC_COMMANDS_SAFE_FOR_FUZZING.end(), rpc_command) != RPC_COMMANDS_SAFE_FOR_FUZZING.end();
            const bool not_safe_for_fuzzing = std::find(RPC_COMMANDS_NOT_SAFE_FOR_FUZZING.begin(), RPC_COMMANDS_NOT_SAFE_FOR_FUZZING.end(), rpc_command) != RPC_COMMANDS_NOT_SAFE_FOR_FUZZING.end();
            if (!(safe_for_fuzzing || not_safe_for_fuzzing)) {
                std::cerr << "Error: RPC command \"" << rpc_command << "\" not found in RPC_COMMANDS_SAFE_FOR_FUZZING or RPC_COMMANDS_NOT_SAFE_FOR_FUZZING. Please update " << __FILE__ << ".\n";
                std::terminate();
            }
            if (safe_for_fuzzing && not_safe_for_fuzzing) {
                std::cerr << "Error: RPC command \"" << rpc_command << "\" found in *both* RPC_COMMANDS_SAFE_FOR_FUZZING and RPC_COMMANDS_NOT_SAFE_FOR_FUZZING. Please update " << __FILE__ << ".\n";
                std::terminate();
            }
        }
        const char* limit_to_rpc_command_env = std::getenv("LIMIT_TO_RPC_COMMAND");
        if (limit_to_rpc_command_env != nullptr) {
            g_limit_to_rpc_command = std::string{limit_to_rpc_command_env};
        }
        */
}

#[fuzz_test(initializer = "initialize_rpc")]
fn rpc() {
    todo!();
    /*
    
        FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
        SetMockTime(ConsumeTime(fuzzed_data_provider));
        const std::string rpc_command = fuzzed_data_provider.ConsumeRandomLengthString(64);
        if (!g_limit_to_rpc_command.empty() && rpc_command != g_limit_to_rpc_command) {
            return;
        }
        const bool safe_for_fuzzing = std::find(RPC_COMMANDS_SAFE_FOR_FUZZING.begin(), RPC_COMMANDS_SAFE_FOR_FUZZING.end(), rpc_command) != RPC_COMMANDS_SAFE_FOR_FUZZING.end();
        if (!safe_for_fuzzing) {
            return;
        }
        std::vector<std::string> arguments;
        while (fuzzed_data_provider.ConsumeBool()) {
            arguments.push_back(ConsumeRPCArgument(fuzzed_data_provider));
        }
        try {
            rpc_testing_setup->CallRPC(rpc_command, arguments);
        } catch (const UniValue&) {
        } catch (const std::runtime_error&) {
        }

    */
}