Пример #1
0
// Validate script consensus conformance based on flags provided.
static bool check_consensus(const script& prevout_script,
    const transaction& current_tx, size_t input_index,
    uint32_t options)
{
    BITCOIN_ASSERT(input_index <= max_uint32);
    BITCOIN_ASSERT(input_index < current_tx.inputs.size());
    const auto input_index32 = static_cast<uint32_t>(input_index);
    const auto bip16_enabled = ((options & validation_options::p2sh) != 0);

#ifdef WITH_CONSENSUS
    using namespace bc::consensus;
    const auto previous_output_script = prevout_script.to_data(false);
    data_chunk current_transaction = current_tx.to_data();

    const auto flags = (bip16_enabled ? verify_flags_p2sh : verify_flags_none);
    const auto result = verify_script(current_transaction.data(),
        current_transaction.size(), previous_output_script.data(),
        previous_output_script.size(), input_index32, flags);

    const auto valid = (result == verify_result::verify_result_eval_true);
#else
    // Copy the const prevout script so it can be run.
    auto previous_output_script = prevout_script;
    const auto& current_input_script = current_tx.inputs[input_index].script;

    const auto valid = script::verify(current_input_script,
        previous_output_script, current_tx, input_index32, bip16_enabled);
#endif

    if (!valid)
        log::warning(LOG_VALIDATE) << "Invalid transaction ["
        << encode_hash(current_tx.hash()) << "]";

    return valid;
}
// Validate script consensus conformance based on flags provided.
bool validate_transaction::check_consensus(const script& prevout_script,
    const transaction& current_tx, size_t input_index, uint32_t flags)
{
    BITCOIN_ASSERT(input_index <= max_uint32);
    BITCOIN_ASSERT(input_index < current_tx.inputs.size());
    const auto input_index32 = static_cast<uint32_t>(input_index);

#ifdef WITH_CONSENSUS
    using namespace bc::consensus;
    const auto previous_output_script = prevout_script.to_data(false);
    data_chunk current_transaction = current_tx.to_data();

    // Convert native flags to libbitcoin-consensus flags.
    uint32_t consensus_flags = verify_flags_none;

    if ((flags & script_context::bip16_enabled) != 0)
        consensus_flags |= verify_flags_p2sh;

    if ((flags & script_context::bip65_enabled) != 0)
        consensus_flags |= verify_flags_checklocktimeverify;

    if ((flags & script_context::bip66_enabled) != 0)
        consensus_flags |= verify_flags_dersig;

    const auto result = verify_script(current_transaction.data(),
        current_transaction.size(), previous_output_script.data(),
        previous_output_script.size(), input_index32, consensus_flags);

    const auto valid = (result == verify_result::verify_result_eval_true);
#else
    // Copy the const prevout script so it can be run.
    auto previous_output_script = prevout_script;
    const auto& current_input_script = current_tx.inputs[input_index].script;

    const auto valid = script::verify(current_input_script,
        previous_output_script, current_tx, input_index32, flags);
#endif

    if (!valid)
        log::warning(LOG_BLOCKCHAIN)
            << "Invalid transaction ["
            << encode_hash(current_tx.hash()) << "]";

    return valid;
}
// TODO: cache transaction wire serialization.
code validate_input::verify_script(const transaction& tx, uint32_t input_index,
    uint32_t forks, bool use_libconsensus)
{
    if (!use_libconsensus)
        return script::verify(tx, input_index, forks);

    BITCOIN_ASSERT(input_index < tx.inputs().size());
    const auto& prevout = tx.inputs()[input_index].previous_output().metadata;
    const auto script_data = prevout.cache.script().to_data(false);
    const auto prevout_value = prevout.cache.value();

    const auto tx_data = tx.to_data(true, true);

    // libconsensus
    return convert_result(consensus::verify_script(tx_data.data(),
        tx_data.size(), script_data.data(), script_data.size(), prevout_value,
        input_index, convert_flags(forks)));
}