Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

NEO网络协议

宠着祖宗
155 0 0
网络协议
7 C  U3 H2 M3 W+ P+ h在网络结构上,NEO 采用点对点网络结构,并使用 TCP 协议进行通讯。+ v9 _& P! _0 ~8 u) b# ^: r% Y1 e
网络中存在两种节点类型,分别是普通节点和共识节点。普通节点可以广播、接收和转发交易、区块等,而共识节点可以创建区块。
. `0 B& Z' c. @0 _' q0 jNEO 的网络协议规范与比特币的协议大致类似,但在区块、交易等的数据结构上有很大的不同。; o( \2 I4 t& n: F/ X" M. B  m1 V# a
约定5 {. g/ k, `, E$ W$ A9 H* [' T
字节序
4 U, e% _' D/ dNEO 系统中所有的整数类型都是采用小端序 (Little Endian) 编码,只有 IP 地址和端口号采用大端序 (Big Endian) 编码。2 y- K4 L/ k1 V7 i7 p
散列- ^2 R6 `- J3 f4 p1 w
NEO 系统中会用到 2 种不同的散列函数:SHA256 和 RIPEMD160。前者用于生成较长的散列值,而后者用于生成较短的散列值。通常生成一个对象的散列值时,会运用两次散列函数,例如要生成区块或交易的散列时,会计算两次 SHA256;生成合约地址时,会先计算脚本的 SHA256 散列,然后再计算上一个散列的 RIPEMD160 散列。8 Q2 }: v4 P  a2 s6 u" W
此外,区块中还会用到一种散列树 (Merkle Tree) 的结构,它将每一笔交易的散列两两相接后再计算一次散列,并重复以上过程直到只剩下一个根散列 (Merkle Root)。! n4 l) r; v+ [' F( ~7 T. T+ C
变长类型
0 C- r$ i) e) S6 L% Z1 w" Kvarint:变长整数,可以根据表达的值进行编码以节省空间。4 |: w/ j. c; i' T; ]0 T
长度格式
0xffffffff90xff + uint64
# m+ d: _4 @" t4 s# J
varstr:变长字符串,由一个变长整数后接字符串构成。字符串采用 UTF8 编码。% e7 H6 f  u3 b1 m* j; K
尺寸字段数据类型说明
?lengthvarint字符串的长度,以字节为单位
lengthstringuint8[length]字符串本身
$ y; a) i( U3 y  }& R3 `
array:数组,由一个变长整数后接元素序列构成。
% G1 }/ p. t% J& `9 }3 h定点数
) t* Z3 m& S$ E* x) MNEO 系统中的金额、价格等数据,统一采用 64 位定点数,小数部分精确到 10-8,可表示的范围是:[-263/108, +263/108)
+ _6 F4 F7 _1 N' D- o. K  }: Q数据结构2 D9 E  Z* [$ X; ^! i! _: r% V
区块链
  ?4 B, [9 e4 {8 C+ W9 c区块链是一种逻辑结构,它以单向链表的形式将区块串联起来,用于存放全网的交易、资产等数据。* m4 X  J) l3 ^/ b1 N2 _$ n1 C
区块
0 |8 U3 B& i8 z- C8 i7 L
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
?*?Transactionstx[]交易列表
! d/ ]) _: c1 `  t0 D
在计算区块散列时,并不会把整个区块都计算在内,而是只计算区块头的前 7 个字段:Version, PrevBlock, MerkleRoot, Timestamp, Height, Nonce, NextMiner。由于 MerkleRoot 已经包含了所有交易的散列值,因此修改交易也会改变区块的散列值。
. r! k" R8 ~- h" K区块头的数据结构如下:- K' G* j7 G0 s
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
1-uint8固定为 0
- P& _* R% p: X8 L4 y
每个区块的时间戳必须晚于前一个区块的时间戳,一般两个区块的时间戳相差 15 秒左右,但是也允许出现不精确的情况。区块的高度值必须恰好等于前一个区块的高度值加一。7 @/ U+ W9 P+ A, o& v( a8 @
交易
# ^$ b' c: j: A9 N9 o, M
尺寸字段数据类型说明
1Typeuint8交易类型
1Versionuint8交易版本,目前为 0
?--特定于交易类型的数据
?*?Attributestx_attr[]该交易所具备的额外特性
34*?Inputstx_in[]输入
60*?Outputstx_out[]输出
?*?Scriptsscript[]用于验证该交易的脚本列表

) i3 f" e3 L+ b! [- KNEO 系统中的一切事务都以交易为单位进行记录。交易有以下几种类型:/ o+ \9 z' U7 D7 V" b
名称系统费用说明
0x00MinerTransaction0用于分配字节费的交易
0x01IssueTransaction500|0用于分发资产的交易
0x02ClaimTransaction0用于分配 NeoGas 的交易
0x20EnrollmentTransaction1000(已弃用) 用于报名成为共识候选人的特殊交易
0x40RegisterTransaction10000|0(已弃用) 用于资产登记的交易
0x80ContractTransaction0合约交易,这是最常用的一种交易
0xd0PublishTransaction500*n(已弃用)智能合约发布的特殊交易
0xd1InvocationTransaction0调用智能合约的特殊交易
* r( `8 K* _" V9 o: Y* p
每一种类型的交易除了具有交易的公共字段之外,还会具有自己的专属字段。关于不同类型交易的专属字段,下文会有详细说明。
7 k+ B  Z  S( s/ o, y, P; nMinerTransaction0 r! U: ~. V( h8 A/ @3 G
尺寸字段数据类型说明
---交易的公共字段
4Nonceuint32随机数
---交易的公共字段
4 F) s$ _- p+ {8 h* K
每一个区块的第一笔交易必然是 MinerTransaction。它用于将当前区块中所有的交易手续费奖励给记账人。
$ x) w& ~  {5 b4 i5 ^7 u3 R9 Q, m交易中的随机数用于防止出现散列冲突。. [" ?5 J9 a) n+ B' u; t+ i
IssueTransaction
3 n/ V5 r0 n: ^0 ]9 _3 O1 ^2 W资产发行交易没有额外的特殊字段。
7 v1 ?1 u( d, p1 R! K( W& @, a; A资产管理员可以通过资产发行交易,将已经登记过的资产在 NEO 区块链上制造出来,并发送到任意地址。
* t; j2 D1 d8 l特别的,如果发行的资产是 NEO,那么这笔交易将可以免费发送。
. C) @3 b8 I  XClaimTransaction
/ z- h( m; h' Q
尺寸字段数据类型说明
---交易的公共字段
34*?Claimstx_in[]用于分配的 NEO
---交易的公共字段

/ N+ \, x9 Q& D" a8 LEnrollmentTransaction
9 V6 w/ }& f7 T9 _4 X$ ]; g$ e4 u+ E( d- @, k, }
[!Warning]
+ ^6 l% W; h4 k! J! j已弃用,已被智能合约的 Neo.Blockchain.RegisterValidator 所替代。
. {7 M6 _. _" v

$ T4 F! g$ F* q( s$ R- m0 _4 m查看 替代的 .NET 智能合约框架
/ [  y. O$ v9 v3 N+ ]2 L查看 替代智能合约 API 2 ]# k% i% N& r( ^" o- O0 i9 a
RegisterTransaction
( @7 L  Y/ i3 U" O3 O! c/ a. \  f
0 O) E1 L" k. C( ~+ e0 _& K[!Warning]. ~) \9 ^6 _# O  p, W" u
已弃用,已被智能合约的 Neo.Blockchain.CreateAsset 所替代。! j5 d, a9 d: `  m8 r0 x' E
( ]# V8 q; }7 |  _5 T
查看 替代的 .NET 智能合约框架
8 B$ I! y& \9 P6 G/ a4 ~3 S  s查看 替代智能合约 API 6 l1 u: y- `- B! D
ContractTransaction. Q  ^+ M% q- M& c: L" e8 J
合约交易没有任何特殊的地方。& P" T9 U3 }0 Q; N+ @
PublishTransaction
7 S8 u+ S5 ]9 n( Z6 i  _' [: e5 ^/ r4 x
[!Warning]5 h9 [  |1 J( z
已弃用,已被智能合约的 Neo.Blockchain.CreateContract 所替代。6 K8 T4 N2 m/ q; ]* u
' r5 ^/ h! f# `, n
查看 替代的 .NET 智能合约框架
- e( E! A& [; u1 h! q7 K# U查看 替代智能合约 API
- D1 I9 p- i6 e1 D4 rInvocationTransaction
" g  }. Y/ z1 x- v4 ~
尺寸字段数据类型说明
---交易的公共字段
?Scriptuint8[]所调用的智能合约的脚本
8Gasint64运行所调用的智能合约需要的费用
---交易的公共字段
: t" t, K. [+ h- E% Z, u: _
交易特性( _% _% ]; h, n3 ~
尺寸字段数据类型说明
1Usageuint8用途
0|1lengthuint8数据长度(特定情况下会省略)
lengthDatauint8[length]特定于用途的外部数据
" d! B6 s) V/ h- L6 \/ p
有时候交易中会需要包含一些供外部使用的数据,这些数据将统一被放置在交易特性字段中。
/ K' M0 v2 z+ @# h# J' Q每个交易特性可以有不同的用途:1 L+ [  r& J# ^: G3 P! n/ O+ s
名称说明
0x00ContractHash外部合同的散列值
0x02-0x03ECDH02-ECDH03用于 ECDH 密钥交换的公钥
0x20Script用于对交易进行额外的验证
0x30Vote用于投票选出记账人
0x81DescriptionUrl外部介绍信息地址
0x90Description简短的介绍信息
0xa1-0xafHash1-Hash15用于存放自定义的散列值
0xf0-0xffRemark-Remark15备注
0 Z% B6 L! e8 m" S- |+ A
对于 ContractHash,ECDH 系列,Vote,Hash 系列,数据长度固定为 32 字节,length 字段省略;
+ t+ K* `9 u3 ~( S对于 Script,数据长度固定为 20 字节,存放地址;
, R9 b7 A% S% n! b9 @. p对于 DescriptionUrl,必须明确给出数据长度,且长度不能超过 255 字节;
( t. k  ]' K% A  a. Q# |对于 Description 和 Remark 系列,必须明确给出数据长度, 且长度不能超过 65535 字节。3 }9 {4 q$ t* k7 M1 K* i: Y5 O
交易输入% w. X4 G2 S; I/ H0 k2 v
尺寸字段数据类型说明
32PrevHashuint256引用交易的散列值
2PrevIndexuint16引用交易输出的索引

3 k$ K3 X/ q* ~/ B/ a交易输出
" P: c1 F2 I7 {
尺寸字段数据类型说明
32AssetIduint256资产编号
8Valueint64金额
20ScriptHashuint160收款地址

& z+ g8 x) f! q1 K9 }5 d/ r每个交易中最多只能包含 65536 个输出。
8 w1 v. a; s3 B( L验证脚本2 e; [  M' h: X
尺寸字段数据类型说明
?StackScriptuint8[]栈脚本代码
?RedeemScriptuint8[]合约脚本代码
% h) @+ o! Q7 I7 o
栈脚本中只能包含压栈操作指令,用于向合约脚本传递参数(如签名等)。脚本解释器会先执行栈脚本代码,然后执行合约脚本代码。
' V# c3 y; u" f7 Y0 s' H在一笔交易中,合约脚本代码的散列值必须与交易输出中的一致,这是验证的一部分。关于脚本执行的过程,后文会详细阐述。7 k* k7 Y( r" i9 |, r7 b* V" }
网络消息/ W8 ]1 Q4 H2 O9 P
所有的网络消息都通过以下消息结构来发送:+ i' [; A3 {5 M6 P3 w
尺寸字段数据类型说明
4Magicuint32协议标识号
12Commandchar[12]命令
4lengthuint32Payload 的长度
4Checksumuint32校验和
lengthPayloaduint8[length]消息内容

" Q0 s$ t6 L$ z8 e9 H- y已定义的 Magic 值:
! G, z% b! u8 v" ^/ x2 }) `' P6 v3 ?
说明
0x00746e41正式网
0x74746e41测试网

; g4 P  s' O8 L8 K, {# k! sCommand 采用 utf8 编码,长度为 12 字节,多余部分用 0 填充。- s8 e4 P- s: ^1 C1 v$ n9 }
Checksum 是 Payload 两次 SHA256 散列后的前 4 个字节。4 r8 ~! C  f) y, ~( u
Payload 根据不同的命令有不同的详细格式,见下文。
  J+ ~) U/ }  k3 ^! |" }5 M# R- A9 xversion
% d' {/ [6 ?6 H6 w# I6 O" T5 g
尺寸字段数据类型说明
4Versionuint32协议版本,目前为 0
8Servicesuint64节点提供的服务,目前为 1
4Timestampuint32当前时间
2Portuint16监听的端口,如果不监听则为 0
4Nonceuint32用于区分相同公网 IP 的节点
?UserAgentvarstr客户端标识
4StartHeightuint32区块链高度
1Relaybool是否接收并转发

/ {3 |# Y! F" [' e一个节点收到连接请求时,它立即宣告其版本。在通信双方都得到对方版本之前,不会有其他通信。
1 j3 Y/ m/ j) T6 |verack
" o( Z  a8 f1 W9 a  Q, B节点收到 version 消息后,立刻回复一个 verack 作为应答。' E; q  H) P% p9 j' n( R; B
此消息没有 payload。5 u, I& C4 I8 q( m
getaddr
2 z3 G; Q1 {4 I/ H  D4 g向一个节点请求一批新的活动节点,以增加自身的连接数。
+ n/ B" u$ B) w2 `此消息没有 payload。& Q3 G' [1 ]; z# W& d
addr
0 K1 v2 B' `- j- I7 F
尺寸字段数据类型说明
30*?AddressListnet_addr[]网络上其他节点的地址
* ]; e1 s! q) i$ a0 e* [& }  S
节点收到 getaddr 消息后,返回一个 addr 消息作为应答,提供网络上已知节点的信息。6 T3 j/ [5 ~5 i! g$ X4 B8 B% U# Q
getheaders
, {2 ~9 ]# k1 ^6 f0 F
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列

7 {- f' B& R3 ~+ _; P* g" a向一个节点请求包含编号 HashStart 到 HashStop 的至多 2000 个 block 的 header 包。要获取之后的 block 散列,需要重新发送 getheaders 消息。这个消息用于快速下载不包含相关交易的 blockchain。
/ Q9 A. j0 f  g: {" nheaders. c, N) I9 n! z
尺寸字段数据类型说明
?*?Headersheader[]区块头
6 Y+ D0 v2 C, O$ g
节点收到 getheaders 消息后,返回一个 headers 消息作为应答,提供请求的区块头。
1 s' E/ }: g; egetblocks) F( b( \% \+ L4 d% i' }5 G
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列
8 g" O4 Q( K4 F- ]
向一个节点请求包含编号从 HashStart 到 HashStop 的 block 列表的 inv 消息。若 HashStart 到 HashStop 的 block 数超过 500,则在 500 处截止。欲获取后面的 block 散列,需要重新发送 getblocks 消息。
7 d( ~+ O" e& X$ O7 Oinv  i- Y" |# ~; Z. Z. |
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单
6 O" X# x! x4 E( i
节点通过此消息可以广播它拥有的对象信息。这个消息可以主动发送,也可以用于应答 getbloks 消息。
8 i8 F% \1 V3 p& z清单类型有以下几种:0 ?/ o+ Q/ F! I8 l8 O( X
名称说明
0x01TX交易
0x02Block区块
0xe0Consensus共识数据

' Z, w- {: t: Mgetdata
) _3 f( p* d3 S; e" U; z% _
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单

: s; [0 T& j$ Q+ y1 P向一个节点请求指定的对象,它通常在接收到 inv 包并滤去已知元素后发送。
# b2 B- V. @* s/ g) Fblock) Y5 M+ t- }" v% c" k( d
尺寸字段数据类型说明
?Blockblock区块

' {" J: F9 y/ ~向一个节点发送一个区块,用于响应请求数据的 getdata 消息。' a! j: f1 L5 o
tx! x  l/ U; I3 i2 O  g
尺寸字段数据类型说明
?Transactiontx交易

* a: f4 y1 Y& u, a/ {# u8 _# {向一个节点发送一笔交易,用于响应请求数据的 getdata 消息。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

宠着祖宗 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    1