Proof-of-concept tool performing bitcoin protocol handshake with a set of nodes, according to the protocol documentation.
It consists of two parts:
- Library, defining Bitcoin protocol messages' data structures.
- Binary, built with tokio-rs, that handles all the IO with remote node(s).
You need to provide the address of a Bitcoin's DNS seed.
Usage: bitcoin-handshake [OPTIONS] <DNS_SEED>
Arguments:
<DNS_SEED> Bitcoin DNS seed to connect to
Options:
-p, --port <PORT> TCP port to connect to [default: 8333]
-t, --timeout <TIMEOUT> Handshake timeout, in seconds [default: 10]
-h, --help Print help information
-V, --version Print version information
For example:
cargo run -- seed.bitcoin.sipa.be
This will give you output similiar to following one:
2022-11-17T22:46:55.331282Z INFO bitcoin_handshake: Resolving DNS seed `seed.bitcoin.sipa.be`
2022-11-17T22:46:55.334820Z INFO bitcoin_handshake: Resolved 25 addreses. Starting handshakes...
2022-11-17T22:46:55.410754Z ERROR handshake{target=13.48.127.4:8333}: bitcoin_handshake: handshake attempt failed with: IO Error during (de)serialization: failed to fill whole buffer
2022-11-17T22:46:55.417025Z ERROR handshake{target=176.9.84.209:8333}: bitcoin_handshake: handshake attempt failed with: IO Error during (de)serialization: failed to fill whole buffer
2022-11-17T22:46:55.442688Z ERROR handshake{target=65.108.200.37:8333}: bitcoin_handshake: handshake attempt failed with: IO Error during (de)serialization: failed to fill whole buffer
2022-11-17T22:46:55.442910Z WARN handshake{target=87.236.195.198:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.447682Z WARN handshake{target=104.244.73.6:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.455978Z WARN handshake{target=5.9.105.68:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.465712Z WARN handshake{target=3.8.133.46:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.465785Z WARN handshake{target=188.166.102.98:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.469527Z ERROR handshake{target=31.18.168.192:8333}: bitcoin_handshake: handshake attempt failed with: IO Error during (de)serialization: failed to fill whole buffer
2022-11-17T22:46:55.479653Z ERROR handshake{target=79.115.212.244:8333}: bitcoin_handshake: handshake attempt failed with: IO Error during (de)serialization: failed to fill whole buffer
2022-11-17T22:46:55.485573Z WARN handshake{target=84.255.244.61:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.487334Z ERROR handshake{target=80.94.107.94:8333}: bitcoin_handshake: handshake attempt failed with: IO Error during (de)serialization: failed to fill whole buffer
2022-11-17T22:46:55.497705Z WARN handshake{target=143.110.175.248:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.581902Z WARN handshake{target=2.59.236.56:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.739703Z WARN handshake{target=3.138.122.100:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.784641Z WARN handshake{target=173.48.112.106:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.786252Z WARN handshake{target=74.76.43.77:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.876216Z WARN handshake{target=154.38.167.152:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.882179Z WARN handshake{target=3.101.67.35:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.882410Z WARN handshake{target=13.66.248.91:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.891033Z WARN handshake{target=13.57.250.92:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:55.891536Z ERROR handshake{target=13.112.248.184:8333}: bitcoin_handshake: handshake attempt failed with: IO Error during (de)serialization: failed to fill whole buffer
2022-11-17T22:46:56.119996Z WARN handshake{target=13.113.139.174:8333}: bitcoin_handshake: expected message command `verack` but got `sendheaders` instead
2022-11-17T22:46:56.120468Z INFO bitcoin_handshake: Finished! Handshake results: 2 OK | 16 PARTIALLY OK | 7 FAILED
The last line of the output should contain the results of handshake attempts.
The log level output can be controlled using RUST_LOG
environment variable (defaults to info
).
The tool tries to perform an exchange of version
and verack
messages.
sequenceDiagram
bitcoin-handshake->>Node: Version
Node->>bitcoin-handshake: Version
bitcoin-handshake->>Node: VerAck
Node->>bitcoin-handshake: VerAck
Node-->>bitcoin-handshake: (other messages)
After this exchange, other messages can flow between nodes.
However, more often than not, bitcoin nodes tend to omit returning the verack
message,
and instead start sending other messages like inv
or sendheaders
. This is either
an implementation flaw/optimization, or a misunderstanding of the protocol doc on my side.
Due to this, we treat a handshake that did not return the verack
message, but still sends
other messages, as PARTIALLY OK
.
No bitcoin-related crates were used, for a reason.
This create can potentially, but unlikely, be evolved into full-fledged bitcoin protocol implementation.