remove from mempool on mine; TEMPORARY log math proof of fee inclusion in coinbase tx
This commit is contained in:
@@ -15,6 +15,8 @@ int TxMempool_Insert(signed_transaction_t tx);
|
|||||||
bool TxMempool_Lookup(uint8_t* txHash, signed_transaction_t* out);
|
bool TxMempool_Lookup(uint8_t* txHash, signed_transaction_t* out);
|
||||||
bool TxMempool_Snapshot(signed_transaction_t** outTxs, size_t* outCount);
|
bool TxMempool_Snapshot(signed_transaction_t** outTxs, size_t* outCount);
|
||||||
void TxMempool_Print();
|
void TxMempool_Print();
|
||||||
|
// Remove a transaction from the mempool by its hash. Returns true if removed.
|
||||||
|
bool TxMempool_Remove(const uint8_t* txHash);
|
||||||
void TxMempool_Destroy();
|
void TxMempool_Destroy();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <block/chain.h>
|
#include <block/chain.h>
|
||||||
#include <constants.h>
|
#include <constants.h>
|
||||||
#include <runtime_state.h>
|
#include <runtime_state.h>
|
||||||
|
#include <txmempool.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -243,8 +244,33 @@ bool Chain_AddBlock(blockchain_t* chain, block_t* block) {
|
|||||||
}
|
}
|
||||||
expectedCoinbaseAmount += totalFees;
|
expectedCoinbaseAmount += totalFees;
|
||||||
|
|
||||||
|
// Debug: log expected coinbase and fees to aid diagnosis when nodes disagree
|
||||||
|
{
|
||||||
|
uint64_t cbAmount = 0;
|
||||||
|
if (block->transactions && DynArr_size(block->transactions) > 0) {
|
||||||
|
signed_transaction_t* firstTx = (signed_transaction_t*)DynArr_at(block->transactions, 0);
|
||||||
|
if (firstTx && Address_IsCoinbase(firstTx->transaction.senderAddress)) {
|
||||||
|
cbAmount = firstTx->transaction.amount1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char supplyStr[80];
|
||||||
|
Uint256ToDecimal(¤tSupply, supplyStr, sizeof(supplyStr));
|
||||||
|
printf("Chain_AddBlock: blockIndex=%zu expectedCoinbase=%llu totalFees=%llu observedBlockCoinbase=%llu currentReward=%llu currentSupply=%s\n",
|
||||||
|
expectedIndex,
|
||||||
|
(unsigned long long)expectedCoinbaseAmount,
|
||||||
|
(unsigned long long)totalFees,
|
||||||
|
(unsigned long long)cbAmount,
|
||||||
|
(unsigned long long)currentReward,
|
||||||
|
supplyStr);
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t observedFees = 0;
|
uint64_t observedFees = 0;
|
||||||
if (!Block_ValidateCoinbaseAndFees(block, expectedCoinbaseAmount, &observedFees) || observedFees != totalFees) {
|
if (!Block_ValidateCoinbaseAndFees(block, expectedCoinbaseAmount, &observedFees) || observedFees != totalFees) {
|
||||||
|
// Log mismatch details for debugging
|
||||||
|
printf("Chain_AddBlock: validation failed: expectedCoinbase=%llu totalFees=%llu observedFees=%llu\n",
|
||||||
|
(unsigned long long)expectedCoinbaseAmount,
|
||||||
|
(unsigned long long)totalFees,
|
||||||
|
(unsigned long long)observedFees);
|
||||||
free(spendableTxs);
|
free(spendableTxs);
|
||||||
ok = false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
@@ -294,6 +320,21 @@ bool Chain_AddBlock(blockchain_t* chain, block_t* block) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove mined non-coinbase transactions from the mempool so they are not re-mined or re-broadcast.
|
||||||
|
if (blk->transactions) {
|
||||||
|
for (size_t i = 0; i < DynArr_size(blk->transactions); ++i) {
|
||||||
|
signed_transaction_t* tx = (signed_transaction_t*)DynArr_at(blk->transactions, i);
|
||||||
|
if (!tx) continue;
|
||||||
|
if (Address_IsCoinbase(tx->transaction.senderAddress)) continue;
|
||||||
|
uint8_t txHash[32];
|
||||||
|
Transaction_CalculateHash(tx, txHash);
|
||||||
|
if (TxMempool_Remove(txHash)) {
|
||||||
|
// optional: log removal
|
||||||
|
// printf("TxMempool_Remove: removed tx from mempool: "); PrintHexBytes(txHash, 32); printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// ok remains true if no failures
|
// ok remains true if no failures
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
@@ -304,6 +345,36 @@ bool Chain_AddBlock(blockchain_t* chain, block_t* block) {
|
|||||||
printf("Added new block to chain:\n");
|
printf("Added new block to chain:\n");
|
||||||
Block_ShortPrint(block);
|
Block_ShortPrint(block);
|
||||||
|
|
||||||
|
// After adding block, print a simple mathematical 'proof' that fees were included
|
||||||
|
{
|
||||||
|
uint64_t coinbaseAmount = 0;
|
||||||
|
uint64_t totalFees = 0;
|
||||||
|
if (block->transactions) {
|
||||||
|
for (size_t i = 0; i < DynArr_size(block->transactions); ++i) {
|
||||||
|
signed_transaction_t* tx = (signed_transaction_t*)DynArr_at(block->transactions, i);
|
||||||
|
if (!tx) { continue; }
|
||||||
|
if (Address_IsCoinbase(tx->transaction.senderAddress)) {
|
||||||
|
coinbaseAmount = tx->transaction.amount1;
|
||||||
|
} else {
|
||||||
|
if (UINT64_MAX - totalFees >= tx->transaction.fee) {
|
||||||
|
totalFees += tx->transaction.fee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t base = currentReward;
|
||||||
|
if (coinbaseAmount > 0 || totalFees > 0) {
|
||||||
|
printf("Proof: coinbase(%llu) == baseReward(%llu) + totalFees(%llu) => %llu == %llu + %llu\n",
|
||||||
|
(unsigned long long)coinbaseAmount,
|
||||||
|
(unsigned long long)base,
|
||||||
|
(unsigned long long)totalFees,
|
||||||
|
(unsigned long long)coinbaseAmount,
|
||||||
|
(unsigned long long)base,
|
||||||
|
(unsigned long long)totalFees);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
58
src/main.c
58
src/main.c
@@ -429,6 +429,22 @@ static bool MineAndAppendBlock(blockchain_t* chain,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print mathematical proof that fees are included in the coinbase payout for miner visibility.
|
||||||
|
{
|
||||||
|
uint64_t cb = 0;
|
||||||
|
uint64_t fees = 0;
|
||||||
|
if (Block_GetCoinbaseAndFeeTotals(block, &cb, &fees)) {
|
||||||
|
uint64_t base = *currentReward;
|
||||||
|
printf("Mined block proof: coinbase(%llu) == baseReward(%llu) + totalFees(%llu) => %llu == %llu + %llu\n",
|
||||||
|
(unsigned long long)cb,
|
||||||
|
(unsigned long long)base,
|
||||||
|
(unsigned long long)fees,
|
||||||
|
(unsigned long long)cb,
|
||||||
|
(unsigned long long)base,
|
||||||
|
(unsigned long long)fees);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// After successfully appending a block, attempt to attach any orphans.
|
// After successfully appending a block, attempt to attach any orphans.
|
||||||
size_t attached = OrphanPool_AttemptAttach(chain);
|
size_t attached = OrphanPool_AttemptAttach(chain);
|
||||||
if (attached > 0) {
|
if (attached > 0) {
|
||||||
@@ -832,7 +848,7 @@ int main(int argc, char* argv[]) {
|
|||||||
char supplyStr[80];
|
char supplyStr[80];
|
||||||
Uint256ToDecimal(¤tSupply, supplyStr, sizeof(supplyStr));
|
Uint256ToDecimal(¤tSupply, supplyStr, sizeof(supplyStr));
|
||||||
printf("Current chain has %zu blocks, total supply %s\n", Chain_Size(chain), supplyStr);
|
printf("Current chain has %zu blocks, total supply %s\n", Chain_Size(chain), supplyStr);
|
||||||
printf("Commands: mine <x>, send <address> <amount> [fee], balance [address], connect <ipv4>, sync (requires nodes), flushchain, fullverify, blockdetail <block number>, wipechain, genaddr, exit\n");
|
printf("Commands: mine <x>, send <address> <amount> [fee], txpooldetail <txhash>, balance [address], connect <ipv4>, sync (requires nodes), flushchain, fullverify, blockdetail <block number>, wipechain, genaddr, exit\n");
|
||||||
|
|
||||||
char line[1024];
|
char line[1024];
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -1302,6 +1318,46 @@ int main(int argc, char* argv[]) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strcmp(cmd, "txpooldetail") == 0) {
|
||||||
|
char* hashStr = strtok(NULL, " \t");
|
||||||
|
if (!hashStr) {
|
||||||
|
printf("usage: txpooldetail <txhash>\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t txHash[32];
|
||||||
|
if (!ParseHexAddress32(hashStr, txHash)) {
|
||||||
|
printf("invalid tx hash: expected 64 hex chars\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction_t tx;
|
||||||
|
if (!TxMempool_Lookup(txHash, &tx)) {
|
||||||
|
printf("transaction not found in mempool\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char senderHex[65];
|
||||||
|
char recip1Hex[65];
|
||||||
|
char recip2Hex[65];
|
||||||
|
AddressToHexString(tx.transaction.senderAddress, senderHex);
|
||||||
|
AddressToHexString(tx.transaction.recipientAddress1, recip1Hex);
|
||||||
|
AddressToHexString(tx.transaction.recipientAddress2, recip2Hex);
|
||||||
|
|
||||||
|
uint8_t calcHash[32];
|
||||||
|
Transaction_CalculateHash(&tx, calcHash);
|
||||||
|
|
||||||
|
printf("Transaction details:\n");
|
||||||
|
printf(" TxHash: "); PrintHexBytes(calcHash, 32); printf("\n");
|
||||||
|
printf(" Sender: %s%s\n", senderHex, Address_IsCoinbase(tx.transaction.senderAddress) ? " (coinbase)" : "");
|
||||||
|
printf(" Recipient1: %s\n", recip1Hex);
|
||||||
|
printf(" Recipient2: %s\n", recip2Hex);
|
||||||
|
printf(" Amount1: %llu\n", (unsigned long long)tx.transaction.amount1);
|
||||||
|
printf(" Amount2: %llu\n", (unsigned long long)tx.transaction.amount2);
|
||||||
|
printf(" Fee: %llu\n", (unsigned long long)tx.transaction.fee);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(cmd, "blockdetail") == 0) {
|
if (strcmp(cmd, "blockdetail") == 0) {
|
||||||
|
|||||||
@@ -139,3 +139,21 @@ void TxMempool_Destroy() {
|
|||||||
g_txMempoolLockInitialized = false;
|
g_txMempoolLockInitialized = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TxMempool_Remove(const uint8_t* txHash) {
|
||||||
|
if (!txMempool || !txHash) { return false; }
|
||||||
|
|
||||||
|
pthread_mutex_lock(&g_txMempoolLock);
|
||||||
|
key32_t key;
|
||||||
|
memcpy(key.bytes, txHash, 32);
|
||||||
|
|
||||||
|
khiter_t k = kh_get(tx_mempool_map_m, txMempool, key);
|
||||||
|
if (k == kh_end(txMempool)) {
|
||||||
|
pthread_mutex_unlock(&g_txMempoolLock);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
kh_del(tx_mempool_map_m, txMempool, k);
|
||||||
|
pthread_mutex_unlock(&g_txMempoolLock);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user