Skip to content

Commit

Permalink
headersdb_file: added chainwork to database record
Browse files Browse the repository at this point in the history
headersdb_file: added chainwork to load and write
headersdb_file: updated chainwork check on reorg
headersdb_file: updated current version for chainwork
headersdb_file: updated load to connect first header
tests: updated reorg_test to load and write headers
  • Loading branch information
edtubbs committed May 31, 2024
1 parent 5fb26c2 commit 8eea8bd
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 34 deletions.
57 changes: 24 additions & 33 deletions src/headersdb_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#include <dogecoin/validation.h>

static const unsigned char file_hdr_magic[4] = {0xA8, 0xF0, 0x11, 0xC5}; /* header magic */
static const uint32_t current_version = 2;
static const uint32_t current_version = 3; /* 3: added chainwork */

/**
* "Compare two block headers by their hashes."
Expand Down Expand Up @@ -203,7 +203,6 @@ dogecoin_bool dogecoin_headers_db_load(dogecoin_headers_db* db, const char *file
return false;
}
}
dogecoin_bool firstblock = true;
size_t connected_headers_count = 0;
if (db->headers_tree_file && !create)
{
Expand All @@ -213,46 +212,35 @@ dogecoin_bool dogecoin_headers_db_load(dogecoin_headers_db* db, const char *file
// print progress
if (connected_headers_count % 1000 == 0)
{
printf("\r%ld headers loaded", connected_headers_count);
printf("\r%ld headers loaded\n", connected_headers_count);
fflush(stdout);
}

uint8_t buf_all[32+4+80];
uint8_t buf_all[32+4+32+80];
if (fread(buf_all, sizeof(buf_all), 1, db->headers_tree_file) == 1) {
struct const_buffer cbuf_all = {buf_all, sizeof(buf_all)};

//load all

uint256 hash;
uint32_t height;
uint256 chainwork;
deser_u256(hash, &cbuf_all);
deser_u32(&height, &cbuf_all);
deser_u256(chainwork, &cbuf_all);
dogecoin_bool connected;
if (firstblock)

dogecoin_blockindex *pindex = dogecoin_headers_db_connect_hdr(db, &cbuf_all, true, &connected);
if (!connected)
{
dogecoin_blockindex *chainheader = dogecoin_calloc(1, sizeof(dogecoin_blockindex));
chainheader->height = height;
if (!dogecoin_block_header_deserialize(&chainheader->header, &cbuf_all, db->params, &chainheader->chainwork)) {
dogecoin_block_header_free(&chainheader->header);
dogecoin_free(chainheader);
fprintf(stderr, "\nError: Invalid data found.\n");
return -1;
}
dogecoin_block_header_hash(&chainheader->header, (uint8_t *)&chainheader->hash);
chainheader->prev = NULL;
db->chaintip = chainheader;
firstblock = false;
} else {
dogecoin_blockindex *pindex = dogecoin_headers_db_connect_hdr(db, &cbuf_all, true, &connected);
if (!connected)
{
printf("\nConnecting header %s failed (at height: %d) read_write: %d\n", hash_to_string(hash), db->chaintip->height, db->read_write_file);
dogecoin_free(pindex);
}
else {
connected_headers_count++;
}
printf("\nConnecting header %s failed (at height: %d) read_write: %d\n", hash_to_string(hash), db->chaintip->height, db->read_write_file);
dogecoin_free(pindex);
}
else {
connected_headers_count++;
}

memcpy(db->chaintip->chainwork, chainwork, sizeof(uint256));
}
}
}
Expand All @@ -269,9 +257,10 @@ dogecoin_bool dogecoin_headers_db_load(dogecoin_headers_db* db, const char *file
* @return Nothing.
*/
dogecoin_bool dogecoin_headers_db_write(dogecoin_headers_db* db, dogecoin_blockindex *blockindex) {
cstring *rec = cstr_new_sz(100);
cstring *rec = cstr_new_sz(148); // hash + height + chainwork + header
ser_u256(rec, blockindex->hash);
ser_u32(rec, blockindex->height);
ser_u256(rec, blockindex->chainwork);
dogecoin_block_header_serialize(rec, &blockindex->header);
size_t res = fwrite(rec->str, rec->len, 1, db->headers_tree_file);
dogecoin_file_commit(db->headers_tree_file);
Expand Down Expand Up @@ -357,7 +346,9 @@ dogecoin_blockindex * dogecoin_headers_db_connect_hdr(dogecoin_headers_db* db, s
dogecoin_free(blockindex_chainwork);

// Chain reorganization if necessary
if (fork_from_block && blockindex->height > db->chaintip->height && arith_uint256_greater_than(added_chainwork, chaintip_chainwork)) {
if (fork_from_block && blockindex->height > db->chaintip->height &&
(arith_uint256_greater_than(added_chainwork, chaintip_chainwork) ||
(arith_uint256_equal(added_chainwork, chaintip_chainwork) && blockindex->header.timestamp > db->chaintip->header.timestamp))) {

// Identify the common ancestor
dogecoin_blockindex* common_ancestor = db->chaintip;
Expand Down Expand Up @@ -420,10 +411,6 @@ dogecoin_blockindex * dogecoin_headers_db_connect_hdr(dogecoin_headers_db* db, s
db->chaintip = blockindex;
}

// Free the dynamically allocated memory
dogecoin_free(chaintip_chainwork);
dogecoin_free(added_chainwork);

if (!load_process && db->read_write_file)
{
if (!dogecoin_headers_db_write(db, blockindex)) {
Expand All @@ -434,6 +421,10 @@ dogecoin_blockindex * dogecoin_headers_db_connect_hdr(dogecoin_headers_db* db, s
dogecoin_btree_tsearch(blockindex, &db->tree_root, dogecoin_header_compare);
}

// Free the dynamically allocated memory
dogecoin_free(chaintip_chainwork);
dogecoin_free(added_chainwork);

if (db->max_hdr_in_mem > 0) {
// de-allocate no longer required headers
// keep them only on-disk
Expand Down
13 changes: 12 additions & 1 deletion test/spv_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ void test_reorg() {
unlink(headersfile);

// Initialize SPV client
dogecoin_spv_client* client = dogecoin_spv_client_new(chain, false, true, false, false, 8, NULL);
dogecoin_spv_client* client = dogecoin_spv_client_new(chain, false, false, false, false, 8, NULL);
client->header_message_processed = test_spv_header_message_processed;
client->sync_completed = test_spv_sync_completed;
dogecoin_spv_client_load(client, headersfile, false);
Expand Down Expand Up @@ -571,4 +571,15 @@ void test_reorg() {
dogecoin_spv_client_free(client);
remove_all_hashes();
remove_all_maps();

// Re-initialize SPV client and load the headers database
client = dogecoin_spv_client_new(chain, false, false, false, false, 8, NULL);
client->header_message_processed = test_spv_header_message_processed;
client->sync_completed = test_spv_sync_completed;
dogecoin_spv_client_load(client, headersfile, false);

// Cleanup
dogecoin_spv_client_free(client);
remove_all_hashes();
remove_all_maps();
}

0 comments on commit 8eea8bd

Please sign in to comment.