Rename extern/global variables to g_varName instead of varName to avoid shadowing
This commit is contained in:
@@ -12,7 +12,7 @@ extern "C" {
|
|||||||
|
|
||||||
typedef struct Autolykos2Context Autolykos2Context;
|
typedef struct Autolykos2Context Autolykos2Context;
|
||||||
|
|
||||||
extern uint64_t autolykos2_sleepBetweenHashOperationsMicroseconds;
|
extern uint64_t g_autolykos2_sleepBetweenHashOperationsMicroseconds;
|
||||||
|
|
||||||
Autolykos2Context* Autolykos2_Create(void);
|
Autolykos2Context* Autolykos2_Create(void);
|
||||||
void Autolykos2_Destroy(Autolykos2Context* ctx);
|
void Autolykos2_Destroy(Autolykos2Context* ctx);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ KHASH_INIT(balance_sheet_map_m, key32_t, balance_sheet_entry_t, 1, hash_key32, e
|
|||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
extern khash_t(balance_sheet_map_m)* sheetMap;
|
extern khash_t(balance_sheet_map_m)* g_sheetMap;
|
||||||
|
|
||||||
void BalanceSheet_Init();
|
void BalanceSheet_Init();
|
||||||
int BalanceSheet_Insert(balance_sheet_entry_t entry);
|
int BalanceSheet_Insert(balance_sheet_entry_t entry);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ typedef struct blockchain {
|
|||||||
* an epoch once the *following* entry has been computed, so it is valid on
|
* an epoch once the *following* entry has been computed, so it is valid on
|
||||||
* [0, dagEpochsComputed - 1).
|
* [0, dagEpochsComputed - 1).
|
||||||
*
|
*
|
||||||
* Guarded by `dagCacheLock`, which is always taken AFTER `chainLock` and is never held across a
|
* Guarded by `dagCacheLock`, which is always taken AFTER `g_chainLock` and is never held across a
|
||||||
* call back into chain.c.
|
* call back into chain.c.
|
||||||
**/
|
**/
|
||||||
dag_epoch_state_t* dagEpochs;
|
dag_epoch_state_t* dagEpochs;
|
||||||
@@ -106,7 +106,7 @@ uint64_t Chain_ReorgPenaltyForDepth(uint64_t reorgDepth);
|
|||||||
**/
|
**/
|
||||||
bool Chain_BlockRespectsSenderOrdering(const block_t* block);
|
bool Chain_BlockRespectsSenderOrdering(const block_t* block);
|
||||||
|
|
||||||
// Recompute `currentSupply` and `currentReward` from the in-memory chain blocks.
|
// Recompute `g_currentSupply` and `g_currentReward` from the in-memory chain blocks.
|
||||||
// Returns true on success and updates runtime state globals.
|
// Returns true on success and updates runtime state globals.
|
||||||
bool Chain_RecomputeRuntimeState(blockchain_t* chain);
|
bool Chain_RecomputeRuntimeState(blockchain_t* chain);
|
||||||
|
|
||||||
@@ -120,15 +120,15 @@ bool Chain_LoadBlockFromFile(const char* dirpath, uint64_t blockNumber, bool loa
|
|||||||
|
|
||||||
// Difficulty
|
// Difficulty
|
||||||
// Retarget for the block at `height`, measured over the window [height - INTERVAL, height - 1].
|
// Retarget for the block at `height`, measured over the window [height - INTERVAL, height - 1].
|
||||||
// `chain` must hold blocks 0..height-1. Takes no locks; safe to call while holding `chainLock`.
|
// `chain` must hold blocks 0..height-1. Takes no locks; safe to call while holding `g_chainLock`.
|
||||||
uint32_t Chain_ComputeTargetAtHeight(blockchain_t* chain, uint64_t height, uint32_t currentTarget);
|
uint32_t Chain_ComputeTargetAtHeight(blockchain_t* chain, uint64_t height, uint32_t currentTarget);
|
||||||
|
|
||||||
// The consensus-required difficultyTarget for the block at `height`, derived from the chain alone.
|
// The consensus-required difficultyTarget for the block at `height`, derived from the chain alone.
|
||||||
// Takes no locks; safe to call while holding `chainLock`.
|
// Takes no locks; safe to call while holding `g_chainLock`.
|
||||||
uint32_t Chain_GetTargetForHeight(blockchain_t* chain, uint64_t height);
|
uint32_t Chain_GetTargetForHeight(blockchain_t* chain, uint64_t height);
|
||||||
|
|
||||||
// Refresh runtime state derived from the chain tip (difficulty target, epoch DAG).
|
// Refresh runtime state derived from the chain tip (difficulty target, epoch DAG).
|
||||||
// Call after any change to the tip. Must NOT be called while holding `chainLock`.
|
// Call after any change to the tip. Must NOT be called while holding `g_chainLock`.
|
||||||
void Chain_OnTipAdvanced(blockchain_t* chain);
|
void Chain_OnTipAdvanced(blockchain_t* chain);
|
||||||
|
|
||||||
// DAG
|
// DAG
|
||||||
@@ -145,7 +145,7 @@ void Chain_OnTipAdvanced(blockchain_t* chain);
|
|||||||
* true when validating or mining a block at that height. Returns false if it cannot produce both
|
* true when validating or mining a block at that height. Returns false if it cannot produce both
|
||||||
* values; callers MUST treat that as an invalid proof rather than falling back to a default.
|
* values; callers MUST treat that as an invalid proof rather than falling back to a default.
|
||||||
*
|
*
|
||||||
* Takes `chainLock` for reading internally. Must NOT be called while holding it.
|
* Takes `g_chainLock` for reading internally. Must NOT be called while holding it.
|
||||||
**/
|
**/
|
||||||
bool Chain_DagParamsForHeight(blockchain_t* chain, uint64_t blockHeight,
|
bool Chain_DagParamsForHeight(blockchain_t* chain, uint64_t blockHeight,
|
||||||
size_t* outDagBytes, uint8_t outSeed[32]);
|
size_t* outDagBytes, uint8_t outSeed[32]);
|
||||||
@@ -155,7 +155,7 @@ bool Chain_DagParamsForHeight(blockchain_t* chain, uint64_t blockHeight,
|
|||||||
bool Chain_ComputeBlockWork(uint32_t difficultyTargetBits, uint256_t* outWork);
|
bool Chain_ComputeBlockWork(uint32_t difficultyTargetBits, uint256_t* outWork);
|
||||||
|
|
||||||
// Summed work of the chain's blocks over the half-open range [from, to).
|
// Summed work of the chain's blocks over the half-open range [from, to).
|
||||||
// Takes no locks; safe to call while holding `chainLock`.
|
// Takes no locks; safe to call while holding `g_chainLock`.
|
||||||
bool Chain_ComputeWorkRange(blockchain_t* chain, size_t from, size_t to, uint256_t* outWork);
|
bool Chain_ComputeWorkRange(blockchain_t* chain, size_t from, size_t to, uint256_t* outWork);
|
||||||
|
|
||||||
// Summed work of a candidate branch that is not (yet) part of the chain.
|
// Summed work of a candidate branch that is not (yet) part of the chain.
|
||||||
|
|||||||
+7
-7
@@ -208,7 +208,7 @@ static const uint64_t TAIL_EMISSION = 750000000000ULL; // 0.75 coins per block f
|
|||||||
// Phase 3: update once per effective epoch and keep a fixed per-block reward for that epoch.
|
// Phase 3: update once per effective epoch and keep a fixed per-block reward for that epoch.
|
||||||
//
|
//
|
||||||
// The *AtHeight variants take the height directly and never call Chain_Size/Chain_GetBlockCopy, so
|
// The *AtHeight variants take the height directly and never call Chain_Size/Chain_GetBlockCopy, so
|
||||||
// they are safe to call from inside a chainLock critical section. chainLock is a non-recursive
|
// they are safe to call from inside a g_chainLock critical section. g_chainLock is a non-recursive
|
||||||
// pthread_rwlock_t: taking it for reading while this thread already holds it for writing deadlocks
|
// pthread_rwlock_t: taking it for reading while this thread already holds it for writing deadlocks
|
||||||
// as soon as another thread is queued for the write lock.
|
// as soon as another thread is queued for the write lock.
|
||||||
static inline uint64_t GetInflationRateRewardAtHeight(uint256_t currentSupply, uint64_t height) {
|
static inline uint64_t GetInflationRateRewardAtHeight(uint256_t currentSupply, uint64_t height) {
|
||||||
@@ -218,8 +218,8 @@ static inline uint64_t GetInflationRateRewardAtHeight(uint256_t currentSupply, u
|
|||||||
: 1;
|
: 1;
|
||||||
|
|
||||||
if (height == 0) {
|
if (height == 0) {
|
||||||
currentReward = TAIL_EMISSION;
|
g_currentReward = TAIL_EMISSION;
|
||||||
return currentReward;
|
return g_currentReward;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (height % effectiveEpochLength == 0) {
|
if (height % effectiveEpochLength == 0) {
|
||||||
@@ -242,11 +242,11 @@ static inline uint64_t GetInflationRateRewardAtHeight(uint256_t currentSupply, u
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t inflationPerBlock = quotient.limbs[0];
|
uint64_t inflationPerBlock = quotient.limbs[0];
|
||||||
currentReward = (inflationPerBlock > TAIL_EMISSION) ? inflationPerBlock : TAIL_EMISSION;
|
g_currentReward = (inflationPerBlock > TAIL_EMISSION) ? inflationPerBlock : TAIL_EMISSION;
|
||||||
return currentReward;
|
return g_currentReward;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (currentReward > TAIL_EMISSION) ? currentReward : TAIL_EMISSION;
|
return (g_currentReward > TAIL_EMISSION) ? g_currentReward : TAIL_EMISSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t GetInflationRateReward(uint256_t currentSupply, blockchain_t* chain) {
|
static inline uint64_t GetInflationRateReward(uint256_t currentSupply, blockchain_t* chain) {
|
||||||
@@ -313,7 +313,7 @@ static inline uint64_t CalculateBlockReward(uint256_t currentSupply, blockchain_
|
|||||||
|
|
||||||
// Hashing DAG: see Chain_DagParamsForHeight in block/chain.h. Both the size and the epoch seed are
|
// Hashing DAG: see Chain_DagParamsForHeight in block/chain.h. Both the size and the epoch seed are
|
||||||
// derived from the chain by that one function, so the mining and verification paths cannot drift
|
// derived from the chain by that one function, so the mining and verification paths cannot drift
|
||||||
// apart. The previous CalculateTargetDAGSize/GetNextDAGSeed pair lived here, took chainLock
|
// apart. The previous CalculateTargetDAGSize/GetNextDAGSeed pair lived here, took g_chainLock
|
||||||
// internally, was not epoch-aligned, and disagreed with the verifier's own copy in main.c.
|
// internally, was not epoch-aligned, and disagreed with the verifier's own copy in main.c.
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+12
-12
@@ -8,22 +8,22 @@
|
|||||||
#include <block/chain.h>
|
#include <block/chain.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
extern uint64_t currentBlockHeight;
|
extern uint64_t g_currentBlockHeight;
|
||||||
extern blockchain_t* currentChain;
|
extern blockchain_t* g_currentChain;
|
||||||
extern uint256_t currentSupply;
|
extern uint256_t g_currentSupply;
|
||||||
extern uint64_t currentReward;
|
extern uint64_t g_currentReward;
|
||||||
extern uint32_t difficultyTarget;
|
extern uint32_t g_difficultyTarget;
|
||||||
extern const char* chainDataDir;
|
extern const char* g_chainDataDir;
|
||||||
extern unsigned short listenPort;
|
extern unsigned short g_listenPort;
|
||||||
extern bool echoPeersEnabled;
|
extern bool g_echoPeersEnabled;
|
||||||
extern bool forceOrphanReorgEnabled;
|
extern bool g_forceOrphanReorgEnabled;
|
||||||
// Random per-run identity of this node, advertised in HELLO/ACK_HELLO. A host can be reachable
|
// Random per-run identity of this node, advertised in HELLO/ACK_HELLO. A host can be reachable
|
||||||
// under many addresses (especially over IPv6), so an (ip, port) endpoint is not a peer identity:
|
// under many addresses (especially over IPv6), so an (ip, port) endpoint is not a peer identity:
|
||||||
// this nonce is what lets us recognise our own connections and a peer we already talk to.
|
// this nonce is what lets us recognise our own connections and a peer we already talk to.
|
||||||
extern uint64_t localNodeId;
|
extern uint64_t g_localNodeId;
|
||||||
|
|
||||||
// Global synchronization primitives for runtime state
|
// Global synchronization primitives for runtime state
|
||||||
extern pthread_rwlock_t chainLock; // protects chain structure and related mutations
|
extern pthread_rwlock_t g_chainLock; // protects chain structure and related mutations
|
||||||
extern pthread_mutex_t balanceSheetLock; // protects balance sheet map
|
extern pthread_mutex_t g_balanceSheetLock; // protects balance sheet map
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ KHASH_INIT(tx_mempool_map_m, key32_t, signed_transaction_t, 1, hash_key32, eq_ke
|
|||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
extern khash_t(tx_mempool_map_m)* txMempool;
|
extern khash_t(tx_mempool_map_m)* g_txMempool;
|
||||||
|
|
||||||
void TxMempool_Init();
|
void TxMempool_Init();
|
||||||
// Assumed that the transation was confirmed to be valid
|
// Assumed that the transation was confirmed to be valid
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint64_t autolykos2_sleepBetweenHashOperationsMicroseconds = 0;
|
uint64_t g_autolykos2_sleepBetweenHashOperationsMicroseconds = 0;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t* buf;
|
uint8_t* buf;
|
||||||
@@ -249,12 +249,12 @@ static bool Autolykos2_HashCore(
|
|||||||
bool ok = Blake2b_Hash(finalInput, sizeof(finalInput), outHash, 32);
|
bool ok = Blake2b_Hash(finalInput, sizeof(finalInput), outHash, 32);
|
||||||
|
|
||||||
// Throttle between hash operations if configured (applies to all hash paths).
|
// Throttle between hash operations if configured (applies to all hash paths).
|
||||||
if (autolykos2_sleepBetweenHashOperationsMicroseconds > 0) {
|
if (g_autolykos2_sleepBetweenHashOperationsMicroseconds > 0) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
DWORD ms = (DWORD)((autolykos2_sleepBetweenHashOperationsMicroseconds + 999) / 1000);
|
DWORD ms = (DWORD)((g_autolykos2_sleepBetweenHashOperationsMicroseconds + 999) / 1000);
|
||||||
Sleep(ms);
|
Sleep(ms);
|
||||||
#else
|
#else
|
||||||
sleep_for_microseconds(autolykos2_sleepBetweenHashOperationsMicroseconds);
|
sleep_for_microseconds(g_autolykos2_sleepBetweenHashOperationsMicroseconds);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,5 +500,5 @@ bool Autolykos2_FindNonceSingleCore(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Autolykos2_SetSleepBetweenHashOperations(uint64_t sleepMicroseconds) {
|
void Autolykos2_SetSleepBetweenHashOperations(uint64_t sleepMicroseconds) {
|
||||||
autolykos2_sleepBetweenHashOperationsMicroseconds = sleepMicroseconds;
|
g_autolykos2_sleepBetweenHashOperationsMicroseconds = sleepMicroseconds;
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-22
@@ -1,7 +1,7 @@
|
|||||||
#include <balance_sheet.h>
|
#include <balance_sheet.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
khash_t(balance_sheet_map_m)* sheetMap = NULL;
|
khash_t(balance_sheet_map_m)* g_sheetMap = NULL;
|
||||||
static pthread_mutex_t g_sheetLock;
|
static pthread_mutex_t g_sheetLock;
|
||||||
|
|
||||||
static bool BalanceSheet_GetSimEntry(
|
static bool BalanceSheet_GetSimEntry(
|
||||||
@@ -139,7 +139,7 @@ static bool BalanceSheet_ApplyCandidateTransaction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int BalanceSheet_InsertLocked(balance_sheet_entry_t entry) {
|
static int BalanceSheet_InsertLocked(balance_sheet_entry_t entry) {
|
||||||
if (!sheetMap) {
|
if (!g_sheetMap) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,22 +147,22 @@ static int BalanceSheet_InsertLocked(balance_sheet_entry_t entry) {
|
|||||||
memcpy(key.bytes, entry.address, 32);
|
memcpy(key.bytes, entry.address, 32);
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
khiter_t k = kh_put(balance_sheet_map_m, sheetMap, key, &ret);
|
khiter_t k = kh_put(balance_sheet_map_m, g_sheetMap, key, &ret);
|
||||||
if (k == kh_end(sheetMap)) {
|
if (k == kh_end(g_sheetMap)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
kh_value(sheetMap, k) = entry;
|
kh_value(g_sheetMap, k) = entry;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BalanceSheet_Init() {
|
void BalanceSheet_Init() {
|
||||||
sheetMap = kh_init(balance_sheet_map_m);
|
g_sheetMap = kh_init(balance_sheet_map_m);
|
||||||
pthread_mutex_init(&g_sheetLock, NULL);
|
pthread_mutex_init(&g_sheetLock, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int BalanceSheet_Insert(balance_sheet_entry_t entry) {
|
int BalanceSheet_Insert(balance_sheet_entry_t entry) {
|
||||||
if (!sheetMap) { return -1; }
|
if (!g_sheetMap) { return -1; }
|
||||||
|
|
||||||
pthread_mutex_lock(&g_sheetLock);
|
pthread_mutex_lock(&g_sheetLock);
|
||||||
int ret = BalanceSheet_InsertLocked(entry);
|
int ret = BalanceSheet_InsertLocked(entry);
|
||||||
@@ -177,9 +177,9 @@ bool BalanceSheet_Lookup(uint8_t* address, balance_sheet_entry_t* out) {
|
|||||||
key32_t key;
|
key32_t key;
|
||||||
memcpy(key.bytes, address, 32);
|
memcpy(key.bytes, address, 32);
|
||||||
|
|
||||||
khiter_t k = kh_get(balance_sheet_map_m, sheetMap, key);
|
khiter_t k = kh_get(balance_sheet_map_m, g_sheetMap, key);
|
||||||
if (k != kh_end(sheetMap)) {
|
if (k != kh_end(g_sheetMap)) {
|
||||||
balance_sheet_entry_t entry = kh_value(sheetMap, k);
|
balance_sheet_entry_t entry = kh_value(g_sheetMap, k);
|
||||||
memcpy(out, &entry, sizeof(balance_sheet_entry_t));
|
memcpy(out, &entry, sizeof(balance_sheet_entry_t));
|
||||||
pthread_mutex_unlock(&g_sheetLock);
|
pthread_mutex_unlock(&g_sheetLock);
|
||||||
return true;
|
return true;
|
||||||
@@ -190,7 +190,7 @@ bool BalanceSheet_Lookup(uint8_t* address, balance_sheet_entry_t* out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BalanceSheet_SaveToFile(const char* outPath) {
|
bool BalanceSheet_SaveToFile(const char* outPath) {
|
||||||
if (!sheetMap) { return false; }
|
if (!g_sheetMap) { return false; }
|
||||||
|
|
||||||
pthread_mutex_lock(&g_sheetLock);
|
pthread_mutex_lock(&g_sheetLock);
|
||||||
char outFile[512];
|
char outFile[512];
|
||||||
@@ -203,9 +203,9 @@ bool BalanceSheet_SaveToFile(const char* outPath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
khiter_t k;
|
khiter_t k;
|
||||||
for (k = kh_begin(sheetMap); k != kh_end(sheetMap); ++k) {
|
for (k = kh_begin(g_sheetMap); k != kh_end(g_sheetMap); ++k) {
|
||||||
if (kh_exist(sheetMap, k)) {
|
if (kh_exist(g_sheetMap, k)) {
|
||||||
balance_sheet_entry_t entry = kh_val(sheetMap, k);
|
balance_sheet_entry_t entry = kh_val(g_sheetMap, k);
|
||||||
if (fwrite(&entry, sizeof(balance_sheet_entry_t), 1, file) != 1) {
|
if (fwrite(&entry, sizeof(balance_sheet_entry_t), 1, file) != 1) {
|
||||||
fclose(file);
|
fclose(file);
|
||||||
pthread_mutex_unlock(&g_sheetLock);
|
pthread_mutex_unlock(&g_sheetLock);
|
||||||
@@ -220,7 +220,7 @@ bool BalanceSheet_SaveToFile(const char* outPath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BalanceSheet_LoadFromFile(const char* inPath) {
|
bool BalanceSheet_LoadFromFile(const char* inPath) {
|
||||||
if (!sheetMap) { return false; }
|
if (!g_sheetMap) { return false; }
|
||||||
|
|
||||||
pthread_mutex_lock(&g_sheetLock);
|
pthread_mutex_lock(&g_sheetLock);
|
||||||
char inFile[512];
|
char inFile[512];
|
||||||
@@ -247,15 +247,15 @@ bool BalanceSheet_LoadFromFile(const char* inPath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BalanceSheet_Print() {
|
void BalanceSheet_Print() {
|
||||||
if (!sheetMap) { return; }
|
if (!g_sheetMap) { return; }
|
||||||
|
|
||||||
pthread_mutex_lock(&g_sheetLock);
|
pthread_mutex_lock(&g_sheetLock);
|
||||||
// Iterate through every entry
|
// Iterate through every entry
|
||||||
khiter_t k;
|
khiter_t k;
|
||||||
for (k = kh_begin(sheetMap); k != kh_end(sheetMap); ++k) {
|
for (k = kh_begin(g_sheetMap); k != kh_end(g_sheetMap); ++k) {
|
||||||
if (kh_exist(sheetMap, k)) {
|
if (kh_exist(g_sheetMap, k)) {
|
||||||
key32_t key = kh_key(sheetMap, k);
|
key32_t key = kh_key(g_sheetMap, k);
|
||||||
balance_sheet_entry_t val = kh_val(sheetMap, k);
|
balance_sheet_entry_t val = kh_val(g_sheetMap, k);
|
||||||
|
|
||||||
char balanceStr[80];
|
char balanceStr[80];
|
||||||
uint256_serialize(&val.balance, balanceStr);
|
uint256_serialize(&val.balance, balanceStr);
|
||||||
@@ -273,8 +273,8 @@ void BalanceSheet_Print() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BalanceSheet_Destroy() {
|
void BalanceSheet_Destroy() {
|
||||||
kh_destroy(balance_sheet_map_m, sheetMap);
|
kh_destroy(balance_sheet_map_m, g_sheetMap);
|
||||||
sheetMap = NULL;
|
g_sheetMap = NULL;
|
||||||
pthread_mutex_destroy(&g_sheetLock);
|
pthread_mutex_destroy(&g_sheetLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+65
-65
@@ -8,10 +8,10 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
uint64_t currentBlockHeight = 0;
|
uint64_t g_currentBlockHeight = 0;
|
||||||
|
|
||||||
// Defined near the DAG helpers at the bottom; needed early by Chain_AddBlockLocked, which verifies
|
// Defined near the DAG helpers at the bottom; needed early by Chain_AddBlockLocked, which verifies
|
||||||
// proof of work while already holding chainLock for writing.
|
// proof of work while already holding g_chainLock for writing.
|
||||||
static bool Chain_DagParamsForHeightLocked(blockchain_t* chain, uint64_t blockHeight,
|
static bool Chain_DagParamsForHeightLocked(blockchain_t* chain, uint64_t blockHeight,
|
||||||
size_t* outDagBytes, uint8_t outSeed[32]);
|
size_t* outDagBytes, uint8_t outSeed[32]);
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ static bool DebitAddress(const uint8_t address[32], const uint256_t* amount, uin
|
|||||||
* or loaded without transactions (Chain_LoadFromFile), so any full replay of the chain has to be
|
* or loaded without transactions (Chain_LoadFromFile), so any full replay of the chain has to be
|
||||||
* able to fall back to the on-disk copy. On success `*outLoadedFromDisk` tells the caller whether
|
* able to fall back to the on-disk copy. On success `*outLoadedFromDisk` tells the caller whether
|
||||||
* the returned block is a temporary that must be released with Chain_ReturnBlockTransactions.
|
* the returned block is a temporary that must be released with Chain_ReturnBlockTransactions.
|
||||||
* Takes no locks; callers are expected to already hold `chainLock`.
|
* Takes no locks; callers are expected to already hold `g_chainLock`.
|
||||||
**/
|
**/
|
||||||
static bool Chain_BorrowBlockTransactions(blockchain_t* chain, size_t index, block_t** outBlock, bool* outLoadedFromDisk) {
|
static bool Chain_BorrowBlockTransactions(blockchain_t* chain, size_t index, block_t** outBlock, bool* outLoadedFromDisk) {
|
||||||
if (!chain || !chain->blocks || !outBlock || !outLoadedFromDisk) {
|
if (!chain || !chain->blocks || !outBlock || !outLoadedFromDisk) {
|
||||||
@@ -141,7 +141,7 @@ static bool Chain_BorrowBlockTransactions(blockchain_t* chain, size_t index, blo
|
|||||||
|
|
||||||
block_t* loadedBlk = NULL;
|
block_t* loadedBlk = NULL;
|
||||||
size_t txCount = 0;
|
size_t txCount = 0;
|
||||||
if (!Chain_LoadBlockFromFile(chainDataDir, (uint64_t)index, true, &loadedBlk, &txCount) || !loadedBlk) {
|
if (!Chain_LoadBlockFromFile(g_chainDataDir, (uint64_t)index, true, &loadedBlk, &txCount) || !loadedBlk) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,9 +190,9 @@ bool Chain_RecomputeRuntimeState(blockchain_t* chain) {
|
|||||||
Chain_ReturnBlockTransactions(blk, loadedFromDisk);
|
Chain_ReturnBlockTransactions(blk, loadedFromDisk);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentSupply = rebuiltSupply;
|
g_currentSupply = rebuiltSupply;
|
||||||
// *AtHeight: never take chainLock from here, callers may already hold it.
|
// *AtHeight: never take g_chainLock from here, callers may already hold it.
|
||||||
currentReward = CalculateBlockRewardAtHeight(currentSupply, (uint64_t)chain->size);
|
g_currentReward = CalculateBlockRewardAtHeight(g_currentSupply, (uint64_t)chain->size);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@ bool Chain_RecomputeRuntimeState(blockchain_t* chain) {
|
|||||||
* headers reading a single byte each -- so blowing it away wholesale is both correct and cheap,
|
* headers reading a single byte each -- so blowing it away wholesale is both correct and cheap,
|
||||||
* and far safer than trying to work out which suffix a reorg actually disturbed.
|
* and far safer than trying to work out which suffix a reorg actually disturbed.
|
||||||
*
|
*
|
||||||
* Takes `dagCacheLock`. Safe to call while holding `chainLock` (that is the required lock order);
|
* Takes `dagCacheLock`. Safe to call while holding `g_chainLock` (that is the required lock order);
|
||||||
* must NOT be called while already holding `dagCacheLock`.
|
* must NOT be called while already holding `dagCacheLock`.
|
||||||
**/
|
**/
|
||||||
static void Chain_InvalidateDagEpochs(blockchain_t* chain) {
|
static void Chain_InvalidateDagEpochs(blockchain_t* chain) {
|
||||||
@@ -280,7 +280,7 @@ void Chain_Destroy(blockchain_t* chain) {
|
|||||||
/**
|
/**
|
||||||
* Append `block` to the tip.
|
* Append `block` to the tip.
|
||||||
*
|
*
|
||||||
* Caller MUST already hold `chainLock` (write) and `balanceSheetLock`, and MUST call
|
* Caller MUST already hold `g_chainLock` (write) and `g_balanceSheetLock`, and MUST call
|
||||||
* Chain_OnTipAdvanced afterwards (outside the locks) if this returns true. Chain_AddBlock is the
|
* Chain_OnTipAdvanced afterwards (outside the locks) if this returns true. Chain_AddBlock is the
|
||||||
* locked wrapper for single appends; Chain_ReplaceBranch drives this directly so that a whole
|
* locked wrapper for single appends; Chain_ReplaceBranch drives this directly so that a whole
|
||||||
* branch swap happens under one lock acquisition.
|
* branch swap happens under one lock acquisition.
|
||||||
@@ -407,7 +407,7 @@ static bool Chain_AddBlockLocked(blockchain_t* chain, block_t* block) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t expectedCoinbaseAmount = currentReward;
|
uint64_t expectedCoinbaseAmount = g_currentReward;
|
||||||
if (UINT64_MAX - expectedCoinbaseAmount < totalFees) {
|
if (UINT64_MAX - expectedCoinbaseAmount < totalFees) {
|
||||||
free(spendableTxs);
|
free(spendableTxs);
|
||||||
ok = false;
|
ok = false;
|
||||||
@@ -425,13 +425,13 @@ static bool Chain_AddBlockLocked(blockchain_t* chain, block_t* block) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
char supplyStr[80];
|
char supplyStr[80];
|
||||||
Uint256ToDecimal(¤tSupply, supplyStr, sizeof(supplyStr));
|
Uint256ToDecimal(&g_currentSupply, supplyStr, sizeof(supplyStr));
|
||||||
printf("Chain_AddBlock: blockIndex=%zu expectedCoinbase=%llu totalFees=%llu observedBlockCoinbase=%llu currentReward=%llu currentSupply=%s\n",
|
printf("Chain_AddBlock: blockIndex=%zu expectedCoinbase=%llu totalFees=%llu observedBlockCoinbase=%llu currentReward=%llu currentSupply=%s\n",
|
||||||
expectedIndex,
|
expectedIndex,
|
||||||
(unsigned long long)expectedCoinbaseAmount,
|
(unsigned long long)expectedCoinbaseAmount,
|
||||||
(unsigned long long)totalFees,
|
(unsigned long long)totalFees,
|
||||||
(unsigned long long)cbAmount,
|
(unsigned long long)cbAmount,
|
||||||
(unsigned long long)currentReward,
|
(unsigned long long)g_currentReward,
|
||||||
supplyStr);
|
supplyStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -479,7 +479,7 @@ static bool Chain_AddBlockLocked(blockchain_t* chain, block_t* block) {
|
|||||||
block_t* blk = (block_t*)vector_back(chain->blocks);
|
block_t* blk = (block_t*)vector_back(chain->blocks);
|
||||||
stored = blk;
|
stored = blk;
|
||||||
chain->size++;
|
chain->size++;
|
||||||
currentBlockHeight = (uint64_t)(chain->size - 1);
|
g_currentBlockHeight = (uint64_t)(chain->size - 1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The chain now owns the transaction vector, so clear the CALLER's pointer to it.
|
* The chain now owns the transaction vector, so clear the CALLER's pointer to it.
|
||||||
@@ -556,14 +556,14 @@ static bool Chain_AddBlockLocked(blockchain_t* chain, block_t* block) {
|
|||||||
|
|
||||||
// Advance supply and reward here rather than in each caller. Callers used to do this
|
// Advance supply and reward here rather than in each caller. Callers used to do this
|
||||||
// themselves, which meant the orphan-attach and maintenance-thread paths never did it: the
|
// themselves, which meant the orphan-attach and maintenance-thread paths never did it: the
|
||||||
// next block's coinbase was then validated against a stale currentReward and rejected
|
// next block's coinbase was then validated against a stale g_currentReward and rejected
|
||||||
// forever. It also has to happen per block so that applying a whole branch works.
|
// forever. It also has to happen per block so that applying a whole branch works.
|
||||||
if (ok) {
|
if (ok) {
|
||||||
(void)uint256_add_u64(¤tSupply, expectedCoinbaseAmount);
|
(void)uint256_add_u64(&g_currentSupply, expectedCoinbaseAmount);
|
||||||
// Must be the *AtHeight variant: we hold chainLock for writing here, and
|
// Must be the *AtHeight variant: we hold g_chainLock for writing here, and
|
||||||
// CalculateBlockReward would take it for reading via Chain_Size. chainLock is not
|
// CalculateBlockReward would take it for reading via Chain_Size. g_chainLock is not
|
||||||
// recursive, so that self-deadlocks as soon as another thread queues for the write lock.
|
// recursive, so that self-deadlocks as soon as another thread queues for the write lock.
|
||||||
currentReward = CalculateBlockRewardAtHeight(currentSupply, (uint64_t)chain->size);
|
g_currentReward = CalculateBlockRewardAtHeight(g_currentSupply, (uint64_t)chain->size);
|
||||||
}
|
}
|
||||||
// ok remains true if no failures
|
// ok remains true if no failures
|
||||||
} while (0);
|
} while (0);
|
||||||
@@ -582,13 +582,13 @@ bool Chain_AddBlock(blockchain_t* chain, block_t* block) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Acquire global write locks to protect chain and balance sheet mutations.
|
// Acquire global write locks to protect chain and balance sheet mutations.
|
||||||
pthread_rwlock_wrlock(&chainLock);
|
pthread_rwlock_wrlock(&g_chainLock);
|
||||||
pthread_mutex_lock(&balanceSheetLock);
|
pthread_mutex_lock(&g_balanceSheetLock);
|
||||||
|
|
||||||
bool ok = Chain_AddBlockLocked(chain, block);
|
bool ok = Chain_AddBlockLocked(chain, block);
|
||||||
|
|
||||||
pthread_mutex_unlock(&balanceSheetLock);
|
pthread_mutex_unlock(&g_balanceSheetLock);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
// Every path that appends comes through here, so this is where difficulty/DAG catch up.
|
// Every path that appends comes through here, so this is where difficulty/DAG catch up.
|
||||||
@@ -601,23 +601,23 @@ bool Chain_AddBlock(blockchain_t* chain, block_t* block) {
|
|||||||
block_t* Chain_GetBlock(blockchain_t* chain, size_t index) {
|
block_t* Chain_GetBlock(blockchain_t* chain, size_t index) {
|
||||||
if (!chain) return NULL;
|
if (!chain) return NULL;
|
||||||
block_t* blk = NULL;
|
block_t* blk = NULL;
|
||||||
pthread_rwlock_rdlock(&chainLock);
|
pthread_rwlock_rdlock(&g_chainLock);
|
||||||
blk = (block_t*)vector_get(chain->blocks, index);
|
blk = (block_t*)vector_get(chain->blocks, index);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
return blk;
|
return blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Chain_GetBlockCopy(blockchain_t* chain, size_t index, block_t** outCopy) {
|
bool Chain_GetBlockCopy(blockchain_t* chain, size_t index, block_t** outCopy) {
|
||||||
if (!chain || !outCopy) return false;
|
if (!chain || !outCopy) return false;
|
||||||
*outCopy = NULL;
|
*outCopy = NULL;
|
||||||
pthread_rwlock_rdlock(&chainLock);
|
pthread_rwlock_rdlock(&g_chainLock);
|
||||||
block_t* src = (block_t*)vector_get(chain->blocks, index);
|
block_t* src = (block_t*)vector_get(chain->blocks, index);
|
||||||
if (!src) {
|
if (!src) {
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
block_t* copy = Block_Copy(src);
|
block_t* copy = Block_Copy(src);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
if (!copy) return false;
|
if (!copy) return false;
|
||||||
*outCopy = copy;
|
*outCopy = copy;
|
||||||
return true;
|
return true;
|
||||||
@@ -626,9 +626,9 @@ bool Chain_GetBlockCopy(blockchain_t* chain, size_t index, block_t** outCopy) {
|
|||||||
size_t Chain_Size(blockchain_t* chain) {
|
size_t Chain_Size(blockchain_t* chain) {
|
||||||
if (!chain) return 0;
|
if (!chain) return 0;
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
pthread_rwlock_rdlock(&chainLock);
|
pthread_rwlock_rdlock(&g_chainLock);
|
||||||
sz = vector_size(chain->blocks);
|
sz = vector_size(chain->blocks);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,7 +671,7 @@ bool Chain_IsValid(blockchain_t* chain) {
|
|||||||
/**
|
/**
|
||||||
* Truncate the chain to `height` blocks and rebuild the balance sheet and supply from what remains.
|
* Truncate the chain to `height` blocks and rebuild the balance sheet and supply from what remains.
|
||||||
*
|
*
|
||||||
* Caller MUST already hold `chainLock` (write) and `balanceSheetLock`, and MUST call
|
* Caller MUST already hold `g_chainLock` (write) and `g_balanceSheetLock`, and MUST call
|
||||||
* Chain_OnTipAdvanced afterwards (outside the locks). Chain_RollbackToHeight is the locked wrapper.
|
* Chain_OnTipAdvanced afterwards (outside the locks). Chain_RollbackToHeight is the locked wrapper.
|
||||||
**/
|
**/
|
||||||
static bool Chain_RollbackToHeightLocked(blockchain_t* chain, size_t height) {
|
static bool Chain_RollbackToHeightLocked(blockchain_t* chain, size_t height) {
|
||||||
@@ -734,7 +734,7 @@ static bool Chain_RollbackToHeightLocked(blockchain_t* chain, size_t height) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
chain->size = vector_size(chain->blocks);
|
chain->size = vector_size(chain->blocks);
|
||||||
currentBlockHeight = chain->size ? (uint64_t)(chain->size - 1) : 0ULL;
|
g_currentBlockHeight = chain->size ? (uint64_t)(chain->size - 1) : 0ULL;
|
||||||
|
|
||||||
// Blocks below the old tip are gone, so the DAG recurrence folded from their votes is stale.
|
// Blocks below the old tip are gone, so the DAG recurrence folded from their votes is stale.
|
||||||
Chain_InvalidateDagEpochs(chain);
|
Chain_InvalidateDagEpochs(chain);
|
||||||
@@ -830,9 +830,9 @@ static bool Chain_RollbackToHeightLocked(blockchain_t* chain, size_t height) {
|
|||||||
Chain_ReturnBlockTransactions(toProcess, loaded);
|
Chain_ReturnBlockTransactions(toProcess, loaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentSupply = rebuiltSupply;
|
g_currentSupply = rebuiltSupply;
|
||||||
// *AtHeight: chainLock is held for writing here (see Chain_RollbackToHeight).
|
// *AtHeight: g_chainLock is held for writing here (see Chain_RollbackToHeight).
|
||||||
currentReward = CalculateBlockRewardAtHeight(currentSupply, (uint64_t)chain->size);
|
g_currentReward = CalculateBlockRewardAtHeight(g_currentSupply, (uint64_t)chain->size);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -840,13 +840,13 @@ static bool Chain_RollbackToHeightLocked(blockchain_t* chain, size_t height) {
|
|||||||
bool Chain_RollbackToHeight(blockchain_t* chain, size_t height) {
|
bool Chain_RollbackToHeight(blockchain_t* chain, size_t height) {
|
||||||
if (!chain || !chain->blocks) return false;
|
if (!chain || !chain->blocks) return false;
|
||||||
|
|
||||||
pthread_rwlock_wrlock(&chainLock);
|
pthread_rwlock_wrlock(&g_chainLock);
|
||||||
pthread_mutex_lock(&balanceSheetLock);
|
pthread_mutex_lock(&g_balanceSheetLock);
|
||||||
|
|
||||||
bool ok = Chain_RollbackToHeightLocked(chain, height);
|
bool ok = Chain_RollbackToHeightLocked(chain, height);
|
||||||
|
|
||||||
pthread_mutex_unlock(&balanceSheetLock);
|
pthread_mutex_unlock(&g_balanceSheetLock);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
|
|
||||||
// A reorg can move the tip back across an adjustment boundary, so the target must come down too.
|
// A reorg can move the tip back across an adjustment boundary, so the target must come down too.
|
||||||
Chain_OnTipAdvanced(chain);
|
Chain_OnTipAdvanced(chain);
|
||||||
@@ -863,7 +863,7 @@ static int Chain_CompareTimestamps(const void* lhs, const void* rhs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Median timestamp of the last MEDIAN_TIME_SPAN blocks. Caller must hold `chainLock`.
|
* Median timestamp of the last MEDIAN_TIME_SPAN blocks. Caller must hold `g_chainLock`.
|
||||||
**/
|
**/
|
||||||
static uint64_t Chain_MedianTimePastLocked(blockchain_t* chain) {
|
static uint64_t Chain_MedianTimePastLocked(blockchain_t* chain) {
|
||||||
if (!chain || !chain->blocks) {
|
if (!chain || !chain->blocks) {
|
||||||
@@ -916,7 +916,7 @@ bool Chain_IsInitialBlockDownload(blockchain_t* chain) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify that a candidate branch is internally linked and attaches to the block below `forkHeight`.
|
* Verify that a candidate branch is internally linked and attaches to the block below `forkHeight`.
|
||||||
* Caller must hold `chainLock`.
|
* Caller must hold `g_chainLock`.
|
||||||
**/
|
**/
|
||||||
static bool Chain_BranchIsLinkedLocked(blockchain_t* chain, size_t forkHeight, block_t** blocks, size_t count) {
|
static bool Chain_BranchIsLinkedLocked(blockchain_t* chain, size_t forkHeight, block_t** blocks, size_t count) {
|
||||||
if (!chain || !chain->blocks || !blocks || count == 0 || forkHeight == 0) {
|
if (!chain || !chain->blocks || !blocks || count == 0 || forkHeight == 0) {
|
||||||
@@ -1035,8 +1035,8 @@ bool Chain_ReplaceBranch(blockchain_t* chain,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_rwlock_wrlock(&chainLock);
|
pthread_rwlock_wrlock(&g_chainLock);
|
||||||
pthread_mutex_lock(&balanceSheetLock);
|
pthread_mutex_lock(&g_balanceSheetLock);
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
block_t** snapshot = NULL; // deep copies of the blocks we are replacing
|
block_t** snapshot = NULL; // deep copies of the blocks we are replacing
|
||||||
@@ -1109,7 +1109,7 @@ bool Chain_ReplaceBranch(blockchain_t* chain,
|
|||||||
// only change when our own tip moves -- so without this the same line is printed
|
// only change when our own tip moves -- so without this the same line is printed
|
||||||
// every second for as long as the branch stays deferred, which on a node that is
|
// every second for as long as the branch stays deferred, which on a node that is
|
||||||
// not mining is forever. Report each distinct deferral once, and again whenever the
|
// not mining is forever. Report each distinct deferral once, and again whenever the
|
||||||
// situation actually changes. Guarded by chainLock (held for writing here).
|
// situation actually changes. Guarded by g_chainLock (held for writing here).
|
||||||
static size_t lastDeferredFork = SIZE_MAX;
|
static size_t lastDeferredFork = SIZE_MAX;
|
||||||
static uint64_t lastDeferredTip = UINT64_MAX;
|
static uint64_t lastDeferredTip = UINT64_MAX;
|
||||||
static uint64_t lastDeferredPenalty = UINT64_MAX;
|
static uint64_t lastDeferredPenalty = UINT64_MAX;
|
||||||
@@ -1247,8 +1247,8 @@ bool Chain_ReplaceBranch(blockchain_t* chain,
|
|||||||
Chain_FreeBlockArray(snapshot, snapshotCount);
|
Chain_FreeBlockArray(snapshot, snapshotCount);
|
||||||
Chain_FreeBlockArray(candidate, candidate ? count : 0);
|
Chain_FreeBlockArray(candidate, candidate ? count : 0);
|
||||||
|
|
||||||
pthread_mutex_unlock(&balanceSheetLock);
|
pthread_mutex_unlock(&g_balanceSheetLock);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
|
|
||||||
Chain_OnTipAdvanced(chain);
|
Chain_OnTipAdvanced(chain);
|
||||||
|
|
||||||
@@ -1257,8 +1257,8 @@ bool Chain_ReplaceBranch(blockchain_t* chain,
|
|||||||
|
|
||||||
void Chain_Wipe(blockchain_t* chain) {
|
void Chain_Wipe(blockchain_t* chain) {
|
||||||
Chain_ClearBlocks(chain);
|
Chain_ClearBlocks(chain);
|
||||||
currentBlockHeight = 0;
|
g_currentBlockHeight = 0;
|
||||||
difficultyTarget = INITIAL_DIFFICULTY;
|
g_difficultyTarget = INITIAL_DIFFICULTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Chain_SaveToFile(blockchain_t* chain, const char* dirpath, uint256_t currentSupply, uint64_t currentReward) {
|
bool Chain_SaveToFile(blockchain_t* chain, const char* dirpath, uint256_t currentSupply, uint64_t currentReward) {
|
||||||
@@ -1293,7 +1293,7 @@ bool Chain_SaveToFile(blockchain_t* chain, const char* dirpath, uint256_t curren
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_rwlock_wrlock(&chainLock);
|
pthread_rwlock_wrlock(&g_chainLock);
|
||||||
|
|
||||||
FILE* metaFile = fopen(metaTmpPath, "wb+");
|
FILE* metaFile = fopen(metaTmpPath, "wb+");
|
||||||
FILE* chainFile = fopen(chainTmpPath, "wb+");
|
FILE* chainFile = fopen(chainTmpPath, "wb+");
|
||||||
@@ -1302,7 +1302,7 @@ bool Chain_SaveToFile(blockchain_t* chain, const char* dirpath, uint256_t curren
|
|||||||
if (metaFile) fclose(metaFile);
|
if (metaFile) fclose(metaFile);
|
||||||
if (chainFile) fclose(chainFile);
|
if (chainFile) fclose(chainFile);
|
||||||
if (tableFile) fclose(tableFile);
|
if (tableFile) fclose(tableFile);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
remove(metaTmpPath);
|
remove(metaTmpPath);
|
||||||
remove(chainTmpPath);
|
remove(chainTmpPath);
|
||||||
remove(tableTmpPath);
|
remove(tableTmpPath);
|
||||||
@@ -1317,7 +1317,7 @@ bool Chain_SaveToFile(blockchain_t* chain, const char* dirpath, uint256_t curren
|
|||||||
fclose(metaFile);
|
fclose(metaFile);
|
||||||
fclose(chainFile);
|
fclose(chainFile);
|
||||||
fclose(tableFile);
|
fclose(tableFile);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
remove(metaTmpPath);
|
remove(metaTmpPath);
|
||||||
remove(chainTmpPath);
|
remove(chainTmpPath);
|
||||||
remove(tableTmpPath);
|
remove(tableTmpPath);
|
||||||
@@ -1334,7 +1334,7 @@ bool Chain_SaveToFile(blockchain_t* chain, const char* dirpath, uint256_t curren
|
|||||||
fclose(metaFile);
|
fclose(metaFile);
|
||||||
fclose(chainFile);
|
fclose(chainFile);
|
||||||
fclose(tableFile);
|
fclose(tableFile);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
remove(metaTmpPath);
|
remove(metaTmpPath);
|
||||||
remove(chainTmpPath);
|
remove(chainTmpPath);
|
||||||
remove(tableTmpPath);
|
remove(tableTmpPath);
|
||||||
@@ -1349,7 +1349,7 @@ bool Chain_SaveToFile(blockchain_t* chain, const char* dirpath, uint256_t curren
|
|||||||
fclose(metaFile);
|
fclose(metaFile);
|
||||||
fclose(chainFile);
|
fclose(chainFile);
|
||||||
fclose(tableFile);
|
fclose(tableFile);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
remove(metaTmpPath);
|
remove(metaTmpPath);
|
||||||
remove(chainTmpPath);
|
remove(chainTmpPath);
|
||||||
remove(tableTmpPath);
|
remove(tableTmpPath);
|
||||||
@@ -1362,7 +1362,7 @@ bool Chain_SaveToFile(blockchain_t* chain, const char* dirpath, uint256_t curren
|
|||||||
fclose(metaFile);
|
fclose(metaFile);
|
||||||
fclose(chainFile);
|
fclose(chainFile);
|
||||||
fclose(tableFile);
|
fclose(tableFile);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
remove(metaTmpPath);
|
remove(metaTmpPath);
|
||||||
remove(chainTmpPath);
|
remove(chainTmpPath);
|
||||||
remove(tableTmpPath);
|
remove(tableTmpPath);
|
||||||
@@ -1377,7 +1377,7 @@ bool Chain_SaveToFile(blockchain_t* chain, const char* dirpath, uint256_t curren
|
|||||||
fclose(metaFile);
|
fclose(metaFile);
|
||||||
fclose(chainFile);
|
fclose(chainFile);
|
||||||
fclose(tableFile);
|
fclose(tableFile);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
remove(metaTmpPath);
|
remove(metaTmpPath);
|
||||||
remove(chainTmpPath);
|
remove(chainTmpPath);
|
||||||
remove(tableTmpPath);
|
remove(tableTmpPath);
|
||||||
@@ -1395,7 +1395,7 @@ bool Chain_SaveToFile(blockchain_t* chain, const char* dirpath, uint256_t curren
|
|||||||
fclose(metaFile);
|
fclose(metaFile);
|
||||||
fclose(chainFile);
|
fclose(chainFile);
|
||||||
fclose(tableFile);
|
fclose(tableFile);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
remove(metaTmpPath);
|
remove(metaTmpPath);
|
||||||
remove(chainTmpPath);
|
remove(chainTmpPath);
|
||||||
remove(tableTmpPath);
|
remove(tableTmpPath);
|
||||||
@@ -1436,14 +1436,14 @@ bool Chain_SaveToFile(blockchain_t* chain, const char* dirpath, uint256_t curren
|
|||||||
fclose(tableFile);
|
fclose(tableFile);
|
||||||
|
|
||||||
if (rename(metaTmpPath, metaPath) != 0 || rename(chainTmpPath, chainPath) != 0 || rename(tableTmpPath, tablePath) != 0) {
|
if (rename(metaTmpPath, metaPath) != 0 || rename(chainTmpPath, chainPath) != 0 || rename(tableTmpPath, tablePath) != 0) {
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
remove(metaTmpPath);
|
remove(metaTmpPath);
|
||||||
remove(chainTmpPath);
|
remove(chainTmpPath);
|
||||||
remove(tableTmpPath);
|
remove(tableTmpPath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2023,7 +2023,7 @@ static bool Chain_ReserveDagEpochsLocked(blockchain_t* chain, size_t needed) {
|
|||||||
* [0, k * EPOCH_LENGTH) to all be present. Growth is the default: the size only stays put or falls
|
* [0, k * EPOCH_LENGTH) to all be present. Growth is the default: the size only stays put or falls
|
||||||
* when miners actively say so, and there is no vote that makes it climb faster.
|
* when miners actively say so, and there is no vote that makes it climb faster.
|
||||||
*
|
*
|
||||||
* Caller must hold `chainLock` (read) and `chain->dagCacheLock`.
|
* Caller must hold `g_chainLock` (read) and `chain->dagCacheLock`.
|
||||||
**/
|
**/
|
||||||
static bool Chain_ExtendDagEpochsLocked(blockchain_t* chain, size_t epochIndex) {
|
static bool Chain_ExtendDagEpochsLocked(blockchain_t* chain, size_t epochIndex) {
|
||||||
if (!chain || !chain->blocks) {
|
if (!chain || !chain->blocks) {
|
||||||
@@ -2112,7 +2112,7 @@ static bool Chain_ExtendDagEpochsLocked(blockchain_t* chain, size_t epochIndex)
|
|||||||
* last block of the previous epoch. Constant for a whole epoch, which is what lets the DAG be
|
* last block of the previous epoch. Constant for a whole epoch, which is what lets the DAG be
|
||||||
* generated once per epoch instead of once per block.
|
* generated once per epoch instead of once per block.
|
||||||
*
|
*
|
||||||
* Caller must hold `chainLock`.
|
* Caller must hold `g_chainLock`.
|
||||||
**/
|
**/
|
||||||
static bool Chain_EpochDagSeedForHeightLocked(blockchain_t* chain, uint64_t blockHeight, uint8_t outSeed[32]) {
|
static bool Chain_EpochDagSeedForHeightLocked(blockchain_t* chain, uint64_t blockHeight, uint8_t outSeed[32]) {
|
||||||
const uint64_t epochIndex = blockHeight / (uint64_t)EPOCH_LENGTH;
|
const uint64_t epochIndex = blockHeight / (uint64_t)EPOCH_LENGTH;
|
||||||
@@ -2136,10 +2136,10 @@ static bool Chain_EpochDagSeedForHeightLocked(blockchain_t* chain, uint64_t bloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* As Chain_DagParamsForHeight, but assumes `chainLock` is already held (read OR write).
|
* As Chain_DagParamsForHeight, but assumes `g_chainLock` is already held (read OR write).
|
||||||
*
|
*
|
||||||
* Needed because Chain_AddBlockLocked verifies proof of work while holding the write lock, and
|
* Needed because Chain_AddBlockLocked verifies proof of work while holding the write lock, and
|
||||||
* chainLock is not recursive -- taking it for reading there deadlocks the moment another thread
|
* g_chainLock is not recursive -- taking it for reading there deadlocks the moment another thread
|
||||||
* queues for the write lock.
|
* queues for the write lock.
|
||||||
**/
|
**/
|
||||||
static bool Chain_DagParamsForHeightLocked(blockchain_t* chain, uint64_t blockHeight,
|
static bool Chain_DagParamsForHeightLocked(blockchain_t* chain, uint64_t blockHeight,
|
||||||
@@ -2153,7 +2153,7 @@ static bool Chain_DagParamsForHeightLocked(blockchain_t* chain, uint64_t blockHe
|
|||||||
uint64_t bytes = 0;
|
uint64_t bytes = 0;
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
|
||||||
// Lock order is chainLock -> dagCacheLock, everywhere. Nothing under dagCacheLock calls back
|
// Lock order is g_chainLock -> dagCacheLock, everywhere. Nothing under dagCacheLock calls back
|
||||||
// into chain.c, so this pair cannot deadlock.
|
// into chain.c, so this pair cannot deadlock.
|
||||||
pthread_mutex_lock(&chain->dagCacheLock);
|
pthread_mutex_lock(&chain->dagCacheLock);
|
||||||
if (Chain_ExtendDagEpochsLocked(chain, epochIndex)) {
|
if (Chain_ExtendDagEpochsLocked(chain, epochIndex)) {
|
||||||
@@ -2186,9 +2186,9 @@ bool Chain_DagParamsForHeight(blockchain_t* chain, uint64_t blockHeight,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_rwlock_rdlock(&chainLock);
|
pthread_rwlock_rdlock(&g_chainLock);
|
||||||
const bool ok = Chain_DagParamsForHeightLocked(chain, blockHeight, outDagBytes, outSeed);
|
const bool ok = Chain_DagParamsForHeightLocked(chain, blockHeight, outDagBytes, outSeed);
|
||||||
pthread_rwlock_unlock(&chainLock);
|
pthread_rwlock_unlock(&g_chainLock);
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -2202,7 +2202,7 @@ void Chain_OnTipAdvanced(blockchain_t* chain) {
|
|||||||
|
|
||||||
// Refresh the cached target for the block that comes next, so every path that moves the tip
|
// Refresh the cached target for the block that comes next, so every path that moves the tip
|
||||||
// (mining, P2P accept, sync, orphan attach, reorg) stays on the same difficulty as its peers.
|
// (mining, P2P accept, sync, orphan attach, reorg) stays on the same difficulty as its peers.
|
||||||
difficultyTarget = Chain_GetTargetForHeight(chain, (uint64_t)chainSize);
|
g_difficultyTarget = Chain_GetTargetForHeight(chain, (uint64_t)chainSize);
|
||||||
|
|
||||||
// The epoch DAG is deliberately NOT rebuilt here. It is a mining accelerator only -- validation
|
// The epoch DAG is deliberately NOT rebuilt here. It is a mining accelerator only -- validation
|
||||||
// derives its lanes from the epoch seed, so a node that does not mine never allocates one --
|
// derives its lanes from the epoch seed, so a node that does not mine never allocates one --
|
||||||
|
|||||||
+58
-58
@@ -29,18 +29,18 @@
|
|||||||
#define CHAIN_DATA_DIR "chain_data"
|
#define CHAIN_DATA_DIR "chain_data"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
blockchain_t* currentChain = NULL;
|
blockchain_t* g_currentChain = NULL;
|
||||||
const char* chainDataDir = CHAIN_DATA_DIR;
|
const char* g_chainDataDir = CHAIN_DATA_DIR;
|
||||||
unsigned short listenPort = LISTEN_PORT;
|
unsigned short g_listenPort = LISTEN_PORT;
|
||||||
bool echoPeersEnabled = ECHO_PEERS != 0;
|
bool g_echoPeersEnabled = ECHO_PEERS != 0;
|
||||||
bool forceOrphanReorgEnabled = false;
|
bool g_forceOrphanReorgEnabled = false;
|
||||||
uint256_t currentSupply = {{0, 0, 0, 0}};
|
uint256_t g_currentSupply = {{0, 0, 0, 0}};
|
||||||
uint64_t currentReward = 750000000000ULL;
|
uint64_t g_currentReward = 750000000000ULL;
|
||||||
uint64_t localNodeId = 0; // Randomised in main() before the node comes up
|
uint64_t g_localNodeId = 0; // Randomised in main() before the node comes up
|
||||||
|
|
||||||
// Define the synchronization primitives declared in runtime_state.h
|
// Define the synchronization primitives declared in runtime_state.h
|
||||||
pthread_rwlock_t chainLock;
|
pthread_rwlock_t g_chainLock;
|
||||||
pthread_mutex_t balanceSheetLock;
|
pthread_mutex_t g_balanceSheetLock;
|
||||||
|
|
||||||
void handle_sigint(int sig) {
|
void handle_sigint(int sig) {
|
||||||
printf("Caught signal %d, exiting...\n", sig);
|
printf("Caught signal %d, exiting...\n", sig);
|
||||||
@@ -52,7 +52,7 @@ void handle_sigint(int sig) {
|
|||||||
static void ApplyRuntimeConfigFromEnv(void) {
|
static void ApplyRuntimeConfigFromEnv(void) {
|
||||||
const char* dataDir = getenv("SKALACOIN_CHAIN_DATA_DIR");
|
const char* dataDir = getenv("SKALACOIN_CHAIN_DATA_DIR");
|
||||||
if (dataDir && dataDir[0] != '\0') {
|
if (dataDir && dataDir[0] != '\0') {
|
||||||
chainDataDir = dataDir;
|
g_chainDataDir = dataDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* portStr = getenv("SKALACOIN_LISTEN_PORT");
|
const char* portStr = getenv("SKALACOIN_LISTEN_PORT");
|
||||||
@@ -60,29 +60,29 @@ static void ApplyRuntimeConfigFromEnv(void) {
|
|||||||
char* end = NULL;
|
char* end = NULL;
|
||||||
long parsed = strtol(portStr, &end, 10);
|
long parsed = strtol(portStr, &end, 10);
|
||||||
if (end != portStr && *end == '\0' && parsed > 0 && parsed <= 65535) {
|
if (end != portStr && *end == '\0' && parsed > 0 && parsed <= 65535) {
|
||||||
listenPort = (unsigned short)parsed;
|
g_listenPort = (unsigned short)parsed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* echoStr = getenv("SKALACOIN_ECHO_PEERS");
|
const char* echoStr = getenv("SKALACOIN_ECHO_PEERS");
|
||||||
if (echoStr && echoStr[0] != '\0') {
|
if (echoStr && echoStr[0] != '\0') {
|
||||||
echoPeersEnabled = (strcmp(echoStr, "0") != 0);
|
g_echoPeersEnabled = (strcmp(echoStr, "0") != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* forceOrphanStr = getenv("SKALACOIN_FORCE_ORPHAN_REORG");
|
const char* forceOrphanStr = getenv("SKALACOIN_FORCE_ORPHAN_REORG");
|
||||||
if (forceOrphanStr && forceOrphanStr[0] != '\0') {
|
if (forceOrphanStr && forceOrphanStr[0] != '\0') {
|
||||||
forceOrphanReorgEnabled = (strcmp(forceOrphanStr, "0") != 0);
|
g_forceOrphanReorgEnabled = (strcmp(forceOrphanStr, "0") != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t difficultyTarget = INITIAL_DIFFICULTY;
|
uint32_t g_difficultyTarget = INITIAL_DIFFICULTY;
|
||||||
|
|
||||||
static bool MineBlock(blockchain_t* chain, block_t* block) {
|
static bool MineBlock(blockchain_t* chain, block_t* block) {
|
||||||
if (!chain || !block) {
|
if (!chain || !block) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the epoch parameters ONCE. Doing it per nonce would take chainLock millions of times
|
// Resolve the epoch parameters ONCE. Doing it per nonce would take g_chainLock millions of times
|
||||||
// per block and contend with every network thread.
|
// per block and contend with every network thread.
|
||||||
size_t dagBytes = 0;
|
size_t dagBytes = 0;
|
||||||
uint8_t seed[32];
|
uint8_t seed[32];
|
||||||
@@ -568,8 +568,8 @@ static bool MineAndAppendBlock(blockchain_t* chain,
|
|||||||
if (attached > 0) {
|
if (attached > 0) {
|
||||||
printf("Attached %zu orphan(s) after mining/appending block\n", attached);
|
printf("Attached %zu orphan(s) after mining/appending block\n", attached);
|
||||||
// Persist chain/sheet after attaching orphans
|
// Persist chain/sheet after attaching orphans
|
||||||
Chain_SaveToFile(chain, chainDataDir, *currentSupply, *currentReward);
|
Chain_SaveToFile(chain, g_chainDataDir, *currentSupply, *currentReward);
|
||||||
BalanceSheet_SaveToFile(chainDataDir);
|
BalanceSheet_SaveToFile(g_chainDataDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t canonicalHash[32];
|
uint8_t canonicalHash[32];
|
||||||
@@ -711,9 +711,9 @@ static bool VerifyChainFully(blockchain_t* chain) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t expectedReward = 0;
|
uint64_t expectedReward = 0;
|
||||||
uint64_t savedReward = currentReward;
|
uint64_t savedReward = g_currentReward;
|
||||||
expectedReward = CalculateBlockReward(replaySupply, prevChain);
|
expectedReward = CalculateBlockReward(replaySupply, prevChain);
|
||||||
currentReward = savedReward;
|
g_currentReward = savedReward;
|
||||||
|
|
||||||
if (!Block_AllTransactionsValid(blk)) {
|
if (!Block_AllTransactionsValid(blk)) {
|
||||||
Block_Destroy(blk);
|
Block_Destroy(blk);
|
||||||
@@ -772,7 +772,7 @@ static bool VerifyChainFully(blockchain_t* chain) {
|
|||||||
// Use when error
|
// Use when error
|
||||||
[[noreturn]] void KillEverythingAndExit(net_node_t* node, blockchain_t* chain) {
|
[[noreturn]] void KillEverythingAndExit(net_node_t* node, blockchain_t* chain) {
|
||||||
Node_Destroy(node);
|
Node_Destroy(node);
|
||||||
currentChain = NULL;
|
g_currentChain = NULL;
|
||||||
Chain_Destroy(chain);
|
Chain_Destroy(chain);
|
||||||
Block_ShutdownPowContext();
|
Block_ShutdownPowContext();
|
||||||
BalanceSheet_Destroy();
|
BalanceSheet_Destroy();
|
||||||
@@ -818,12 +818,12 @@ int main(int argc, char* argv[]) {
|
|||||||
// Pick this run's node identity before the node (and with it the listener) comes up, so every
|
// Pick this run's node identity before the node (and with it the listener) comes up, so every
|
||||||
// handshake can carry it. Peers are identified by this nonce rather than by an (ip, port)
|
// handshake can carry it. Peers are identified by this nonce rather than by an (ip, port)
|
||||||
// endpoint, which a multi-homed host has several of.
|
// endpoint, which a multi-homed host has several of.
|
||||||
localNodeId = random_secure_eight_byte();
|
g_localNodeId = random_secure_eight_byte();
|
||||||
printf("Node identity: %016" PRIx64 "\n", localNodeId);
|
printf("Node identity: %016" PRIx64 "\n", g_localNodeId);
|
||||||
|
|
||||||
// Initialize runtime locks before any thread or helper can touch chain state.
|
// Initialize runtime locks before any thread or helper can touch chain state.
|
||||||
pthread_rwlock_init(&chainLock, NULL);
|
pthread_rwlock_init(&g_chainLock, NULL);
|
||||||
pthread_mutex_init(&balanceSheetLock, NULL);
|
pthread_mutex_init(&g_balanceSheetLock, NULL);
|
||||||
|
|
||||||
BalanceSheet_Init();
|
BalanceSheet_Init();
|
||||||
blockchain_t* chain = Chain_Create();
|
blockchain_t* chain = Chain_Create();
|
||||||
@@ -833,19 +833,19 @@ int main(int argc, char* argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChain = chain;
|
g_currentChain = chain;
|
||||||
|
|
||||||
net_node_t* node = Node_Create();
|
net_node_t* node = Node_Create();
|
||||||
if (!node) {
|
if (!node) {
|
||||||
currentChain = NULL;
|
g_currentChain = NULL;
|
||||||
Chain_Destroy(chain);
|
Chain_Destroy(chain);
|
||||||
BalanceSheet_Destroy();
|
BalanceSheet_Destroy();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t lastSavedHash[32] = {0};
|
uint8_t lastSavedHash[32] = {0};
|
||||||
if (!Chain_LoadFromFile(chain, chainDataDir, ¤tSupply, &difficultyTarget, ¤tReward, lastSavedHash, false)) {
|
if (!Chain_LoadFromFile(chain, g_chainDataDir, &g_currentSupply, &g_difficultyTarget, &g_currentReward, lastSavedHash, false)) {
|
||||||
printf("No existing chain loaded from %s\n", chainDataDir);
|
printf("No existing chain loaded from %s\n", g_chainDataDir);
|
||||||
} else {
|
} else {
|
||||||
// Recompute runtime supply/reward from loaded blocks to avoid trusting stale meta values.
|
// Recompute runtime supply/reward from loaded blocks to avoid trusting stale meta values.
|
||||||
if (!Chain_RecomputeRuntimeState(chain)) {
|
if (!Chain_RecomputeRuntimeState(chain)) {
|
||||||
@@ -857,7 +857,7 @@ int main(int argc, char* argv[]) {
|
|||||||
Chain_OnTipAdvanced(chain);
|
Chain_OnTipAdvanced(chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!BalanceSheet_LoadFromFile(chainDataDir)) {
|
if (!BalanceSheet_LoadFromFile(g_chainDataDir)) {
|
||||||
printf("Failed to load the balance sheet or none existing\n");
|
printf("Failed to load the balance sheet or none existing\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -866,8 +866,8 @@ int main(int argc, char* argv[]) {
|
|||||||
? (PHASE1_TARGET_BLOCKS / EMISSION_ACCELERATION_FACTOR)
|
? (PHASE1_TARGET_BLOCKS / EMISSION_ACCELERATION_FACTOR)
|
||||||
: 1;
|
: 1;
|
||||||
|
|
||||||
if ((uint64_t)Chain_Size(chain) < effectivePhase1Blocks || currentReward == 0) {
|
if ((uint64_t)Chain_Size(chain) < effectivePhase1Blocks || g_currentReward == 0) {
|
||||||
currentReward = CalculateBlockReward(currentSupply, chain);
|
g_currentReward = CalculateBlockReward(g_currentSupply, chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -895,13 +895,13 @@ int main(int argc, char* argv[]) {
|
|||||||
printf("Loaded chain with %zu blocks from disk\n", Chain_Size(chain));
|
printf("Loaded chain with %zu blocks from disk\n", Chain_Size(chain));
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "loaded chain is invalid, wiping persisted state.\n");
|
fprintf(stderr, "loaded chain is invalid, wiping persisted state.\n");
|
||||||
WipeChainFiles(chainDataDir);
|
WipeChainFiles(g_chainDataDir);
|
||||||
Chain_Wipe(chain);
|
Chain_Wipe(chain);
|
||||||
BalanceSheet_Destroy();
|
BalanceSheet_Destroy();
|
||||||
BalanceSheet_Init();
|
BalanceSheet_Init();
|
||||||
currentSupply = uint256_from_u64(0);
|
g_currentSupply = uint256_from_u64(0);
|
||||||
difficultyTarget = INITIAL_DIFFICULTY;
|
g_difficultyTarget = INITIAL_DIFFICULTY;
|
||||||
currentReward = CalculateBlockReward(currentSupply, chain);
|
g_currentReward = CalculateBlockReward(g_currentSupply, chain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -984,7 +984,7 @@ int main(int argc, char* argv[]) {
|
|||||||
if (!GenerateTestMinerIdentity(minerPrivateKey, minerCompressedPubkey, minerAddress)) {
|
if (!GenerateTestMinerIdentity(minerPrivateKey, minerCompressedPubkey, minerAddress)) {
|
||||||
fprintf(stderr, "failed to generate test miner keypair\n");
|
fprintf(stderr, "failed to generate test miner keypair\n");
|
||||||
Node_Destroy(node);
|
Node_Destroy(node);
|
||||||
currentChain = NULL;
|
g_currentChain = NULL;
|
||||||
Chain_Destroy(chain);
|
Chain_Destroy(chain);
|
||||||
Block_ShutdownPowContext();
|
Block_ShutdownPowContext();
|
||||||
BalanceSheet_Destroy();
|
BalanceSheet_Destroy();
|
||||||
@@ -996,7 +996,7 @@ int main(int argc, char* argv[]) {
|
|||||||
printf("Test miner address: %s\n", minerAddressHex);
|
printf("Test miner address: %s\n", minerAddressHex);
|
||||||
|
|
||||||
char supplyStr[80];
|
char supplyStr[80];
|
||||||
Uint256ToDecimal(¤tSupply, supplyStr, sizeof(supplyStr));
|
Uint256ToDecimal(&g_currentSupply, 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], sendrawtx <hex_tx>, txpooldetail <txhash>, balance [address], connect <ipv4> [port], peers, sync [force] (requires nodes), dagvote <grow|hold|down>, flushchain, fullverify, blockdetail <block number>, wipechain, genaddr, exit\n");
|
printf("Commands: mine <x>, send <address> <amount> [fee], sendrawtx <hex_tx>, txpooldetail <txhash>, balance [address], connect <ipv4> [port], peers, sync [force] (requires nodes), dagvote <grow|hold|down>, flushchain, fullverify, blockdetail <block number>, wipechain, genaddr, exit\n");
|
||||||
|
|
||||||
@@ -1079,7 +1079,7 @@ int main(int argc, char* argv[]) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t coinbaseAmount = currentReward;
|
uint64_t coinbaseAmount = g_currentReward;
|
||||||
if (UINT64_MAX - coinbaseAmount < totalFees) {
|
if (UINT64_MAX - coinbaseAmount < totalFees) {
|
||||||
free(acceptedTxs);
|
free(acceptedTxs);
|
||||||
Block_Destroy(block);
|
Block_Destroy(block);
|
||||||
@@ -1095,7 +1095,7 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
free(acceptedTxs);
|
free(acceptedTxs);
|
||||||
|
|
||||||
if (!MineAndAppendBlock(chain, block, ¤tSupply, ¤tReward)) {
|
if (!MineAndAppendBlock(chain, block, &g_currentSupply, &g_currentReward)) {
|
||||||
Block_Destroy(block);
|
Block_Destroy(block);
|
||||||
minedAll = false;
|
minedAll = false;
|
||||||
break;
|
break;
|
||||||
@@ -1110,14 +1110,14 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
if (i % 50 == 0) {
|
if (i % 50 == 0) {
|
||||||
// Mid-mine flush
|
// Mid-mine flush
|
||||||
(void)FlushChainAndSheet(chain, chainDataDir, currentSupply, currentReward);
|
(void)FlushChainAndSheet(chain, g_chainDataDir, g_currentSupply, g_currentReward);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (minedAll) {
|
if (minedAll) {
|
||||||
(void)FlushChainAndSheet(chain, chainDataDir, currentSupply, currentReward);
|
(void)FlushChainAndSheet(chain, g_chainDataDir, g_currentSupply, g_currentReward);
|
||||||
printf("mine finished and chain flushed\n");
|
printf("mine finished and chain flushed\n");
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@@ -1189,7 +1189,7 @@ int main(int argc, char* argv[]) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t coinbaseAmount = currentReward;
|
uint64_t coinbaseAmount = g_currentReward;
|
||||||
AddCoinbaseTransaction(block, minerAddress, coinbaseAmount);
|
AddCoinbaseTransaction(block, minerAddress, coinbaseAmount);
|
||||||
|
|
||||||
signed_transaction_t spendTx;
|
signed_transaction_t spendTx;
|
||||||
@@ -1212,12 +1212,12 @@ int main(int argc, char* argv[]) {
|
|||||||
AddressToHexString(recipientAddress, recipientHex);
|
AddressToHexString(recipientAddress, recipientHex);
|
||||||
printf("%s\n\nMining block...\n", recipientHex);
|
printf("%s\n\nMining block...\n", recipientHex);
|
||||||
|
|
||||||
if (!MineAndAppendBlock(chain, block, ¤tSupply, ¤tReward)) {
|
if (!MineAndAppendBlock(chain, block, &g_currentSupply, &g_currentReward)) {
|
||||||
Block_Destroy(block);
|
Block_Destroy(block);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
FlushChainAndSheet(chain, chainDataDir, currentSupply, currentReward);
|
FlushChainAndSheet(chain, g_chainDataDir, g_currentSupply, g_currentReward);
|
||||||
|
|
||||||
Block_Destroy(block); // the chain took the transaction array; this frees the wrapper
|
Block_Destroy(block); // the chain took the transaction array; this frees the wrapper
|
||||||
if (node) {
|
if (node) {
|
||||||
@@ -1749,7 +1749,7 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
block_t* detailBlock = NULL;
|
block_t* detailBlock = NULL;
|
||||||
size_t txCount = 0;
|
size_t txCount = 0;
|
||||||
if (!Chain_LoadBlockFromFile(chainDataDir, (uint64_t)requestedBlock, false, &detailBlock, &txCount)) {
|
if (!Chain_LoadBlockFromFile(g_chainDataDir, (uint64_t)requestedBlock, false, &detailBlock, &txCount)) {
|
||||||
printf("block %llu not found\n", requestedBlock);
|
printf("block %llu not found\n", requestedBlock);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1757,7 +1757,7 @@ int main(int argc, char* argv[]) {
|
|||||||
uint8_t canonicalHash[32];
|
uint8_t canonicalHash[32];
|
||||||
uint8_t powHash[32];
|
uint8_t powHash[32];
|
||||||
Block_CalculateHash(detailBlock, canonicalHash);
|
Block_CalculateHash(detailBlock, canonicalHash);
|
||||||
if (!ComputeHistoricalAutolykosHashFromDisk(chainDataDir, (uint64_t)requestedBlock, detailBlock, powHash)) {
|
if (!ComputeHistoricalAutolykosHashFromDisk(g_chainDataDir, (uint64_t)requestedBlock, detailBlock, powHash)) {
|
||||||
Block_Destroy(detailBlock);
|
Block_Destroy(detailBlock);
|
||||||
printf("failed to calculate block %llu proof hash\n", requestedBlock);
|
printf("failed to calculate block %llu proof hash\n", requestedBlock);
|
||||||
continue;
|
continue;
|
||||||
@@ -1822,7 +1822,7 @@ int main(int argc, char* argv[]) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short peerPort = listenPort;
|
unsigned short peerPort = g_listenPort;
|
||||||
if (portStr) {
|
if (portStr) {
|
||||||
char* end = NULL;
|
char* end = NULL;
|
||||||
long parsedPort = strtol(portStr, &end, 10);
|
long parsedPort = strtol(portStr, &end, 10);
|
||||||
@@ -1860,7 +1860,7 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(cmd, "flushchain") == 0) {
|
if (strcmp(cmd, "flushchain") == 0) {
|
||||||
if (FlushChainAndSheet(chain, chainDataDir, currentSupply, currentReward)) {
|
if (FlushChainAndSheet(chain, g_chainDataDir, g_currentSupply, g_currentReward)) {
|
||||||
printf("chain flushed\n");
|
printf("chain flushed\n");
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@@ -1880,7 +1880,7 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
bool loaded = Chain_LoadFromFile(
|
bool loaded = Chain_LoadFromFile(
|
||||||
verifyChain,
|
verifyChain,
|
||||||
chainDataDir,
|
g_chainDataDir,
|
||||||
&verifySupply,
|
&verifySupply,
|
||||||
&verifyDifficulty,
|
&verifyDifficulty,
|
||||||
&verifyReward,
|
&verifyReward,
|
||||||
@@ -1899,13 +1899,13 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(cmd, "wipechain") == 0) {
|
if (strcmp(cmd, "wipechain") == 0) {
|
||||||
WipeChainFiles(chainDataDir);
|
WipeChainFiles(g_chainDataDir);
|
||||||
Chain_Wipe(chain);
|
Chain_Wipe(chain);
|
||||||
BalanceSheet_Destroy();
|
BalanceSheet_Destroy();
|
||||||
BalanceSheet_Init();
|
BalanceSheet_Init();
|
||||||
currentSupply = uint256_from_u64(0);
|
g_currentSupply = uint256_from_u64(0);
|
||||||
difficultyTarget = INITIAL_DIFFICULTY;
|
g_difficultyTarget = INITIAL_DIFFICULTY;
|
||||||
currentReward = CalculateBlockReward(currentSupply, chain);
|
g_currentReward = CalculateBlockReward(g_currentSupply, chain);
|
||||||
|
|
||||||
// No DAG rebuild needed: Chain_Wipe drops the memoised epoch table, and MineBlock
|
// No DAG rebuild needed: Chain_Wipe drops the memoised epoch table, and MineBlock
|
||||||
// rebuilds the DAG on demand for whatever epoch it next mines in.
|
// rebuilds the DAG on demand for whatever epoch it next mines in.
|
||||||
@@ -1934,16 +1934,16 @@ int main(int argc, char* argv[]) {
|
|||||||
printf("Unknown command. Available: mine, send, sendrawtx, sync, txpooldetail, blockdetail, balance, connect, peers, flushchain, fullverify, wipechain, genaddr, exit\n");
|
printf("Unknown command. Available: mine, send, sendrawtx, sync, txpooldetail, blockdetail, balance, connect, peers, flushchain, fullverify, wipechain, genaddr, exit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)FlushChainAndSheet(chain, chainDataDir, currentSupply, currentReward);
|
(void)FlushChainAndSheet(chain, g_chainDataDir, g_currentSupply, g_currentReward);
|
||||||
|
|
||||||
Block_ShutdownPowContext();
|
Block_ShutdownPowContext();
|
||||||
Node_Destroy(node);
|
Node_Destroy(node);
|
||||||
currentChain = NULL;
|
g_currentChain = NULL;
|
||||||
Chain_Destroy(chain);
|
Chain_Destroy(chain);
|
||||||
BalanceSheet_Destroy();
|
BalanceSheet_Destroy();
|
||||||
|
|
||||||
pthread_mutex_destroy(&balanceSheetLock);
|
pthread_mutex_destroy(&g_balanceSheetLock);
|
||||||
pthread_rwlock_destroy(&chainLock);
|
pthread_rwlock_destroy(&g_chainLock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-36
@@ -25,11 +25,11 @@ static net_node_t* Node_FromConnection(tcp_connection_t* conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t Node_GetCurrentBlockHeight(void) {
|
static uint64_t Node_GetCurrentBlockHeight(void) {
|
||||||
if (currentChain) {
|
if (g_currentChain) {
|
||||||
return (uint64_t)Chain_Size(currentChain);
|
return (uint64_t)Chain_Size(g_currentChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
return currentBlockHeight;
|
return g_currentBlockHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compares two listen endpoints (family + IP + port).
|
// Compares two listen endpoints (family + IP + port).
|
||||||
@@ -300,7 +300,7 @@ static node_identity_result_t Node_CheckPeerIdentity(net_node_t* node, tcp_conne
|
|||||||
struct sockaddr_storage ep;
|
struct sockaddr_storage ep;
|
||||||
int haveEp = Node_ConnListenEndpoint(conn, &ep);
|
int haveEp = Node_ConnListenEndpoint(conn, &ep);
|
||||||
|
|
||||||
if (conn->peerNodeId == localNodeId) {
|
if (conn->peerNodeId == g_localNodeId) {
|
||||||
// We dialled ourselves (or accepted our own dial). Remember the endpoint as our own so
|
// We dialled ourselves (or accepted our own dial). Remember the endpoint as our own so
|
||||||
// discovery stops offering it back to us, and drop the connection.
|
// discovery stops offering it back to us, and drop the connection.
|
||||||
if (haveEp && node->discovery) {
|
if (haveEp && node->discovery) {
|
||||||
@@ -449,12 +449,12 @@ static void* Node_MaintenanceThread(void* arg) {
|
|||||||
net_node_t* n = (net_node_t*)arg;
|
net_node_t* n = (net_node_t*)arg;
|
||||||
if (!n) return NULL;
|
if (!n) return NULL;
|
||||||
while (n->maintenanceRunning) {
|
while (n->maintenanceRunning) {
|
||||||
if (currentChain) {
|
if (g_currentChain) {
|
||||||
size_t attached = OrphanPool_AttemptAttach(currentChain);
|
size_t attached = OrphanPool_AttemptAttach(g_currentChain);
|
||||||
if (attached > 0) {
|
if (attached > 0) {
|
||||||
printf("Maintenance: attached %zu orphan(s)\n", attached);
|
printf("Maintenance: attached %zu orphan(s)\n", attached);
|
||||||
Chain_SaveToFile(currentChain, chainDataDir, currentSupply, currentReward);
|
Chain_SaveToFile(g_currentChain, g_chainDataDir, g_currentSupply, g_currentReward);
|
||||||
BalanceSheet_SaveToFile(chainDataDir);
|
BalanceSheet_SaveToFile(g_chainDataDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Drop transactions too old to be worth holding, so the pool is not inflated by junk that
|
// Drop transactions too old to be worth holding, so the pool is not inflated by junk that
|
||||||
@@ -546,7 +546,7 @@ static node_block_accept_result_t Node_ParseAndAcceptBlock(const unsigned char*
|
|||||||
|
|
||||||
// The chain check has to come first now: PoW validity is chain-relative (the epoch DAG size and
|
// The chain check has to come first now: PoW validity is chain-relative (the epoch DAG size and
|
||||||
// seed are derived from it), so there is nothing to validate against without a chain.
|
// seed are derived from it), so there is nothing to validate against without a chain.
|
||||||
if (!currentChain) {
|
if (!g_currentChain) {
|
||||||
printf("Rejected BLOCK_DATA at height %" PRIu64 ": no active chain\n", blockHeight);
|
printf("Rejected BLOCK_DATA at height %" PRIu64 ": no active chain\n", blockHeight);
|
||||||
vector_destroy(&blk->transactions);
|
vector_destroy(&blk->transactions);
|
||||||
free(blk);
|
free(blk);
|
||||||
@@ -570,11 +570,11 @@ static node_block_accept_result_t Node_ParseAndAcceptBlock(const unsigned char*
|
|||||||
|
|
||||||
// The orphan pool stamps the local tip height at first sight; that stamp drives the reorg
|
// The orphan pool stamps the local tip height at first sight; that stamp drives the reorg
|
||||||
// penalty and must be taken now, not re-derived later from a moved tip.
|
// penalty and must be taken now, not re-derived later from a moved tip.
|
||||||
uint64_t chainSize = Chain_Size(currentChain);
|
uint64_t chainSize = Chain_Size(g_currentChain);
|
||||||
const uint64_t observedAtTipHeight = chainSize > 0 ? (chainSize - 1) : 0ULL;
|
const uint64_t observedAtTipHeight = chainSize > 0 ? (chainSize - 1) : 0ULL;
|
||||||
|
|
||||||
// Temporary debug mode: force network-received blocks through the orphan pool to exercise reorg handling.
|
// Temporary debug mode: force network-received blocks through the orphan pool to exercise reorg handling.
|
||||||
if (forceOrphanReorgEnabled && blk->header.blockNumber > 0) {
|
if (g_forceOrphanReorgEnabled && blk->header.blockNumber > 0) {
|
||||||
OrphanPool_Insert(blk, blockHeight, observedAtTipHeight);
|
OrphanPool_Insert(blk, blockHeight, observedAtTipHeight);
|
||||||
printf("Forced orphan BLOCK_DATA at height %" PRIu64 "\n", blockHeight);
|
printf("Forced orphan BLOCK_DATA at height %" PRIu64 "\n", blockHeight);
|
||||||
return NODE_BLOCK_ORPHAN_QUEUED;
|
return NODE_BLOCK_ORPHAN_QUEUED;
|
||||||
@@ -591,7 +591,7 @@ static node_block_accept_result_t Node_ParseAndAcceptBlock(const unsigned char*
|
|||||||
// branch. Dropping both (as this used to) made any fork that diverges below the tip
|
// branch. Dropping both (as this used to) made any fork that diverges below the tip
|
||||||
// impossible to discover: the fork point itself was always thrown away.
|
// impossible to discover: the fork point itself was always thrown away.
|
||||||
block_t* local = NULL;
|
block_t* local = NULL;
|
||||||
if (Chain_GetBlockCopy(currentChain, (size_t)blk->header.blockNumber, &local) && local) {
|
if (Chain_GetBlockCopy(g_currentChain, (size_t)blk->header.blockNumber, &local) && local) {
|
||||||
uint8_t localHash[32];
|
uint8_t localHash[32];
|
||||||
uint8_t incomingHash[32];
|
uint8_t incomingHash[32];
|
||||||
Block_CalculateHash(local, localHash);
|
Block_CalculateHash(local, localHash);
|
||||||
@@ -613,7 +613,7 @@ static node_block_accept_result_t Node_ParseAndAcceptBlock(const unsigned char*
|
|||||||
// blk->header.blockNumber == chainSize -> candidate to append. Ensure prevHash matches current tip.
|
// blk->header.blockNumber == chainSize -> candidate to append. Ensure prevHash matches current tip.
|
||||||
if (chainSize > 0) {
|
if (chainSize > 0) {
|
||||||
block_t* last = NULL;
|
block_t* last = NULL;
|
||||||
if (!Chain_GetBlockCopy(currentChain, (size_t)(chainSize - 1), &last) || !last) {
|
if (!Chain_GetBlockCopy(g_currentChain, (size_t)(chainSize - 1), &last) || !last) {
|
||||||
// Can't verify parent; queue as orphan conservatively
|
// Can't verify parent; queue as orphan conservatively
|
||||||
OrphanPool_Insert(blk, blockHeight, observedAtTipHeight);
|
OrphanPool_Insert(blk, blockHeight, observedAtTipHeight);
|
||||||
printf("Queued orphan BLOCK_DATA at height %" PRIu64 " (unable to verify parent)\n", blockHeight);
|
printf("Queued orphan BLOCK_DATA at height %" PRIu64 " (unable to verify parent)\n", blockHeight);
|
||||||
@@ -633,7 +633,7 @@ static node_block_accept_result_t Node_ParseAndAcceptBlock(const unsigned char*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Chain_AddBlock(currentChain, blk)) {
|
if (!Chain_AddBlock(g_currentChain, blk)) {
|
||||||
// Chain_AddBlock failed; cleanup. Safe either way: if it failed before taking the block we
|
// Chain_AddBlock failed; cleanup. Safe either way: if it failed before taking the block we
|
||||||
// still own the transactions, and if it failed after (the ledger pass can fail with the
|
// still own the transactions, and if it failed after (the ledger pass can fail with the
|
||||||
// block already pushed) our pointer to them was cleared, so this frees only the wrapper.
|
// block already pushed) our pointer to them was cleared, so this frees only the wrapper.
|
||||||
@@ -642,25 +642,25 @@ static node_block_accept_result_t Node_ParseAndAcceptBlock(const unsigned char*
|
|||||||
return NODE_BLOCK_REJECTED;
|
return NODE_BLOCK_REJECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// currentSupply/currentReward are advanced inside Chain_AddBlock, so that every path that
|
// g_currentSupply/g_currentReward are advanced inside Chain_AddBlock, so that every path that
|
||||||
// appends (mining, this one, orphan attach, reorg) keeps them consistent.
|
// appends (mining, this one, orphan attach, reorg) keeps them consistent.
|
||||||
|
|
||||||
// Persist on accept if requested
|
// Persist on accept if requested
|
||||||
if (persist) {
|
if (persist) {
|
||||||
Chain_SaveToFile(currentChain, chainDataDir, currentSupply, currentReward);
|
Chain_SaveToFile(g_currentChain, g_chainDataDir, g_currentSupply, g_currentReward);
|
||||||
BalanceSheet_SaveToFile(chainDataDir);
|
BalanceSheet_SaveToFile(g_chainDataDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chain_AddBlock took ownership of the transaction array and cleared our pointer to it, so
|
// Chain_AddBlock took ownership of the transaction array and cleared our pointer to it, so
|
||||||
// destroying the wrapper here frees only the wrapper.
|
// destroying the wrapper here frees only the wrapper.
|
||||||
Block_Destroy(blk);
|
Block_Destroy(blk);
|
||||||
// Attempt to attach any orphans that may now have their parents present.
|
// Attempt to attach any orphans that may now have their parents present.
|
||||||
size_t attached = OrphanPool_AttemptAttach(currentChain);
|
size_t attached = OrphanPool_AttemptAttach(g_currentChain);
|
||||||
if (attached > 0) {
|
if (attached > 0) {
|
||||||
printf("Attached %zu orphan(s) after accepting block\n", attached);
|
printf("Attached %zu orphan(s) after accepting block\n", attached);
|
||||||
// Persist after attaching orphans
|
// Persist after attaching orphans
|
||||||
Chain_SaveToFile(currentChain, chainDataDir, currentSupply, currentReward);
|
Chain_SaveToFile(g_currentChain, g_chainDataDir, g_currentSupply, g_currentReward);
|
||||||
BalanceSheet_SaveToFile(chainDataDir);
|
BalanceSheet_SaveToFile(g_chainDataDir);
|
||||||
}
|
}
|
||||||
return NODE_BLOCK_ACCEPTED;
|
return NODE_BLOCK_ACCEPTED;
|
||||||
}
|
}
|
||||||
@@ -710,7 +710,7 @@ net_node_t* Node_Create() {
|
|||||||
node->seenBlocks = set_create(32); // 32-byte canonical hashes; raw bytes, so memcmp equality is right
|
node->seenBlocks = set_create(32); // 32-byte canonical hashes; raw bytes, so memcmp equality is right
|
||||||
TxMempool_Init();
|
TxMempool_Init();
|
||||||
|
|
||||||
TcpServer_Init(node->server, listenPort, "::");
|
TcpServer_Init(node->server, g_listenPort, "::");
|
||||||
|
|
||||||
node->server->owner = node;
|
node->server->owner = node;
|
||||||
node->server->on_connect = Node_Server_OnConnect;
|
node->server->on_connect = Node_Server_OnConnect;
|
||||||
@@ -725,7 +725,7 @@ net_node_t* Node_Create() {
|
|||||||
// the node still works without discovery, it just won't crawl for new peers.
|
// the node still works without discovery, it just won't crawl for new peers.
|
||||||
node->udpNode = (udp_node_t*)malloc(sizeof(udp_node_t));
|
node->udpNode = (udp_node_t*)malloc(sizeof(udp_node_t));
|
||||||
if (node->udpNode) {
|
if (node->udpNode) {
|
||||||
if (UdpNode_Init(node->udpNode, (uint16_t)listenPort) == 0) {
|
if (UdpNode_Init(node->udpNode, (uint16_t)g_listenPort) == 0) {
|
||||||
UdpNode_SetCallbacks(node->udpNode, Node_OnPongThunk, Node_OnPingTimeoutThunk, node);
|
UdpNode_SetCallbacks(node->udpNode, Node_OnPongThunk, Node_OnPingTimeoutThunk, node);
|
||||||
if (UdpNode_Start(node->udpNode) == 0) {
|
if (UdpNode_Start(node->udpNode) == 0) {
|
||||||
node->discovery = NodeDiscovery_Create(node, node->udpNode);
|
node->discovery = NodeDiscovery_Create(node, node->udpNode);
|
||||||
@@ -968,13 +968,13 @@ void Node_Server_OnConnect(tcp_connection_t* client) {
|
|||||||
Node_ForwardConnect(node, client);
|
Node_ForwardConnect(node, client);
|
||||||
printf("Inbound node connected: %u\n", client ? client->connectionId : 0U);
|
printf("Inbound node connected: %u\n", client ? client->connectionId : 0U);
|
||||||
|
|
||||||
if (echoPeersEnabled && node && client) {
|
if (g_echoPeersEnabled && node && client) {
|
||||||
// Attempt to create an outbound connection back to the peer's IP on our configured port.
|
// Attempt to create an outbound connection back to the peer's IP on our configured port.
|
||||||
// We avoid connecting if we already have an outbound to the same IP.
|
// We avoid connecting if we already have an outbound to the same IP.
|
||||||
char ipbuf[INET6_ADDRSTRLEN];
|
char ipbuf[INET6_ADDRSTRLEN];
|
||||||
if (TcpConnection_GetPeerAddrStr(client, ipbuf, sizeof(ipbuf))) {
|
if (TcpConnection_GetPeerAddrStr(client, ipbuf, sizeof(ipbuf))) {
|
||||||
// Use the configured port as the target port for the peer's listening service.
|
// Use the configured port as the target port for the peer's listening service.
|
||||||
unsigned short targetPort = listenPort;
|
unsigned short targetPort = g_listenPort;
|
||||||
|
|
||||||
int shouldConnect = 1;
|
int shouldConnect = 1;
|
||||||
pthread_mutex_lock(&node->outboundLock);
|
pthread_mutex_lock(&node->outboundLock);
|
||||||
@@ -1051,10 +1051,10 @@ void Node_Server_OnData(tcp_connection_t* client) {
|
|||||||
uint64_t currentHeight = Node_GetCurrentBlockHeight();
|
uint64_t currentHeight = Node_GetCurrentBlockHeight();
|
||||||
memcpy(ackData + ackOffset, ¤tHeight, sizeof(currentHeight));
|
memcpy(ackData + ackOffset, ¤tHeight, sizeof(currentHeight));
|
||||||
ackOffset += sizeof(currentHeight);
|
ackOffset += sizeof(currentHeight);
|
||||||
uint16_t myListenPort = (uint16_t)listenPort;
|
uint16_t myListenPort = (uint16_t)g_listenPort;
|
||||||
memcpy(ackData + ackOffset, &myListenPort, sizeof(myListenPort));
|
memcpy(ackData + ackOffset, &myListenPort, sizeof(myListenPort));
|
||||||
ackOffset += sizeof(myListenPort);
|
ackOffset += sizeof(myListenPort);
|
||||||
uint64_t myNodeId = localNodeId;
|
uint64_t myNodeId = g_localNodeId;
|
||||||
memcpy(ackData + ackOffset, &myNodeId, sizeof(myNodeId));
|
memcpy(ackData + ackOffset, &myNodeId, sizeof(myNodeId));
|
||||||
ackOffset += sizeof(myNodeId);
|
ackOffset += sizeof(myNodeId);
|
||||||
|
|
||||||
@@ -1130,9 +1130,9 @@ void Node_Server_OnData(tcp_connection_t* client) {
|
|||||||
// Find the block (deep-copy it for safe access)
|
// Find the block (deep-copy it for safe access)
|
||||||
block_t* block = NULL;
|
block_t* block = NULL;
|
||||||
bool loadedFromDisk = false;
|
bool loadedFromDisk = false;
|
||||||
if (!Chain_GetBlockCopy(currentChain, (size_t)requestedHeight, &block) || !block) {
|
if (!Chain_GetBlockCopy(g_currentChain, (size_t)requestedHeight, &block) || !block) {
|
||||||
// Try loading from disk directly
|
// Try loading from disk directly
|
||||||
if (!Chain_LoadBlockFromFile(chainDataDir, requestedHeight, true, &block, NULL) || !block) {
|
if (!Chain_LoadBlockFromFile(g_chainDataDir, requestedHeight, true, &block, NULL) || !block) {
|
||||||
printf("Requested block height %" PRIu64 " not found, ignoring\n", requestedHeight);
|
printf("Requested block height %" PRIu64 " not found, ignoring\n", requestedHeight);
|
||||||
const char* msg = "Requested block not found!";
|
const char* msg = "Requested block not found!";
|
||||||
Node_SendPacket(Node_FromConnection(client), client, PACKET_TYPE_ERROR, msg, strlen(msg));
|
Node_SendPacket(Node_FromConnection(client), client, PACKET_TYPE_ERROR, msg, strlen(msg));
|
||||||
@@ -1142,7 +1142,7 @@ void Node_Server_OnData(tcp_connection_t* client) {
|
|||||||
} else if (!block->transactions) {
|
} else if (!block->transactions) {
|
||||||
// In-memory chain may be compacted to headers only after persistence.
|
// In-memory chain may be compacted to headers only after persistence.
|
||||||
block_t* fullBlock = NULL;
|
block_t* fullBlock = NULL;
|
||||||
if (Chain_LoadBlockFromFile(chainDataDir, requestedHeight, true, &fullBlock, NULL) && fullBlock) {
|
if (Chain_LoadBlockFromFile(g_chainDataDir, requestedHeight, true, &fullBlock, NULL) && fullBlock) {
|
||||||
Block_Destroy(block);
|
Block_Destroy(block);
|
||||||
block = fullBlock;
|
block = fullBlock;
|
||||||
loadedFromDisk = true;
|
loadedFromDisk = true;
|
||||||
@@ -1349,11 +1349,11 @@ void Node_Client_OnConnect(tcp_connection_t* client) {
|
|||||||
memcpy((unsigned char*)data + offset, &blockHeight, sizeof(blockHeight));
|
memcpy((unsigned char*)data + offset, &blockHeight, sizeof(blockHeight));
|
||||||
offset += sizeof(blockHeight);
|
offset += sizeof(blockHeight);
|
||||||
// Advertise the port we listen on so the peer can share us with others (and reach us back)
|
// Advertise the port we listen on so the peer can share us with others (and reach us back)
|
||||||
uint16_t myListenPort = (uint16_t)listenPort;
|
uint16_t myListenPort = (uint16_t)g_listenPort;
|
||||||
memcpy((unsigned char*)data + offset, &myListenPort, sizeof(myListenPort));
|
memcpy((unsigned char*)data + offset, &myListenPort, sizeof(myListenPort));
|
||||||
offset += sizeof(myListenPort);
|
offset += sizeof(myListenPort);
|
||||||
// ...and who we are, so the peer can tell this connection apart from our other addresses
|
// ...and who we are, so the peer can tell this connection apart from our other addresses
|
||||||
uint64_t myNodeId = localNodeId;
|
uint64_t myNodeId = g_localNodeId;
|
||||||
memcpy((unsigned char*)data + offset, &myNodeId, sizeof(myNodeId));
|
memcpy((unsigned char*)data + offset, &myNodeId, sizeof(myNodeId));
|
||||||
offset += sizeof(myNodeId);
|
offset += sizeof(myNodeId);
|
||||||
|
|
||||||
@@ -1625,20 +1625,20 @@ int Node_GetBestOutboundPeer(net_node_t* node, tcp_connection_t** outConn, uint6
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Node_BroadcastChainRange(net_node_t* node, size_t startHeightInclusive, tcp_connection_t* sourceConn) {
|
void Node_BroadcastChainRange(net_node_t* node, size_t startHeightInclusive, tcp_connection_t* sourceConn) {
|
||||||
if (!node || !currentChain) return;
|
if (!node || !g_currentChain) return;
|
||||||
|
|
||||||
size_t chainSize = Chain_Size(currentChain);
|
size_t chainSize = Chain_Size(g_currentChain);
|
||||||
if (startHeightInclusive >= chainSize) return;
|
if (startHeightInclusive >= chainSize) return;
|
||||||
|
|
||||||
for (size_t h = startHeightInclusive; h < chainSize; ++h) {
|
for (size_t h = startHeightInclusive; h < chainSize; ++h) {
|
||||||
block_t* blk = NULL;
|
block_t* blk = NULL;
|
||||||
if (!Chain_GetBlockCopy(currentChain, h, &blk) || !blk) {
|
if (!Chain_GetBlockCopy(g_currentChain, h, &blk) || !blk) {
|
||||||
if (!Chain_LoadBlockFromFile(chainDataDir, h, true, &blk, NULL) || !blk) {
|
if (!Chain_LoadBlockFromFile(g_chainDataDir, h, true, &blk, NULL) || !blk) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (!blk->transactions) {
|
} else if (!blk->transactions) {
|
||||||
block_t* full = NULL;
|
block_t* full = NULL;
|
||||||
if (Chain_LoadBlockFromFile(chainDataDir, h, true, &full, NULL) && full) {
|
if (Chain_LoadBlockFromFile(g_chainDataDir, h, true, &full, NULL) && full) {
|
||||||
Block_Destroy(blk);
|
Block_Destroy(blk);
|
||||||
blk = full;
|
blk = full;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,11 +153,11 @@ static void Discovery_SeedSelfEndpoints(node_discovery_t* disc) {
|
|||||||
if (it->ifa_addr->sa_family == AF_INET) {
|
if (it->ifa_addr->sa_family == AF_INET) {
|
||||||
struct sockaddr_in* o = (struct sockaddr_in*)&ep;
|
struct sockaddr_in* o = (struct sockaddr_in*)&ep;
|
||||||
memcpy(o, it->ifa_addr, sizeof(struct sockaddr_in));
|
memcpy(o, it->ifa_addr, sizeof(struct sockaddr_in));
|
||||||
o->sin_port = htons(listenPort);
|
o->sin_port = htons(g_listenPort);
|
||||||
} else if (it->ifa_addr->sa_family == AF_INET6) {
|
} else if (it->ifa_addr->sa_family == AF_INET6) {
|
||||||
struct sockaddr_in6* o = (struct sockaddr_in6*)&ep;
|
struct sockaddr_in6* o = (struct sockaddr_in6*)&ep;
|
||||||
memcpy(o, it->ifa_addr, sizeof(struct sockaddr_in6));
|
memcpy(o, it->ifa_addr, sizeof(struct sockaddr_in6));
|
||||||
o->sin6_port = htons(listenPort);
|
o->sin6_port = htons(g_listenPort);
|
||||||
o->sin6_scope_id = 0; // endpoints on the wire are scopeless; compare them the same way
|
o->sin6_scope_id = 0; // endpoints on the wire are scopeless; compare them the same way
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
@@ -494,7 +494,7 @@ void NodeDiscovery_NoteIdentity(node_discovery_t* disc, const struct sockaddr_st
|
|||||||
if (!disc || !endpoint || nodeId == 0) return;
|
if (!disc || !endpoint || nodeId == 0) return;
|
||||||
|
|
||||||
pthread_mutex_lock(&disc->lock);
|
pthread_mutex_lock(&disc->lock);
|
||||||
if (nodeId == localNodeId) {
|
if (nodeId == g_localNodeId) {
|
||||||
// The peer on the other end is us under one of our own addresses. Record it and drop it so
|
// The peer on the other end is us under one of our own addresses. Record it and drop it so
|
||||||
// discovery stops treating it as a peer.
|
// discovery stops treating it as a peer.
|
||||||
Discovery_AddSelfUnlocked(disc, endpoint);
|
Discovery_AddSelfUnlocked(disc, endpoint);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ static uint64_t g_nextSequence = 0;
|
|||||||
// thread. It used to have no synchronisation at all, so a concurrent Insert could realloc the
|
// thread. It used to have no synchronisation at all, so a concurrent Insert could realloc the
|
||||||
// array out from under a scan that was holding a raw element pointer.
|
// array out from under a scan that was holding a raw element pointer.
|
||||||
//
|
//
|
||||||
// Lock ordering: this mutex is never held while calling into chain.c (which takes chainLock).
|
// Lock ordering: this mutex is never held while calling into chain.c (which takes g_chainLock).
|
||||||
// Candidate branches are collected under the lock, the lock is dropped, and only then is
|
// Candidate branches are collected under the lock, the lock is dropped, and only then is
|
||||||
// Chain_ReplaceBranch/Chain_AddBlock called.
|
// Chain_ReplaceBranch/Chain_AddBlock called.
|
||||||
static pthread_mutex_t g_orphanLock = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t g_orphanLock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|||||||
+32
-32
@@ -5,10 +5,10 @@
|
|||||||
static pthread_mutex_t g_txMempoolLock;
|
static pthread_mutex_t g_txMempoolLock;
|
||||||
static bool g_txMempoolLockInitialized = false;
|
static bool g_txMempoolLockInitialized = false;
|
||||||
|
|
||||||
khash_t(tx_mempool_map_m)* txMempool = NULL;
|
khash_t(tx_mempool_map_m)* g_txMempool = NULL;
|
||||||
|
|
||||||
void TxMempool_Init() {
|
void TxMempool_Init() {
|
||||||
txMempool = kh_init(tx_mempool_map_m);
|
g_txMempool = kh_init(tx_mempool_map_m);
|
||||||
pthread_mutex_init(&g_txMempoolLock, NULL);
|
pthread_mutex_init(&g_txMempoolLock, NULL);
|
||||||
g_txMempoolLockInitialized = true;
|
g_txMempoolLockInitialized = true;
|
||||||
}
|
}
|
||||||
@@ -37,20 +37,20 @@ bool TxMempool_PolicyAccepts(const signed_transaction_t* tx, uint64_t nowMs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t TxMempool_PruneExpired(uint64_t nowMs) {
|
size_t TxMempool_PruneExpired(uint64_t nowMs) {
|
||||||
if (!txMempool) {
|
if (!g_txMempool) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t removed = 0;
|
size_t removed = 0;
|
||||||
|
|
||||||
pthread_mutex_lock(&g_txMempoolLock);
|
pthread_mutex_lock(&g_txMempoolLock);
|
||||||
for (khiter_t k = kh_begin(txMempool); k != kh_end(txMempool); ++k) {
|
for (khiter_t k = kh_begin(g_txMempool); k != kh_end(g_txMempool); ++k) {
|
||||||
if (!kh_exist(txMempool, k)) {
|
if (!kh_exist(g_txMempool, k)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const uint64_t ts = kh_value(txMempool, k).transaction.timestamp;
|
const uint64_t ts = kh_value(g_txMempool, k).transaction.timestamp;
|
||||||
if (nowMs > ts && (nowMs - ts) > TX_EXPIRY_MS) {
|
if (nowMs > ts && (nowMs - ts) > TX_EXPIRY_MS) {
|
||||||
kh_del(tx_mempool_map_m, txMempool, k);
|
kh_del(tx_mempool_map_m, g_txMempool, k);
|
||||||
removed++;
|
removed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ size_t TxMempool_PruneExpired(uint64_t nowMs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int TxMempool_Insert(signed_transaction_t tx) {
|
int TxMempool_Insert(signed_transaction_t tx) {
|
||||||
if (!txMempool) { return -1; }
|
if (!g_txMempool) { return -1; }
|
||||||
|
|
||||||
pthread_mutex_lock(&g_txMempoolLock);
|
pthread_mutex_lock(&g_txMempoolLock);
|
||||||
uint8_t txHash[32];
|
uint8_t txHash[32];
|
||||||
@@ -70,13 +70,13 @@ int TxMempool_Insert(signed_transaction_t tx) {
|
|||||||
memcpy(key.bytes, txHash, 32);
|
memcpy(key.bytes, txHash, 32);
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
khiter_t k = kh_put(tx_mempool_map_m, txMempool, key, &ret);
|
khiter_t k = kh_put(tx_mempool_map_m, g_txMempool, key, &ret);
|
||||||
if (k == kh_end(txMempool)) {
|
if (k == kh_end(g_txMempool)) {
|
||||||
pthread_mutex_unlock(&g_txMempoolLock);
|
pthread_mutex_unlock(&g_txMempoolLock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
kh_value(txMempool, k) = tx;
|
kh_value(g_txMempool, k) = tx;
|
||||||
|
|
||||||
pthread_mutex_unlock(&g_txMempoolLock);
|
pthread_mutex_unlock(&g_txMempoolLock);
|
||||||
|
|
||||||
@@ -84,15 +84,15 @@ 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) {
|
||||||
if (!txMempool || !txHash || !out) { return false; }
|
if (!g_txMempool || !txHash || !out) { return false; }
|
||||||
|
|
||||||
pthread_mutex_lock(&g_txMempoolLock);
|
pthread_mutex_lock(&g_txMempoolLock);
|
||||||
key32_t key;
|
key32_t key;
|
||||||
memcpy(key.bytes, txHash, 32);
|
memcpy(key.bytes, txHash, 32);
|
||||||
|
|
||||||
khiter_t k = kh_get(tx_mempool_map_m, txMempool, key);
|
khiter_t k = kh_get(tx_mempool_map_m, g_txMempool, key);
|
||||||
if (k != kh_end(txMempool)) {
|
if (k != kh_end(g_txMempool)) {
|
||||||
signed_transaction_t tx = kh_value(txMempool, k);
|
signed_transaction_t tx = kh_value(g_txMempool, k);
|
||||||
memcpy(out, &tx, sizeof(signed_transaction_t));
|
memcpy(out, &tx, sizeof(signed_transaction_t));
|
||||||
pthread_mutex_unlock(&g_txMempoolLock);
|
pthread_mutex_unlock(&g_txMempoolLock);
|
||||||
return true;
|
return true;
|
||||||
@@ -110,7 +110,7 @@ bool TxMempool_Snapshot(signed_transaction_t** outTxs, size_t* outCount) {
|
|||||||
*outTxs = NULL;
|
*outTxs = NULL;
|
||||||
*outCount = 0;
|
*outCount = 0;
|
||||||
|
|
||||||
if (!txMempool) {
|
if (!g_txMempool) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,8 +118,8 @@ bool TxMempool_Snapshot(signed_transaction_t** outTxs, size_t* outCount) {
|
|||||||
|
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
khiter_t k;
|
khiter_t k;
|
||||||
for (k = kh_begin(txMempool); k != kh_end(txMempool); ++k) {
|
for (k = kh_begin(g_txMempool); k != kh_end(g_txMempool); ++k) {
|
||||||
if (kh_exist(txMempool, k)) {
|
if (kh_exist(g_txMempool, k)) {
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,9 +136,9 @@ bool TxMempool_Snapshot(signed_transaction_t** outTxs, size_t* outCount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
for (k = kh_begin(txMempool); k != kh_end(txMempool); ++k) {
|
for (k = kh_begin(g_txMempool); k != kh_end(g_txMempool); ++k) {
|
||||||
if (kh_exist(txMempool, k)) {
|
if (kh_exist(g_txMempool, k)) {
|
||||||
snapshot[index++] = kh_value(txMempool, k);
|
snapshot[index++] = kh_value(g_txMempool, k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,13 +150,13 @@ bool TxMempool_Snapshot(signed_transaction_t** outTxs, size_t* outCount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TxMempool_Print() {
|
void TxMempool_Print() {
|
||||||
if (!txMempool) { return; }
|
if (!g_txMempool) { return; }
|
||||||
|
|
||||||
pthread_mutex_lock(&g_txMempoolLock);
|
pthread_mutex_lock(&g_txMempoolLock);
|
||||||
khiter_t k;
|
khiter_t k;
|
||||||
for (k = kh_begin(txMempool); k != kh_end(txMempool); ++k) {
|
for (k = kh_begin(g_txMempool); k != kh_end(g_txMempool); ++k) {
|
||||||
if (kh_exist(txMempool, k)) {
|
if (kh_exist(g_txMempool, k)) {
|
||||||
signed_transaction_t tx = kh_val(txMempool, k);
|
signed_transaction_t tx = kh_val(g_txMempool, k);
|
||||||
char senderHex[65];
|
char senderHex[65];
|
||||||
char recipient1Hex[65];
|
char recipient1Hex[65];
|
||||||
char recipient2Hex[65];
|
char recipient2Hex[65];
|
||||||
@@ -174,10 +174,10 @@ void TxMempool_Print() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TxMempool_Destroy() {
|
void TxMempool_Destroy() {
|
||||||
if (txMempool) {
|
if (g_txMempool) {
|
||||||
pthread_mutex_lock(&g_txMempoolLock);
|
pthread_mutex_lock(&g_txMempoolLock);
|
||||||
kh_destroy(tx_mempool_map_m, txMempool);
|
kh_destroy(tx_mempool_map_m, g_txMempool);
|
||||||
txMempool = NULL;
|
g_txMempool = NULL;
|
||||||
pthread_mutex_unlock(&g_txMempoolLock);
|
pthread_mutex_unlock(&g_txMempoolLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,19 +188,19 @@ void TxMempool_Destroy() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TxMempool_Remove(const uint8_t* txHash) {
|
bool TxMempool_Remove(const uint8_t* txHash) {
|
||||||
if (!txMempool || !txHash) { return false; }
|
if (!g_txMempool || !txHash) { return false; }
|
||||||
|
|
||||||
pthread_mutex_lock(&g_txMempoolLock);
|
pthread_mutex_lock(&g_txMempoolLock);
|
||||||
key32_t key;
|
key32_t key;
|
||||||
memcpy(key.bytes, txHash, 32);
|
memcpy(key.bytes, txHash, 32);
|
||||||
|
|
||||||
khiter_t k = kh_get(tx_mempool_map_m, txMempool, key);
|
khiter_t k = kh_get(tx_mempool_map_m, g_txMempool, key);
|
||||||
if (k == kh_end(txMempool)) {
|
if (k == kh_end(g_txMempool)) {
|
||||||
pthread_mutex_unlock(&g_txMempoolLock);
|
pthread_mutex_unlock(&g_txMempoolLock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
kh_del(tx_mempool_map_m, txMempool, k);
|
kh_del(tx_mempool_map_m, g_txMempool, k);
|
||||||
pthread_mutex_unlock(&g_txMempoolLock);
|
pthread_mutex_unlock(&g_txMempoolLock);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user