Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions builds/gnu/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ src_libbitcoin_node_la_SOURCES = \
${srcdir}/../../src/protocols/protocol_transaction_in_106.cpp \
${srcdir}/../../src/protocols/protocol_transaction_out_106.cpp \
${srcdir}/../../src/protocols/protocol_transaction_out_70001.cpp \
${srcdir}/../../src/protocols/protocol_transaction_out_70013.cpp \
${srcdir}/../../src/sessions/session.cpp \
${srcdir}/../../src/sessions/session_inbound.cpp \
${srcdir}/../../src/sessions/session_manual.cpp \
Expand Down Expand Up @@ -175,6 +176,7 @@ include_bitcoin_node_protocols_HEADERS = \
${srcdir}/../../include/bitcoin/node/protocols/protocol_transaction_in_106.hpp \
${srcdir}/../../include/bitcoin/node/protocols/protocol_transaction_out_106.hpp \
${srcdir}/../../include/bitcoin/node/protocols/protocol_transaction_out_70001.hpp \
${srcdir}/../../include/bitcoin/node/protocols/protocol_transaction_out_70013.hpp \
${srcdir}/../../include/bitcoin/node/protocols/protocols.hpp

include_bitcoin_node_sessionsdir = \
Expand Down
2 changes: 2 additions & 0 deletions builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
<ClCompile Include="..\..\..\..\src\protocols\protocol_transaction_in_106.cpp" />
<ClCompile Include="..\..\..\..\src\protocols\protocol_transaction_out_106.cpp" />
<ClCompile Include="..\..\..\..\src\protocols\protocol_transaction_out_70001.cpp" />
<ClCompile Include="..\..\..\..\src\protocols\protocol_transaction_out_70013.cpp" />
<ClCompile Include="..\..\..\..\src\sessions\session.cpp" />
<ClCompile Include="..\..\..\..\src\sessions\session_inbound.cpp" />
<ClCompile Include="..\..\..\..\src\sessions\session_manual.cpp" />
Expand Down Expand Up @@ -210,6 +211,7 @@
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocol_transaction_in_106.hpp" />
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocol_transaction_out_106.hpp" />
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocol_transaction_out_70001.hpp" />
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocol_transaction_out_70013.hpp" />
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocols.hpp" />
<ClInclude Include="..\..\..\..\include\bitcoin\node\sessions\session.hpp" />
<ClInclude Include="..\..\..\..\include\bitcoin\node\sessions\session_inbound.hpp" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@
<ClCompile Include="..\..\..\..\src\protocols\protocol_transaction_out_70001.cpp">
<Filter>src\protocols</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\src\protocols\protocol_transaction_out_70013.cpp">
<Filter>src\protocols</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\src\sessions\session.cpp">
<Filter>src\sessions</Filter>
</ClCompile>
Expand Down Expand Up @@ -320,6 +323,9 @@
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocol_transaction_out_70001.hpp">
<Filter>include\bitcoin\node\protocols</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocol_transaction_out_70013.hpp">
<Filter>include\bitcoin\node\protocols</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocols.hpp">
<Filter>include\bitcoin\node\protocols</Filter>
</ClInclude>
Expand Down
2 changes: 2 additions & 0 deletions builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
<ClCompile Include="..\..\..\..\src\protocols\protocol_transaction_in_106.cpp" />
<ClCompile Include="..\..\..\..\src\protocols\protocol_transaction_out_106.cpp" />
<ClCompile Include="..\..\..\..\src\protocols\protocol_transaction_out_70001.cpp" />
<ClCompile Include="..\..\..\..\src\protocols\protocol_transaction_out_70013.cpp" />
<ClCompile Include="..\..\..\..\src\sessions\session.cpp" />
<ClCompile Include="..\..\..\..\src\sessions\session_inbound.cpp" />
<ClCompile Include="..\..\..\..\src\sessions\session_manual.cpp" />
Expand Down Expand Up @@ -210,6 +211,7 @@
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocol_transaction_in_106.hpp" />
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocol_transaction_out_106.hpp" />
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocol_transaction_out_70001.hpp" />
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocol_transaction_out_70013.hpp" />
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocols.hpp" />
<ClInclude Include="..\..\..\..\include\bitcoin\node\sessions\session.hpp" />
<ClInclude Include="..\..\..\..\include\bitcoin\node\sessions\session_inbound.hpp" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@
<ClCompile Include="..\..\..\..\src\protocols\protocol_transaction_out_70001.cpp">
<Filter>src\protocols</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\src\protocols\protocol_transaction_out_70013.cpp">
<Filter>src\protocols</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\src\sessions\session.cpp">
<Filter>src\sessions</Filter>
</ClCompile>
Expand Down Expand Up @@ -320,6 +323,9 @@
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocol_transaction_out_70001.hpp">
<Filter>include\bitcoin\node\protocols</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocol_transaction_out_70013.hpp">
<Filter>include\bitcoin\node\protocols</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\include\bitcoin\node\protocols\protocols.hpp">
<Filter>include\bitcoin\node\protocols</Filter>
</ClInclude>
Expand Down
1 change: 1 addition & 0 deletions include/bitcoin/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#include <bitcoin/node/protocols/protocol_transaction_in_106.hpp>
#include <bitcoin/node/protocols/protocol_transaction_out_106.hpp>
#include <bitcoin/node/protocols/protocol_transaction_out_70001.hpp>
#include <bitcoin/node/protocols/protocol_transaction_out_70013.hpp>
#include <bitcoin/node/protocols/protocols.hpp>
#include <bitcoin/node/sessions/session.hpp>
#include <bitcoin/node/sessions/session_inbound.hpp>
Expand Down
1 change: 1 addition & 0 deletions include/bitcoin/node/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ enum error_t : uint8_t

