Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

NEO网络协议

宠着祖宗
94 0 0
网络协议9 v$ h! n4 w! t6 v- v/ V* J
在网络结构上,NEO 采用点对点网络结构,并使用 TCP 协议进行通讯。
$ R) z- G- @) g! x网络中存在两种节点类型,分别是普通节点和共识节点。普通节点可以广播、接收和转发交易、区块等,而共识节点可以创建区块。: p: a. y7 J( z+ @8 n. y5 D0 ^
NEO 的网络协议规范与比特币的协议大致类似,但在区块、交易等的数据结构上有很大的不同。. c% A* Q9 J! M5 z6 M2 D3 G: p+ [. ?
约定
2 E2 [; u3 n( h) x字节序
# w; O$ a" I3 P! h. }NEO 系统中所有的整数类型都是采用小端序 (Little Endian) 编码,只有 IP 地址和端口号采用大端序 (Big Endian) 编码。
" K/ t9 w0 G% D散列
) [$ q/ e  A3 V9 Z5 n8 ]3 `NEO 系统中会用到 2 种不同的散列函数:SHA256 和 RIPEMD160。前者用于生成较长的散列值,而后者用于生成较短的散列值。通常生成一个对象的散列值时,会运用两次散列函数,例如要生成区块或交易的散列时,会计算两次 SHA256;生成合约地址时,会先计算脚本的 SHA256 散列,然后再计算上一个散列的 RIPEMD160 散列。
1 q. Z; f+ N9 ~" c此外,区块中还会用到一种散列树 (Merkle Tree) 的结构,它将每一笔交易的散列两两相接后再计算一次散列,并重复以上过程直到只剩下一个根散列 (Merkle Root)。
7 _6 M) B6 @! d+ E- \, p变长类型( M# w' S6 o  w8 a
varint:变长整数,可以根据表达的值进行编码以节省空间。* [' S, }5 d* [. L
长度格式
0xffffffff90xff + uint64

0 Q( Y0 ~9 H6 A7 D1 V2 ^- t. d! l  Xvarstr:变长字符串,由一个变长整数后接字符串构成。字符串采用 UTF8 编码。
" M  {: f/ Y7 P& F& X+ c
尺寸字段数据类型说明
?lengthvarint字符串的长度,以字节为单位
lengthstringuint8[length]字符串本身

; I  I) o. I) W/ n& [7 M! harray:数组,由一个变长整数后接元素序列构成。- V6 ]3 D) t. x8 X
定点数
- e( D- |1 H: @* mNEO 系统中的金额、价格等数据,统一采用 64 位定点数,小数部分精确到 10-8,可表示的范围是:[-263/108, +263/108)  S2 k- [7 f* g3 A
数据结构
! f2 \) Y  \' R  t  Z9 L. i区块链8 C/ D5 S2 |& t7 u* j* k# m5 [
区块链是一种逻辑结构,它以单向链表的形式将区块串联起来,用于存放全网的交易、资产等数据。* E  q5 A: I( H: x' L
区块( T7 b/ y7 d4 ^) w6 U" d- j# r
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
?*?Transactionstx[]交易列表

- n; V& U2 T* P& `( J在计算区块散列时,并不会把整个区块都计算在内,而是只计算区块头的前 7 个字段:Version, PrevBlock, MerkleRoot, Timestamp, Height, Nonce, NextMiner。由于 MerkleRoot 已经包含了所有交易的散列值,因此修改交易也会改变区块的散列值。* A0 r: q2 t; A  w' y$ \
区块头的数据结构如下:
4 V4 c$ O/ v2 o) N, K9 R/ d
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
1-uint8固定为 0

7 H# Y/ j1 `2 q( m' [9 O, Y4 S" f% W每个区块的时间戳必须晚于前一个区块的时间戳,一般两个区块的时间戳相差 15 秒左右,但是也允许出现不精确的情况。区块的高度值必须恰好等于前一个区块的高度值加一。
. h' l0 O" D/ U交易7 d- k2 f7 ^7 H& Q( B; O  ~
尺寸字段数据类型说明
1Typeuint8交易类型
1Versionuint8交易版本,目前为 0
?--特定于交易类型的数据
?*?Attributestx_attr[]该交易所具备的额外特性
34*?Inputstx_in[]输入
60*?Outputstx_out[]输出
?*?Scriptsscript[]用于验证该交易的脚本列表

3 \  B% X2 f% q: o, YNEO 系统中的一切事务都以交易为单位进行记录。交易有以下几种类型:
  f0 d% U6 w, L3 w# G/ O
名称系统费用说明
0x00MinerTransaction0用于分配字节费的交易
0x01IssueTransaction500|0用于分发资产的交易
0x02ClaimTransaction0用于分配 NeoGas 的交易
0x20EnrollmentTransaction1000(已弃用) 用于报名成为共识候选人的特殊交易
0x40RegisterTransaction10000|0(已弃用) 用于资产登记的交易
0x80ContractTransaction0合约交易,这是最常用的一种交易
0xd0PublishTransaction500*n(已弃用)智能合约发布的特殊交易
0xd1InvocationTransaction0调用智能合约的特殊交易
7 Q& a" F2 n# E. v; ^
每一种类型的交易除了具有交易的公共字段之外,还会具有自己的专属字段。关于不同类型交易的专属字段,下文会有详细说明。4 {6 S6 ?* H+ b  Y$ D: u
MinerTransaction
! Z7 Y/ k5 W, ~* R/ Y
尺寸字段数据类型说明
---交易的公共字段
4Nonceuint32随机数
---交易的公共字段
; ^) x& c! d1 Q- D% v6 D
每一个区块的第一笔交易必然是 MinerTransaction。它用于将当前区块中所有的交易手续费奖励给记账人。
* k1 Q+ I9 s4 @; ~4 K% _交易中的随机数用于防止出现散列冲突。
% s4 h+ l. \; R4 y  lIssueTransaction, A$ r! I, t1 f% U4 K
资产发行交易没有额外的特殊字段。
4 }' B5 ?* Q% G6 q5 P$ v  E- w资产管理员可以通过资产发行交易,将已经登记过的资产在 NEO 区块链上制造出来,并发送到任意地址。
  V6 J7 X7 A3 ~9 U2 S特别的,如果发行的资产是 NEO,那么这笔交易将可以免费发送。: I; h0 w* j+ X% b5 R# m
ClaimTransaction$ k4 r6 l% U  O; ]
尺寸字段数据类型说明
---交易的公共字段
34*?Claimstx_in[]用于分配的 NEO
---交易的公共字段

