<p>I learn bitcoin and I am trying to send a version message and get response, respectevily, by using C++. I can not find any examples or articles how to do it in C++. I'm forming request and send it by boost asio to remote bitcoin nodes, but I get no response. My request is a hex string that i convert to the binary std::vectorstd::bitset&lt;8&gt; container. Wireshark doesn't see my requests correctly or, most likely,  i do simething incorrect</p>
<pre><code>void hex2bin(string hex, vector&lt;bitset&lt;8&gt;&gt;&amp; binary_vector)
{
    for (std::size_t size = 0; size &lt; hex.size(); ++size)
        binary_vector.push_back(bitset&lt;8&gt;(hex[size]));
}

void checksum(vector &lt;bitset&lt;8&gt;&gt; payload_bytes, string&amp; checksum)
{
    string payload_str;
    for (bitset&lt;8&gt; byte : payload_bytes) payload_str += byte.to_string();

    SHA256 sha256;
    sha256.update(payload_str);
    uint8_t* digest = sha256.digest();
    sha256.update(sha256.toString(digest));
    digest = sha256.digest();
    payload_str = sha256.toString(digest);

    checksum = payload_str.substr(0, 8);
    delete[] digest;
}

vector&lt;bitset&lt;8&gt;&gt; message::get_version_message_payload(int _start_height, bool is_debug)
{
    vector&lt;std::bitset&lt;8&gt;&gt; payload_bytes;

    for (int i = 0; i &lt; _seeds_ips.size(); ++i)
    {
        // Payload fields definition

        stringstream sstream;

        // Version - 4 bytes
        int32_t version = 70015;
        sstream &lt;&lt; hex &lt;&lt; _byteswap_ulong(version);

        // Service - 8 bytes
        string service = &quot; 01 00 00 00 00 00 00 00 &quot;;
        sstream &lt;&lt; service;

        // Timestamp - 8 bytes
        int64_t timestamp = _byteswap_uint64(duration_cast&lt;seconds&gt;(system_clock::now().time_since_epoch()).count());
        sstream &lt;&lt; hex &lt;&lt; timestamp;

        // Addr_recv - 26 bytes
        string addr_service = service;

        string ip_prefix = &quot; 00 00 00 00 00 00 00 00 00 00 FF FF &quot;;
        // replace ip
        string ip = _seeds_ips[i];
        vector&lt;string&gt; ip_res;
        ip2hex(ip, ip_res);
        sstream &lt;&lt; ip_prefix;
        for (string s : ip_res) sstream &lt;&lt; hex &lt;&lt; stoi(s);
        int32_t port = 8333;
        sstream &lt;&lt; hex &lt;&lt; port;

        // Addr_from
        ip = &quot;127.0.0.1&quot;;
        vector&lt;string&gt; from_ip_res;
        ip2hex(ip, from_ip_res);
        sstream &lt;&lt; ip_prefix;
        for (string s : from_ip_res) sstream &lt;&lt; hex &lt;&lt; stoi(s);
        sstream &lt;&lt; hex &lt;&lt; port &lt;&lt; &quot; &quot;;

        // Service
        std::random_device rd;
        std::mt19937_64 n64(rd());

        uint64_t nonce = n64();
        sstream &lt;&lt; hex &lt;&lt; _byteswap_uint64(nonce) &lt;&lt; &quot; &quot;;

        // User-agent
        string user_agent = &quot; 0F 2F 53 61 74 6F 73 68 69 3A 30 2E 37 2E 32 2F &quot;;

        // Block height
        int32_t start_height = _start_height;
        sstream &lt;&lt; hex &lt;&lt; _byteswap_ulong(start_height) &lt;&lt; &quot; &quot;;

        string request_string = sstream.str();
        hex2bin(request_string, payload_bytes);

        if (is_debug)
        {
            cout &lt;&lt; &quot;Payload in hex: &quot; &lt;&lt; sstream.str() &lt;&lt; endl;
        }

        if (payload_bytes.size() &gt; 0) return payload_bytes;
    }

    return payload_bytes;
}