/// transaction pool
pooling_disabled,
insufficient_fee,
empty_package,

/// fee estimation
Expand Down
4 changes: 3 additions & 1 deletion include/bitcoin/node/impl/sessions/session_peer.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ inline void CLASS::attach_protocols(const channel_ptr& channel) NOEXCEPT
// Relay is configured, active, and txs are ready (txs in/out).
if (txs_in_out && peer->peer_version()->relay)
{
if (peer->is_negotiated(level::bip37))
if (peer->is_negotiated(level::bip133))
channel->attach<protocol_transaction_out_70013>(self)->start();
else if (peer->is_negotiated(level::bip37))
channel->attach<protocol_transaction_out_70001>(self)->start();
else
channel->attach<protocol_transaction_out_106>(self)->start();
Expand Down
63 changes: 63 additions & 0 deletions include/bitcoin/node/protocols/protocol_transaction_out_70013.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef LIBBITCOIN_NODE_PROTOCOLS_PROTOCOL_TRANSACTION_OUT_70013_HPP
#define LIBBITCOIN_NODE_PROTOCOLS_PROTOCOL_TRANSACTION_OUT_70013_HPP

#include <bitcoin/node/define.hpp>
#include <bitcoin/node/protocols/protocol_transaction_out_70001.hpp>

namespace libbitcoin {
namespace node {

class BCN_API protocol_transaction_out_70013
: public protocol_transaction_out_70001,
protected network::tracker<protocol_transaction_out_70013>
{
public:
typedef std::shared_ptr<protocol_transaction_out_70013> ptr;

protocol_transaction_out_70013(const auto& session,
const network::channel::ptr& channel) NOEXCEPT
: protocol_transaction_out_70001(session, channel),
network::tracker<protocol_transaction_out_70013>(session->log)
{
}

/// Start protocol (strand required).
void start() NOEXCEPT override;

protected:
/// Capture the peer's minimum fee rate for announcements.
virtual bool handle_receive_fee_filter(const code& ec,
const network::messages::peer::fee_filter::cptr& message) NOEXCEPT;

/// Bypasses announcement of a tx below the peer's minimum fee rate.
bool do_announce(transaction_t link) NOEXCEPT override;

private:
bool insufficient(const database::fee_rate& rate) const NOEXCEPT;

// This is protected by strand.
uint64_t minimum_fee_{};
};

} // namespace node
} // namespace libbitcoin

#endif
1 change: 1 addition & 0 deletions include/bitcoin/node/protocols/protocols.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@
#include <bitcoin/node/protocols/protocol_transaction_in_106.hpp>
#include <bitcoin/node/protocols/protocol_transaction_out_106.hpp>
#include <bitcoin/node/protocols/protocol_transaction_out_70001.hpp>
#include <bitcoin/node/protocols/protocol_transaction_out_70013.hpp>

#endif
1 change: 1 addition & 0 deletions include/bitcoin/node/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class BCN_API settings
virtual size_t maximum_height_() const NOEXCEPT;
virtual size_t maximum_concurrency_() const NOEXCEPT;
virtual size_t fee_estimate_horizon_() const NOEXCEPT;
virtual uint64_t minimum_fee_rate_() const NOEXCEPT;
virtual uint64_t services_provided() const NOEXCEPT;
virtual uint64_t services_required() const NOEXCEPT;
virtual bool fee_estimate_enabled() const NOEXCEPT;
Expand Down
30 changes: 27 additions & 3 deletions src/chasers/chaser_transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ using namespace system;
using namespace system::chain;
using namespace std::placeholders;

constexpr uint64_t vbytes_per_vkbyte = 1'000;

BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)

