Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

NEO网络协议

宠着祖宗
96 0 0
网络协议' ~/ y. W3 L2 r% Q3 L! e/ g
在网络结构上,NEO 采用点对点网络结构,并使用 TCP 协议进行通讯。
% |% q5 T0 G" E' z$ f+ K+ v5 n网络中存在两种节点类型,分别是普通节点和共识节点。普通节点可以广播、接收和转发交易、区块等,而共识节点可以创建区块。* x( s+ a9 C8 A# C  x  w9 v% E
NEO 的网络协议规范与比特币的协议大致类似,但在区块、交易等的数据结构上有很大的不同。
2 g* x4 v6 A+ g* s+ S4 o约定6 f* o( h6 E3 B) N( @
字节序
6 p0 t) a% t" X. s  JNEO 系统中所有的整数类型都是采用小端序 (Little Endian) 编码,只有 IP 地址和端口号采用大端序 (Big Endian) 编码。( i- H# H, [* l; R4 M" V* i
散列: ^, c" Y/ b  ^, B4 C, z
NEO 系统中会用到 2 种不同的散列函数:SHA256 和 RIPEMD160。前者用于生成较长的散列值,而后者用于生成较短的散列值。通常生成一个对象的散列值时,会运用两次散列函数,例如要生成区块或交易的散列时,会计算两次 SHA256;生成合约地址时,会先计算脚本的 SHA256 散列,然后再计算上一个散列的 RIPEMD160 散列。) }0 j8 y- C9 K4 U, f3 M" c
此外,区块中还会用到一种散列树 (Merkle Tree) 的结构,它将每一笔交易的散列两两相接后再计算一次散列,并重复以上过程直到只剩下一个根散列 (Merkle Root)。
) ~9 a4 H: f; u' \  H变长类型
% M9 \( F* K+ c4 ^, Vvarint:变长整数,可以根据表达的值进行编码以节省空间。
0 R' s/ L3 m. U7 G
长度格式
0xffffffff90xff + uint64

& D) v) L' H% ~. `varstr:变长字符串,由一个变长整数后接字符串构成。字符串采用 UTF8 编码。) f: q1 N1 S: t) |6 w, V$ D
尺寸字段数据类型说明
?lengthvarint字符串的长度,以字节为单位
lengthstringuint8[length]字符串本身

