예제 #1
0
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;
}
예제 #2
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;
}
예제 #3
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;
}
예제 #4
0
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
    }
}
예제 #5
0
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;
    }
}
예제 #6
0
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");
}