Skip to content

Commit

Permalink
hash: added dogecoin_hashwriter_free
Browse files Browse the repository at this point in the history
auxpow: updated check_merkle_branch iterator to size_t and hash parameters
block: updated dogecoin_block_header_free to clear version and removed debug print
headersdb_file: updated dogecoin_headers_db_free to free chaintip to chainbottom
headersdb_file: updated dogecoin_headers_db_connect_hdr to free blockindex
spv: updated dogecoin_spv_client_free to check for headers_db_ctx
spv: updated dogecoin_net_spv_post_cmd to recover after invalid headers and blocks
spv: updated dogecoin_net_spv_periodic_statecheck to continue after full block sync
spv: updated dogecoin_net_spv_request_headers to confirm height
transaction: updated sign_transaction_w_privkey to free script_pubkey and txtmp
tx: updated dogecoin_tx_out_pubkey_hash_to_p2pkh_address to free copy of txout
wallet: removed dogecoin_wallet_add_to_spent as dogecoin_wallet_scrape_utxos already handles unspent and spends vector/rbtrees
wallet: updated dogecoin_wallet_new frees and to call dogecoin_hdnode_free
wallet: updated dogecoin_wallet_free to call dogecoin_btree_tdestroy with NULL/free
wallet: updated dogecoin_wallet_create to check for open wallet file
  • Loading branch information
edtubbs committed Dec 1, 2023
1 parent 93d8f3b commit 455d198
Show file tree
Hide file tree
Showing 12 changed files with 198 additions and 164 deletions.
6 changes: 6 additions & 0 deletions include/dogecoin/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ static hashwriter* init_hashwriter(int n_type, int n_version) {
return hw;
}

static void dogecoin_hashwriter_free(hashwriter* hw) {
free(hw->ctx->sha);
free(hw->ctx);
dogecoin_free(hw->hash);
dogecoin_free(hw);
}

