Appearance
btcd/wire/common.go
基于chan的buf管理
type binaryFreeList chan []byte //数字缓冲区 type scriptFreeList chan []byte //脚本缓冲区
这里的思路还是比较巧妙的,使用了chan的方式来管理[]byte,减少了不断的分配[]byte,同时使用chan来规避锁的问题. 我不知道go内部chan写入读出是否要用到锁,但是至少规避了List的管理.
Borrow 方法: 如果有可用的缓冲区则取走,否则分配 Return 方法:将用完的缓冲区通过chan放回去,为下次Borrow做准备.
这里面预设了最大的缓冲区大小,总的来说还是满巧妙的.
VarInt编码
0-0xfd 直接是0xfd, 0xfd-maxuint16 0xfd+ 两个字节的数值本身 maxuint16-maxuint32 0xfe+加四字节数值本身 maxuint32-maxuint64 0xff+8字节数值本身
实际上这类似于以太坊的RLP编码思路,
VarBytes,VarString编码方式
VarInt编码的长度+数据本身
比特币的消息通信
消息往来
Peer A Sends Peer B Responds
----------------------------------------------------------------------------
getaddr message (MsgGetAddr) addr message (MsgAddr)
getblocks message (MsgGetBlocks) inv message (MsgInv)
inv message (MsgInv) getdata message (MsgGetData)
getdata message (MsgGetData) block message (MsgBlock) -or-
tx message (MsgTx) -or-
notfound message (MsgNotFound)
getheaders message (MsgGetHeaders) headers message (MsgHeaders)
ping message (MsgPing) pong message (MsgHeaders)* -or-
(none -- Ability to send message is enough)
读取消息
pver是消息版本信息,(BIP定义了很多版本),目前是FeeFilterVersion 70013 btcnet 有四种情况,分别如下
go
// MainNet represents the main bitcoin network.
MainNet BitcoinNet = 0xd9b4bef9
// TestNet represents the regression test network.
TestNet BitcoinNet = 0xdab5bffa
// TestNet3 represents the test network (version 3).
TestNet3 BitcoinNet = 0x0709110b
// SimNet represents the simulation test network.
SimNet BitcoinNet = 0x12141c16
Go
// Use the most recent protocol version supported by the package and the
// main bitcoin network.
pver := wire.ProtocolVersion
btcnet := wire.MainNet
// Reads and validates the next bitcoin message from conn using the
// protocol version pver and the bitcoin network btcnet. The returns
// are a wire.Message, a []byte which contains the unmarshalled
// raw payload, and a possible error.
msg, rawPayload, err := wire.ReadMessage(conn, pver, btcnet)
if err != nil {
// Log and handle the error
}
发送消息
Go
// Use the most recent protocol version supported by the package and the
// main bitcoin network.
pver := wire.ProtocolVersion
btcnet := wire.MainNet
// Create a new getaddr bitcoin message.
msg := wire.NewMsgGetAddr()
// Writes a bitcoin message msg to conn using the protocol version
// pver, and the bitcoin network btcnet. The return is a possible
// error.
err := wire.WriteMessage(conn, msg, pver, btcnet)
if err != nil {
// Log and handle the error
}
消息类型验证
go
// Assumes msg is already a valid concrete message such as one created
// via NewMsgVersion or read via ReadMessage.
switch msg := msg.(type) {
case *wire.MsgVersion:
// The message is a pointer to a MsgVersion struct.
fmt.Printf("Protocol version: %v", msg.ProtocolVersion)
case *wire.MsgBlock:
// The message is a pointer to a MsgBlock struct.
fmt.Printf("Number of tx in block: %v", msg.Header.TxnCount)
}