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
13 changes: 13 additions & 0 deletions src/impl/bitcoin_family/coin/base_p2p_messages.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@
#include <core/message.hpp>
#include <core/message_macro.hpp>

// READWRITE collision guard.
// The C2POOL_SERIALIZE_METHODS bodies below rely on core/pack.hpp's READWRITE
// contract (formatter.action(stream, ...)). btclibs/serialize.h, pulled
// transitively into some translation units, re-#defines READWRITE to the legacy
// (s, ser_action) contract and can win by include order, breaking every body here
// ("use of undeclared identifier 's' / 'ser_action'" on macOS arm64 / Linux).
// Re-assert the core contract so this header is include-order-independent; mirrors
// btc/coin/p2p_messages.hpp, whose include chain keeps the core macro active.
#ifdef READWRITE
# undef READWRITE
#endif
#define READWRITE(...) formatter.action(stream, __VA_ARGS__)

namespace bitcoin_family
{
namespace coin
Expand Down
1 change: 1 addition & 0 deletions src/impl/ltc/coin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set(ltc_coin_impl
p2p_node.cpp p2p_node.hpp
p2p_messages.hpp
node.hpp
coin_node.hpp coin_node.cpp
)

set(ltc_coin_interface
Expand Down
60 changes: 60 additions & 0 deletions src/impl/ltc/coin/coin_node.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "coin_node.hpp"

#include <stdexcept>
#include <utility>

namespace ltc
{

namespace coin
{

core::coin::WorkView CoinNode::get_work_view()
{
// No work source configured at all -> empty view.
if (!m_embedded && !m_rpc)
return {};

// Embedded preferred, external RPC fallback. getwork() throws
// std::runtime_error when no template can be produced -- propagated to the
// caller (web_server), matching the ICoinNode contract. Folds the old
// web_server.cpp:2167-2168 embedded-vs-rpc decision coin-side.
rpc::WorkData wd = m_embedded ? m_embedded->getwork() : m_rpc->getwork();

// Retain the FULL WorkData (incl. m_txs) coin-side. Variable::set takes its
// argument BY VALUE, so this copies wd; sequenced BEFORE the std::move()s
// below so the copy completes first -- never move out of wd beforehand.
// (Pre-seam this was web_server.cpp:2171-2172 m_coin_node->work.set(wd),
// which only ran in rpc mode; keeping it unconditional here is strictly
// safe -- the agnostic slice still leaves, the payload still stays.)
work.set(wd);

core::coin::WorkView v;
v.m_data = std::move(wd.m_data);
v.m_hashes = std::move(wd.m_hashes);
v.m_latency = wd.m_latency;
return v;
}

bool CoinNode::submit_block_hex(const std::string& block_hex, bool ignore_failure)
{
// Guard sits ahead of the submit: in embedded-only mode m_rpc can be null.
// Returning false is the correct "no RPC sink" result (mirrors the old
// web_server.cpp:2728 `if (m_coin_rpc)` guard).
if (!m_rpc)
return false;

// MWEB arity bridge: ltc NodeRPC::submit_block_hex is the 3-arg
// (block_hex, mweb, ignore_failure) form. The ICoinNode contract is the
// 2-arg coin-agnostic form, so we supply mweb="" here. The sole pre-seam
// caller (web_server.cpp:2730) already passed "" for mweb, so this is
// behaviour-preserving. FLAG (per integrator, for review): when MWEB
// submit grows a non-empty extension-block path, mweb must NOT be hard-""
// -- it would need a coin-side source (e.g. the retained WorkData) rather
// than a new arg on the shared seam, since mweb is LTC-specific.
return m_rpc->submit_block_hex(block_hex, "", ignore_failure);
}

} // namespace coin

} // namespace ltc
73 changes: 73 additions & 0 deletions src/impl/ltc/coin/coin_node.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#pragma once

// ---------------------------------------------------------------------------
// ltc::coin::CoinNode -- concrete core::coin::ICoinNode for LTC (family-1 P2
// WorkView seam). This is the REFERENCE impl the btc::coin::CoinNode mirrors
// (piece-5(c)); the control flow / sequencing here are the load-bearing part.
//
// m_embedded : CoinNodeInterface* -- EmbeddedCoinNode in-process source
// m_rpc : NodeRPC* -- external coin-RPC client
// work : Variable<rpc::WorkData> -- full per-coin WorkData kept coin-side
//
// web_server (shared core) historically held raw pointers to CONCRETE ltc types
// (ltc::coin::NodeRPC, ltc::interfaces::Node) and called getwork()/submit on
// them directly -- that names ltc:: symbols in web_server.cpp.o and breaks the
// BTC link. This type collapses the embedded-vs-rpc decision plus the full
// WorkData retention coin-side, and exposes only the coin-agnostic
// core::coin::ICoinNode contract across the seam (WorkView, 2-arg submit).
//
// MWEB arity: ltc::coin::NodeRPC::submit_block_hex is the 3-arg
// (block_hex, mweb, ignore_failure) LTC form. The ICoinNode override is the
// coin-agnostic 2-arg form; it forwards to the 3-arg rpc with mweb="" coin-side.
// The sole pre-seam caller (web_server.cpp:2730) already passed mweb="", so
// dropping the mweb slot across the seam is behaviour-preserving for MWEB
// submit. (See coin_node.cpp for the forward + the standing flag.)
// ---------------------------------------------------------------------------

#include <string>

#include <core/coin/node_iface.hpp>
#include <core/coin/work_view.hpp>
#include <core/events.hpp>

#include "rpc.hpp"
#include "rpc_data.hpp"
#include "template_builder.hpp"

namespace ltc
{

namespace coin
{

class CoinNode : public core::coin::ICoinNode
{
// Embedded in-process template source (EmbeddedCoinNode, via the
// CoinNodeInterface base). May be null when the node runs RPC-only.
// is_embedded() reports its presence.
CoinNodeInterface* m_embedded = nullptr;

// External coin-RPC client. May be null in embedded-only mode; it is the
// sole sink for submit_block_hex(). has_rpc() reports its presence.
NodeRPC* m_rpc = nullptr;

// Full per-coin WorkData (incl. vector<Transaction> m_txs) retained
// coin-side via work.set(wd); only the agnostic WorkView slice crosses the
// seam into core/web_server. Replaces the old ltc::interfaces::Node::work
// slot that web_server used to reach through m_coin_node.
Variable<rpc::WorkData> work;

public:
CoinNode(CoinNodeInterface* embedded, NodeRPC* rpc)
: m_embedded(embedded), m_rpc(rpc) {}

core::coin::WorkView get_work_view() override;
bool submit_block_hex(const std::string& block_hex, bool ignore_failure) override;

bool is_embedded() const override { return m_embedded != nullptr; }
bool has_rpc() const override { return m_rpc != nullptr; }
};

} // namespace coin

} // namespace ltc
Loading