Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

NEO网络协议

宠着祖宗
153 0 0
网络协议* j6 E. d/ `6 `8 `  m
在网络结构上,NEO 采用点对点网络结构,并使用 TCP 协议进行通讯。, ^& ^( Q! `3 C" V% X) ?# Y
网络中存在两种节点类型,分别是普通节点和共识节点。普通节点可以广播、接收和转发交易、区块等,而共识节点可以创建区块。
9 i0 M( s5 H  J' ]8 D/ GNEO 的网络协议规范与比特币的协议大致类似,但在区块、交易等的数据结构上有很大的不同。
; t" G3 z9 [( z+ {3 C9 a约定/ r6 k7 V7 i& s$ A4 W
字节序3 {# T* a' e, m7 p/ Q. N( d1 _  u
NEO 系统中所有的整数类型都是采用小端序 (Little Endian) 编码,只有 IP 地址和端口号采用大端序 (Big Endian) 编码。' d1 t$ r* l: X# W- U
散列
+ g9 J/ g- y- X& B5 sNEO 系统中会用到 2 种不同的散列函数:SHA256 和 RIPEMD160。前者用于生成较长的散列值,而后者用于生成较短的散列值。通常生成一个对象的散列值时,会运用两次散列函数,例如要生成区块或交易的散列时,会计算两次 SHA256;生成合约地址时,会先计算脚本的 SHA256 散列,然后再计算上一个散列的 RIPEMD160 散列。' X+ h1 [+ d9 E) ?, s) p
此外,区块中还会用到一种散列树 (Merkle Tree) 的结构,它将每一笔交易的散列两两相接后再计算一次散列,并重复以上过程直到只剩下一个根散列 (Merkle Root)。
$ y- f0 l+ H6 D$ B变长类型
: g# t4 B. ?  a) M7 avarint:变长整数,可以根据表达的值进行编码以节省空间。
" C0 N7 ^3 n% [3 B2 T' n4 ]8 F
长度格式
0xffffffff90xff + uint64
7 i. f  M3 x5 G; C# X3 g
varstr:变长字符串,由一个变长整数后接字符串构成。字符串采用 UTF8 编码。! F. D( u2 K  L
尺寸字段数据类型说明
?lengthvarint字符串的长度,以字节为单位
lengthstringuint8[length]字符串本身

" w. G; r; ]+ R* n' \" d2 garray:数组,由一个变长整数后接元素序列构成。' q$ y6 d7 F3 V  @
定点数& A7 K/ {& s$ K3 ~, u  Q( H% }6 s
NEO 系统中的金额、价格等数据,统一采用 64 位定点数,小数部分精确到 10-8,可表示的范围是:[-263/108, +263/108)
, X$ u& G4 A3 ~) o数据结构
/ x  ~& T; t8 W7 g2 F( ?区块链
( P7 S# w5 g  v* p% m4 A$ {区块链是一种逻辑结构,它以单向链表的形式将区块串联起来,用于存放全网的交易、资产等数据。0 l. x" p- e& y* ~
区块* ~+ O3 H1 A- [7 E7 ~1 R4 _/ h8 q/ Y
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
?*?Transactionstx[]交易列表
: P" P# m% k& t: i) k/ V
在计算区块散列时,并不会把整个区块都计算在内,而是只计算区块头的前 7 个字段:Version, PrevBlock, MerkleRoot, Timestamp, Height, Nonce, NextMiner。由于 MerkleRoot 已经包含了所有交易的散列值,因此修改交易也会改变区块的散列值。
; U, R- n# i& r4 Q. a区块头的数据结构如下:
6 F1 r9 _/ m: d; M, Y6 C
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
1-uint8固定为 0

, c5 S( `: K# @& }2 c每个区块的时间戳必须晚于前一个区块的时间戳,一般两个区块的时间戳相差 15 秒左右,但是也允许出现不精确的情况。区块的高度值必须恰好等于前一个区块的高度值加一。. V5 F. A+ @4 f: m0 F# ?. y
交易1 r3 P7 w2 |4 i- g
尺寸字段数据类型说明
1Typeuint8交易类型
1Versionuint8交易版本,目前为 0
?--特定于交易类型的数据
?*?Attributestx_attr[]该交易所具备的额外特性
34*?Inputstx_in[]输入
60*?Outputstx_out[]输出
?*?Scriptsscript[]用于验证该交易的脚本列表
" c: f' g) E3 I+ d9 g0 x
NEO 系统中的一切事务都以交易为单位进行记录。交易有以下几种类型:: W- r7 U' p* {! D" `/ W
名称系统费用说明
0x00MinerTransaction0用于分配字节费的交易
0x01IssueTransaction500|0用于分发资产的交易
0x02ClaimTransaction0用于分配 NeoGas 的交易
0x20EnrollmentTransaction1000(已弃用) 用于报名成为共识候选人的特殊交易
0x40RegisterTransaction10000|0(已弃用) 用于资产登记的交易
0x80ContractTransaction0合约交易,这是最常用的一种交易
0xd0PublishTransaction500*n(已弃用)智能合约发布的特殊交易
0xd1InvocationTransaction0调用智能合约的特殊交易

% `6 ?' ]7 A/ y- q) N2 z9 r每一种类型的交易除了具有交易的公共字段之外,还会具有自己的专属字段。关于不同类型交易的专属字段,下文会有详细说明。
% D8 M4 a9 e4 I2 h5 n! W1 fMinerTransaction0 R' }4 Q' ^4 y9 n2 x
尺寸字段数据类型说明
---交易的公共字段
4Nonceuint32随机数
---交易的公共字段
7 t3 \# C' X: I+ w; e3 Y# L+ f: w) d
每一个区块的第一笔交易必然是 MinerTransaction。它用于将当前区块中所有的交易手续费奖励给记账人。, L% Z7 N- j" X" e! C8 B! m
交易中的随机数用于防止出现散列冲突。6 d7 @' S9 f, u" A& U2 {+ l
IssueTransaction
  R( {7 @( ~* ]/ S/ \资产发行交易没有额外的特殊字段。) v' B% T2 b( q  v. p
资产管理员可以通过资产发行交易,将已经登记过的资产在 NEO 区块链上制造出来,并发送到任意地址。* i3 V- e  e1 B$ a' f0 _( g
特别的,如果发行的资产是 NEO,那么这笔交易将可以免费发送。
1 r9 E+ j& f) [5 v; V2 UClaimTransaction
/ q/ P' K# l7 w9 T- N7 k9 @& {
尺寸字段数据类型说明
---交易的公共字段
34*?Claimstx_in[]用于分配的 NEO
---交易的公共字段
: f: O. Y) T0 c( m! R5 i  I, H
EnrollmentTransaction
& A+ Q" }' T- V1 F2 N7 t/ `# c2 L, ?/ Y
[!Warning]
  }) q" }$ @0 W已弃用,已被智能合约的 Neo.Blockchain.RegisterValidator 所替代。
0 ?  c( _) L( m4 s( K# H
7 L# ~$ u2 E* m# Q8 x  V( Q6 ~  I8 O/ |
查看 替代的 .NET 智能合约框架. a" O9 ^/ |/ F. @- l% t. }' p
查看 替代智能合约 API
) a9 f1 V4 |5 _" o, F  K; NRegisterTransaction
* R8 a: e" n# _' _, y, o8 I* w5 K! `1 K4 c7 f
[!Warning]& }6 D4 N8 p9 r* H
已弃用,已被智能合约的 Neo.Blockchain.CreateAsset 所替代。
# x! Z1 |5 v; I5 S# _  _! a
5 [2 I+ C+ w$ c
查看 替代的 .NET 智能合约框架0 c; z, ~& f; Y) n
查看 替代智能合约 API + V, ~- p( N! l5 O/ s7 C+ Z' H
ContractTransaction0 U7 j# h( ], W
合约交易没有任何特殊的地方。
1 }1 X( ?  R) K- [; m! O9 ZPublishTransaction
3 z+ r! u  L4 f3 m# y# _  A& s6 ?. S! B$ {
[!Warning]
3 @4 n7 P+ f$ p# z/ m! _; H2 Y0 @: v已弃用,已被智能合约的 Neo.Blockchain.CreateContract 所替代。
" c. ?4 x9 O1 M4 L* h; E  A
1 K' W5 p* m, N8 q
查看 替代的 .NET 智能合约框架
) m3 ?8 y7 A- ]. s0 p查看 替代智能合约 API
6 q! H2 h, D9 {- ~4 YInvocationTransaction
2 o4 H% l( Q6 s( x+ r; F6 W2 L8 `
尺寸字段数据类型说明
---交易的公共字段
?Scriptuint8[]所调用的智能合约的脚本
8Gasint64运行所调用的智能合约需要的费用
---交易的公共字段
2 u( P) p* D3 ~/ m2 c1 c
交易特性
" E5 G1 o( P. n; m! y* \
尺寸字段数据类型说明
1Usageuint8用途
0|1lengthuint8数据长度(特定情况下会省略)
lengthDatauint8[length]特定于用途的外部数据

' l+ W; P# F' k1 p6 X- P有时候交易中会需要包含一些供外部使用的数据,这些数据将统一被放置在交易特性字段中。/ r6 k' t6 c2 c
每个交易特性可以有不同的用途:
* U% e7 C# Q  {" [
名称说明
0x00ContractHash外部合同的散列值
0x02-0x03ECDH02-ECDH03用于 ECDH 密钥交换的公钥
0x20Script用于对交易进行额外的验证
0x30Vote用于投票选出记账人
0x81DescriptionUrl外部介绍信息地址
0x90Description简短的介绍信息
0xa1-0xafHash1-Hash15用于存放自定义的散列值
0xf0-0xffRemark-Remark15备注

( M) ^6 w, t8 `/ r& Y对于 ContractHash,ECDH 系列,Vote,Hash 系列,数据长度固定为 32 字节,length 字段省略;
! f' z! P6 w$ p+ ~  ~; p6 k9 [. Q) y对于 Script,数据长度固定为 20 字节,存放地址;7 _& }5 R3 e6 ]: f  Z
对于 DescriptionUrl,必须明确给出数据长度,且长度不能超过 255 字节;
; A/ ~2 X1 Y3 Z% X6 P: Q对于 Description 和 Remark 系列,必须明确给出数据长度, 且长度不能超过 65535 字节。
4 _% K4 @. [/ V3 v交易输入
* Y5 I1 |1 O) w; s3 K  z5 ?
尺寸字段数据类型说明
32PrevHashuint256引用交易的散列值
2PrevIndexuint16引用交易输出的索引
' D/ g/ X8 _3 ^6 H6 y. ?
交易输出: p; V7 C! l# x, u, R
尺寸字段数据类型说明
32AssetIduint256资产编号
8Valueint64金额
20ScriptHashuint160收款地址
1 H! w" x0 ]# ~5 s, r9 Y
每个交易中最多只能包含 65536 个输出。
% m0 F! O7 {+ K& N$ c' a验证脚本
* R* N* p9 J$ p: I
尺寸字段数据类型说明
?StackScriptuint8[]栈脚本代码
?RedeemScriptuint8[]合约脚本代码
" A: K$ \* O( x/ \( s  ^
栈脚本中只能包含压栈操作指令,用于向合约脚本传递参数(如签名等)。脚本解释器会先执行栈脚本代码,然后执行合约脚本代码。5 ~3 S, X* z( M9 f
在一笔交易中,合约脚本代码的散列值必须与交易输出中的一致,这是验证的一部分。关于脚本执行的过程,后文会详细阐述。
1 S( x* l, h* P9 O网络消息9 A3 @! P& r) R/ _% D
所有的网络消息都通过以下消息结构来发送:
( G& B8 B7 Z9 T+ e1 o
尺寸字段数据类型说明
4Magicuint32协议标识号
12Commandchar[12]命令
4lengthuint32Payload 的长度
4Checksumuint32校验和
lengthPayloaduint8[length]消息内容

- l$ }& B$ c& o; \已定义的 Magic 值:
0 J0 T" c* O& u& a# ]
说明
0x00746e41正式网
0x74746e41测试网
3 w' N, Q1 O6 ?* h! A7 j
Command 采用 utf8 编码,长度为 12 字节,多余部分用 0 填充。* a* V2 X2 w- u1 A3 Q: s4 A
Checksum 是 Payload 两次 SHA256 散列后的前 4 个字节。
( f3 W9 t3 |2 pPayload 根据不同的命令有不同的详细格式,见下文。. J$ ^0 R! `7 x) t" j
version/ \1 x, T! L0 Q3 `* X2 X, O
尺寸字段数据类型说明
4Versionuint32协议版本,目前为 0
8Servicesuint64节点提供的服务,目前为 1
4Timestampuint32当前时间
2Portuint16监听的端口,如果不监听则为 0
4Nonceuint32用于区分相同公网 IP 的节点
?UserAgentvarstr客户端标识
4StartHeightuint32区块链高度
1Relaybool是否接收并转发
* X# |4 k2 p' P2 k8 y
一个节点收到连接请求时,它立即宣告其版本。在通信双方都得到对方版本之前,不会有其他通信。1 ^1 F3 ^* F" B- g6 C4 E) @) b
verack
5 V5 k1 x: `$ R3 @5 E. [+ \节点收到 version 消息后,立刻回复一个 verack 作为应答。
  `$ j: }: ?' o/ o4 R3 _此消息没有 payload。
" ]# i( B3 s+ x: Cgetaddr5 C0 h' @$ C! z" G
向一个节点请求一批新的活动节点,以增加自身的连接数。
9 l! k( W6 Q  p- Y此消息没有 payload。4 `7 z4 A+ M  z2 ~0 ~
addr
; x7 Z$ a# o7 B$ B- S* c# M$ p
尺寸字段数据类型说明
30*?AddressListnet_addr[]网络上其他节点的地址

5 P8 y" D6 s. T6 M* U节点收到 getaddr 消息后,返回一个 addr 消息作为应答,提供网络上已知节点的信息。1 T% d# k) m; k5 W4 z4 J4 r
getheaders7 c; G8 x$ t/ W* g
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列
8 K$ Q" `. l/ ]0 X3 [
向一个节点请求包含编号 HashStart 到 HashStop 的至多 2000 个 block 的 header 包。要获取之后的 block 散列,需要重新发送 getheaders 消息。这个消息用于快速下载不包含相关交易的 blockchain。7 l) b2 J& B! Q- o, O7 v: y
headers
* C4 x! t/ k) i% e& a% I. v
尺寸字段数据类型说明
?*?Headersheader[]区块头
1 A* Z. F6 n4 X0 E% u' V# p
节点收到 getheaders 消息后,返回一个 headers 消息作为应答,提供请求的区块头。8 Y* X  |' x0 B1 ^6 p
getblocks
3 ]* z5 U/ T1 l) _& t
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列

# [& P) [* X2 E) K3 t& K. [" p向一个节点请求包含编号从 HashStart 到 HashStop 的 block 列表的 inv 消息。若 HashStart 到 HashStop 的 block 数超过 500,则在 500 处截止。欲获取后面的 block 散列,需要重新发送 getblocks 消息。/ Q- O9 E' O' K  j( e4 o
inv
3 h& ^8 z9 k$ D5 w; H* \; P3 I% L* K2 h
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单

5 m0 K1 y- m5 }( c节点通过此消息可以广播它拥有的对象信息。这个消息可以主动发送,也可以用于应答 getbloks 消息。# T+ ^* l7 r* s5 q8 ?: K
清单类型有以下几种:
2 C) O8 ]5 M# K8 F- }; d
名称说明
0x01TX交易
0x02Block区块
0xe0Consensus共识数据

, y* Z: u$ w2 V) M# A/ cgetdata
6 p9 `" l  O. i3 i, W8 F) L
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单

4 A6 j% H8 u4 Y& U& ^' E向一个节点请求指定的对象,它通常在接收到 inv 包并滤去已知元素后发送。0 Y' m" }  M+ p' a
block. _$ q5 x2 u! M& c' g2 G) |! L
尺寸字段数据类型说明
?Blockblock区块
7 l  X) g+ [9 Z8 v
向一个节点发送一个区块,用于响应请求数据的 getdata 消息。, b% \/ `! e' L+ _8 X' W
tx$ m) L6 k4 d+ d3 y4 [+ }
尺寸字段数据类型说明
?Transactiontx交易

1 D; Y9 v! M! {! C0 _3 g0 k: T6 r向一个节点发送一笔交易,用于响应请求数据的 getdata 消息。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

宠着祖宗 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    1