void message::version_message(int start_height, vector&lt;bitset&lt;8&gt;&gt;&amp; message)
{
    stringstream sstream;

    vector&lt;bitset&lt;8&gt;&gt; payload_bytes = get_version_message_payload(start_height, true);

    // Magic
    string magic = &quot;F9 BE B4 D9&quot;;
    sstream &lt;&lt; magic;

    // Version command
    string command = &quot;76 65 72 73 69 6F 6E 00 00 00 00 00 &quot;;
    sstream &lt;&lt; command;

    // Length of payload
    uint32_t length = payload_bytes.size();
    sstream &lt;&lt; hex &lt;&lt; _byteswap_ulong(length) &lt;&lt; &quot; &quot;;

    // Checksum
    string _checksum;
    checksum(payload_bytes, _checksum);
    // Maybe it will occure error. It should be little endian.
    for (char ch : _checksum) sstream &lt;&lt; hex &lt;&lt; ch;

    // Payload
    hex2bin(sstream.str(), message);

    for (bitset&lt;8&gt; byte : payload_bytes) message.push_back(byte);
    cout &lt;&lt; &quot;Version message in hex: &quot; &lt;&lt; sstream.str();
}
</code></pre>
<p><b> TCP sending </b></p>
<pre><code>int tcp_client::send_version_message()
{
    std::vector&lt;std::string&gt; ips;
    get_ips(ips);

    io_context ioc;
    ip::tcp::resolver resolver(ioc);
    ip::tcp::socket socket(ioc);
    error_code erc;

    for (int i = 0; i &lt; ips.size(); ++i)
    {
        std::cout &lt;&lt; &quot;Trying establish connection with &quot; &lt;&lt; ips[i] &lt;&lt; std::endl;
        connect(socket, resolver.resolve(ips[i], &quot;8333&quot;), erc);
        std::cout &lt;&lt; &quot;Connection status: &quot; &lt;&lt; erc.message() &lt;&lt; std::endl;
        std::cout &lt;&lt; &quot;----------------------------------------------------&quot; &lt;&lt; std::endl;
        std::cout &lt;&lt; std::endl;
        if (erc) ++i;
        else
        {
            vector&lt;bitset&lt;8&gt;&gt; version_message;
            // Feeding version_message by bytes;
            vector&lt;string&gt; ips;
            get_ips(ips);
            message msg(ips);
            msg.version_message(500000, version_message);

            cout &lt;&lt; &quot;\nBytes to send: &quot; &lt;&lt; version_message.size() &lt;&lt; &quot; bytes&quot; &lt;&lt; endl;
            if (version_message.size() &gt; 1)
            {
                socket.write_some(buffer(version_message.data(), version_message.size()), erc);
                cout &lt;&lt; &quot;Status after writing request: &quot; &lt;&lt; erc.message() &lt;&lt; endl;
                socket.wait(socket.wait_read);
                //std::cout &lt;&lt; &quot;Sending version message status: &quot; &lt;&lt; erc.message() &lt;&lt; std::endl;
                if (erc) ++i;
                else
                {
                    vector&lt;char&gt; response;
                    socket.read_some(buffer(response.data(), response.size()), erc);
                    cout &lt;&lt; &quot;Bytes reading status: &quot; &lt;&lt; erc.message() &lt;&lt; endl;
                    std::cout &lt;&lt; &quot;Response bytes number: &quot; &lt;&lt; response.size() &lt;&lt; endl;
                    for (char ch : response)
                        std::cout &lt;&lt; ch &lt;&lt; &quot; &quot;;
                }
            }
            std::cout &lt;&lt; &quot;----------------------------------------------------&quot; &lt;&lt; std::endl;
            std::cout &lt;&lt; std::endl;
        }
    }
    
    return 0;
}
</code></pre>
<p><b>Result</b></p>
<p><a href="https://i.sstatic.net/pyROu.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/pyROu.png" alt="enter image description here" /></a></p>
<p><b>My request dump</b></p>
<pre><code>&gt; Message Payload: Version: 7f 11 01 00 
&gt; Service:  01 00 00 00 00 00 00 00
&gt; Timestamp: 90 89 35 61 00 00 00 00 
&gt; Addr_recv:  01 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00 00 00 FF FF 67 ef 13 8e 208d 
&gt; Addr_from:  01 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00 00 00 FF FF d7 ef 9c d5 208d
&gt; Nonce: 5b ba 47 6c 56 c3 3a 5f 
&gt; User Agent: 10 2f 53 61 74 6f 73 68 69 3a 30 2e 32 31 2e 30 2f 
&gt; Start Height: 20 a1 07 00 
&gt; Relay: 00

&gt; Message Structure: Magic: F9 BE B4 D9 
&gt; Command: 76 65 72 73 69 6F 6E 00 00 00 00 00 
&gt; Payload Length: 13 01 00 00 
&gt; Payload Checksum: d6 0e 2e 4c
</code></pre>

