Skip to content

Commit 35078aa

Browse files
committed
Add AuxPoW submission diagnostics for DOGE ban investigation
Logs at freeze time: header hash, version, prev, merkle, bits Logs at submit time: hash comparison, fabe6d6d search in parent coinbase, committed root vs submitted hash, raw byte search mimicking dogecoind's CheckAuxPowProofOfWork validation.
1 parent f7e82e7 commit 35078aa

1 file changed

Lines changed: 120 additions & 0 deletions

File tree

src/c2pool/merged/merged_mining.cpp

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,113 @@ void MergedMiningManager::try_submit_merged_blocks(
929929
uint32_t nonce = 0;
930930
std::memcpy(p, &nonce, 4);
931931

932+
// ── DIAGNOSTIC: verify AuxPoW will pass dogecoind validation ──
933+
{
934+
// 1. Hash the submitted DOGE header (what dogecoind will compute)
935+
uint256 submitted_hash = Hash(header_bytes);
936+
LOG_WARNING << "[MM-DIAG:" << chain.config.symbol << "] submitted_header_hash="
937+
<< submitted_hash.GetHex();
938+
LOG_WARNING << "[MM-DIAG:" << chain.config.symbol << "] frozen_block_hash="
939+
<< chain.frozen_block_hash.GetHex();
940+
LOG_WARNING << "[MM-DIAG:" << chain.config.symbol << "] current_work.block_hash="
941+
<< chain.current_work.block_hash.GetHex();
942+
if (submitted_hash != chain.frozen_block_hash) {
943+
LOG_ERROR << "[MM-DIAG:" << chain.config.symbol
944+
<< "] HASH MISMATCH! submitted_header_hash != frozen_block_hash"
945+
<< " — dogecoind WILL reject this block!";
946+
}
947+
948+
// 2. Header field comparison
949+
LOG_WARNING << "[MM-DIAG:" << chain.config.symbol << "] header fields:"
950+
<< " version=0x" << std::hex << version << std::dec
951+
<< " prev=" << prev_hash.GetHex().substr(0, 16) << "..."
952+
<< " merkle=" << merkle_root.GetHex().substr(0, 16) << "..."
953+
<< " time=" << curtime << " bits=0x" << std::hex << nbits << std::dec
954+
<< " nonce=0";
955+
956+
// 3. Check MM commitment in parent coinbase
957+
auto mm_root_for_check = proof.root;
958+
LOG_WARNING << "[MM-DIAG:" << chain.config.symbol << "] proof.root="
959+
<< mm_root_for_check.GetHex()
960+
<< " proof.branch_size=" << proof.branch.size()
961+
<< " proof.index=" << proof.index
962+
<< " tree_size=" << m_tree.size;
963+
964+
// 4. Search for fabe6d6d in parent coinbase
965+
auto parent_cb_bytes = from_hex(parent_coinbase_hex);
966+
static const uint8_t MAGIC[] = {0xfa, 0xbe, 0x6d, 0x6d};
967+
auto magic_pos = std::search(parent_cb_bytes.begin(), parent_cb_bytes.end(),
968+
std::begin(MAGIC), std::end(MAGIC));
969+
if (magic_pos == parent_cb_bytes.end()) {
970+
LOG_ERROR << "[MM-DIAG:" << chain.config.symbol
971+
<< "] fabe6d6d NOT FOUND in parent coinbase! len="
972+
<< parent_cb_bytes.size();
973+
} else {
974+
size_t offset = std::distance(parent_cb_bytes.begin(), magic_pos);
975+
LOG_WARNING << "[MM-DIAG:" << chain.config.symbol
976+
<< "] fabe6d6d found at offset " << offset
977+
<< " in parent coinbase (len=" << parent_cb_bytes.size() << ")";
978+
// Extract 32 bytes after magic as the committed root
979+
if (offset + 4 + 32 <= parent_cb_bytes.size()) {
980+
// The committed root is in BE in the coinbase
981+
// Convert to uint256 for comparison
982+
uint256 committed_root;
983+
// Reverse BE→LE into uint256
984+
uint8_t* dst = reinterpret_cast<uint8_t*>(committed_root.data());
985+
for (int i = 0; i < 32; ++i)
986+
dst[i] = parent_cb_bytes[offset + 4 + 31 - i];
987+
LOG_WARNING << "[MM-DIAG:" << chain.config.symbol
988+
<< "] committed_root (from coinbase)="
989+
<< committed_root.GetHex();
990+
LOG_WARNING << "[MM-DIAG:" << chain.config.symbol
991+
<< "] submitted_hash (dogecoind expects)="
992+
<< submitted_hash.GetHex();
993+
if (committed_root != submitted_hash) {
994+
LOG_ERROR << "[MM-DIAG:" << chain.config.symbol
995+
<< "] ROOT MISMATCH! committed_root != submitted_hash"
996+
<< " — this is why dogecoind rejects!";
997+
} else {
998+
LOG_WARNING << "[MM-DIAG:" << chain.config.symbol
999+
<< "] Root matches — searching for raw bytes...";
1000+
}
1001+
}
1002+
// 5. Raw byte search (exactly what dogecoind does)
1003+
// dogecoind searches for submitted_hash reversed (BE) in scriptSig
1004+
std::vector<uint8_t> hash_be(32);
1005+
const uint8_t* hp = reinterpret_cast<const uint8_t*>(submitted_hash.data());
1006+
for (int i = 0; i < 32; ++i) hash_be[i] = hp[31 - i];
1007+
// Extract scriptSig from parent coinbase (skip version+vin_count+prevout)
1008+
// version(4) + vin_count(1) + prev_hash(32) + prev_idx(4) = 41, then scriptSig_len
1009+
if (parent_cb_bytes.size() > 42) {
1010+
size_t ssoff = 41;
1011+
uint8_t sslen_byte = parent_cb_bytes[ssoff];
1012+
LOG_WARNING << "[MM-DIAG:" << chain.config.symbol
1013+
<< "] scriptSig offset=" << ssoff
1014+
<< " len_byte=0x" << std::hex << (int)sslen_byte << std::dec;
1015+
auto ss_begin = parent_cb_bytes.begin() + ssoff + 1;
1016+
auto ss_end = ss_begin + sslen_byte;
1017+
if (ss_end > parent_cb_bytes.end()) ss_end = parent_cb_bytes.end();
1018+
auto found = std::search(ss_begin, ss_end, hash_be.begin(), hash_be.end());
1019+
if (found == ss_end) {
1020+
LOG_ERROR << "[MM-DIAG:" << chain.config.symbol
1021+
<< "] submitted_hash (BE) NOT FOUND in scriptSig!"
1022+
<< " hash_be=" << to_hex(hash_be.data(), 32);
1023+
// Dump scriptSig hex for manual inspection
1024+
std::string ss_hex = to_hex(
1025+
reinterpret_cast<const uint8_t*>(&*ss_begin),
1026+
std::distance(ss_begin, ss_end));
1027+
LOG_ERROR << "[MM-DIAG:" << chain.config.symbol
1028+
<< "] scriptSig hex=" << ss_hex;
1029+
} else {
1030+
LOG_WARNING << "[MM-DIAG:" << chain.config.symbol
1031+
<< "] submitted_hash found in scriptSig at offset "
1032+
<< std::distance(ss_begin, found) << " — should pass!";
1033+
}
1034+
}
1035+
}
1036+
}
1037+
// ── END DIAGNOSTIC ──
1038+
9321039
// Assemble: header + auxpow + coinbase + template txs
9331040
std::ostringstream blk;
9341041
blk << to_hex(header_bytes.data(), 80);
@@ -1109,6 +1216,19 @@ MergedMiningManager::build_merged_header_info() const
11091216
uint32_t nonce = 0;
11101217
std::memcpy(p, &nonce, 4);
11111218

1219+
// DIAGNOSTIC: log frozen header hash for comparison at submit time
1220+
{
1221+
uint256 frozen_hdr_hash = Hash(info.block_header);
1222+
LOG_WARNING << "[MM-FREEZE:" << snap.chain_id << "] frozen_header_hash="
1223+
<< frozen_hdr_hash.GetHex()
1224+
<< " version=0x" << std::hex << version << std::dec
1225+
<< " prev=" << prev_hash_hex.substr(0, 16) << "..."
1226+
<< " merkle=" << merkle_root.GetHex().substr(0, 16) << "..."
1227+
<< " time=" << curtime
1228+
<< " bits=" << bits_hex
1229+
<< " cb_len=" << info.coinbase_hex.size()/2;
1230+
}
1231+
11121232
LOG_TRACE << "[MM-header] header built, pushing result";
11131233
result.push_back(std::move(info));
11141234
LOG_TRACE << "[MM-header] chain done";

0 commit comments

Comments
 (0)