/** SipHash 2-4 */
typedef struct siphasher {
Expand Down
1 change: 0 additions & 1 deletion include/dogecoin/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ LIBDOGECOIN_API int64_t dogecoin_wallet_wtx_get_available_credit(dogecoin_wallet
LIBDOGECOIN_API dogecoin_bool dogecoin_wallet_txout_is_mine(dogecoin_wallet* wallet, dogecoin_tx_out* tx_out);

/** checks if a transaction outpoint is owned by the wallet */
LIBDOGECOIN_API void dogecoin_wallet_add_to_spent(dogecoin_wallet* wallet, const dogecoin_wtx* wtx);
LIBDOGECOIN_API dogecoin_bool dogecoin_wallet_is_spent(dogecoin_wallet* wallet, uint256 hash, uint32_t n);
LIBDOGECOIN_API dogecoin_bool dogecoin_wallet_get_unspents(dogecoin_wallet* wallet, vector* unspents);
LIBDOGECOIN_API dogecoin_bool dogecoin_wallet_get_unspent(dogecoin_wallet* wallet, vector* unspent);
Expand Down
6 changes: 3 additions & 3 deletions src/auxpow.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ uint256* check_merkle_branch(uint256* hash, const vector* merkle_branch, int ind
uint256* current_hash = dogecoin_uint256_vla(1);
memcpy(current_hash, hash, sizeof(uint256)); // Copy the initial hash

for (int i = 0; i < merkle_branch->len; ++i) {
for (size_t i = 0; i < merkle_branch->len; ++i) {
uint256* next_branch_hash = (uint256*)vector_idx(merkle_branch, i);
uint256* new_hash;

if (index & 1) {
new_hash = Hash(next_branch_hash, current_hash);
new_hash = Hash((const uint256*) next_branch_hash, (const uint256*) current_hash);
} else {
new_hash = Hash(current_hash, next_branch_hash);
new_hash = Hash((const uint256*) current_hash, (const uint256*) next_branch_hash);
}

memcpy(current_hash, new_hash, sizeof(uint256)); // Update the current hash
Expand Down
7 changes: 3 additions & 4 deletions src/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,10 @@ dogecoin_auxpow_block* dogecoin_auxpow_block_new() {
block->parent_coinbase = dogecoin_tx_new();
dogecoin_mem_zero(&block->parent_hash, DOGECOIN_HASH_LENGTH);
block->parent_merkle_count = 0;
block->parent_coinbase_merkle;
block->parent_coinbase_merkle = NULL;
block->parent_merkle_index = 0;
block->aux_merkle_count = 0;
block->aux_merkle_branch;
block->aux_merkle_branch = NULL;
block->aux_merkle_index = 0;
block->parent_header = dogecoin_block_header_new();
block->header->auxpow->check = check;
Expand All @@ -194,7 +194,7 @@ dogecoin_auxpow_block* dogecoin_auxpow_block_new() {
*/
void dogecoin_block_header_free(dogecoin_block_header* header) {
if (!header) return;
header->version = 1;
header->version = 0;
dogecoin_mem_zero(&header->prev_block, DOGECOIN_HASH_LENGTH);
dogecoin_mem_zero(&header->merkle_root, DOGECOIN_HASH_LENGTH);
header->bits = 0;
Expand Down Expand Up @@ -419,7 +419,6 @@ int deserialize_dogecoin_auxpow_block(dogecoin_auxpow_block* block, struct const

if (!check_auxpow(block, (dogecoin_chainparams*)params)) {
printf("check_auxpow failed!\n");
print_block(block);
return false;
}

Expand Down
32 changes: 24 additions & 8 deletions src/headersdb_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,19 @@ void dogecoin_headers_db_free(dogecoin_headers_db* db) {
db->tree_root = NULL;
}

// Free all blockindex structures starting from chaintip to chainbottom
if (db->chaintip) {
dogecoin_blockindex *scan_tip = db->chaintip;
while (scan_tip && scan_tip != db->chainbottom) {
dogecoin_blockindex *prev = scan_tip->prev;
dogecoin_free(scan_tip);
scan_tip = prev;
}
}

db->chaintip = NULL;
db->chainbottom = NULL;

dogecoin_free(db);
}

Expand Down Expand Up @@ -261,7 +274,12 @@ dogecoin_blockindex * dogecoin_headers_db_connect_hdr(dogecoin_headers_db* db, s
*connected = false;

dogecoin_blockindex *blockindex = dogecoin_calloc(1, sizeof(dogecoin_blockindex));
if (!dogecoin_block_header_deserialize(&blockindex->header, buf, db->params)) return NULL;
if (!dogecoin_block_header_deserialize(&blockindex->header, buf, db->params))
{
dogecoin_free(blockindex);
fprintf(stderr, "Error deserializing block header\n");
return NULL;
}

dogecoin_block_header_hash(&blockindex->header, (uint8_t *)&blockindex->hash);

Expand Down Expand Up @@ -340,14 +358,12 @@ dogecoin_blockindex * dogecoin_headers_db_connect_hdr(dogecoin_headers_db* db, s
}
}
*connected = true;
return blockindex;
} else {
// Connection not established, free allocated memory
dogecoin_free(blockindex);
return NULL;
}
else {
//TODO, add to orphans
char hex[65] = {0};
utils_bin_to_hex(blockindex->hash, DOGECOIN_HASH_LENGTH, hex);
}

return blockindex;
}

/**
Expand Down
105 changes: 57 additions & 48 deletions src/spv.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ void dogecoin_net_spv_node_handshake_done(dogecoin_node *node);
* the nodegroup's handshake_done_cb to dogecoin_net_spv_node_handshake_done,
* the nodegroup's node_connection_state_changed_cb to NULL, and the
* nodegroup's periodic_timer_cb to dogecoin_net_spv_node_timer_callback
*
*
* @param nodegroup The nodegroup to set the callbacks for.
*/
void dogecoin_net_set_spv(dogecoin_node_group *nodegroup)
Expand All @@ -81,11 +81,11 @@ void dogecoin_net_set_spv(dogecoin_node_group *nodegroup)

/**
* The function creates a new dogecoin_spv_client object and initializes it
*
*
* @param params The chainparams struct that we created earlier.
* @param debug If true, the node will print out debug messages to stdout.
* @param headers_memonly If true, the headers database will not be loaded from disk.
*
*
* @return A pointer to a dogecoin_spv_client object.
*/
dogecoin_spv_client* dogecoin_spv_client_new(const dogecoin_chainparams *params, dogecoin_bool debug, dogecoin_bool headers_memonly, dogecoin_bool use_checkpoints, dogecoin_bool full_sync)
Expand Down Expand Up @@ -128,7 +128,7 @@ dogecoin_spv_client* dogecoin_spv_client_new(const dogecoin_chainparams *params,

/**
* It adds peers to the nodegroup.
*
*
* @param client the dogecoin_spv_client object
* @param ips A comma-separated list of IPs or seeds to connect to.
*/
Expand All @@ -140,7 +140,7 @@ void dogecoin_spv_client_discover_peers(dogecoin_spv_client* client, const char
/**
* The function loops through all the nodes in the node group and connects to the next nodes in the
* node group
*
*
* @param client The dogecoin_spv_client object.
*/
void dogecoin_spv_client_runloop(dogecoin_spv_client* client)
Expand All @@ -151,9 +151,9 @@ void dogecoin_spv_client_runloop(dogecoin_spv_client* client)

/**
* It frees the memory allocated for the client
*
*
* @param client The client object to be freed.
*
*
* @return Nothing.
*/
void dogecoin_spv_client_free(dogecoin_spv_client *client)
Expand All @@ -163,7 +163,10 @@ void dogecoin_spv_client_free(dogecoin_spv_client *client)

if (client->headers_db)
{
client->headers_db->free(client->headers_db_ctx);
if (client->headers_db_ctx)
{
client->headers_db->free(client->headers_db_ctx);
}
client->headers_db_ctx = NULL;
client->headers_db = NULL;
}
Expand All @@ -178,10 +181,10 @@ void dogecoin_spv_client_free(dogecoin_spv_client *client)

/**
* Loads the headers database from a file
*
*
* @param client the client object
* @param file_path The path to the headers database file.
*
*
* @return A boolean value.
*/
dogecoin_bool dogecoin_spv_client_load(dogecoin_spv_client *client, const char *file_path)
Expand All @@ -198,7 +201,7 @@ dogecoin_bool dogecoin_spv_client_load(dogecoin_spv_client *client, const char *

/**
* If we are in the header sync state, we request headers from a random node
*
*
* @param node the node that we are checking
* @param now The current time in seconds.
*/
Expand Down Expand Up @@ -242,21 +245,25 @@ void dogecoin_net_spv_periodic_statecheck(dogecoin_node *node, uint64_t *now)
dogecoin_net_spv_request_headers(client);
}

if ((client->stateflags & SPV_FULLBLOCK_SYNC_FLAG) == SPV_FULLBLOCK_SYNC_FLAG) {
dogecoin_net_spv_request_headers(client);
}

client->last_statecheck_time = *now;
}

/**
* This function is called by the dogecoin_node_timer_callback function.
*
* It checks if the last_statecheck_time is greater than the minimum time delta for state checks.
*
* If it is, it calls the dogecoin_net_spv_periodic_statecheck function.
*
* The dogecoin_net_spv_periodic_statecheck function checks if the node is connected to the network.
*
* This function is called by the dogecoin_node_timer_callback function.
*
* It checks if the last_statecheck_time is greater than the minimum time delta for state checks.
*
* If it is, it calls the dogecoin_net_spv_periodic_statecheck function.
*
* The dogecoin_net_spv_periodic_statecheck function checks if the node is connected to the network.
*
* @param node The node that the timer is being called on.
* @param now the current time in seconds since the epoch
*
*
* @return A boolean value.
*/
static dogecoin_bool dogecoin_net_spv_node_timer_callback(dogecoin_node *node, uint64_t *now)
Expand All @@ -273,10 +280,10 @@ static dogecoin_bool dogecoin_net_spv_node_timer_callback(dogecoin_node *node, u

/**
* Fill up the blocklocators vector with the blocklocators from the headers database
*
*
* @param client the spv client
* @param blocklocators a vector of block hashes that we want to scan from
*
*
* @return The blocklocators are being returned.
*/
void dogecoin_net_spv_fill_block_locator(dogecoin_spv_client *client, vector *blocklocators) {
Expand All @@ -298,7 +305,7 @@ void dogecoin_net_spv_fill_block_locator(dogecoin_spv_client *client, vector *bl
}
}
}
if (blocklocators->len > 0) return; // return if we could fill up the blocklocator with checkpoints
if (blocklocators->len > 0) return; // return if we could fill up the blocklocator with checkpoints
}
uint256 *hash = dogecoin_calloc(1, sizeof(uint256));
memcpy_safe(hash, &client->chainparams->genesisblockhash, sizeof(uint256));
Expand All @@ -312,7 +319,7 @@ void dogecoin_net_spv_fill_block_locator(dogecoin_spv_client *client, vector *bl
/**
* This function is called when a node is in headers sync state. It will request the next block headers
* from the node
*
*
* @param node The node that is requesting headers or blocks.
* @param blocks boolean, true if we want to request blocks, false if we want to request headers
*/
Expand Down Expand Up @@ -345,9 +352,9 @@ void dogecoin_net_spv_node_request_headers_or_blocks(dogecoin_node *node, dogeco
/**
* If we have not yet reached the height of the blockchain tip, we request headers from a peer. If we
* have reached the height of the blockchain tip, we request blocks from a peer
*
*
* @param client the spv client
*
*
* @return dogecoin_bool
*/
dogecoin_bool dogecoin_net_spv_request_headers(dogecoin_spv_client *client)
Expand All @@ -368,7 +375,7 @@ dogecoin_bool dogecoin_net_spv_request_headers(dogecoin_spv_client *client)
dogecoin_node *check_node = vector_idx(client->nodegroup->nodes, i);
if (((check_node->state & NODE_CONNECTED) == NODE_CONNECTED) && check_node->version_handshake)
{
if (check_node->bestknownheight > client->headers_db->getchaintip(client->headers_db_ctx)->height) {
if (check_node->bestknownheight >= client->headers_db->getchaintip(client->headers_db_ctx)->height) {
dogecoin_net_spv_node_request_headers_or_blocks(check_node, false);
new_headers_available = true;
return new_headers_available;
Expand All @@ -385,7 +392,7 @@ dogecoin_bool dogecoin_net_spv_request_headers(dogecoin_spv_client *client)
dogecoin_node *check_node = vector_idx(client->nodegroup->nodes, i);
if (((check_node->state & NODE_CONNECTED) == NODE_CONNECTED) && check_node->version_handshake)
{
if (check_node->bestknownheight > client->headers_db->getchaintip(client->headers_db_ctx)->height) {
if (check_node->bestknownheight >= client->headers_db->getchaintip(client->headers_db_ctx)->height) {
dogecoin_net_spv_node_request_headers_or_blocks(check_node, true);
return true;
} else if (check_node->bestknownheight == client->headers_db->getchaintip(client->headers_db_ctx)->height) {
Expand All @@ -406,7 +413,7 @@ dogecoin_bool dogecoin_net_spv_request_headers(dogecoin_spv_client *client)

/**
* When the handshake is done, we request the headers
*
*
* @param node The node that just completed the handshake.
*/
void dogecoin_net_spv_node_handshake_done(dogecoin_node *node)
Expand All @@ -416,11 +423,11 @@ void dogecoin_net_spv_node_handshake_done(dogecoin_node *node)

/**
* The function is called when a new message is received from a peer
*
*
* @param node
* @param hdr
* @param buf
*
*
* @return Nothing.
*/
void dogecoin_net_spv_post_cmd(dogecoin_node *node, dogecoin_p2p_msg_hdr *hdr, struct const_buffer *buf)
Expand Down Expand Up @@ -470,28 +477,26 @@ void dogecoin_net_spv_post_cmd(dogecoin_node *node, dogecoin_p2p_msg_hdr *hdr, s
dogecoin_bool connected;
dogecoin_blockindex *pindex = client->headers_db->connect_hdr(client->headers_db_ctx, buf, false, &connected);

if (!pindex) {
return;
}

uint32_t amount_of_txs;
if (!deser_varlen(&amount_of_txs, buf)) {
return;
}

// flag off the block request stall check
node->time_last_request = time(NULL);

// for now, turn of stall checks if we are near the tip
if (pindex->header.timestamp > node->time_last_request - 30*60) {
node->time_last_request = 0;
}

if (connected) {
if (client->header_connected) { client->header_connected(client); }

// for now, turn of stall checks if we are near the tip
if (pindex->header.timestamp > node->time_last_request - 30*60) {
node->time_last_request = 0;
}

time_t lasttime = pindex->header.timestamp;
printf("Downloaded new block with size %d at height %d from %s\n", hdr->data_len, pindex->height, ctime(&lasttime));
uint64_t start = time(NULL);

uint32_t amount_of_txs;
if (!deser_varlen(&amount_of_txs, buf)) {
return;
}

client->nodegroup->log_write_cb("Start parsing %d transactions...\n", (int)amount_of_txs);

size_t consumedlength = 0;
Expand All @@ -508,6 +513,12 @@ void dogecoin_net_spv_post_cmd(dogecoin_node *node, dogecoin_p2p_msg_hdr *hdr, s
}
client->nodegroup->log_write_cb("done (took %llu secs)\n", (unsigned long long)(time(NULL) - start));
}
else
{
client->nodegroup->log_write_cb("Got invalid block (not in sequence) from node %d\n", node->nodeid);
dogecoin_net_spv_request_headers(client);
return;
}

if (dogecoin_hash_equal(node->last_requested_inv, pindex->hash)) {
// last requested block reached, consider stop syncing
Expand Down Expand Up @@ -540,12 +551,10 @@ void dogecoin_net_spv_post_cmd(dogecoin_node *node, dogecoin_p2p_msg_hdr *hdr, s
client->nodegroup->log_write_cb("Header deserialization (tx count skip) failed (node %d)\n", node->nodeid);
return;
}

if (!connected)
{
client->nodegroup->log_write_cb("Got invalid headers (not in sequence) from node %d\n", node->nodeid);
node->state &= ~NODE_HEADERSYNC;
dogecoin_node_misbehave(node);
dogecoin_net_spv_request_headers(client);
} else {
if (client->header_connected) { client->header_connected(client); }
Expand Down
Loading

0 comments on commit 455d198

Please sign in to comment.