balance sheet stuff, added khash hashmaps

This commit is contained in:
2026-04-02 21:21:12 +02:00
parent b20ba9802e
commit df7787ed2d
10 changed files with 824 additions and 16 deletions

79
src/balance_sheet.c Normal file
View File

@@ -0,0 +1,79 @@
#include <balance_sheet.h>
khash_t(balance_sheet_map_m)* sheetMap = NULL;
void BalanceSheet_Init() {
sheetMap = kh_init(balance_sheet_map_m);
}
int BalanceSheet_Insert(balance_sheet_entry_t entry) {
if (!sheetMap) { return -1; }
// Encapsulate key
key32_t key;
memcpy(key.bytes, entry.address, 32);
int ret;
khiter_t k = kh_put(balance_sheet_map_m, sheetMap, key, &ret);
if (k == kh_end(sheetMap)) {
return -1;
}
kh_value(sheetMap, k) = entry;
return ret;
}
bool BalanceSheet_Lookup(uint8_t* address, balance_sheet_entry_t* out) {
if (!address || !out) { return false; }
key32_t key;
memcpy(key.bytes, address, 32);
khiter_t k = kh_get(balance_sheet_map_m, sheetMap, key);
if (k != kh_end(sheetMap)) {
balance_sheet_entry_t entry = kh_value(sheetMap, k);
memcpy(out, &entry, sizeof(balance_sheet_entry_t));
return true;
}
return false;
}
/* TODO */
bool BalanceSheet_SaveToFile(const char* outPath) {
if (!sheetMap) { return false; }
return true;
}
/* TODO */
bool BalanceSheet_LoadFromFile(const char* inPath) {
if (!sheetMap) { return false; }
return true;
}
void BalanceSheet_Print() {
if (!sheetMap) { return; }
// Iterate through every entry
khiter_t k;
size_t iter = 0;
for (k = kh_begin(sheetMap); k != kh_end(sheetMap); ++k) {
if (kh_exist(sheetMap, k)) {
key32_t key = kh_key(sheetMap, k);
balance_sheet_entry_t val = kh_val(sheetMap, k);
printf("Sheet entry %llu: mapkey=%02x%02x%02x%02x... address=%02x%02x%02x%02x... balance=%llu\n",
(unsigned long long)(iter),
key.bytes[0], key.bytes[1], key.bytes[2], key.bytes[3],
val.address[0], val.address[1], val.address[2], val.address[3],
(unsigned long long)(val.balance),
iter++);
}
}
}
void BalanceSheet_Destroy() {
kh_destroy(balance_sheet_map_m, sheetMap);
sheetMap = NULL;
}

View File

