Awesome
bitcoin-protocol
Bitcoin network protocol streams
This module encodes and decodes low-level network protocol data using streams.
You may want a higher-level module like bitcoin-net, which some things for you such as connection handshakes, sending keepalive pings, etc.
Usage
npm install bitcoin-protocol
var net = require('net')
var bp = require('bitcoin-protocol')
var decoder = bp.createDecodeStream()
decoder.on('data', function (message) { console.log(message) })
var encoder = bp.createEncodeStream()
var socket = net.connect(8333, '127.0.0.1', function () {
socket.pipe(decoder)
encoder.pipe(socket)
encoder.write({
magic: 0xd9b4bef9,
command: 'version',
payload: {
version: 70012,
services: Buffer(8).fill(0),
timestamp: Math.round(Date.now() / 1000),
receiverAddress: {
services: Buffer('0100000000000000', 'hex'),
address: '0.0.0.0',
port: 8333
},
senderAddress: {
services: Buffer(8).fill(0),
address: '0.0.0.0',
port: 8333
},
nonce: Buffer(8).fill(123),
userAgent: 'foobar',
startHeight: 0,
relay: true
}
})
})
Methods
createDecodeStream([opts])
Creates a stream which parses raw network bytes written to it and outputs message objects.
Opts may contain:
{
magic: Number
// If provided, the decoder will check if messages' "magic" field matches
// this value. If it does not match, the stream will emit an error.
}
createEncodeStream([opts])
Creates a stream which encodes message objects to raw network bytes.
Opts may contain:
{
magic: Number
// If provided, the encoder will automatically add the "magic" field to each
// message written to it.
}
Format
Decoder
Emitted by the decoder:
{
magic: Number,
command: String,
length: Number,
checksum: Buffer, // 8 bytes,
payload: Object // see below for detailed payload formats
}
Encoder
Written to the encoder:
{
magic: Number, // optional if you set this in the options
command: String,
payload: Object // see below for detailed payload formats
}
Payload Reference
The formats for the objects used as message payloads for the various commands are as follows. See the wiki for more information about these messages.
version
{
version: Number,
services: Buffer, // 8 bytes
timestamp: Number,
receiverAddress: {
services: Buffer, // 8 bytes
address: String, // ipv4 or ipv6
port: Number
},
senderAddress: {
services: Buffer, // 8 bytes
address: String, // ipv4 or ipv6
port: Number
},
nonce: Buffer, // 8 bytes
userAgent: String,
startHeight: Number,
relay: Boolean
}
verack
, getaddr
, mempool
, filterclear
, sendheaders
// no payload needed
addr
[
{
time: Number,
services: Buffer, // 8 bytes
address: String, // ipv4 or ipv6
port: Number
},
...
]
inv
, getdata
, notfound
[
{
type: Number,
hash: Buffer // 32 bytes
},
...
]
getblocks
, getheaders
{
version: Number,
locator: [
Buffer // 32 bytes
],
hashStop: Buffer // 32 bytes
}
tx
{
version: Number,
ins: [
{
hash: Buffer, // 32 bytes
index: Number,
script: Buffer, // varying length
sequence: Number
},
...
],
outs: [
{
value: BN, // from 'bn.js' package
script: Buffer // varying length
},
...
],
locktime: Number
}
block
{
header: {
version: Number,
prevHash: Buffer, // 32 bytes
merkleRoot: Buffer, // 32 bytes
timestamp: Number,
bits: Number,
nonce: Number,
},
transactions: [
{}, // same format as 'tx' message
...
]
}
headers
[
{
header: {
version: Number,
prevHash: Buffer, // 32 bytes
merkleRoot: Buffer, // 32 bytes
timestamp: Number,
bits: Number,
nonce: Number,
},
nTransactions: Number
},
...
]
ping
, pong
{
nonce: Buffer // 8 bytes
}
reject
{
message: String,
ccode: Number,
reason: String,
data: Buffer // varying length
}
filterload
{
data: Buffer, // varying length
nHashFuncs: Number,
nTweak: Number,
nFlags: Number
}
filteradd
{
data: Buffer // varying length
}
merkleblock
{
header: {
version: Number,
prevHash: Buffer, // 32 bytes
merkleRoot: Buffer, // 32 bytes
timestamp: Number,
bits: Number,
nonce: Number
},
numTransactions: Number,
hashes: [
Buffer // 32 bytes
],
flags: Buffer // varying length
}
alert
{
payload: Buffer, // varying length
signature: Buffer // varying length
}