Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
b1c0273
bch(coin): port rpc_data + transaction into bch::coin (M3 slice 1)
frstrtr Jun 15, 2026
56a3301
bch(coin): port block + txidcache into bch::coin (M3 slice 2)
frstrtr Jun 16, 2026
0fadfb9
bch(coin): port node_interface + CoinNodeInterface into bch::coin (M3…
frstrtr Jun 16, 2026
59a5aeb
bch(coin): port NodeRPC decl + concrete CoinNode seam (M3 slice 4)
frstrtr Jun 16, 2026
adc1d0b
bch(coin): port rpc.cpp body + config_pool + softfork_check (M3 slice 5)
frstrtr Jun 16, 2026
4b15148
bch(coin): port chain_seeds with BCH DNS seeds (M3 slice 6)
frstrtr Jun 16, 2026
3c40145
bch(coin): port p2p_messages wire layer (M3 slice 7)
frstrtr Jun 16, 2026
21bf392
bch(coin): port mempool with BCH byte-size + no-witness divergences (…
frstrtr Jun 16, 2026
a991889
bch(coin): port compact_blocks (BIP152) with BCH no-witness + txid sh…
frstrtr Jun 16, 2026
1a7aafe
bch(coin): wire BIP152 cmpct carriers into p2p_messages + Handler (M3…
frstrtr Jun 16, 2026
550f788
bch(coin): port p2p_connection per-peer request/reply matcher (M3 sli…
frstrtr Jun 16, 2026
1baed0f
bch(coin): port p2p_node embedded peer driver (M3 slice 12)
frstrtr Jun 16, 2026
0fe2542
bch(coin): port embedded Node front-end + config-resolve site (M3 sli…
frstrtr Jun 16, 2026
6b438c2
bch(config): port config.hpp aggregator + reconcile config_coin.hpp (…
frstrtr Jun 16, 2026
760b90a
bch(config): port config_coin.cpp CoinConfig get_default/load body (M…
frstrtr Jun 16, 2026
23c7585
bch(consensus): version-gate donation script + wire donation_consensu…
frstrtr Jun 16, 2026
d80a980
bch(pplns): port PPLNS window accumulator + expected-payouts entry po…
frstrtr Jun 16, 2026
56a2e29
bch(share): port share/share_check/share_types/share_messages + cstdi…
frstrtr Jun 16, 2026
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
136 changes: 136 additions & 0 deletions src/impl/bch/coin/block.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#pragma once

#include "transaction.hpp"

#include <core/uint256.hpp>
#include <core/pack_types.hpp>
#include <core/netaddress.hpp>

// ---------------------------------------------------------------------------
// bch::coin block -- ported from src/impl/btc/coin/block.hpp.
//
// >>> BCH DIVERGENCES <<<
// * NO SegWit (M1 §4.1): the block tx vector is serialized with the plain
// legacy encoding -- the BTC source wrapped it in TX_WITH_WITNESS(m_txs);
// BCH has no witness data, so m_txs serializes directly via the legacy
// Transaction format (see transaction.hpp banner).
// * CTOR (Canonical Transaction Ordering, Nov 2018 fork): non-coinbase txs
// in a block MUST be ordered by ascending txid. CTOR is a consensus rule
// enforced by the template builder / validation path, NOT by this struct --
// BlockType stores txs in whatever order it is given. The ordering insertion
// point lives in coin/template_builder.hpp (a later slice).
//
// The 80-byte block header (version|prev|merkle|time|bits|nonce) is structurally
// identical to BTC. The ASERT DAA (Nov 2020) changes how m_bits is *computed*,
// not the header layout, so BlockHeaderType is unchanged here.
// ---------------------------------------------------------------------------

namespace bch
{

namespace coin
{

struct SmallBlockHeaderType
{
uint64_t m_version {};
uint256 m_previous_block{};
uint32_t m_timestamp{};
uint32_t m_bits{};
uint32_t m_nonce{};

C2POOL_SERIALIZE_METHODS(SmallBlockHeaderType) { READWRITE(VarInt(obj.m_version), obj.m_previous_block, obj.m_timestamp, obj.m_bits, obj.m_nonce); }

SmallBlockHeaderType() {}

void SetNull()
{
m_version = 0;
m_previous_block.SetNull();
m_timestamp = 0;
m_bits = 0;
m_nonce = 0;
}

bool IsNull() const
{
return (m_bits == 0);
}
};

struct BlockHeaderType : SmallBlockHeaderType
{
uint256 m_merkle_root;

// Full block header uses fixed 4-byte int32 version (not VarInt like SmallBlockHeaderType)
template<typename Stream>
void Serialize(Stream& s) const {
uint32_t version32 = static_cast<uint32_t>(m_version);
::Serialize(s, version32);
::Serialize(s, m_previous_block);
::Serialize(s, m_merkle_root);
::Serialize(s, m_timestamp);
::Serialize(s, m_bits);
::Serialize(s, m_nonce);
}
template<typename Stream>
void Unserialize(Stream& s) {
uint32_t version32;
::Unserialize(s, version32);
m_version = version32;
::Unserialize(s, m_previous_block);
::Unserialize(s, m_merkle_root);
::Unserialize(s, m_timestamp);
::Unserialize(s, m_bits);
::Unserialize(s, m_nonce);
}

BlockHeaderType() : SmallBlockHeaderType() { }

void SetNull()
{
SmallBlockHeaderType::SetNull();
m_merkle_root.SetNull();
}

bool IsNull() const
{
return (m_bits == 0);
}

};

struct BlockType : BlockHeaderType
{
std::vector<MutableTransaction> m_txs;

// BCH: legacy (no-witness) tx-vector serialization -- see file banner.
template <typename Stream>
void Serialize(Stream& s) const {
BlockHeaderType::Serialize(s);
::Serialize(s, m_txs);
}

template <typename Stream>
void Unserialize(Stream& s) {
BlockHeaderType::Unserialize(s);
::Unserialize(s, m_txs);
}

BlockType() : BlockHeaderType() { }

void SetNull()
{
BlockHeaderType::SetNull();
m_txs.clear();
}

bool IsNull() const
{
return BlockHeaderType::IsNull();
}
};

} // namespace coin

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

/// DNS seed hostnames and hardcoded fallback IPs for Bitcoin Cash P2P networks.
/// Source: ref bitcoin-cash-node/src/chainparams.cpp (vSeeds.emplace_back +
/// nDefaultPort per CChainParams subclass).
///
/// BCH shares BTC default ports on mainnet (8333) and testnet3 (18333) by fork
/// inheritance, but the DNS seed hostnames are entirely BCH-operated and
/// disjoint from Bitcoin Core's. testnet4 (28333) and the ports above are the
/// BCHN-specific values, NOT the BTC testnet4 (48333) set in btc/coin/.
///
/// Trailing-dot convention from btc/coin/chain_seeds.hpp is intentionally NOT
/// applied here: BCHN chainparams stores the hostnames bare, and the BCH DNS
/// seeders are matched against bare names by the reference daemon.

#include <core/dns_seeder.hpp>
#include <core/netaddress.hpp>
#include <vector>

namespace bch {
namespace coin {

/// DNS seeds for Bitcoin Cash mainnet (port 8333).
/// Source: bitcoin-cash-node/src/chainparams.cpp lines 210-229.
inline std::vector<c2pool::dns::DnsSeed> bch_mainnet_dns_seeds()
{
return {
{"seed.flowee.cash", 8333},
{"seed-bch.bitcoinforks.org", 8333},
{"btccash-seeder.bitcoinunlimited.info", 8333},
{"seed.bchd.cash", 8333},
{"seed.bch.loping.net", 8333},
{"dnsseed.electroncash.de", 8333},
{"bchseed.c3-soft.com", 8333},
{"bch.bitjson.com", 8333},
};
}

/// DNS seeds for Bitcoin Cash testnet3 (port 18333).
/// Source: bitcoin-cash-node/src/chainparams.cpp lines 467-471.
inline std::vector<c2pool::dns::DnsSeed> bch_testnet_dns_seeds()
{
return {
{"testnet-seed.bchd.cash", 18333},
{"seed.tbch.loping.net", 18333},
{"testnet-seed.bitcoinunlimited.info", 18333},
};
}

/// DNS seeds for Bitcoin Cash testnet4 (port 28333).
/// Source: bitcoin-cash-node/src/chainparams.cpp lines 682-688.
/// testnet4 is the preferred c2pool-bch M3 integration target — small, fresh.
inline std::vector<c2pool::dns::DnsSeed> bch_testnet4_dns_seeds()
{
return {
{"testnet4-seed-bch.toom.im", 28333},
{"seed.tbch4.loping.net", 28333},
{"testnet4-seed.flowee.cash", 28333},
{"testnet4.bitjson.com", 28333},
};
}

/// Hardcoded fallback peers for Bitcoin Cash mainnet (port 8333).
/// Used if DNS seeds fail after 60 seconds. Sample of the BCHN-operated DNS
/// seed hosts themselves (long-running, dual DNS+node) — replace with current
/// top-uptime peers if these become stale.
inline std::vector<NetService> bch_mainnet_fixed_seeds()
{
return {
{"seed.flowee.cash", 8333},
{"seed.bch.loping.net", 8333},
{"seed.bchd.cash", 8333},
{"bch.bitjson.com", 8333},
};
}

/// Hardcoded fallback peers for Bitcoin Cash testnet3.
inline std::vector<NetService> bch_testnet_fixed_seeds()
{
return {
{"seed.tbch.loping.net", 18333},
{"testnet-seed.bchd.cash", 18333},
};
}

/// Hardcoded fallback peers for Bitcoin Cash testnet4.
inline std::vector<NetService> bch_testnet4_fixed_seeds()
{
return {
{"seed.tbch4.loping.net", 28333},
{"testnet4.bitjson.com", 28333},
};
}

/// Get DNS seeds for the appropriate BCH network.
/// (testnet currently routes to testnet3 — switch to bch_testnet4_dns_seeds()
/// in the M3 live-validation step if testnet4 is the integration target.)
inline std::vector<c2pool::dns::DnsSeed> bch_dns_seeds(bool testnet)
{
return testnet ? bch_testnet_dns_seeds() : bch_mainnet_dns_seeds();
}

/// Get fixed fallback seeds for the appropriate BCH network.
inline std::vector<NetService> bch_fixed_seeds(bool testnet)
{
return testnet ? bch_testnet_fixed_seeds() : bch_mainnet_fixed_seeds();
}

} // namespace coin
} // namespace bch
50 changes: 50 additions & 0 deletions src/impl/bch/coin/coin_node.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include "coin_node.hpp"

#include <stdexcept>
#include <utility>

namespace bch
{

namespace coin
{

core::coin::WorkView CoinNode::get_work_view()
{
// No work source configured at all -> empty view (1:1 with the btc/ltc reference).
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.
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.
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-preferred mode m_rpc can be
// null. Returning false is the correct "no RPC sink" result.
if (!m_rpc)
return false;

// BCH's NodeRPC::submit_block_hex is the agnostic 2-arg/no-mweb form (MWEB
// is LTC-specific and absent here), so we forward directly -- no 3-arg
// mweb="" coin-side overload exists or is needed for BCH.
return m_rpc->submit_block_hex(block_hex, ignore_failure);
}

} // namespace coin

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

// ---------------------------------------------------------------------------
// bch::coin::CoinNode -- concrete core::coin::ICoinNode for BCH (family-1 P2
// WorkView seam). 1:1 mirror of the btc::coin::CoinNode reference, member-mapped
// onto BCH's node types (M3 slices 1-4):
// m_embedded : CoinNodeInterface* -- embedded in-process work source
// m_rpc : NodeRPC* -- external coin-RPC client
// work : Variable<rpc::WorkData> -- full per-coin WorkData kept coin-side
//
// Build-INERT: defines the type but is NOT yet wired into web_server (a separate
// member-wiring cluster). impl_bch stays unregistered in CMake (bch = skip-green)
// so CI is untouched; the seam gate flips only after wiring + a clean nm census.
//
// BCH carries NO MWEB: get_work_view() hands core only the agnostic slice and
// submit_block_hex() forwards the 2-arg/no-mweb form (mweb is LTC-specific).
// ---------------------------------------------------------------------------

#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 bch
{

namespace coin
{

class CoinNode : public core::coin::ICoinNode
{
// Embedded in-process template source. 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-preferred mode; it is
// the sole sink for submit_block_hex(). has_rpc() reports its presence.
NodeRPC* m_rpc = nullptr;

// Full per-coin WorkData (incl. m_txs) retained coin-side via work.set(wd);
// only the agnostic WorkView slice crosses the seam into core/web_server.
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 bch
Loading
Loading