balance sheet stuff, added khash hashmaps
This commit is contained in:
79
src/balance_sheet.c
Normal file
79
src/balance_sheet.c
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
28
src/main.c
28
src/main.c
@@ -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, ¤tSupply, &difficultyTarget, ¤tReward)) {
|
||||
uint8_t lastSavedHash[32];
|
||||
bool isFirstBlockOfLoadedChain = true;
|
||||
|
||||
if (!Chain_LoadFromFile(chain, chainDataDir, ¤tSupply, &difficultyTarget, ¤tReward, 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;
|
||||
|
||||
Reference in New Issue
Block a user