int network_manager_claim_invs(struct network_manager* nm, struct network_peer* peer, struct inv const* invs, size_t num_invs) { // Only returns 0 (success) if all invs can be claimed int all_good = 1; for(size_t i = 0; i < num_invs; i++) { Word_t* pindex = NULL; JHSG(pindex, nm->claimed_invs, (uint8_t*)(&invs[i]), sizeof(struct inv)); if(pindex != NULL) { // This inv is claimed already all_good = 0; break; } } if(all_good == 0) return -1; // Mark all invs as claimed for(size_t i = 0; i < num_invs; i++) { Word_t* pindex = NULL; JHSI(pindex, nm->claimed_invs, (uint8_t*)(&invs[i]), sizeof(struct inv)); assert(pindex != NULL); *pindex = 1; } return 0; }
static int start_peer(struct network_manager* nm) { // Randomly pick an address to connect to struct network_address address; int have_address = 0; for(int i = 0; i < 50; i++) { if(database_get_random_peer_address(chaind_database(nm->chaind), &address) <= 0) { // Error, or no address to select break; } // Apply default port if sin_port == 0 if(address.sin_port == 0) address.sin_port = htons(NETWORK_DEFAULT_PORT); if(network_manager_get_peer_by_address(nm, &address) == NULL) { have_address = 1; break; } } if(!have_address) return -1; struct network_peer* peer = network_peer_create(nm); struct network_peer** ppeer = NULL; Word_t peer_id = nm->next_peer_id; JLI(ppeer, nm->peer_list, peer_id); *ppeer = peer; nm->next_peer_id += 1; Word_t* pindex; JHSI(pindex, nm->peer_by_address, (uint8_t*)&address, sizeof(struct network_address)); *pindex = peer_id; int res = network_peer_connect(peer, &address, blockchain_link_height(chaind_best_blockchain_link(nm->chaind))); if(res != 0) { int rc; JLD(rc, nm->peer_list, peer_id); JHSD(rc, nm->peer_by_address, (uint8_t*)&address, sizeof(struct network_address)); network_peer_destroy(peer); return res; } nm->num_peers += 1; return 0; }
static inline void insert_state(store_t *store, fcs_cache_key_t *key) { Word_t *PValue; JHSI(PValue, *store, &(key->s), sizeof(key->s)); *PValue = 1; }
static void GCC_INLINE fc_solve_cache_stacks( fc_solve_hard_thread_t * hard_thread, fcs_state_t * new_state_key, fcs_state_extra_info_t * new_state_val ) { int a; #if (FCS_STACK_STORAGE == FCS_STACK_STORAGE_INTERNAL_HASH) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE SFO_hash_value_t hash_value_int; #endif #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_JUDY) PWord_t * PValue; #endif void * cached_stack; char * new_ptr; fc_solve_instance_t * instance = hard_thread->instance; #ifndef HARD_CODED_NUM_STACKS int stacks_num = instance->stacks_num; #endif fcs_cards_column_t column; register int col_len; for(a=0 ; a < LOCAL_STACKS_NUM ; a++) { /* * If the stack is not a copy - it is already cached so skip * to the next stack * */ if (! (new_state_val->stacks_copy_on_write_flags & (1 << a))) { continue; } /* new_state_key->stacks[a] = realloc(new_state_key->stacks[a], fcs_stack_len(new_state_key, a)+1); */ column = fcs_state_get_col(*new_state_key, a); col_len = (fcs_col_len(column)+1); fcs_compact_alloc_typed_ptr_into_var(new_ptr, char, hard_thread->stacks_allocator, col_len); memcpy(new_ptr, column, col_len); new_state_key->stacks[a] = new_ptr; #if FCS_STACK_STORAGE == FCS_STACK_STORAGE_INTERNAL_HASH #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE /* Calculate the hash value for the stack */ /* This hash function was ripped from the Perl source code. * (It is not derived work however). */ { const char * s_ptr = (char*)(new_state_key->stacks[a]); const char * s_end = s_ptr+fcs_stack_len(*new_state_key, a)+1; hash_value_int = 0; while (s_ptr < s_end) { hash_value_int += (hash_value_int << 5) + *(s_ptr++); } hash_value_int += (hash_value_int >> 5); } if (hash_value_int < 0) { /* * This is a bit mask that nullifies the sign bit of the * number so it will always be positive * */ hash_value_int &= (~(1<<((sizeof(hash_value_int)<<3)-1))); } #endif { void * dummy; int verdict; column = fcs_state_get_col(*new_state_key, a); verdict = fc_solve_hash_insert( instance->stacks_hash, column, column, &cached_stack, &dummy, perl_hash_function( (ub1 *)new_state_key->stacks[a], col_len ) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE , hash_value_int #endif ); replace_with_cached(verdict); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_AVL_TREE) || (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_REDBLACK_TREE) #if (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_AVL_TREE) #define LIBAVL_INSERT(x,y) avl_insert(x,y) #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_REDBLACK_TREE) #define LIBAVL_INSERT(x,y) rb_insert(x,y) #else #error unknown FCS_STACK_STORAGE #endif cached_stack = LIBAVL_INSERT( instance->stacks_tree, new_state_key->stacks[a] ); #undef LIBAVL_INSERT replace_with_cached(cached_stack != NULL); #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBREDBLACK_TREE) cached_stack = (void *)rbsearch( new_state_key->stacks[a], instance->stacks_tree ); replace_with_cached(cached_stack != new_state_key->stacks[a]); #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GLIB_TREE) cached_stack = g_tree_lookup( instance->stacks_tree, (gpointer)new_state_key->stacks[a] ); /* replace_with_cached contains an if statement */ replace_with_cached(cached_stack != NULL) else { g_tree_insert( instance->stacks_tree, (gpointer)new_state_key->stacks[a], (gpointer)new_state_key->stacks[a] ); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GLIB_HASH) cached_stack = g_hash_table_lookup( instance->stacks_hash, (gconstpointer)new_state_key->stacks[a] ); replace_with_cached(cached_stack != NULL) else { g_hash_table_insert( instance->stacks_hash, (gpointer)new_state_key->stacks[a], (gpointer)new_state_key->stacks[a] ); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_JUDY) JHSI( PValue, instance->stacks_judy_array, new_state_key->stacks[a], (fcs_stack_len(*new_state_key, a)+1) ); /* TODO : Handle out-of-memory. */ if (*PValue == 0) { /* A new stack */ *PValue = (PWord_t)new_state_key->stacks[a]; } else { cached_stack = (void *)(*PValue); replace_with_cached(1); } #else #error FCS_STACK_STORAGE is not set to a good value. #endif } }
GCC_INLINE int fc_solve_check_and_add_state( fc_solve_soft_thread_t * soft_thread, fcs_state_extra_info_t * new_state_val, fcs_state_extra_info_t * * existing_state_val ) { #if (FCS_STATE_STORAGE == FCS_STATE_STORAGE_INTERNAL_HASH) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE SFO_hash_value_t hash_value_int; #endif #endif #if (FCS_STATE_STORAGE == FCS_STATE_STORAGE_INDIRECT) fcs_standalone_state_ptrs_t * pos_ptr; int found; #endif fc_solve_hard_thread_t * hard_thread = soft_thread->hard_thread; fc_solve_instance_t * instance = hard_thread->instance; fcs_state_t * new_state_key = new_state_val->key; int is_state_new; if (check_if_limits_exceeded()) { return FCS_STATE_BEGIN_SUSPEND_PROCESS; } fc_solve_cache_stacks(hard_thread, new_state_key, new_state_val); fc_solve_canonize_state(new_state_val, INSTANCE_FREECELLS_NUM, INSTANCE_STACKS_NUM ); /* The objective of this part of the code is: 1. To check if new_state_key / new_state_val is already in the prev_states collection. 2. If not, to add it and to set check to true. 3. If so, to set check to false. */ #if (FCS_STATE_STORAGE == FCS_STATE_STORAGE_INTERNAL_HASH) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE { const char * s_ptr = (char*)new_state_key; const char * s_end = s_ptr+sizeof(*new_state_key); hash_value_int = 0; while (s_ptr < s_end) { hash_value_int += (hash_value_int << 5) + *(s_ptr++); } hash_value_int += (hash_value_int>>5); } if (hash_value_int < 0) { /* * This is a bit mask that nullifies the sign bit of the * number so it will always be positive * */ hash_value_int &= (~(1<<((sizeof(hash_value_int)<<3)-1))); } #endif { void * existing_key_void, * existing_val_void; is_state_new = (fc_solve_hash_insert( instance->hash, new_state_key, new_state_val, &existing_key_void, &existing_val_void, perl_hash_function( (ub1 *)new_state_key, sizeof(*new_state_key) ) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE , hash_value_int #endif ) == 0); if (! is_state_new) { *existing_state_val = existing_val_void; } } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_INDIRECT) /* Try to see if the state is found in indirect_prev_states */ if ((pos_ptr = (fcs_standalone_state_ptrs_t *)bsearch(&new_state_key, instance->indirect_prev_states, instance->num_indirect_prev_states, sizeof(instance->indirect_prev_states[0]), fc_solve_state_compare_indirect)) == NULL) { /* It isn't in prev_states, but maybe it's in the sort margin */ pos_ptr = (fcs_standalone_state_ptrs_t *)fc_solve_bsearch( &new_state_key, instance->indirect_prev_states_margin, instance->num_prev_states_margin, sizeof(instance->indirect_prev_states_margin[0]), fc_solve_state_compare_indirect_with_context, NULL, &found); if (found) { is_state_new = 0; *existing_state_val = pos_ptr->val; } else { /* Insert the state into its corresponding place in the sort * margin */ memmove((void*)(pos_ptr+1), (void*)pos_ptr, sizeof(*pos_ptr) * (instance->num_prev_states_margin- (pos_ptr-instance->indirect_prev_states_margin) )); pos_ptr->key = new_state_key; pos_ptr->val = new_state_val; instance->num_prev_states_margin++; if (instance->num_prev_states_margin >= PREV_STATES_SORT_MARGIN) { /* The sort margin is full, let's combine it with the main array */ instance->indirect_prev_states = realloc( instance->indirect_prev_states, sizeof(instance->indirect_prev_states[0]) * (instance->num_indirect_prev_states + instance->num_prev_states_margin ) ); fc_solve_merge_large_and_small_sorted_arrays( instance->indirect_prev_states, instance->num_indirect_prev_states, instance->indirect_prev_states_margin, instance->num_prev_states_margin, sizeof(instance->indirect_prev_states[0]), fc_solve_state_compare_indirect_with_context, NULL ); instance->num_indirect_prev_states += instance->num_prev_states_margin; instance->num_prev_states_margin=0; } is_state_new = 1; } } else { *existing_state_val = pos_ptr->val; is_state_new = 0; } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_LIBREDBLACK_TREE) *existing_state_val = (fcs_state_extra_info_t *)rbsearch(new_state_val, instance->tree ); is_state_new = ((*existing_state_val) == new_state_val); #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_LIBAVL_AVL_TREE) || (FCS_STATE_STORAGE == FCS_STATE_STORAGE_LIBAVL_REDBLACK_TREE) #if (FCS_STATE_STORAGE == FCS_STATE_STORAGE_LIBAVL_AVL_TREE) #define fcs_libavl_states_tree_insert(a,b) avl_insert((a),(b)) #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_LIBAVL_REDBLACK_TREE) #define fcs_libavl_states_tree_insert(a,b) rb_insert((a),(b)) #endif *existing_state = fcs_libavl_states_tree_insert(instance->tree, new_state); is_state_new = (*existing_state == NULL); #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_GLIB_TREE) *existing_state = g_tree_lookup(instance->tree, (gpointer)new_state); if (*existing_state == NULL) { /* The new state was not found. Let's insert it. * The value must be the same as the key, so g_tree_lookup() * will return it. */ g_tree_insert( instance->tree, (gpointer)new_state, (gpointer)new_state ); is_state_new = 1; } else { is_state_new = 0; } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_GLIB_HASH) *existing_state = g_hash_table_lookup(instance->hash, (gpointer)new_state); if (*existing_state == NULL) { /* The new state was not found. Let's insert it. * The value must be the same as the key, so g_tree_lookup() * will return it. */ g_hash_table_insert( instance->hash, (gpointer)new_state, (gpointer)new_state ); is_state_new = 1; } else { is_state_new = 0; } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_DB_FILE) { DBT key, value; key.data = new_state; key.size = sizeof(*new_state); if (instance->db->get( instance->db, NULL, &key, &value, 0 ) == 0) { /* The new state was not found. Let's insert it. * The value must be the same as the key, so g_tree_lookup() * will return it. */ value.data = key.data; value.size = key.size; instance->db->put( instance->db, NULL, &key, &value, 0); is_state_new = 1; } else { is_state_new = 0; *existing_state = (fcs_state_with_locations_t *)(value.data); } } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_JUDY) { PWord_t * PValue; JHSI(PValue, instance->judy_array, new_state_key, sizeof(*new_state_key)); /* TODO : Handle out-of-memory. */ if (*PValue == 0) { /* A new state. */ is_state_new = 1; *PValue = (PWord_t)(*existing_state_val = new_state_val); } else { /* Already exists. */ is_state_new = 0; *existing_state_val = (fcs_state_extra_info_t *)(*PValue); } } #else #error no define #endif if (is_state_new) { /* The new state was not found in the cache, and it was already inserted */ if (new_state_val->parent_val) { new_state_val->parent_val->num_active_children++; } instance->num_states_in_collection++; if (new_state_val->moves_to_parent != NULL) { new_state_val->moves_to_parent = fc_solve_move_stack_compact_allocate( hard_thread, new_state_val->moves_to_parent ); } return FCS_STATE_DOES_NOT_EXIST; } else { return FCS_STATE_ALREADY_EXISTS; } }
void network_manager_handle_inv(struct network_manager* nm, struct network_peer* peer, struct inv const* inv) { // Determine if we know about this item and if so, ignore it bytes_to_hexstring(inv->hash, INV_HASH_SIZE, s, 1); printf("got inv %s %s", inv->type == INV_TYPE_TX ? "tx" : "block", s); // Check if it's in mempool struct memory_pool* memory_pool = chaind_memory_pool(nm->chaind); if(memory_pool_has_inv(memory_pool, inv)) { printf(" (mempool)\n"); return; } // Check the list of invs we care about. We include the inv->type field // in the index in case a block and tx have the same hash, despite it // being astronomically unlikely. Word_t* pindex = NULL; JHSG(pindex, nm->wanted_invs_by_inv, (uint8_t*)inv, sizeof(struct inv)); if(pindex != NULL) { printf(" (invpool)\n"); return; } // Check if it's in the database struct database* database = chaind_database(nm->chaind); if(database_has_inv(database, inv) != 0) { printf(" (db)\n"); return; } // We don't know this inv, so we take note in the appropriate list struct inv* ninv = (struct inv*)malloc(sizeof(struct inv)); memcpy(ninv, inv, sizeof(struct inv)); // Add to the list of items we need to get Word_t index = 0; struct inv** pinv = NULL; switch(inv->type) { case INV_TYPE_BLOCK: index = nm->head_block_inv_id; JLI(pinv, nm->block_inv_list, index); assert(pinv != NULL); *pinv = ninv; nm->head_block_inv_id += 1; break; case INV_TYPE_TX: index = nm->head_tx_inv_id; JLI(pinv, nm->tx_inv_list, index); assert(pinv != NULL); *pinv = ninv; nm->head_tx_inv_id += 1; break; case INV_TYPE_ERROR: // TODO break; } if(inv->type != INV_TYPE_ERROR) { JHSI(pindex, nm->wanted_invs_by_inv, (uint8_t*)inv, sizeof(struct inv)); assert(pindex != NULL); *pindex = index; } printf("\n"); }