CC BY-SA 4.0
2021-09-06T03:53:52.047Z
It looks like you are just sending the hex itself, not the bytes represented by the hex. I don't see where the conversion from hex to bytes occurs. The hexdump you show indicates that you are sending hex characters, not the bytes they represent.
Ava Chow
CC BY-SA 4.0
2021-09-06T04:36:53.303Z
@AndrewChow, conversion in method hex2bin. Firstly I create a string in hex format, then I make a dump of request and after that I convert my hex string to vector<bitset<8>> and send it like raw bytes. I changed image to what occurs when I send raw bytes.
recei
CC BY-SA 4.0
2021-09-06T16:04:57.847Z
Your hex2bin method is not converting hex to binary at all. It is just packing a string of characters into their corresponding ascii bytes. That is not a hex to binary conversion. Your hexdump also indicates that you are just sending the hex characters, not the bytes that those hex actually represent.
Ava Chow
CC BY-SA 4.0
2021-09-11T17:19:56.040Z
I fixed my convertion problems, but where should i store bits which i want to send? vector<char>, bitset?
recei
CC BY-SA 4.0
2021-09-11T22:00:49.763Z
Typically sequences of bytes are stored as vector<unsigned char>
Ava Chow
<network><protocol><p2p><c++><message>
Version message C++
recei
# Version message C++

(Asked by: username_0 on 2021-09-04)

I learn bitcoin and I am trying to send a version message and get response, respectevily, by using C++. I can not find any examples or articles how to do it in C++. I'm forming request and send it by boost asio to remote bitcoin nodes, but I get no response. My request is a hex string that i convert to the binary std::vectorstd::bitset<8> container. Wireshark doesn't see my requests correctly or, most likely,  i do simething incorrect
void hex2bin(string hex, vector>& binary_vector)
{
    for (std::size_t size = 0; size < hex.size(); ++size)
        binary_vector.push_back(bitset<8>(hex[size]));
}

void checksum(vector > payload_bytes, string& checksum)
{
    string payload_str;
    for (bitset<8> byte : payload_bytes) payload_str += byte.to_string();

    SHA256 sha256;
    sha256.update(payload_str);
    uint8_t* digest = sha256.digest();
    sha256.update(sha256.toString(digest));
    digest = sha256.digest();
    payload_str = sha256.toString(digest);

    checksum = payload_str.substr(0, 8);
    delete[] digest;
}

vector> message::get_version_message_payload(int _start_height, bool is_debug)
{
    vector> payload_bytes;

    for (int i = 0; i < _seeds_ips.size(); ++i)
    {
        // Payload fields definition

        stringstream sstream;

        // Version - 4 bytes
        int32_t version = 70015;
        sstream << hex << _byteswap_ulong(version);

        // Service - 8 bytes
        string service = " 01 00 00 00 00 00 00 00 ";
        sstream << service;

        // Timestamp - 8 bytes
        int64_t timestamp = _byteswap_uint64(duration_cast(system_clock::now().time_since_epoch()).count());
        sstream << hex << timestamp;

        // Addr_recv - 26 bytes
        string addr_service = service;

        string ip_prefix = " 00 00 00 00 00 00 00 00 00 00 FF FF ";
        // replace ip
        string ip = _seeds_ips[i];
        vector ip_res;
        ip2hex(ip, ip_res);
        sstream << ip_prefix;
        for (string s : ip_res) sstream << hex << stoi(s);
        int32_t port = 8333;
        sstream << hex << port;

        // Addr_from
        ip = "127.0.0.1";
        vector from_ip_res;
        ip2hex(ip, from_ip_res);
        sstream << ip_prefix;
        for (string s : from_ip_res) sstream << hex << stoi(s);
        sstream << hex << port << " ";

        // Service
        std::random_device rd;
        std::mt19937_64 n64(rd());

        uint64_t nonce = n64();
        sstream << hex << _byteswap_uint64(nonce) << " ";

        // User-agent
        string user_agent = " 0F 2F 53 61 74 6F 73 68 69 3A 30 2E 37 2E 32 2F ";

        // Block height
        int32_t start_height = _start_height;
        sstream << hex << _byteswap_ulong(start_height) << " ";

        string request_string = sstream.str();
        hex2bin(request_string, payload_bytes);

        if (is_debug)
        {
            cout << "Payload in hex: " << sstream.str() << endl;
        }

        if (payload_bytes.size() > 0) return payload_bytes;
    }

    return payload_bytes;
}

