Esempio n. 1
0
File: tx.c Progetto: afk11/libbtc
void btc_tx_serialize(cstring* s, const btc_tx* tx)
{
    ser_s32(s, tx->version);

    ser_varlen(s, tx->vin ? tx->vin->len : 0);

    unsigned int i;
    if (tx->vin) {
        for (i = 0; i < tx->vin->len; i++) {
            btc_tx_in* tx_in;

            tx_in = vector_idx(tx->vin, i);
            btc_tx_in_serialize(s, tx_in);
        }
    }

    ser_varlen(s, tx->vout ? tx->vout->len : 0);

    if (tx->vout) {
        for (i = 0; i < tx->vout->len; i++) {
            btc_tx_out* tx_out;

            tx_out = vector_idx(tx->vout, i);
            btc_tx_out_serialize(s, tx_out);
        }
    }

    ser_u32(s, tx->locktime);
}
Esempio n. 2
0
File: tx.c Progetto: afk11/libbtc
void btc_tx_copy(btc_tx* dest, const btc_tx* src)
{
    dest->version = src->version;
    dest->locktime = src->locktime;

    if (!src->vin)
        dest->vin = NULL;
    else {
        unsigned int i;

        if (dest->vin)
            vector_free(dest->vin, true);

        dest->vin = vector_new(src->vin->len, btc_tx_in_free_cb);

        for (i = 0; i < src->vin->len; i++) {
            btc_tx_in *tx_in_old, *tx_in_new;

            tx_in_old = vector_idx(src->vin, i);
            tx_in_new = malloc(sizeof(*tx_in_new));
            btc_tx_in_copy(tx_in_new, tx_in_old);
            vector_add(dest->vin, tx_in_new);
        }
    }

    if (!src->vout)
        dest->vout = NULL;
    else {
        unsigned int i;

        if (dest->vout)
            vector_free(dest->vout, true);

        dest->vout = vector_new(src->vout->len,
                                btc_tx_out_free_cb);

        for (i = 0; i < src->vout->len; i++) {
            btc_tx_out *tx_out_old, *tx_out_new;

            tx_out_old = vector_idx(src->vout, i);
            tx_out_new = malloc(sizeof(*tx_out_new));
            btc_tx_out_copy(tx_out_new, tx_out_old);
            vector_add(dest->vout, tx_out_new);
        }
    }
}
Esempio n. 3
0
File: net.c Progetto: libbtc/libbtc
int btc_node_group_amount_of_connected_nodes(btc_node_group *group)
{
    int cnt=0;
    for (size_t i = 0; i < group->nodes->len; i++)
    {
        btc_node *node = vector_idx(group->nodes, i);
        if ((node->state & NODE_CONNECTED) == NODE_CONNECTED)
            cnt++;
    }
    return cnt;
}
Esempio n. 4
0
File: tx.c Progetto: afk11/libbtc
btc_bool btc_tx_is_coinbase(btc_tx* tx)
{
    if (tx->vin->len == 1)
    {
        btc_tx_in *vin = vector_idx(tx->vin, 0);

        if (btc_hash_is_empty(vin->prevout.hash) && vin->prevout.n == UINT32_MAX)
            return true;
    }
    return false;
}
Esempio n. 5
0
File: net.c Progetto: libbtc/libbtc
btc_bool btc_node_group_connect_next_nodes(btc_node_group *group)
{
    btc_bool connected_at_least_to_one_node = false;
    int connect_amount = group->desired_amount_connected_nodes - btc_node_group_amount_of_connected_nodes(group);
    if (connect_amount <= 0)
        return true;

    /* search for a potential node that has not errored and is not connected or in connecting state */
    for (size_t i = 0; i < group->nodes->len; i++)
    {
        btc_node *node = vector_idx(group->nodes, i);
        if (
            !((node->state & NODE_CONNECTED) == NODE_CONNECTED)
            &&
            !((node->state & NODE_CONNECTING) == NODE_CONNECTING)
            &&
            !((node->state & NODE_ERRORED) == NODE_ERRORED)
        )
        {
            /* setup buffer event */
            node->event_bev = bufferevent_socket_new(group->event_base, -1, BEV_OPT_CLOSE_ON_FREE);
            bufferevent_setcb(node->event_bev, read_cb, write_cb, event_cb, node);
            bufferevent_enable(node->event_bev, EV_READ|EV_WRITE);
            if (bufferevent_socket_connect(node->event_bev, (struct sockaddr *)&node->addr, sizeof(node->addr)) < 0)
            {
                /* Error starting connection */
                if (node->event_bev)
                    bufferevent_free(node->event_bev);
                return false;
            }

            /* setup periodic timer */
            node->time_started_con = time(NULL);
            struct timeval tv;
            tv.tv_sec = BTC_PERIODICAL_NODE_TIMER_S;
            tv.tv_usec = 0;
            node->timer_event = event_new(group->event_base, 0, EV_TIMEOUT|EV_PERSIST, node_periodical_timer,
                                          (void*)node);
            event_add(node->timer_event, &tv);
            node->state |= NODE_CONNECTING;
            connected_at_least_to_one_node = true;
            connect_amount--;
            if (connect_amount <= 0)
                return true;
        }
    }
    /* node group misses a node to connect to */
    return connected_at_least_to_one_node;
}
Esempio n. 6
0
void test_protocol()
{
    /* get new string buffer */
    cstring *version_msg_cstr = cstr_new_sz(256);
    cstring *inv_msg_cstr = cstr_new_sz(256);

    struct sockaddr_in test_sa, test_sa_check;
    memset(&test_sa, 0, sizeof(test_sa));
    memset(&test_sa_check, 0, sizeof(test_sa_check));
    test_sa.sin_family = AF_INET;
    struct sockaddr_in6 test_sa6, test_sa6_check;
    test_sa6.sin6_family = AF_INET6;
    test_sa6.sin6_port = htons(1024);
    evutil_inet_pton(AF_INET, "10.0.0.1", &test_sa.sin_addr); // store IP in antelope

    char i6buf[1024];
    memset(&i6buf, 0, 1024);

    evutil_inet_pton(AF_INET6, "::1", &test_sa6.sin6_addr);
    btc_p2p_address ipv6Test;
    btc_p2p_address_init(&ipv6Test);
    btc_addr_to_p2paddr((struct sockaddr *)&test_sa6, &ipv6Test);
    btc_p2paddr_to_addr(&ipv6Test, (struct sockaddr *)&test_sa6_check);
    memset(&i6buf, 0, 1024);
    u_assert_int_eq(test_sa6.sin6_port, test_sa6_check.sin6_port);

    /* copy socket_addr to p2p addr */
    btc_p2p_address fromAddr;
    btc_p2p_address_init(&fromAddr);
    btc_p2p_address toAddr;
    btc_p2p_address_init(&toAddr);
    btc_addr_to_p2paddr((struct sockaddr *)&test_sa, &toAddr);
    btc_p2paddr_to_addr(&toAddr, (struct sockaddr *)&test_sa_check);
    u_assert_int_eq(test_sa.sin_port, test_sa_check.sin_port);
    evutil_inet_ntop(AF_INET, &test_sa_check.sin_addr, i6buf, 1024);
    u_assert_str_eq(i6buf, "10.0.0.1");

    /* create a inv message struct */
    btc_p2p_inv_msg inv_msg, inv_msg_check;
    memset(&inv_msg, 0, sizeof(inv_msg));

    uint256 hash = {0};

    btc_p2p_msg_inv_init(&inv_msg, 1, hash);
    btc_p2p_msg_inv_ser(&inv_msg, inv_msg_cstr);

    struct const_buffer buf_inv = {inv_msg_cstr->str, inv_msg_cstr->len};
    u_assert_int_eq(btc_p2p_msg_inv_deser(&inv_msg_check, &buf_inv), true);
    u_assert_int_eq(inv_msg_check.type, 1);
    u_assert_mem_eq(inv_msg_check.hash, inv_msg.hash, sizeof(inv_msg.hash));
    cstr_free(inv_msg_cstr, true);

    /* create a version message struct */
    btc_p2p_version_msg version_msg;
    memset(&version_msg, 0, sizeof(version_msg));

    /* create a serialized version message */
    btc_p2p_msg_version_init(&version_msg, &fromAddr, &toAddr, "client", false);
    btc_p2p_msg_version_ser(&version_msg, version_msg_cstr);

    /* create p2p message */
    cstring *p2p_msg = btc_p2p_message_new((unsigned const char *)&btc_chainparams_main.netmagic, BTC_MSG_VERSION, version_msg_cstr->str, version_msg_cstr->len);

    struct const_buffer buf = {p2p_msg->str, p2p_msg->len};
    btc_p2p_msg_hdr hdr;
    btc_p2p_deser_msghdr(&hdr, &buf);

    u_assert_mem_eq(hdr.netmagic, &btc_chainparams_main.netmagic, 4);
    u_assert_str_eq(hdr.command, BTC_MSG_VERSION);
    u_assert_int_eq(hdr.data_len, version_msg_cstr->len);
    u_assert_int_eq(buf.len, hdr.data_len);
    u_assert_int_eq(buf.len, hdr.data_len);
    u_assert_mem_eq(buf.p, version_msg_cstr->str, hdr.data_len);

    btc_p2p_version_msg v_msg_check;
    u_assert_int_eq(btc_p2p_msg_version_deser(&v_msg_check, &buf), true);

    u_assert_int_eq(v_msg_check.version, BTC_PROTOCOL_VERSION);
    u_assert_str_eq(v_msg_check.useragent, "client");
    u_assert_int_eq(v_msg_check.start_height, 0);

    cstr_free(p2p_msg, true);
    cstr_free(version_msg_cstr, true);

    /* getheaders */
    uint256 genesis_hash = {0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xd6, 0x68, 0x9c, 0x08, 0x5a, 0xe1, 0x65, 0x83, 0x1e, 0x93, 0x4f, 0xf7, 0x63, 0xae, 0x46, 0xa2, 0xa6, 0xc1, 0x72, 0xb3, 0xf1, 0xb6, 0x0a, 0x8c, 0xe2, 0x6f};
    vector *blocklocators = vector_new(1, NULL);
    vector_add(blocklocators, genesis_hash);
    cstring *getheader_msg = cstr_new_sz(256);
    btc_p2p_msg_getheaders(blocklocators, NULL, getheader_msg);
    p2p_msg = btc_p2p_message_new((unsigned const char *)&btc_chainparams_main.netmagic, BTC_MSG_GETHEADERS, getheader_msg->str, getheader_msg->len);


    buf.p = p2p_msg->str;
    buf.len = p2p_msg->len;
    btc_p2p_deser_msghdr(&hdr, &buf);
    u_assert_str_eq(hdr.command, BTC_MSG_GETHEADERS);
    u_assert_int_eq(hdr.data_len, getheader_msg->len);


    uint256 hashstop_check;
    vector *blocklocators_check = vector_new(1, free);
    btc_p2p_deser_msg_getheaders(blocklocators_check, hashstop_check, &buf);
    u_assert_mem_eq(NULLHASH, hashstop_check, sizeof(hashstop_check));
    uint8_t *hash_loc_0 = vector_idx(blocklocators_check, 0);
    u_assert_mem_eq(genesis_hash, hash_loc_0, sizeof(genesis_hash));


    /* cleanup */
    cstr_free(getheader_msg, true);
    vector_free(blocklocators, true);
    vector_free(blocklocators_check, true);
    cstr_free(p2p_msg, true);
}
Esempio n. 7
0
File: tx.c Progetto: afk11/libbtc
btc_bool btc_tx_sighash(const btc_tx* tx_to, const cstring* fromPubKey, unsigned int in_num, int hashtype, uint8_t* hash)
{
    if (in_num >= tx_to->vin->len)
        return false;

    btc_bool ret = true;

    btc_tx* tx_tmp = btc_tx_new();
    btc_tx_copy(tx_tmp, tx_to);

    cstring* new_script = cstr_new_sz(fromPubKey->len);
    btc_script_copy_without_op_codeseperator(fromPubKey, new_script);

    unsigned int i;
    btc_tx_in* tx_in;
    for (i = 0; i < tx_tmp->vin->len; i++) {
        tx_in = vector_idx(tx_tmp->vin, i);
        cstr_resize(tx_in->script_sig, 0);

        if (i == in_num)
            cstr_append_buf(tx_in->script_sig,
                            new_script->str,
                            new_script->len);
    }
    cstr_free(new_script, true);
    /* Blank out some of the outputs */
    if ((hashtype & 0x1f) == SIGHASH_NONE) {
        /* Wildcard payee */
        if (tx_tmp->vout)
            vector_free(tx_tmp->vout, true);

        tx_tmp->vout = vector_new(1, btc_tx_out_free_cb);

        /* Let the others update at will */
        for (i = 0; i < tx_tmp->vin->len; i++) {
            tx_in = vector_idx(tx_tmp->vin, i);
            if (i != in_num)
                tx_in->sequence = 0;
        }
    }

    else if ((hashtype & 0x1f) == SIGHASH_SINGLE) {
        /* Only lock-in the txout payee at same index as txin */
        unsigned int n_out = in_num;
        if (n_out >= tx_tmp->vout->len) {
            //TODO: set error code
            ret = false;
            goto out;
        }

        vector_resize(tx_tmp->vout, n_out + 1);

        for (i = 0; i < n_out; i++) {
            btc_tx_out* tx_out;

            tx_out = vector_idx(tx_tmp->vout, i);
            tx_out->value = -1;
            if (tx_out->script_pubkey) {
                cstr_free(tx_out->script_pubkey, true);
                tx_out->script_pubkey = NULL;
            }
        }

        /* Let the others update at will */
        for (i = 0; i < tx_tmp->vin->len; i++) {
            tx_in = vector_idx(tx_tmp->vin, i);
            if (i != in_num)
                tx_in->sequence = 0;
        }
    }

    /* Blank out other inputs completely;
     not recommended for open transactions */
    if (hashtype & SIGHASH_ANYONECANPAY) {
        if (in_num > 0)
            vector_remove_range(tx_tmp->vin, 0, in_num);
        vector_resize(tx_tmp->vin, 1);
    }

    cstring* s = cstr_new_sz(512);
    btc_tx_serialize(s, tx_tmp);
    ser_s32(s, hashtype);

    sha256_Raw((const uint8_t*)s->str, s->len, hash);
    sha256_Raw(hash, 32, hash);

    cstr_free(s, true);

out:
    btc_tx_free(tx_tmp);

    return ret;
}