+ c4 U& [, W# O7 F  dEnrollmentTransaction; t, ~9 r) c& z: y
! x$ F8 t$ l) ^( p4 r. h! W3 I1 o
[!Warning]2 F# K  }1 N% [, u7 B" p& U" s  X
已弃用,已被智能合约的 Neo.Blockchain.RegisterValidator 所替代。
, E+ ?' D: P) y' L' x8 H( f$ A

- r3 j* l1 v* n! g" p* N' }查看 替代的 .NET 智能合约框架
8 z8 T; W$ Q: h0 w查看 替代智能合约 API
0 o( E4 {% [0 D  k& t0 K4 _; ?, eRegisterTransaction
& T3 Q6 L6 D0 A7 e1 k/ C' M6 s5 e) r: a; ]8 L
[!Warning]+ }+ G/ t! l3 [( h; O  M
已弃用,已被智能合约的 Neo.Blockchain.CreateAsset 所替代。# w4 i7 a7 w+ |  G4 ^, p
4 U) e+ m3 x: D( f% w- D* d% u' _" _' e
查看 替代的 .NET 智能合约框架6 X1 G8 G! U+ {1 A
查看 替代智能合约 API ' |- B2 ~2 v+ V. ^
ContractTransaction, M$ q; e, r/ H8 j  O
合约交易没有任何特殊的地方。
( h  V( d' \+ L, j4 ~PublishTransaction; n+ \  f5 b: _; E7 ?5 M
6 a  v! V0 n" k+ x% ^0 E3 u
[!Warning]
* h8 j/ j5 h4 ^$ T3 Y已弃用,已被智能合约的 Neo.Blockchain.CreateContract 所替代。
+ k" E. }$ W# T9 z# V+ |7 u+ w
  V8 Y6 `! C5 C" H" T
查看 替代的 .NET 智能合约框架
3 O2 j6 g) U+ g9 y查看 替代智能合约 API & K- J$ j, W0 s4 K
InvocationTransaction
6 s8 f" D; G7 S! ?' A
尺寸字段数据类型说明
---交易的公共字段
?Scriptuint8[]所调用的智能合约的脚本
8Gasint64运行所调用的智能合约需要的费用
---交易的公共字段
9 ]9 a, l6 J( v1 H
交易特性9 @' m: ^8 H  N+ e, V% s
尺寸字段数据类型说明
1Usageuint8用途
0|1lengthuint8数据长度(特定情况下会省略)
lengthDatauint8[length]特定于用途的外部数据
3 ~* J* r* O# D' @* o5 b' M
有时候交易中会需要包含一些供外部使用的数据,这些数据将统一被放置在交易特性字段中。  n" o/ Q5 b" _" o7 v, L
每个交易特性可以有不同的用途:) t5 O$ Z  Y: p' w' G
名称说明
0x00ContractHash外部合同的散列值
0x02-0x03ECDH02-ECDH03用于 ECDH 密钥交换的公钥
0x20Script用于对交易进行额外的验证
0x30Vote用于投票选出记账人
0x81DescriptionUrl外部介绍信息地址
0x90Description简短的介绍信息
0xa1-0xafHash1-Hash15用于存放自定义的散列值
0xf0-0xffRemark-Remark15备注
  G5 J7 d. }+ r& w
对于 ContractHash,ECDH 系列,Vote,Hash 系列,数据长度固定为 32 字节,length 字段省略;
" b3 M8 q. A7 T! V对于 Script,数据长度固定为 20 字节,存放地址;# N6 y9 l' q  W
对于 DescriptionUrl,必须明确给出数据长度,且长度不能超过 255 字节;7 E! M& E, b: \2 G& s
对于 Description 和 Remark 系列,必须明确给出数据长度, 且长度不能超过 65535 字节。$ M" C3 O; q9 w0 U( t  W3 `
交易输入! H' v' J7 i  D  ]: |7 q
尺寸字段数据类型说明
32PrevHashuint256引用交易的散列值
2PrevIndexuint16引用交易输出的索引
- A# E- \, a  p( G5 i" q% q/ N
交易输出( J, R0 F$ O# E) k( a+ y0 j
尺寸字段数据类型说明
32AssetIduint256资产编号
8Valueint64金额
20ScriptHashuint160收款地址

. M; Q( K6 Y1 z2 Z0 R( N每个交易中最多只能包含 65536 个输出。
) e) b6 j; }: C验证脚本, I" D5 ]& ^) A6 q7 w. g$ D+ K
尺寸字段数据类型说明
?StackScriptuint8[]栈脚本代码
?RedeemScriptuint8[]合约脚本代码

9 D9 @0 ]3 H/ q! R  o) {" P7 b栈脚本中只能包含压栈操作指令,用于向合约脚本传递参数(如签名等)。脚本解释器会先执行栈脚本代码,然后执行合约脚本代码。- A, `1 N" F" W4 H
在一笔交易中,合约脚本代码的散列值必须与交易输出中的一致,这是验证的一部分。关于脚本执行的过程,后文会详细阐述。
" v% o9 ~  ~/ l9 h% W6 h网络消息7 L  H. g$ k0 Z2 D. }3 `9 k
所有的网络消息都通过以下消息结构来发送:  Y4 a5 [2 K: ]
尺寸字段数据类型说明
4Magicuint32协议标识号
12Commandchar[12]命令
4lengthuint32Payload 的长度
4Checksumuint32校验和
lengthPayloaduint8[length]消息内容

! I4 V1 }* b8 Z$ S$ ]1 J& M已定义的 Magic 值:
" D6 G3 Y2 Q8 r
说明
0x00746e41正式网
0x74746e41测试网
2 R- m+ M9 T3 g
Command 采用 utf8 编码,长度为 12 字节,多余部分用 0 填充。
% H9 d) W  J- e! b6 rChecksum 是 Payload 两次 SHA256 散列后的前 4 个字节。
9 w/ n9 Q& @  [) ~/ B, DPayload 根据不同的命令有不同的详细格式,见下文。( g3 _$ j% j4 R$ ~% z5 e+ F
version* S; z) K& M- ]. \$ y& |
尺寸字段数据类型说明
4Versionuint32协议版本,目前为 0
8Servicesuint64节点提供的服务,目前为 1
4Timestampuint32当前时间
2Portuint16监听的端口,如果不监听则为 0
4Nonceuint32用于区分相同公网 IP 的节点
?UserAgentvarstr客户端标识
4StartHeightuint32区块链高度
1Relaybool是否接收并转发
) K! R6 v. b$ ?/ p9 q7 ~
一个节点收到连接请求时,它立即宣告其版本。在通信双方都得到对方版本之前,不会有其他通信。5 u$ T  E! _! c" ^& t0 ]
verack0 K+ z) [. V3 M- O
节点收到 version 消息后,立刻回复一个 verack 作为应答。% T1 L( i+ \  i
此消息没有 payload。+ h* k8 r6 Y  E- z/ P; Q
getaddr
1 a$ g: S& H0 m; o- i& y/ ~1 u向一个节点请求一批新的活动节点,以增加自身的连接数。- v, b' h3 d$ }/ ^
此消息没有 payload。  s+ o5 f: ^" o. [
addr* ~5 I* g' y+ w$ A# b( A
尺寸字段数据类型说明
30*?AddressListnet_addr[]网络上其他节点的地址
" v* ^- |* _9 `" a/ ^' s1 n) L- }
节点收到 getaddr 消息后,返回一个 addr 消息作为应答,提供网络上已知节点的信息。
( G6 a! c/ R, R8 cgetheaders8 O& D. p  |. z8 i
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列

' x  q/ X/ z1 Z4 P" T# ]向一个节点请求包含编号 HashStart 到 HashStop 的至多 2000 个 block 的 header 包。要获取之后的 block 散列,需要重新发送 getheaders 消息。这个消息用于快速下载不包含相关交易的 blockchain。  n  ^$ T5 _. _9 Z% c/ P& x  ~
headers
9 n4 f3 N0 T6 ], a/ x5 _+ u
尺寸字段数据类型说明
?*?Headersheader[]区块头
8 o$ B1 @+ `* `
节点收到 getheaders 消息后,返回一个 headers 消息作为应答,提供请求的区块头。+ t3 Y+ |0 j, G# y5 g/ b
getblocks
6 o  b% ]8 z, ]5 ^7 R% P
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列

