Skip to content

Commit d186a8b

Browse files
authored
Merge pull request #46 from frstrtr/a1/bitcoin-family-extraction
bucket-A1: extract bitcoin_family base from src/impl/ltc/ (breaking ChainParams API refactor, runtime-behavior-preserving for LTC)
2 parents bfdb355 + 780d673 commit d186a8b

25 files changed

Lines changed: 1004 additions & 687 deletions

src/c2pool/c2pool_refactored.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,8 +1570,8 @@ int main(int argc, char* argv[]) {
15701570
LOG_INFO << "╚══════════════════════════════════════════════════════════════╝";
15711571

15721572
auto ltc_params = settings->m_testnet
1573-
? ltc::coin::LTCChainParams::testnet()
1574-
: ltc::coin::LTCChainParams::mainnet();
1573+
? ltc::coin::make_ltc_chain_params_testnet()
1574+
: ltc::coin::make_ltc_chain_params_mainnet();
15751575

15761576
// LevelDB-backed header chain for persistence across restarts
15771577
// Use absolute path under ~/.c2pool/ (matches sharechain + found_blocks)

src/c2pool/storage/sharechain_storage.cpp

Lines changed: 3 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include "sharechain_storage.hpp"
22
#include <functional>
3-
#include <impl/ltc/share.hpp>
43

54
namespace c2pool {
65
namespace storage {
@@ -35,60 +34,7 @@ bool SharechainStorage::is_available() const {
3534
return m_leveldb_store != nullptr;
3635
}
3736

38-
template<typename ShareChainType>
39-
void SharechainStorage::save_sharechain(const ShareChainType& chain)
40-
{
41-
if (!m_leveldb_store) {
42-
LOG_ERROR << "LevelDB store not available";
43-
return;
44-
}
45-
46-
try {
47-
// For now, log that we would save (full integration needs sharechain API)
48-
LOG_INFO << "LevelDB sharechain storage is ready for persistent share storage";
49-
LOG_INFO << " Network: " << m_network_name;
50-
LOG_INFO << " Current stored shares: " << m_leveldb_store->get_share_count();
51-
LOG_INFO << " Storage path: " << m_leveldb_store->get_base_path() << "/" << m_network_name << "/sharechain_leveldb";
52-
53-
} catch (const std::exception& e) {
54-
LOG_ERROR << "Error with LevelDB sharechain storage: " << e.what();
55-
}
56-
}
57-
58-
template<typename ShareChainType>
59-
bool SharechainStorage::load_sharechain(ShareChainType& chain)
60-
{
61-
if (!m_leveldb_store) {
62-
LOG_WARNING << "LevelDB store not available, starting with empty sharechain";
63-
return false;
64-
}
65-
66-
try {
67-
uint64_t stored_shares = m_leveldb_store->get_share_count();
68-
if (stored_shares == 0) {
69-
LOG_INFO << "No shares found in LevelDB storage, starting fresh";
70-
return false;
71-
}
72-
73-
uint256 best_hash = m_leveldb_store->get_best_hash();
74-
uint64_t best_height = m_leveldb_store->get_best_height();
75-
76-
LOG_INFO << "LevelDB sharechain storage contains " << stored_shares << " shares";
77-
LOG_INFO << " Best height: " << best_height;
78-
LOG_INFO << " Best hash: " << best_hash.ToString().substr(0, 16) << "...";
79-
80-
// For now, just report availability - full integration needs sharechain API
81-
LOG_INFO << "LevelDB storage is ready for share loading and recovery";
82-
83-
return stored_shares > 0;
84-
85-
} catch (const std::exception& e) {
86-
LOG_ERROR << "Error loading from LevelDB sharechain storage: " << e.what();
87-
return false;
88-
}
89-
}
90-
91-
bool SharechainStorage::store_share(const uint256& hash, const std::vector<uint8_t>& serialized_data,
37+
bool SharechainStorage::store_share(const uint256& hash, const std::vector<uint8_t>& serialized_data,
9238
const uint256& prev_hash, uint64_t height, uint64_t timestamp,
9339
const uint256& work, const uint256& target, bool is_orphan)
9440
{
@@ -268,57 +214,8 @@ std::vector<uint256> SharechainStorage::get_shares_by_height_range(uint64_t star
268214
return m_leveldb_store->get_shares_by_height_range(start_height, end_height);
269215
}
270216

271-
template<typename ShareChainType>
272-
void SharechainStorage::schedule_periodic_save(ShareChainType& chain, boost::asio::io_context& ioc, int interval_seconds)
273-
{
274-
auto timer = std::make_shared<boost::asio::steady_timer>(ioc);
275-
276-
// Create a safe capture by copying what we need
277-
auto leveldb_store_ptr = m_leveldb_store.get(); // Raw pointer for safety check
278-
279-
// Use a shared_ptr to hold the recursive callback
280-
auto save_task = std::make_shared<std::function<void()>>();
281-
*save_task = [leveldb_store_ptr, timer, interval_seconds, save_task]() {
282-
if (leveldb_store_ptr) {
283-
LOG_INFO << "Periodic LevelDB storage maintenance";
284-
285-
try {
286-
uint64_t share_count = leveldb_store_ptr->get_share_count();
287-
uint64_t best_height = leveldb_store_ptr->get_best_height();
288-
289-
LOG_INFO << "LevelDB Storage Stats:";
290-
LOG_INFO << " Total shares: " << share_count;
291-
LOG_INFO << " Best height: " << best_height;
292-
293-
// Periodic compaction (every hour)
294-
static int compact_counter = 0;
295-
if (++compact_counter >= (3600 / interval_seconds)) {
296-
LOG_INFO << "Compacting LevelDB sharechain storage...";
297-
leveldb_store_ptr->compact();
298-
compact_counter = 0;
299-
}
300-
} catch (const std::exception& e) {
301-
LOG_ERROR << "Error in periodic LevelDB maintenance: " << e.what();
302-
}
303-
}
304-
305-
timer->expires_after(std::chrono::seconds(interval_seconds));
306-
timer->async_wait([save_task](const boost::system::error_code&) {
307-
if (save_task) (*save_task)();
308-
});
309-
};
310-
311-
// Start after initial delay
312-
timer->expires_after(std::chrono::seconds(30));
313-
timer->async_wait([save_task](const boost::system::error_code&) {
314-
if (save_task) (*save_task)();
315-
});
316-
}
317-
318-
// Explicit template instantiations for common types
319-
template void SharechainStorage::save_sharechain<ltc::ShareChain>(const ltc::ShareChain& chain);
320-
template bool SharechainStorage::load_sharechain<ltc::ShareChain>(ltc::ShareChain& chain);
321-
template void SharechainStorage::schedule_periodic_save<ltc::ShareChain>(ltc::ShareChain& chain, boost::asio::io_context& ioc, int interval_seconds);
217+
// Template method bodies (save_sharechain, load_sharechain, schedule_periodic_save)
218+
// live in the header so any coin's ShareChain type gets implicit instantiation.
322219

323220
} // namespace storage
324221
} // namespace c2pool

src/c2pool/storage/sharechain_storage.hpp

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,45 @@ class SharechainStorage {
4949
* @param chain The sharechain to save
5050
*/
5151
template<typename ShareChainType>
52-
void save_sharechain(const ShareChainType& chain);
53-
52+
void save_sharechain(const ShareChainType& /*chain*/)
53+
{
54+
if (!m_leveldb_store) {
55+
LOG_ERROR << "LevelDB store not available";
56+
return;
57+
}
58+
try {
59+
LOG_INFO << "LevelDB sharechain storage is ready for persistent share storage";
60+
LOG_INFO << " Network: " << m_network_name;
61+
} catch (const std::exception& e) {
62+
LOG_ERROR << "Error with LevelDB sharechain storage: " << e.what();
63+
}
64+
}
65+
5466
/**
5567
* @brief Load sharechain from persistent storage
5668
* @tparam ShareChainType Type of sharechain to load into
5769
* @param chain The sharechain to load into
5870
* @return True if shares were loaded
5971
*/
6072
template<typename ShareChainType>
61-
bool load_sharechain(ShareChainType& chain);
73+
bool load_sharechain(ShareChainType& /*chain*/)
74+
{
75+
if (!m_leveldb_store) {
76+
LOG_WARNING << "LevelDB store not available, starting with empty sharechain";
77+
return false;
78+
}
79+
try {
80+
uint64_t stored_shares = m_leveldb_store->get_share_count();
81+
if (stored_shares == 0) {
82+
LOG_INFO << "No shares found in LevelDB storage, starting fresh";
83+
return false;
84+
}
85+
return stored_shares > 0;
86+
} catch (const std::exception& e) {
87+
LOG_ERROR << "Error loading from LevelDB sharechain storage: " << e.what();
88+
return false;
89+
}
90+
}
6291

6392
/**
6493
* @brief Store a specific share in the database
@@ -169,7 +198,33 @@ class SharechainStorage {
169198
* @param interval_seconds Maintenance interval
170199
*/
171200
template<typename ShareChainType>
172-
void schedule_periodic_save(ShareChainType& chain, boost::asio::io_context& ioc, int interval_seconds = 300);
201+
void schedule_periodic_save(ShareChainType& /*chain*/, boost::asio::io_context& ioc, int interval_seconds = 300)
202+
{
203+
auto timer = std::make_shared<boost::asio::steady_timer>(ioc);
204+
auto leveldb_store_ptr = m_leveldb_store.get();
205+
auto save_task = std::make_shared<std::function<void()>>();
206+
*save_task = [leveldb_store_ptr, timer, interval_seconds, save_task]() {
207+
if (leveldb_store_ptr) {
208+
LOG_INFO << "Periodic LevelDB storage maintenance";
209+
try {
210+
uint64_t share_count = leveldb_store_ptr->get_share_count();
211+
uint64_t best_height = leveldb_store_ptr->get_best_height();
212+
LOG_INFO << " Share count: " << share_count;
213+
LOG_INFO << " Best height: " << best_height;
214+
} catch (const std::exception& e) {
215+
LOG_ERROR << "Error in periodic maintenance: " << e.what();
216+
}
217+
}
218+
timer->expires_after(std::chrono::seconds(interval_seconds));
219+
timer->async_wait([save_task](const boost::system::error_code&) {
220+
if (save_task) (*save_task)();
221+
});
222+
};
223+
timer->expires_after(std::chrono::seconds(30));
224+
timer->async_wait([save_task](const boost::system::error_code&) {
225+
if (save_task) (*save_task)();
226+
});
227+
}
173228
};
174229

175230
} // namespace storage

src/core/pow.hpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#pragma once
2+
3+
// PoW function types and built-in algorithm implementations.
4+
// Each coin binds its CoinParams::pow_func to one of these.
5+
6+
#include "uint256.hpp"
7+
#include "hash.hpp"
8+
#include <btclibs/crypto/scrypt.h>
9+
10+
#include <cstring>
11+
#include <functional>
12+
#include <span>
13+
14+
namespace core
15+
{
16+
17+
// PoW function: takes an 80-byte block header, returns the PoW hash.
18+
// For most coins, this differs from the block identity hash (SHA256d).
19+
using PowFunc = std::function<uint256(std::span<const unsigned char>)>;
20+
21+
// Block hash function: computes the block's identity hash (used for prev_block references).
22+
// For Bitcoin-family coins this is always SHA256d, but kept separate for generality.
23+
using BlockHashFunc = std::function<uint256(std::span<const unsigned char>)>;
24+
25+
// Subsidy function: given a block height, returns the block reward in satoshis.
26+
using SubsidyFunc = std::function<uint64_t(uint32_t height)>;
27+
28+
// Donation script function: given a share version, returns the donation script bytes.
29+
using DonationScriptFunc = std::function<std::vector<unsigned char>(int64_t share_version)>;
30+
31+
namespace pow
32+
{
33+
34+
// SHA256d (Bitcoin): double SHA-256 of 80-byte header.
35+
inline uint256 sha256d(std::span<const unsigned char> header)
36+
{
37+
return Hash(header);
38+
}
39+
40+
// Scrypt(1024,1,1,256) (Litecoin, Dogecoin): scrypt hash of 80-byte header.
41+
inline uint256 scrypt(std::span<const unsigned char> header)
42+
{
43+
char pow_hash_bytes[32];
44+
scrypt_1024_1_1_256(reinterpret_cast<const char*>(header.data()),
45+
pow_hash_bytes);
46+
uint256 result;
47+
std::memcpy(result.begin(), pow_hash_bytes, 32);
48+
return result;
49+
}
50+
51+
} // namespace pow
52+
} // namespace core
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#pragma once
2+
3+
// Generic Bitcoin-family block header types.
4+
// SmallBlockHeaderType: compact header for p2pool share serialization (VarInt version).
5+
// BlockHeaderType: standard 80-byte block header (fixed uint32 version).
6+
// BaseBlockType: block = header + transactions (no MWEB).
7+
//
8+
// LTC extends BaseBlockType with MWEB support (m_mweb_raw, HogEx).
9+
// Dash, BTC, DOGE use BaseBlockType directly.
10+
11+
#include <core/uint256.hpp>
12+
#include <core/pack_types.hpp>
13+
14+
#include <vector>
15+
16+
namespace bitcoin_family
17+
{
18+
namespace coin
19+
{
20+
21+
struct SmallBlockHeaderType
22+
{
23+
uint64_t m_version {};
24+
uint256 m_previous_block{};
25+
uint32_t m_timestamp{};
26+
uint32_t m_bits{};
27+
uint32_t m_nonce{};
28+
29+
SERIALIZE_METHODS(SmallBlockHeaderType) { READWRITE(VarInt(obj.m_version), obj.m_previous_block, obj.m_timestamp, obj.m_bits, obj.m_nonce); }
30+
31+
SmallBlockHeaderType() {}
32+
33+
void SetNull()
34+
{
35+
m_version = 0;
36+
m_previous_block.SetNull();
37+
m_timestamp = 0;
38+
m_bits = 0;
39+
m_nonce = 0;
40+
}
41+
42+
bool IsNull() const
43+
{
44+
return (m_bits == 0);
45+
}
46+
};
47+
48+
struct BlockHeaderType : SmallBlockHeaderType
49+
{
50+
uint256 m_merkle_root;
51+
52+
// Full block header uses fixed 4-byte int32 version (not VarInt like SmallBlockHeaderType)
53+
template<typename Stream>
54+
void Serialize(Stream& s) const {
55+
uint32_t version32 = static_cast<uint32_t>(m_version);
56+
::Serialize(s, version32);
57+
::Serialize(s, m_previous_block);
58+
::Serialize(s, m_merkle_root);
59+
::Serialize(s, m_timestamp);
60+
::Serialize(s, m_bits);
61+
::Serialize(s, m_nonce);
62+
}
63+
template<typename Stream>
64+
void Unserialize(Stream& s) {
65+
uint32_t version32;
66+
::Unserialize(s, version32);
67+
m_version = version32;
68+
::Unserialize(s, m_previous_block);
69+
::Unserialize(s, m_merkle_root);
70+
::Unserialize(s, m_timestamp);
71+
::Unserialize(s, m_bits);
72+
::Unserialize(s, m_nonce);
73+
}
74+
75+
BlockHeaderType() : SmallBlockHeaderType() { }
76+
77+
void SetNull()
78+
{
79+
SmallBlockHeaderType::SetNull();
80+
m_merkle_root.SetNull();
81+
}
82+
83+
bool IsNull() const
84+
{
85+
return (m_bits == 0);
86+
}
87+
};
88+
89+
} // namespace coin
90+
} // namespace bitcoin_family

0 commit comments

Comments
 (0)