@@ -73,9 +73,47 @@ void Chain_Destroy(blockchain_t* chain) {
}
bool Chain_AddBlock(blockchain_t* chain, block_t* block) {
// Assume the block is pre-verified
if (chain && block && chain->blocks) {
DynArr_push_back(chain->blocks, block);
block_t* blk = (block_t*)DynArr_push_back(chain->blocks, block);
chain->size++;
if (blk && blk->transactions) {
size_t txCount = DynArr_size(blk->transactions);
for (size_t i = 0; i < txCount; i++) {
signed_transaction_t* tx = (signed_transaction_t*)DynArr_at(blk->transactions, i);
if (!tx) { continue; }
// Destination 1
balance_sheet_entry_t entry1;
uint8_t addr1[32];
memcpy(addr1, tx->transaction.recipientAddress1, 32);
// Assume addr1 is never NULL, since we enforce that
if (BalanceSheet_Lookup(addr1, &entry1)) {
entry1.balance += tx->transaction.amount1;
} else {
memcpy(entry1.address, addr1, 32);
entry1.balance = tx->transaction.amount1;
}
BalanceSheet_Insert(entry1); // Insert/Overwrite
// Destination 2
balance_sheet_entry_t entry2;
char ZERO[32] = {0};
uint8_t addr2[32];
memcpy(addr2, tx->transaction.recipientAddress2, 32);
if (memcmp(addr2, ZERO, 32) == 0) { continue; } // Destination 2 not specified, continue
if (BalanceSheet_Lookup(addr2, &entry2)) {
entry2.balance += tx->transaction.amount2;
} else {
memcpy(entry2.address, addr2, 32);
entry2.balance = tx->transaction.amount2;
}
BalanceSheet_Insert(entry2);
}
}
return true;
}
@@ -121,7 +159,8 @@ bool Chain_IsValid(blockchain_t* chain) {
// A potential issue is verifying PoW, since the chain read might only have header data without transactions.
// A potnetial fix is verifying PoW as we go, when getting new blocks from peers, and only accepting blocks
//with valid PoW, so that we can assume all blocks in the chain are valid in that regard.
// with valid PoW, so that we can assume all blocks in the chain are valid in that regard.
// During the initial sync, we can verify the PoW, the validity of each transaction + coinbase, etc.
}
// Genesis needs special handling because the prevHash is always invalid (no previous block)
@@ -289,8 +328,8 @@ bool Chain_SaveToFile(blockchain_t* chain, const char* dirpath, uint256_t curren
return true;
}
bool Chain_LoadFromFile(blockchain_t* chain, const char* dirpath, uint256_t* outCurrentSupply, uint32_t* outDifficultyTarget, uint64_t* outCurrentReward) {
if (!chain || !chain->blocks || !dirpath || !outCurrentSupply) {
bool Chain_LoadFromFile(blockchain_t* chain, const char* dirpath, uint256_t* outCurrentSupply, uint32_t* outDifficultyTarget, uint64_t* outCurrentReward, uint8_t* outLastSavedHash) {
if (!chain || !chain->blocks || !dirpath || !outCurrentSupply || !outLastSavedHash) {
return false;
}
@@ -324,8 +363,7 @@ bool Chain_LoadFromFile(blockchain_t* chain, const char* dirpath, uint256_t* out
size_t savedSize = 0;
if (fread(&savedSize, sizeof(size_t), 1, metaFile) != 1) return false;
uint8_t lastSavedHash[32];
if (fread(lastSavedHash, sizeof(uint8_t), 32, metaFile) != 32) return false;
if (fread(outLastSavedHash, sizeof(uint8_t), 32, metaFile) != 32) return false;
if (fread(outCurrentSupply, sizeof(uint256_t), 1, metaFile) != 1) return false;
if (fread(outDifficultyTarget, sizeof(uint32_t), 1, metaFile) != 1) return false;
if (fread(outCurrentReward, sizeof(uint64_t), 1, metaFile) != 1) return false;

View File

@@ -59,6 +59,8 @@ bool Transaction_Verify(const signed_transaction_t* tx) {
return false; // Cannot send to coinbase address
}
// TODO: Check that the sender has sufficient funds - if not coinbase
if (tx->transaction.amount2 == 0) {
// If amount2 is zero, address2 must be all zeros
uint8_t zeroAddress[32] = {0};

View File

@@ -75,3 +75,13 @@ void Crypto_SignData(const uint8_t* data, size_t len, const uint8_t* privateKey,
secp256k1_ecdsa_signature_serialize_compact(ctx, outSignature, &sig);
secp256k1_context_destroy(ctx);
}
void to_hex(const uint8_t *in, char *out) {
static const char hex[] = "0123456789abcdef";
for (int i = 0; i < 32; i++) {
out[i * 2] = hex[in[i] >> 4];
out[i * 2 + 1] = hex[in[i] & 0x0F];
}
out[64] = '\0';
}

View File

@@ -9,6 +9,7 @@
#include <string.h>
#include <time.h>
#include <signal.h>
#include <balance_sheet.h>
#include <constants.h>
#include <autolykos2/autolykos2.h>
@@ -20,6 +21,7 @@
void handle_sigint(int sig) {
printf("Caught signal %d, exiting...\n", sig);
Block_ShutdownPowContext();
BalanceSheet_Destroy();
exit(0);
}
@@ -95,8 +97,9 @@ static bool MineBlock(block_t* block) {
int main(int argc, char* argv[]) {
signal(SIGINT, handle_sigint);
BalanceSheet_Init();
const char* chainDataDir = CHAIN_DATA_DIR;
const uint64_t blocksToMine = 4000000;
const uint64_t blocksToMine = 100;
const double targetSeconds = TARGET_BLOCK_TIME;
uint256_t currentSupply = uint256_from_u64(0);
@@ -107,7 +110,10 @@ int main(int argc, char* argv[]) {
return 1;
}
if (!Chain_LoadFromFile(chain, chainDataDir, &currentSupply, &difficultyTarget, &currentReward)) {
uint8_t lastSavedHash[32];
bool isFirstBlockOfLoadedChain = true;
if (!Chain_LoadFromFile(chain, chainDataDir, &currentSupply, &difficultyTarget, &currentReward, lastSavedHash)) {
printf("No existing chain loaded from %s\n", chainDataDir);
}
@@ -169,11 +175,15 @@ int main(int argc, char* argv[]) {
block->header.version = 1;
block->header.blockNumber = (uint64_t)Chain_Size(chain);
if (Chain_Size(chain) > 0) {
block_t* lastBlock = Chain_GetBlock(chain, Chain_Size(chain) - 1);
if (lastBlock) {
Block_CalculateHash(lastBlock, block->header.prevHash);
if (!isFirstBlockOfLoadedChain) {
block_t* lastBlock = Chain_GetBlock(chain, Chain_Size(chain) - 1);
if (lastBlock) {
Block_CalculateHash(lastBlock, block->header.prevHash);
} else {
memset(block->header.prevHash, 0, sizeof(block->header.prevHash));
}
} else {
memset(block->header.prevHash, 0, sizeof(block->header.prevHash));
memcpy(block->header.prevHash, lastSavedHash, sizeof(lastSavedHash));
}
} else {
memset(block->header.prevHash, 0, sizeof(block->header.prevHash));
@@ -221,7 +231,7 @@ int main(int argc, char* argv[]) {
uint8_t canonicalHash[32];
uint8_t powHash[32];
Block_CalculateHash(block, canonicalHash);
Block_CalculateAutolykos2Hash(block, powHash);
Block_CalculateAutolykos2Hash(block, powHash);
printf("Mined block %llu/%llu (height=%llu) nonce=%llu reward=%llu supply=%s 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,
@@ -252,6 +262,8 @@ int main(int argc, char* argv[]) {
GetNextDAGSeed(chain, dagSeed);
(void)Block_RebuildAutolykos2Dag(CalculateTargetDAGSize(chain), dagSeed);
}
isFirstBlockOfLoadedChain = false;
}
if (!Chain_SaveToFile(chain, chainDataDir, currentSupply, currentReward)) {
@@ -278,6 +290,8 @@ int main(int argc, char* argv[]) {
}
}*/
BalanceSheet_Print();
Chain_Destroy(chain);
Block_ShutdownPowContext();
return 0;