7 t# R5 }9 G, \7 E- r向一个节点请求包含编号从 HashStart 到 HashStop 的 block 列表的 inv 消息。若 HashStart 到 HashStop 的 block 数超过 500,则在 500 处截止。欲获取后面的 block 散列,需要重新发送 getblocks 消息。! |8 G6 m3 d0 g7 o9 b, k- D0 ~- N. r
inv' Z) w/ z' I2 T5 f5 w
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单
. F- q' H" u0 n# @) o
节点通过此消息可以广播它拥有的对象信息。这个消息可以主动发送,也可以用于应答 getbloks 消息。
4 N* y) K& C- C& h# f清单类型有以下几种:
% A4 ^7 \, k3 \) S4 E7 Y
名称说明
0x01TX交易
0x02Block区块
0xe0Consensus共识数据

$ k5 g3 P! k6 {! ?getdata# r0 G! Y7 U2 f; V' L8 o8 S4 ~: t
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单
6 ~- E. X9 z  X5 J( J3 N5 d4 P
向一个节点请求指定的对象,它通常在接收到 inv 包并滤去已知元素后发送。- c, z- M: H3 W  g
block) c- q4 o% s' p: X8 R  o5 w/ ^
尺寸字段数据类型说明
?Blockblock区块

3 X# G! B6 [0 D- Q0 r9 E: F6 R向一个节点发送一个区块,用于响应请求数据的 getdata 消息。9 x2 g& H7 G7 O0 I; C% {* v
tx$ C5 H9 j" s& F& ^: N" N
尺寸字段数据类型说明
?Transactiontx交易
1 G+ W* n  ]4 s. W  V
向一个节点发送一笔交易,用于响应请求数据的 getdata 消息。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

宠着祖宗 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    1