Expand Down Expand Up @@ -179,13 +181,33 @@ code chaser_transaction::validate(size_t& index,
if (txs.empty())
return error::empty_package;

// Conflict within the package, as with a block, since it is accepted whole.
if (block::is_internal_double_spend(txs, false))
return system::error::block_internal_double_spend;

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;

// The package is accepted as a whole, so the whole must pay the rate.
index = zero;
uint64_t fee{};
uint64_t size{};
for (const auto& tx: txs)
{
fee = ceilinged_add(fee, tx->fee());
size = ceilinged_add(size, possible_wide_cast<uint64_t>(
tx->virtual_size()));
}

// Compared in satoshis per virtual kilobyte, so exact and undivided.
if (ceilinged_multiply(fee, vbytes_per_vkbyte) <
ceilinged_multiply(node_settings().minimum_fee_rate_(), size))
return error::insufficient_fee;

return {};
}

Expand All @@ -196,16 +218,18 @@ code chaser_transaction::validate(const chain::transaction& tx) NOEXCEPT
// 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) archive().populate_with_metadata(tx, true, 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_);
if (!ec) ec = tx.confirm_guard(pool_);

// Script validation is the most costly, so it follows the guards.
if (!ec) ec = tx.connect(pool_);
return ec;
}

Expand Down
1 change: 1 addition & 0 deletions src/error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ DEFINE_ERROR_T_MESSAGE_MAP(error)

// transaction pool
{ pooling_disabled, "pooling disabled" },
{ insufficient_fee, "insufficient fee" },
{ empty_package, "empty package" },

// fee estimation
Expand Down
106 changes: 106 additions & 0 deletions src/protocols/protocol_transaction_out_70013.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/**
* 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 <http://www.gnu.org/licenses/>.
*/
#include <bitcoin/node/protocols/protocol_transaction_out_70013.hpp>

#include <bitcoin/node/define.hpp>

namespace libbitcoin {
namespace node {

#define CLASS protocol_transaction_out_70013

using namespace system;
using namespace network::messages::peer;
using namespace std::placeholders;

// The fee filter is expressed in satoshis per virtual kilobyte (bip133).
constexpr uint64_t vbytes_per_vkbyte = 1'000;

// Shared pointers required for lifetime in handler parameters.
BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED)
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)

// start
// ----------------------------------------------------------------------------

void protocol_transaction_out_70013::start() NOEXCEPT
{
BC_ASSERT(stranded());

if (started())
return;

SUBSCRIBE_CHANNEL(fee_filter, handle_receive_fee_filter, _1, _2);
protocol_transaction_out_70001::start();
}

// Inbound (feefilter).
// ----------------------------------------------------------------------------

bool protocol_transaction_out_70013::handle_receive_fee_filter(const code& ec,
const fee_filter::cptr& message) NOEXCEPT
{
BC_ASSERT(stranded());

if (stopped(ec))
return false;

minimum_fee_ = message->minimum_fee;
return true;
}

// Outbound (inv).
// ----------------------------------------------------------------------------

bool protocol_transaction_out_70013::do_announce(transaction_t link) NOEXCEPT
{
BC_ASSERT(stranded());

if (stopped())
return false;

// The tx is archived and its prevouts populated, so the rate is known.
database::fee_rate rate{};
if (!archive().get_tx_fees(rate, link))
{
fault(database::error::integrity);
return false;
}

// bip133: the peer is not sent a tx below the rate it advertised.
if (insufficient(rate))
return true;

return protocol_transaction_out_70001::do_announce(link);
}

// private
bool protocol_transaction_out_70013::insufficient(
const database::fee_rate& rate) const NOEXCEPT
{
return ceilinged_multiply(rate.fee, vbytes_per_vkbyte) <
ceilinged_multiply(minimum_fee_,
possible_wide_cast<uint64_t>(rate.bytes));
}

BC_POP_WARNING()
BC_POP_WARNING()

} // namespace node
} // namespace libbitcoin
8 changes: 8 additions & 0 deletions src/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ size_t settings::maximum_concurrency_() const NOEXCEPT
return to_bool(maximum_concurrency) ? maximum_concurrency : max_size_t;
}

// The configured rate is btc/vkb, as reported to clients (see relayfee).
uint64_t settings::minimum_fee_rate_() const NOEXCEPT
{
// Ceilinged, as a configured minimum is not rounded down.
return to_ceilinged_integer<uint64_t>(minimum_fee_rate *
chain::satoshi_per_bitcoin);
}

size_t settings::fee_estimate_horizon_() const NOEXCEPT
{
return std::min<size_t>(fee_estimate_horizon, estimator::maximum_horizon);
Expand Down
1 change: 1 addition & 0 deletions test/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ BOOST_AUTO_TEST_CASE(settings__node__default_context__expected)
BOOST_REQUIRE_EQUAL(node.provide_filters, false);
BOOST_REQUIRE_EQUAL(node.limited_blocks, false);
BOOST_REQUIRE_EQUAL(node.minimum_fee_rate, 0.0);
BOOST_REQUIRE_EQUAL(node.minimum_fee_rate_(), 0_u64);
BOOST_REQUIRE_EQUAL(node.minimum_bump_rate, 0.0);
BOOST_REQUIRE_EQUAL(node.allowed_deviation, 1.5);
BOOST_REQUIRE_EQUAL(node.batch_signatures, 0_u64);
Expand Down