// 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))); }