diff --git a/builds/cmake/CMakeLists.txt b/builds/cmake/CMakeLists.txt index 351fb6f5..82e81bf7 100644 --- a/builds/cmake/CMakeLists.txt +++ b/builds/cmake/CMakeLists.txt @@ -61,7 +61,7 @@ project( libbitcoin-node LANGUAGES C CXX ) -set( repository_root_dir "${CMAKE_CURRENT_SOURCE_DIR}/../../" ) +set( repository_root_dir "${CMAKE_CURRENT_SOURCE_DIR}/../.." ) if ( MSVC ) set( CMAKE_STATIC_LIBRARY_PREFIX "lib" ) diff --git a/builds/gnu/Makefile.am b/builds/gnu/Makefile.am index 753dc613..2f59415c 100644 --- a/builds/gnu/Makefile.am +++ b/builds/gnu/Makefile.am @@ -57,7 +57,6 @@ src_libbitcoin_node_la_SOURCES = \ ${srcdir}/../../src/estimator.cpp \ ${srcdir}/../../src/full_node.cpp \ ${srcdir}/../../src/settings.cpp \ - ${srcdir}/../../src/validate.cpp \ ${srcdir}/../../src/channels/channel_peer.cpp \ ${srcdir}/../../src/chasers/chaser.cpp \ ${srcdir}/../../src/chasers/chaser_block.cpp \ @@ -115,7 +114,6 @@ include_bitcoin_node_HEADERS = \ ${srcdir}/../../include/bitcoin/node/events.hpp \ ${srcdir}/../../include/bitcoin/node/full_node.hpp \ ${srcdir}/../../include/bitcoin/node/settings.hpp \ - ${srcdir}/../../include/bitcoin/node/validate.hpp \ ${srcdir}/../../include/bitcoin/node/version.hpp include_bitcoin_node_channelsdir = \ diff --git a/builds/gnu/configure.ac b/builds/gnu/configure.ac index ce72f06e..4c67e1c4 100644 --- a/builds/gnu/configure.ac +++ b/builds/gnu/configure.ac @@ -68,7 +68,7 @@ AC_ARG_VAR([CC], "C compiler to use, such as gcc or clang") AC_ARG_VAR([CXX], "C++ compiler to use, such as g++ or clang++") AC_ARG_VAR([PKG_CONFIG_PATH], "Additional directories for package discovery.") -repository_root_dir="@abs_top_srcdir@/../.." +repository_root_dir=`cd "${srcdir}/../.." && pwd` # Check for baseline language coverage in the compiler for the C++20 standard. #------------------------------------------------------------------------------ diff --git a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj index 750d08b1..6d92f85f 100644 --- a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj +++ b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj @@ -164,7 +164,6 @@ - @@ -219,7 +218,6 @@ - diff --git a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters index 10876c36..7bbae4c3 100644 --- a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters +++ b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters @@ -186,9 +186,6 @@ src - - src - @@ -347,9 +344,6 @@ include\bitcoin\node - - include\bitcoin\node - include\bitcoin\node diff --git a/builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj b/builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj index c43c94a9..5a3101e5 100644 --- a/builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj +++ b/builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj @@ -164,7 +164,6 @@ - @@ -219,7 +218,6 @@ - diff --git a/builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj.filters b/builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj.filters index 10876c36..7bbae4c3 100644 --- a/builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj.filters +++ b/builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj.filters @@ -186,9 +186,6 @@ src - - src - @@ -347,9 +344,6 @@ include\bitcoin\node - - include\bitcoin\node - include\bitcoin\node diff --git a/include/bitcoin/node.hpp b/include/bitcoin/node.hpp index 7ce08dfe..27ee6414 100644 --- a/include/bitcoin/node.hpp +++ b/include/bitcoin/node.hpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/include/bitcoin/node/chasers/chaser_transaction.hpp b/include/bitcoin/node/chasers/chaser_transaction.hpp index 637c1865..8b0ec9c8 100644 --- a/include/bitcoin/node/chasers/chaser_transaction.hpp +++ b/include/bitcoin/node/chasers/chaser_transaction.hpp @@ -38,15 +38,29 @@ class BCN_API chaser_transaction code start() NOEXCEPT override; - virtual void store(const system::chain::transaction::cptr& block) NOEXCEPT; + /// Validate and archive a submitted package, accepted as a whole. + /// The package is only validated when test, so nothing is archived. + virtual void submit(const system::chain::transactions_cptr& txs, + bool test, submit_handler&& handler) NOEXCEPT; protected: virtual bool handle_chase(const code& ec, chase event_, event_value value) NOEXCEPT; - virtual void do_confirmed(header_t link) NOEXCEPT; - virtual void do_store( - const system::chain::transaction::cptr& header) NOEXCEPT; + virtual void do_submit(const system::chain::transactions_cptr& txs, + bool test, const submit_handler& handler) NOEXCEPT; + + /// Recompute the pool context, closing the pool if not current. + virtual void do_bump() NOEXCEPT; + +private: + code validate(size_t& index, + const system::chain::transaction_cptrs& txs) NOEXCEPT; + code validate(const system::chain::transaction& tx) NOEXCEPT; + + // These are protected by strand. + system::chain::context pool_{}; + bool pooling_{}; }; } // namespace node diff --git a/include/bitcoin/node/define.hpp b/include/bitcoin/node/define.hpp index 7fa8f00d..91e4f3a5 100644 --- a/include/bitcoin/node/define.hpp +++ b/include/bitcoin/node/define.hpp @@ -54,6 +54,7 @@ typedef std::function estimate_handler; /// Organization types. typedef std::function organize_handler; +typedef std::function submit_handler; typedef database::store store; typedef database::query query; diff --git a/include/bitcoin/node/error.hpp b/include/bitcoin/node/error.hpp index 42c68e88..3c2e2e49 100644 --- a/include/bitcoin/node/error.hpp +++ b/include/bitcoin/node/error.hpp @@ -59,6 +59,10 @@ enum error_t : uint8_t duplicate_block, duplicate_header, + /// transaction pool + pooling_disabled, + empty_package, + /// fee estimation estimate_disabled, estimate_premature, @@ -105,6 +109,7 @@ enum error_t : uint8_t confirm10, confirm11, confirm12, + transaction1, estimates_initialize, estimates_push1, estimates_push2, diff --git a/include/bitcoin/node/full_node.hpp b/include/bitcoin/node/full_node.hpp index 0f36eb57..9eba4fa9 100644 --- a/include/bitcoin/node/full_node.hpp +++ b/include/bitcoin/node/full_node.hpp @@ -73,6 +73,11 @@ class BCN_API full_node virtual void prioritize(const system::hash_digest& hash, organize_handler&& handler) NOEXCEPT; + /// Validate and archive a submitted package, accepted as a whole. + /// The package is only validated when test, so nothing is archived. + virtual void submit(const system::chain::transactions_cptr& txs, + bool test, submit_handler&& handler) NOEXCEPT; + /// Manage download queue. virtual void get_hashes(map_handler&& handler) NOEXCEPT; virtual void put_hashes(const map_ptr& map, diff --git a/include/bitcoin/node/protocols/protocol.hpp b/include/bitcoin/node/protocols/protocol.hpp index 4822057c..a6f580a9 100644 --- a/include/bitcoin/node/protocols/protocol.hpp +++ b/include/bitcoin/node/protocols/protocol.hpp @@ -112,6 +112,11 @@ class BCN_API protocol virtual void prioritize(const system::hash_digest& hash, organize_handler&& handler) NOEXCEPT; + /// Validate and archive a submitted package, accepted as a whole. + /// The package is only validated when test, so nothing is archived. + virtual void submit(const system::chain::transactions_cptr& txs, + bool test, submit_handler&& handler) NOEXCEPT; + /// Events subscription. /// ----------------------------------------------------------------------- diff --git a/include/bitcoin/node/protocols/protocol_transaction_out_106.hpp b/include/bitcoin/node/protocols/protocol_transaction_out_106.hpp index 192ae5f0..b7b858b8 100644 --- a/include/bitcoin/node/protocols/protocol_transaction_out_106.hpp +++ b/include/bitcoin/node/protocols/protocol_transaction_out_106.hpp @@ -36,7 +36,6 @@ class BCN_API protocol_transaction_out_106 const network::channel::ptr& channel) NOEXCEPT : node::protocol_peer(session, channel), node_witness_(session->node_settings().provide_witness), - broadcast_(maximum_retained), network::tracker(session->log) { } @@ -55,10 +54,6 @@ class BCN_API protocol_transaction_out_106 /// Process tx announcement. virtual bool do_announce(transaction_t link) NOEXCEPT; - virtual bool handle_broadcast_transaction(const code& ec, - const network::messages::peer::transaction::cptr& message, - uint64_t sender) NOEXCEPT; - virtual bool handle_receive_get_data(const code& ec, const network::messages::peer::get_data::cptr& message) NOEXCEPT; virtual void send_transaction(const code& ec, size_t index, @@ -71,28 +66,9 @@ class BCN_API protocol_transaction_out_106 virtual bool announce(const system::hash_digest& hash) NOEXCEPT; - /// Retain a broadcast tx, pending request by the peer. - virtual void retain(const system::hash_digest& hash, - const system::chain::transaction::cptr& tx) NOEXCEPT; - - /// Obtain and drop a retained tx, or nullptr. - virtual system::chain::transaction::cptr release( - const system::hash_digest& hash) NOEXCEPT; - private: - using retained_t = std::pair; - using retained_txs = boost::circular_buffer; - - static constexpr size_t maximum_retained = 42; - - retained_txs::iterator find(const system::hash_digest& hash) NOEXCEPT; - // These are thread safe. const bool node_witness_; - - // This is protected by strand. - retained_txs broadcast_; }; } // namespace node diff --git a/include/bitcoin/node/sessions/session.hpp b/include/bitcoin/node/sessions/session.hpp index 14644fe9..97ceaaf9 100644 --- a/include/bitcoin/node/sessions/session.hpp +++ b/include/bitcoin/node/sessions/session.hpp @@ -51,6 +51,11 @@ class BCN_API session virtual void prioritize(const system::hash_digest& hash, organize_handler&& handler) NOEXCEPT; + /// Validate and archive a submitted package, accepted as a whole. + /// The package is only validated when test, so nothing is archived. + virtual void submit(const system::chain::transactions_cptr& txs, + bool test, submit_handler&& handler) NOEXCEPT; + /// Manage download queue. virtual void get_hashes(map_handler&& handler) NOEXCEPT; virtual void put_hashes(const map_ptr& map, diff --git a/include/bitcoin/node/validate.hpp b/include/bitcoin/node/validate.hpp deleted file mode 100644 index 306192ed..00000000 --- a/include/bitcoin/node/validate.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) 2011-2026 libbitcoin developers - * - * This file is part of libbitcoin. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#ifndef LIBBITCOIN_NODE_VALIDATE_HPP -#define LIBBITCOIN_NODE_VALIDATE_HPP - -#include -#include - -namespace libbitcoin { -namespace node { - -/// Transaction validation against the confirmed chain, for services that -/// accept transactions from clients (there is no tx pool until v5). Shared -/// by the server protocols, which obtain the context of the next block. - -/// Validate tx in the given context, populating its prevout metadata. -/// Includes the block-rule guards, a DoS guard for standalone validation. -BCN_API code validate_transaction(const system::chain::transaction& tx, - const query& query, const system::chain::context& pool) NOEXCEPT; - -} // namespace node -} // namespace libbitcoin - -#endif diff --git a/src/chasers/chaser_transaction.cpp b/src/chasers/chaser_transaction.cpp index f1f2af0b..d59354ec 100644 --- a/src/chasers/chaser_transaction.cpp +++ b/src/chasers/chaser_transaction.cpp @@ -26,11 +26,13 @@ namespace libbitcoin { namespace node { #define CLASS chaser_transaction - + +using namespace system; using namespace system::chain; using namespace std::placeholders; BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) +BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR) chaser_transaction::chaser_transaction(full_node& node) NOEXCEPT : chaser(node) @@ -40,10 +42,10 @@ chaser_transaction::chaser_transaction(full_node& node) NOEXCEPT // start // ---------------------------------------------------------------------------- -// TODO: initialize tx graph from store, log and stop on error. code chaser_transaction::start() NOEXCEPT { SUBSCRIBE_CHASE(handle_chase, _1, _2, _3); + POST(do_bump); return error::success; } @@ -56,14 +58,14 @@ bool chaser_transaction::handle_chase(const code&, chase event_, if (closed()) return false; - // TODO: allow required messages. - ////// Stop generating query during suspension. - ////// Incoming events may already be flushed to the strand at this point. - ////if (suspended()) - //// return true; - switch (event_) { + case chase::organized: + case chase::reorganized: + { + POST(do_bump); + break; + } case chase::stop: { return false; @@ -77,34 +79,137 @@ bool chaser_transaction::handle_chase(const code&, chase event_, return true; } -// TODO: handle the new confirmed blocks (may issue 'transaction'). -void chaser_transaction::do_confirmed(header_t) NOEXCEPT +// The pool is closed until the confirmed chain is current, and closes again if +// currency is lost, though the store latch is one way, since the txs archived +// while it was open outlive it. +void chaser_transaction::do_bump() NOEXCEPT { BC_ASSERT(stranded()); + pooling_ = false; + + if (closed() || !is_current_chain(true)) + return; - notify(error::success, chase::transaction, transaction_t{}); + auto& query = archive(); + const auto top = query.get_top_confirmed(); + const auto state = query.get_confirmed_chain_state(system_settings(), + query.to_confirmed(top), top); + + if (!state) + { + fault(error::transaction1); + return; + } + + // The context of the next block, in which a pool tx would confirm. + pool_ = chain_state{ *state, system_settings() }.context(); + query.set_pooling(); + pooling_ = true; } // methods // ---------------------------------------------------------------------------- -void chaser_transaction::store(const transaction::cptr&) NOEXCEPT +void chaser_transaction::submit(const transactions_cptr& txs, bool test, + submit_handler&& handler) NOEXCEPT { - // Push new checked tx into store and update DAG. Issue transaction event - // so that candidate may construct a new template. + if (closed()) + return; + + POST(do_submit, txs, test, std::move(handler)); } // private -void chaser_transaction::do_store(const transaction::cptr&) NOEXCEPT +void chaser_transaction::do_submit(const transactions_cptr& txs, bool test, + const submit_handler& handler) NOEXCEPT { BC_ASSERT(stranded()); - // TODO: validate and store transaction. + if (closed()) + { + handler(network::error::service_stopped, {}); + return; + } - // Relay notification. - ////notify(error::success, chase::transaction, link); + if (!pooling_) + { + handler(error::pooling_disabled, {}); + return; + } + + size_t index{}; + if (const auto ec = validate(index, *txs)) + { + handler(ec, index); + return; + } + + if (test) + { + handler(error::success, {}); + return; + } + + auto& query = archive(); + for (index = {}; index < txs->size(); ++index) + { + database::tx_link link{}; + + // Disk full may leave package partly archived, resolves by resubmit. + if (const auto ec = query.set_code(link, *txs->at(index))) + { + handler(fault(ec), index); + return; + } + + fire(events::tx_archived, link); + notify(error::success, chase::transaction, transaction_t{ link }); + } + + handler(error::success, {}); } +// validation +// ---------------------------------------------------------------------------- + +code chaser_transaction::validate(size_t& index, + const transaction_cptrs& txs) NOEXCEPT +{ + index = zero; + if (txs.empty()) + return error::empty_package; + + if (const auto ec = block::populate(txs, pool_, false)) + return ec; + + for (; index < txs.size(); ++index) + if (const auto ec = validate(*txs.at(index))) + return ec; + + return {}; +} + +code chaser_transaction::validate(const chain::transaction& tx) NOEXCEPT +{ + code ec{}; + + // Ensure tx does not violate tx consensus rules. + if (!ec) ec = tx.check(); + if (!ec) ec = tx.check(pool_); + if (!ec) archive().populate_with_metadata(tx, true); + if (!ec) ec = tx.accept(pool_); + if (!ec) ec = tx.confirm(pool_); + if (!ec) ec = tx.connect(pool_); + + // Ensure tx does not violate presumed block consensus rules. + // This is a DoS guard when validating a tx outside of a block. + if (!ec) ec = tx.check_guard(); + if (!ec) ec = tx.check_guard(pool_); + if (!ec) ec = tx.accept_guard(pool_); + return ec; +} + +BC_POP_WARNING() BC_POP_WARNING() } // namespace node diff --git a/src/error.cpp b/src/error.cpp index 80953428..00fca068 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -49,6 +49,10 @@ DEFINE_ERROR_T_MESSAGE_MAP(error) { duplicate_block, "duplicate block" }, { duplicate_header, "duplicate header" }, + // transaction pool + { pooling_disabled, "pooling disabled" }, + { empty_package, "empty package" }, + // fee estimation { estimate_disabled, "estimate_disabled" }, { estimate_premature, "estimate_premature" }, @@ -95,6 +99,7 @@ DEFINE_ERROR_T_MESSAGE_MAP(error) { confirm10, "confirm10" }, { confirm11, "confirm11" }, { confirm12, "confirm12" }, + { transaction1, "transaction1" }, { estimates_initialize, "estimates_initialize" }, { estimates_push1, "estimates_push1" }, { estimates_push2, "estimates_push2" }, diff --git a/src/full_node.cpp b/src/full_node.cpp index 315c587d..3312fcd5 100644 --- a/src/full_node.cpp +++ b/src/full_node.cpp @@ -183,6 +183,12 @@ void full_node::prioritize(const system::hash_digest& hash, chaser_block_.prioritize(hash, std::move(handler)); } +void full_node::submit(const system::chain::transactions_cptr& txs, bool test, + submit_handler&& handler) NOEXCEPT +{ + chaser_transaction_.submit(txs, test, std::move(handler)); +} + void full_node::get_hashes(map_handler&& handler) NOEXCEPT { chaser_check_.get_hashes(std::move(handler)); diff --git a/src/protocols/protocol.cpp b/src/protocols/protocol.cpp index 99dad0f2..7eaa3c41 100644 --- a/src/protocols/protocol.cpp +++ b/src/protocols/protocol.cpp @@ -139,6 +139,12 @@ void protocol::prioritize(const system::hash_digest& hash, session_->prioritize(hash, std::move(handler)); } +void protocol::submit(const system::chain::transactions_cptr& txs, bool test, + submit_handler&& handler) NOEXCEPT +{ + session_->submit(txs, test, std::move(handler)); +} + void protocol::subscribe_chase(event_notifier&& handler) NOEXCEPT { // This is a shared instance multiply-derived from network::protocol. diff --git a/src/protocols/protocol_transaction_out_106.cpp b/src/protocols/protocol_transaction_out_106.cpp index ca0faabb..4ea50d1c 100644 --- a/src/protocols/protocol_transaction_out_106.cpp +++ b/src/protocols/protocol_transaction_out_106.cpp @@ -18,7 +18,6 @@ */ #include -#include #include namespace libbitcoin { @@ -47,7 +46,6 @@ void protocol_transaction_out_106::start() NOEXCEPT // Events subscription is asynchronous, events may be missed. subscribe_chase(BIND(handle_chase, _1, _2, _3)); - SUBSCRIBE_BROADCAST(transaction, handle_broadcast_transaction, _1, _2, _3); SUBSCRIBE_CHANNEL(get_data, handle_receive_get_data, _1, _2); protocol_peer::start(); } @@ -58,8 +56,6 @@ void protocol_transaction_out_106::stopping(const code& ec) NOEXCEPT // Unsubscriber race is ok. unsubscribe_chase(); - - UNSUBSCRIBE_BROADCAST(); protocol_peer::stopping(ec); } @@ -106,26 +102,6 @@ bool protocol_transaction_out_106::do_announce(transaction_t link) NOEXCEPT return announce(archive().get_tx_key(link)); } -bool protocol_transaction_out_106::handle_broadcast_transaction(const code& ec, - const transaction::cptr& message, uint64_t sender) NOEXCEPT -{ - BC_ASSERT(stranded()); - - if (stopped(ec)) - return false; - - if (sender == identifier()) - return true; - - const auto& tx = message->transaction_ptr; - const auto hash = tx->hash(false); - if (was_announced(hash)) - return true; - - retain(hash, tx); - return announce(hash); -} - bool protocol_transaction_out_106::announce(const hash_digest& hash) NOEXCEPT { BC_ASSERT(stranded()); @@ -146,45 +122,6 @@ bool protocol_transaction_out_106::announce(const hash_digest& hash) NOEXCEPT return true; } -// Retention. -// ---------------------------------------------------------------------------- - -void protocol_transaction_out_106::retain(const hash_digest& hash, - const chain::transaction::cptr& tx) NOEXCEPT -{ - BC_ASSERT(stranded()); - - if (find(hash) != broadcast_.end()) - return; - - broadcast_.push_back({ hash, tx }); -} - -chain::transaction::cptr protocol_transaction_out_106::release( - const hash_digest& hash) NOEXCEPT -{ - BC_ASSERT(stranded()); - - const auto it = find(hash); - if (it == broadcast_.end()) - return {}; - - const auto tx = it->second; - broadcast_.erase(it); - return tx; -} - -protocol_transaction_out_106::retained_txs::iterator -protocol_transaction_out_106::find(const hash_digest& hash) NOEXCEPT -{ - const auto match = [&hash](const auto& entry) NOEXCEPT - { - return entry.first == hash; - }; - - return std::find_if(broadcast_.begin(), broadcast_.end(), match); -} - // Inbound (get_data). // ---------------------------------------------------------------------------- @@ -238,13 +175,6 @@ void protocol_transaction_out_106::send_transaction(const code& ec, return; } - // A broadcast tx is not archived, so is served from retention, once. - if (const auto retained = release(item.hash)) - { - SEND(transaction{ retained }, send_transaction, _1, add1(index), message); - return; - } - // Tx could be always queried with witness and therefore safely cached. // If can then be serialized according to channel configuration, however // that is currently fixed to witness as available in the object. diff --git a/src/sessions/session.cpp b/src/sessions/session.cpp index 9643c009..a01275ec 100644 --- a/src/sessions/session.cpp +++ b/src/sessions/session.cpp @@ -57,6 +57,12 @@ void session::prioritize(const hash_digest& hash, node_.prioritize(hash, std::move(handler)); } +void session::submit(const transactions_cptr& txs, bool test, + submit_handler&& handler) NOEXCEPT +{ + node_.submit(txs, test, std::move(handler)); +} + void session::get_hashes(map_handler&& handler) NOEXCEPT { node_.get_hashes(std::move(handler)); diff --git a/src/validate.cpp b/src/validate.cpp deleted file mode 100644 index e84ba92e..00000000 --- a/src/validate.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (c) 2011-2026 libbitcoin developers - * - * This file is part of libbitcoin. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#include - -#include - -namespace libbitcoin { -namespace node { - -using namespace system; - -code validate_transaction(const chain::transaction& tx, const query& query, - const chain::context& pool) NOEXCEPT -{ - code ec{}; - - // Ensure tx does not violate tx consensus rules. - if (!ec) ec = tx.check(); - if (!ec) ec = tx.check(pool); - if (!ec) query.populate_with_metadata(tx, true); - if (!ec) ec = tx.accept(pool); - if (!ec) ec = tx.confirm(pool); - if (!ec) ec = tx.connect(pool); - - // Ensure tx does not violate presumed block consensus rules. - // This is a DoS guard when validating a tx outside of a block. - if (!ec) ec = tx.check_guard(); - if (!ec) ec = tx.check_guard(pool); - if (!ec) ec = tx.accept_guard(pool); - return ec; -} - -} // namespace node -} // namespace libbitcoin