difficulty calculation, move from randomx to autolykos2
This commit is contained in:
97
src/main.c
97
src/main.c
@@ -8,7 +8,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <randomx/librx_wrapper.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <constants.h>
|
||||
@@ -19,56 +18,11 @@
|
||||
|
||||
void handle_sigint(int sig) {
|
||||
printf("Caught signal %d, exiting...\n", sig);
|
||||
RandomX_Destroy();
|
||||
Block_ShutdownPowContext();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static double MonotonicSeconds(void) {
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (double)ts.tv_sec + ((double)ts.tv_nsec / 1000000000.0);
|
||||
}
|
||||
|
||||
static double MeasureRandomXHashrate(void) {
|
||||
uint8_t input[80] = {0};
|
||||
uint8_t outHash[32];
|
||||
uint64_t counter = 0;
|
||||
|
||||
const double start = MonotonicSeconds();
|
||||
double now = start;
|
||||
do {
|
||||
memcpy(input, &counter, sizeof(counter));
|
||||
RandomX_CalculateHash(input, sizeof(input), outHash);
|
||||
counter++;
|
||||
now = MonotonicSeconds();
|
||||
} while ((now - start) < 0.75); // short local benchmark window
|
||||
|
||||
const double elapsed = now - start;
|
||||
if (elapsed <= 0.0 || counter == 0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return (double)counter / elapsed;
|
||||
}
|
||||
|
||||
static uint32_t CompactTargetForExpectedHashes(double expectedHashes) {
|
||||
if (expectedHashes < 1.0) {
|
||||
expectedHashes = 1.0;
|
||||
}
|
||||
|
||||
// For exponent 0x1f: target = mantissa * 2^(8*(0x1f-3)) = mantissa * 2^224
|
||||
// So expected hashes ~= 2^256 / target = 2^32 / mantissa.
|
||||
double mantissaF = 4294967296.0 / expectedHashes;
|
||||
if (mantissaF < 1.0) {
|
||||
mantissaF = 1.0;
|
||||
}
|
||||
if (mantissaF > 8388607.0) {
|
||||
mantissaF = 8388607.0; // 0x007fffff
|
||||
}
|
||||
|
||||
const uint32_t mantissa = (uint32_t)mantissaF;
|
||||
return (0x1fU << 24) | (mantissa & 0x007fffffU);
|
||||
}
|
||||
uint32_t difficultyTarget = INITIAL_DIFFICULTY;
|
||||
|
||||
static bool MineBlock(block_t* block) {
|
||||
if (!block) {
|
||||
@@ -91,24 +45,18 @@ int main(int argc, char* argv[]) {
|
||||
signal(SIGINT, handle_sigint);
|
||||
|
||||
const char* chainDataDir = CHAIN_DATA_DIR;
|
||||
const uint64_t blocksToMine = 10;
|
||||
const uint64_t blocksToMine = 1000;
|
||||
const double targetSeconds = TARGET_BLOCK_TIME;
|
||||
|
||||
uint256_t currentSupply = uint256_from_u64(0);
|
||||
|
||||
// Init RandomX
|
||||
if (!RandomX_Init("minicoin", false)) { // TODO: Use a key that is not hardcoded; E.g. hash of the last block, every thousand blocks, difficulty recalibration, etc.
|
||||
fprintf(stderr, "failed to initialize RandomX\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
blockchain_t* chain = Chain_Create();
|
||||
if (!chain) {
|
||||
fprintf(stderr, "failed to create chain\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!Chain_LoadFromFile(chain, chainDataDir, ¤tSupply)) {
|
||||
if (!Chain_LoadFromFile(chain, chainDataDir, ¤tSupply, &difficultyTarget)) {
|
||||
printf("No existing chain loaded from %s\n", chainDataDir);
|
||||
}
|
||||
|
||||
@@ -138,17 +86,6 @@ int main(int argc, char* argv[]) {
|
||||
if (argc > 1 && strcmp(argv[1], "-mine") == 0) {
|
||||
printf("Mining %llu blocks with target time %.0fs...\n", (unsigned long long)blocksToMine, targetSeconds);
|
||||
|
||||
const double hps = MeasureRandomXHashrate();
|
||||
const double expectedHashes = (hps > 0.0) ? (hps * targetSeconds) : 65536.0;
|
||||
const uint32_t calibratedBits = CompactTargetForExpectedHashes(expectedHashes);
|
||||
//const uint32_t calibratedBits = 0xffffffff; // Absurdly low diff for testing
|
||||
|
||||
printf("RandomX benchmark: %.2f H/s, target %.0fs, nBits=0x%08x, diff=%.2f\n",
|
||||
hps,
|
||||
targetSeconds,
|
||||
calibratedBits,
|
||||
(double)(1.f / calibratedBits) * 4294967296.0); // Basic representation as a big number for now
|
||||
|
||||
uint8_t minerAddress[32];
|
||||
SHA256((const unsigned char*)"minicoin-miner-1", strlen("minicoin-miner-1"), minerAddress);
|
||||
|
||||
@@ -157,7 +94,7 @@ int main(int argc, char* argv[]) {
|
||||
if (!block) {
|
||||
fprintf(stderr, "failed to create block\n");
|
||||
Chain_Destroy(chain);
|
||||
RandomX_Destroy();
|
||||
Block_ShutdownPowContext();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -174,7 +111,7 @@ int main(int argc, char* argv[]) {
|
||||
memset(block->header.prevHash, 0, sizeof(block->header.prevHash));
|
||||
}
|
||||
block->header.timestamp = (uint64_t)time(NULL);
|
||||
block->header.difficultyTarget = calibratedBits;
|
||||
block->header.difficultyTarget = difficultyTarget;
|
||||
block->header.nonce = 0;
|
||||
|
||||
signed_transaction_t coinbaseTx;
|
||||
@@ -195,7 +132,7 @@ int main(int argc, char* argv[]) {
|
||||
fprintf(stderr, "failed to mine block within nonce range\n");
|
||||
Block_Destroy(block);
|
||||
Chain_Destroy(chain);
|
||||
RandomX_Destroy();
|
||||
Block_ShutdownPowContext();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -203,28 +140,36 @@ int main(int argc, char* argv[]) {
|
||||
fprintf(stderr, "failed to append block to chain\n");
|
||||
Block_Destroy(block);
|
||||
Chain_Destroy(chain);
|
||||
RandomX_Destroy();
|
||||
Block_ShutdownPowContext();
|
||||
return 1;
|
||||
}
|
||||
|
||||
(void)uint256_add_u64(¤tSupply, coinbaseTx.transaction.amount);
|
||||
|
||||
uint8_t blockHash[32];
|
||||
Block_CalculateHash(block, blockHash);
|
||||
printf("Mined block %llu/%llu (height=%llu) nonce=%llu reward=%llu supply=%llu merkle=%02x%02x%02x%02x... hash=%02x%02x%02x%02x...\n",
|
||||
uint8_t canonicalHash[32];
|
||||
uint8_t powHash[32];
|
||||
Block_CalculateHash(block, canonicalHash);
|
||||
Block_CalculateAutolykos2Hash(block, powHash);
|
||||
printf("Mined block %llu/%llu (height=%llu) nonce=%llu reward=%llu supply=%llu diff=%#x merkle=%02x%02x%02x%02x... pow=%02x%02x%02x%02x... canonical=%02x%02x%02x%02x...\n",
|
||||
(unsigned long long)(mined + 1),
|
||||
(unsigned long long)blocksToMine,
|
||||
(unsigned long long)block->header.blockNumber,
|
||||
(unsigned long long)block->header.nonce,
|
||||
(unsigned long long)coinbaseTx.transaction.amount,
|
||||
(unsigned long long)currentSupply.limbs[0],
|
||||
(unsigned int)block->header.difficultyTarget,
|
||||
block->header.merkleRoot[0], block->header.merkleRoot[1], block->header.merkleRoot[2], block->header.merkleRoot[3],
|
||||
blockHash[0], blockHash[1], blockHash[2], blockHash[3]);
|
||||
powHash[0], powHash[1], powHash[2], powHash[3],
|
||||
canonicalHash[0], canonicalHash[1], canonicalHash[2], canonicalHash[3]);
|
||||
|
||||
free(block); // chain stores blocks by value; transactions are owned by chain copy
|
||||
|
||||
// Save chain after each mined block
|
||||
Chain_SaveToFile(chain, chainDataDir, currentSupply);
|
||||
|
||||
if (Chain_Size(chain) % DIFFICULTY_ADJUSTMENT_INTERVAL == 0) {
|
||||
difficultyTarget = Chain_ComputeNextTarget(chain, difficultyTarget);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Chain_SaveToFile(chain, chainDataDir, currentSupply)) {
|
||||
@@ -248,6 +193,6 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
Chain_Destroy(chain);
|
||||
RandomX_Destroy();
|
||||
Block_ShutdownPowContext();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user