# a% k, n( {( z" W; G9 {array:数组,由一个变长整数后接元素序列构成。2 X2 u% _! W# d8 [# u+ N
定点数3 U0 T6 z% {8 j! u6 F- W8 @+ p
NEO 系统中的金额、价格等数据,统一采用 64 位定点数,小数部分精确到 10-8,可表示的范围是:[-263/108, +263/108)
9 K0 D/ E! {. J/ y: C. \数据结构
  u" N  ]1 i* \& n( U+ F; w区块链! {) J% V" M6 K# t( B9 j3 N; g
区块链是一种逻辑结构,它以单向链表的形式将区块串联起来,用于存放全网的交易、资产等数据。) e% J" a: N4 h
区块, z* B8 m  w+ Q" ]+ M
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
?*?Transactionstx[]交易列表
' n  ?$ {% v5 m$ T( W& R0 }
在计算区块散列时,并不会把整个区块都计算在内,而是只计算区块头的前 7 个字段:Version, PrevBlock, MerkleRoot, Timestamp, Height, Nonce, NextMiner。由于 MerkleRoot 已经包含了所有交易的散列值,因此修改交易也会改变区块的散列值。& Y( p6 I0 f+ m$ |+ {; _+ n6 j/ d
区块头的数据结构如下:6 M1 P, N: V2 L: l
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
1-uint8固定为 0
0 J6 W/ {4 P- P# x9 [. \, d
每个区块的时间戳必须晚于前一个区块的时间戳,一般两个区块的时间戳相差 15 秒左右,但是也允许出现不精确的情况。区块的高度值必须恰好等于前一个区块的高度值加一。
4 o( l0 P8 E* |( U3 @1 ^' t0 t交易+ r$ @# @+ [% U; Y9 J3 O
尺寸字段数据类型说明
1Typeuint8交易类型
1Versionuint8交易版本,目前为 0
?--特定于交易类型的数据
?*?Attributestx_attr[]该交易所具备的额外特性
34*?Inputstx_in[]输入
60*?Outputstx_out[]输出
?*?Scriptsscript[]用于验证该交易的脚本列表
; j- _' T- y$ }, f  ]
NEO 系统中的一切事务都以交易为单位进行记录。交易有以下几种类型:: _; N, I8 U0 W$ x2 w5 Q1 x' J
名称系统费用说明
0x00MinerTransaction0用于分配字节费的交易
0x01IssueTransaction500|0用于分发资产的交易
0x02ClaimTransaction0用于分配 NeoGas 的交易
0x20EnrollmentTransaction1000(已弃用) 用于报名成为共识候选人的特殊交易
0x40RegisterTransaction10000|0(已弃用) 用于资产登记的交易
0x80ContractTransaction0合约交易,这是最常用的一种交易
0xd0PublishTransaction500*n(已弃用)智能合约发布的特殊交易
0xd1InvocationTransaction0调用智能合约的特殊交易
9 @1 o( X4 ~0 N6 F
每一种类型的交易除了具有交易的公共字段之外,还会具有自己的专属字段。关于不同类型交易的专属字段,下文会有详细说明。
8 _% [" }7 c/ V* o9 TMinerTransaction
' {5 z# t0 w; P
尺寸字段数据类型说明
---交易的公共字段
4Nonceuint32随机数
---交易的公共字段
0 ^3 J8 x& Z6 L+ g5 @( f
每一个区块的第一笔交易必然是 MinerTransaction。它用于将当前区块中所有的交易手续费奖励给记账人。& `  y9 `- E) s* U+ ]; t
交易中的随机数用于防止出现散列冲突。5 H, G4 w  N+ p1 Y
IssueTransaction1 L+ w7 V/ b/ l& _: n
资产发行交易没有额外的特殊字段。
- K0 I/ F0 `7 k( `" p  _资产管理员可以通过资产发行交易,将已经登记过的资产在 NEO 区块链上制造出来,并发送到任意地址。8 b6 x9 d, S1 n- X( b+ @; P5 @
特别的,如果发行的资产是 NEO,那么这笔交易将可以免费发送。
- E* M: z9 A4 W" i9 s* q1 q# JClaimTransaction
  x2 [; J; a1 e9 ?
尺寸字段数据类型说明
---交易的公共字段
34*?Claimstx_in[]用于分配的 NEO
---交易的公共字段
9 v: D% t  I! w6 a
EnrollmentTransaction. h  T/ O% `2 z/ R
# C- W; h9 P- j
[!Warning]
7 h1 \; u4 k% c- H& F" D已弃用,已被智能合约的 Neo.Blockchain.RegisterValidator 所替代。
6 G- T7 G  ?! b& F) l
* @5 I) a. g( g9 l: K
查看 替代的 .NET 智能合约框架/ Z7 Z' Z  b: K$ t! H+ |  K
查看 替代智能合约 API
) t/ Z  b3 x$ A, {* QRegisterTransaction) A2 L) D8 n9 }+ M5 ?8 Y/ B7 s
  R; e( Z# l- ^- H" I
[!Warning]
+ h8 E3 q) R; [6 c" v5 h8 o2 M& u. R已弃用,已被智能合约的 Neo.Blockchain.CreateAsset 所替代。9 u; [/ f/ D) {
# G! o4 _- H" d
查看 替代的 .NET 智能合约框架: k1 U% {5 s5 L9 g: P# ^
查看 替代智能合约 API
! f" u! A  Z2 K. m! O( BContractTransaction8 m: w. {) I# X2 v. t6 ]
合约交易没有任何特殊的地方。! n, p0 s. N* ]( l4 h2 G
PublishTransaction# W: x2 x" o; h
& g; _" w; P: j2 [; m6 W
[!Warning]; \" }5 Y$ Y- a# j0 _5 {9 B0 y1 p
已弃用,已被智能合约的 Neo.Blockchain.CreateContract 所替代。4 @" C, R! a& K6 o9 Z8 E
8 [6 u% x4 `( }( c- ?+ z4 v
查看 替代的 .NET 智能合约框架1 {" `( J& D8 s
查看 替代智能合约 API
( n6 B2 B  J' SInvocationTransaction  Y7 x9 |( @+ F; @+ ~! z  _$ A# ?
尺寸字段数据类型说明
---交易的公共字段
?Scriptuint8[]所调用的智能合约的脚本
8Gasint64运行所调用的智能合约需要的费用
---交易的公共字段
' V+ r5 B. O( B) B( D3 h
交易特性
0 m1 ]0 J( d& Z
尺寸字段数据类型说明
1Usageuint8用途
0|1lengthuint8数据长度(特定情况下会省略)
lengthDatauint8[length]特定于用途的外部数据

4 s2 f# j; M% T: j# z3 T2 Y5 R有时候交易中会需要包含一些供外部使用的数据,这些数据将统一被放置在交易特性字段中。
3 t$ ]; `! L. ]& E- a每个交易特性可以有不同的用途:
9 L$ O0 R0 }) H/ H# ~
名称说明
0x00ContractHash外部合同的散列值
0x02-0x03ECDH02-ECDH03用于 ECDH 密钥交换的公钥
0x20Script用于对交易进行额外的验证
0x30Vote用于投票选出记账人
0x81DescriptionUrl外部介绍信息地址
0x90Description简短的介绍信息
0xa1-0xafHash1-Hash15用于存放自定义的散列值
0xf0-0xffRemark-Remark15备注
- L6 d0 D) h7 }& Q  j
对于 ContractHash,ECDH 系列,Vote,Hash 系列,数据长度固定为 32 字节,length 字段省略;
' M. D- L- F5 v. {9 D0 R6 Y" Q对于 Script,数据长度固定为 20 字节,存放地址;
. d& q& v; B" S5 Q对于 DescriptionUrl,必须明确给出数据长度,且长度不能超过 255 字节;
" u5 K$ o, ^6 G' ^7 B! s1 Z& l对于 Description 和 Remark 系列,必须明确给出数据长度, 且长度不能超过 65535 字节。
" v6 z4 I1 J# @6 a9 u9 c交易输入9 \' P6 ]2 r$ J. ^! Q
尺寸字段数据类型说明
32PrevHashuint256引用交易的散列值
2PrevIndexuint16引用交易输出的索引

) O/ L" M! r3 U, m- Q交易输出  k: t- F( R) s, c" B6 e
尺寸字段数据类型说明
32AssetIduint256资产编号
8Valueint64金额
20ScriptHashuint160收款地址
' V3 E2 h/ Y! Z
每个交易中最多只能包含 65536 个输出。. l) y" X' p; v+ V  b
验证脚本1 e0 `! w* Z/ B/ t' u( U! e
尺寸字段数据类型说明
?StackScriptuint8[]栈脚本代码
?RedeemScriptuint8[]合约脚本代码
( G. F" N! @3 u2 ^7 M7 j1 U9 X' `  d
栈脚本中只能包含压栈操作指令,用于向合约脚本传递参数(如签名等)。脚本解释器会先执行栈脚本代码,然后执行合约脚本代码。8 C9 o% r9 ^' T
在一笔交易中,合约脚本代码的散列值必须与交易输出中的一致,这是验证的一部分。关于脚本执行的过程,后文会详细阐述。/ I$ e! T& Y: c! A* ?
网络消息
0 t3 l4 D! g' S; ?3 j: n所有的网络消息都通过以下消息结构来发送:5 L( i/ p" ]8 d: Z' Y' \$ |9 X0 `, l1 ?
尺寸字段数据类型说明
4Magicuint32协议标识号
12Commandchar[12]命令
4lengthuint32Payload 的长度
4Checksumuint32校验和
lengthPayloaduint8[length]消息内容
+ S& l6 T1 j: ^
已定义的 Magic 值:
; ~7 [7 p+ y7 e* A3 p
说明
0x00746e41正式网
0x74746e41测试网
& F& P* ~+ V( r5 g' ], l
Command 采用 utf8 编码,长度为 12 字节,多余部分用 0 填充。) M! a6 J9 G' w; x. j/ n$ a# l
Checksum 是 Payload 两次 SHA256 散列后的前 4 个字节。
# q9 i8 l( A7 U$ h+ FPayload 根据不同的命令有不同的详细格式,见下文。! L, q% l' t- y8 H1 t) D/ r) q/ M; i
version: l7 w" l' H6 U% S8 I
尺寸字段数据类型说明
4Versionuint32协议版本,目前为 0
8Servicesuint64节点提供的服务,目前为 1
4Timestampuint32当前时间
2Portuint16监听的端口,如果不监听则为 0
4Nonceuint32用于区分相同公网 IP 的节点
?UserAgentvarstr客户端标识
4StartHeightuint32区块链高度
1Relaybool是否接收并转发

7 O; \; @& J- k/ M" x一个节点收到连接请求时,它立即宣告其版本。在通信双方都得到对方版本之前,不会有其他通信。" e9 L' V* i- T) J) [8 x, ~
verack
2 e0 M1 u4 {1 o) E" H: e! @节点收到 version 消息后,立刻回复一个 verack 作为应答。
) ~% D9 |3 v" n, V2 a+ U, w此消息没有 payload。
1 {" q; K7 Q  o% h; |getaddr6 _# J/ L% E8 \. ^4 }
向一个节点请求一批新的活动节点,以增加自身的连接数。
! |$ U% b$ @* V/ e, j+ Z/ U4 ~此消息没有 payload。6 j( I  `; ]) S, O$ \$ {; C& J
addr1 N7 R( \; g6 H: w( R' ]3 Y6 A
尺寸字段数据类型说明
30*?AddressListnet_addr[]网络上其他节点的地址
$ B! ]$ @, e' ^! j) H: b
节点收到 getaddr 消息后,返回一个 addr 消息作为应答,提供网络上已知节点的信息。
9 M! k3 N9 C2 X, E+ }3 F. ?+ z( rgetheaders5 o$ _# |$ Z) H9 a0 L
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列
: B4 X# ]3 e. c. k8 h* `- I* O
向一个节点请求包含编号 HashStart 到 HashStop 的至多 2000 个 block 的 header 包。要获取之后的 block 散列,需要重新发送 getheaders 消息。这个消息用于快速下载不包含相关交易的 blockchain。
) ~/ h  U1 ?& xheaders8 t, X( U/ D/ C( i' D& x/ P
尺寸字段数据类型说明
?*?Headersheader[]区块头

4 O: {5 v' o4 S- B1 G8 F+ b. O+ h- f2 ]节点收到 getheaders 消息后,返回一个 headers 消息作为应答,提供请求的区块头。- e3 b$ E: F  Q" j
getblocks7 G( H; Z) F* e( P) S# T% B$ g
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列
# X. G+ P3 r$ r. z8 X1 M
向一个节点请求包含编号从 HashStart 到 HashStop 的 block 列表的 inv 消息。若 HashStart 到 HashStop 的 block 数超过 500,则在 500 处截止。欲获取后面的 block 散列,需要重新发送 getblocks 消息。2 r, t, O: ~: s. h8 S
inv) i0 E' t, b8 Q# A4 [, D+ G, q! }. S! V
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单

8 T; B" y; O7 s" D7 e) [节点通过此消息可以广播它拥有的对象信息。这个消息可以主动发送,也可以用于应答 getbloks 消息。# p9 D6 u9 ?. B! O2 s  J4 h6 F
清单类型有以下几种:9 |& W' G4 Z' c* \7 F0 ^
名称说明
0x01TX交易
0x02Block区块
0xe0Consensus共识数据
- k4 Y$ [* _" b( u
getdata3 e4 A/ P, [2 s% ~. r) z
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单
' O9 x$ f. g  Z! I
向一个节点请求指定的对象,它通常在接收到 inv 包并滤去已知元素后发送。5 H/ r) T1 B" D' A$ d3 ^5 w
block
# z5 K5 e- _  W2 \
尺寸字段数据类型说明
?Blockblock区块

' D7 b: y- G9 D* y( U向一个节点发送一个区块,用于响应请求数据的 getdata 消息。2 c7 [8 M- O' r( U! m
tx
5 \" D/ ?! |8 e% P
尺寸字段数据类型说明
?Transactiontx交易
$ H2 v9 q# y( H4 I# Q, @8 a
向一个节点发送一笔交易,用于响应请求数据的 getdata 消息。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

宠着祖宗 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    1