102 lines
3.2 KiB
C++
102 lines
3.2 KiB
C++
|
|
// Minimal Carrot coinbase derivation checker for p2pool (test utility)
|
||
|
|
// Usage (built in p2pool-salvium/build after enabling tests manually if needed):
|
||
|
|
// ./carrot_debug <height> <ko_hex> <view_tag_hex>
|
||
|
|
// Hardcoded wallet keys below (testnet SC1Touh... provided by user).
|
||
|
|
|
||
|
|
#include "common.h"
|
||
|
|
#include "salvium_carrot.h"
|
||
|
|
#include "wallet.h"
|
||
|
|
#include <iostream>
|
||
|
|
|
||
|
|
// User-provided testnet wallet (SC1TouhH...):
|
||
|
|
static const char* SPEND_SEC_HEX = "3e7620c2f3ec905091cb6bc29bf842659fcfe810b459b1dc8ab53382a9718401";
|
||
|
|
static const char* VIEW_SEC_HEX = "d1f69ec092ea9b24d62cd84c2abefd29ac08e8e1725297bdecb71c79b0b01105";
|
||
|
|
|
||
|
|
using namespace p2pool;
|
||
|
|
using namespace p2pool::salvium_carrot;
|
||
|
|
|
||
|
|
static bool parse_hex(const std::string& hex, std::vector<uint8_t>& out)
|
||
|
|
{
|
||
|
|
out.clear();
|
||
|
|
out.reserve(hex.size() / 2);
|
||
|
|
auto cvt = [](char c) -> int {
|
||
|
|
if (c >= '0' && c <= '9') return c - '0';
|
||
|
|
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||
|
|
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
||
|
|
return -1;
|
||
|
|
};
|
||
|
|
if (hex.size() % 2) return false;
|
||
|
|
for (size_t i = 0; i < hex.size(); i += 2) {
|
||
|
|
int hi = cvt(hex[i]);
|
||
|
|
int lo = cvt(hex[i+1]);
|
||
|
|
if (hi < 0 || lo < 0) return false;
|
||
|
|
out.push_back(static_cast<uint8_t>((hi << 4) | lo));
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
int main(int argc, char** argv)
|
||
|
|
{
|
||
|
|
if (argc < 4) {
|
||
|
|
std::cerr << "usage: " << argv[0] << " <height> <ko_hex> <vt_hex>\n";
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint64_t height = std::strtoull(argv[1], nullptr, 10);
|
||
|
|
std::vector<uint8_t> ko_hex, vt_hex;
|
||
|
|
if (!parse_hex(argv[2], ko_hex) || ko_hex.size() != HASH_SIZE) {
|
||
|
|
std::cerr << "bad ko hex\n";
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
if (!parse_hex(argv[3], vt_hex)) {
|
||
|
|
std::cerr << "bad vt hex\n";
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
hash spend_sec{}, view_sec{};
|
||
|
|
{
|
||
|
|
std::vector<uint8_t> buf;
|
||
|
|
if (!parse_hex(SPEND_SEC_HEX, buf) || buf.size() != HASH_SIZE) {
|
||
|
|
std::cerr << "bad spend_sec\n";
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
memcpy(spend_sec.h, buf.data(), HASH_SIZE);
|
||
|
|
if (!parse_hex(VIEW_SEC_HEX, buf) || buf.size() != HASH_SIZE) {
|
||
|
|
std::cerr << "bad view_sec\n";
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
memcpy(view_sec.h, buf.data(), HASH_SIZE);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Build a dummy share set with one miner share for this wallet
|
||
|
|
Wallet w{};
|
||
|
|
w.assign(spend_sec, view_sec, NetworkType::Testnet, false);
|
||
|
|
std::vector<MinerShare> shares;
|
||
|
|
shares.emplace_back(difficulty_type{1,0}, &w);
|
||
|
|
|
||
|
|
// Rewards: use on-chain amount for comparison; we only need one output
|
||
|
|
std::vector<uint64_t> amounts;
|
||
|
|
amounts.push_back(0); // placeholder; will set below
|
||
|
|
|
||
|
|
std::vector<CoinbaseEnote> enotes;
|
||
|
|
amounts[0] = 0; // will be filled by caller; not used to match Ko/vt logic directly
|
||
|
|
|
||
|
|
// Try deriving with the provided amount from Ko (not required to derive Ko)
|
||
|
|
if (!build_coinbase_enotes(shares, amounts, height, enotes) || enotes.empty()) {
|
||
|
|
std::cerr << "build_coinbase_enotes failed\n";
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
const CoinbaseEnote& e = enotes.front();
|
||
|
|
std::cout << "derived Ko=" << e.onetime_address << "\n";
|
||
|
|
std::cout << "derived vt=";
|
||
|
|
for (auto b : e.view_tag) printf("%02x", b);
|
||
|
|
std::cout << "\n";
|
||
|
|
|
||
|
|
bool ko_match = (memcmp(e.onetime_address.h, ko_hex.data(), HASH_SIZE) == 0);
|
||
|
|
bool vt_match = (vt_hex.size() == e.view_tag.size()) && (memcmp(vt_hex.data(), e.view_tag.data(), e.view_tag.size()) == 0);
|
||
|
|
|
||
|
|
std::cout << "ko_match=" << ko_match << " vt_match=" << vt_match << "\n";
|
||
|
|
return (ko_match && vt_match) ? 0 : 1;
|
||
|
|
}
|