void message::version_message(int start_height, vector>& message)
{
    stringstream sstream;

    vector> payload_bytes = get_version_message_payload(start_height, true);

    // Magic
    string magic = "F9 BE B4 D9";
    sstream << magic;

    // Version command
    string command = "76 65 72 73 69 6F 6E 00 00 00 00 00 ";
    sstream << command;

    // Length of payload
    uint32_t length = payload_bytes.size();
    sstream << hex << _byteswap_ulong(length) << " ";

    // Checksum
    string _checksum;
    checksum(payload_bytes, _checksum);
    // Maybe it will occure error. It should be little endian.
    for (char ch : _checksum) sstream << hex << ch;

    // Payload
    hex2bin(sstream.str(), message);

    for (bitset<8> byte : payload_bytes) message.push_back(byte);
    cout << "Version message in hex: " << sstream.str();
}

 TCP sending 
int tcp_client::send_version_message()
{
    std::vector ips;
    get_ips(ips);

    io_context ioc;
    ip::tcp::resolver resolver(ioc);
    ip::tcp::socket socket(ioc);
    error_code erc;

    for (int i = 0; i < ips.size(); ++i)
    {
        std::cout << "Trying establish connection with " << ips[i] << std::endl;
        connect(socket, resolver.resolve(ips[i], "8333"), erc);
        std::cout << "Connection status: " << erc.message() << std::endl;
        std::cout << "----------------------------------------------------" << std::endl;
        std::cout << std::endl;
        if (erc) ++i;
        else
        {
            vector> version_message;
            // Feeding version_message by bytes;
            vector ips;
            get_ips(ips);
            message msg(ips);
            msg.version_message(500000, version_message);

            cout << "\nBytes to send: " << version_message.size() << " bytes" << endl;
            if (version_message.size() > 1)
            {
                socket.write_some(buffer(version_message.data(), version_message.size()), erc);
                cout << "Status after writing request: " << erc.message() << endl;
                socket.wait(socket.wait_read);
                //std::cout << "Sending version message status: " << erc.message() << std::endl;
                if (erc) ++i;
                else
                {
                    vector response;
                    socket.read_some(buffer(response.data(), response.size()), erc);
                    cout << "Bytes reading status: " << erc.message() << endl;
                    std::cout << "Response bytes number: " << response.size() << endl;
                    for (char ch : response)
                        std::cout << ch << " ";
                }
            }
            std::cout << "----------------------------------------------------" << std::endl;
            std::cout << std::endl;
        }
    }
    
    return 0;
}

Result

My request dump
> Message Payload: Version: 7f 11 01 00 
> Service:  01 00 00 00 00 00 00 00
> Timestamp: 90 89 35 61 00 00 00 00 
> Addr_recv:  01 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00 00 00 FF FF 67 ef 13 8e 208d 
> Addr_from:  01 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00 00 00 FF FF d7 ef 9c d5 208d
> Nonce: 5b ba 47 6c 56 c3 3a 5f 
> User Agent: 10 2f 53 61 74 6f 73 68 69 3a 30 2e 32 31 2e 30 2f 
> Start Height: 20 a1 07 00 
> Relay: 00

> Message Structure: Magic: F9 BE B4 D9 
> Command: 76 65 72 73 69 6F 6E 00 00 00 00 00 
> Payload Length: 13 01 00 00 
> Payload Checksum: d6 0e 2e 4c

**Tags:** network, protocol, p2p, c++, message

> **Comments:**
> **username_1**: It looks like you are just sending the hex itself, not the bytes represented by the hex. I don't see where the conversion from hex to bytes occurs. The hexdump you show indicates that you are sending hex characters, not the bytes they represent.  
> **username_0**: @AndrewChow, conversion in method hex2bin. Firstly I create a string in hex format, then I make a dump of request and after that I convert my hex string to vector<bitset<8>> and send it like raw bytes. I changed image to what occurs when I send raw bytes.  
> **username_1**: Your hex2bin method is not converting hex to binary at all. It is just packing a string of characters into their corresponding ascii bytes. That is not a hex to binary conversion. Your hexdump also indicates that you are just sending the hex characters, not the bytes that those hex actually represent.  
> **username_0**: I fixed my convertion problems, but where should i store bits which i want to send? vector<char>, bitset?  
> **username_1**: Typically sequences of bytes are stored as vector<unsigned char>  

---

## 0 answers

