Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

NEO网络协议

宠着祖宗
122 0 0
网络协议
+ \5 ]- \; ?, F6 y1 x: O$ ]在网络结构上,NEO 采用点对点网络结构,并使用 TCP 协议进行通讯。
$ N: e+ w4 n0 U. c) R网络中存在两种节点类型,分别是普通节点和共识节点。普通节点可以广播、接收和转发交易、区块等,而共识节点可以创建区块。2 B; d" Q: P2 Z, x; F
NEO 的网络协议规范与比特币的协议大致类似,但在区块、交易等的数据结构上有很大的不同。2 v+ L6 f$ [; k1 [, V6 u% z2 ~; h! U  w
约定
9 P1 m: W9 E# g$ m字节序/ |$ }- T: f' R( B1 k5 K- W- S( k
NEO 系统中所有的整数类型都是采用小端序 (Little Endian) 编码,只有 IP 地址和端口号采用大端序 (Big Endian) 编码。6 o2 i. n  r! m' t. j6 A
散列
% q# U( J4 l4 `NEO 系统中会用到 2 种不同的散列函数:SHA256 和 RIPEMD160。前者用于生成较长的散列值,而后者用于生成较短的散列值。通常生成一个对象的散列值时,会运用两次散列函数,例如要生成区块或交易的散列时,会计算两次 SHA256;生成合约地址时,会先计算脚本的 SHA256 散列,然后再计算上一个散列的 RIPEMD160 散列。
1 k* ~  f/ d* O8 V/ K此外,区块中还会用到一种散列树 (Merkle Tree) 的结构,它将每一笔交易的散列两两相接后再计算一次散列,并重复以上过程直到只剩下一个根散列 (Merkle Root)。
5 H* W. M- @5 w0 r% K* e变长类型
& `. i! N/ x3 b- g/ g$ g0 hvarint:变长整数,可以根据表达的值进行编码以节省空间。, b( h/ C, }" ?1 W
长度格式
0xffffffff90xff + uint64
, m7 L  `% u7 w/ }4 B- f9 \' \
varstr:变长字符串,由一个变长整数后接字符串构成。字符串采用 UTF8 编码。. Y) }* g& d' s/ @6 S7 D- M8 k0 E" B
尺寸字段数据类型说明
?lengthvarint字符串的长度,以字节为单位
lengthstringuint8[length]字符串本身

0 F" g2 ^4 Q/ A; ?5 h* p( Q: T, Parray:数组,由一个变长整数后接元素序列构成。( R  m3 G5 n& k2 b6 \; x# J
定点数5 i* E2 X7 s: A
NEO 系统中的金额、价格等数据,统一采用 64 位定点数,小数部分精确到 10-8,可表示的范围是:[-263/108, +263/108)9 R7 |' @( p6 O. A2 M
数据结构
* C1 q0 J; D: o# h* ]- g/ I区块链
2 S1 c0 ]& s5 Y2 E% u区块链是一种逻辑结构,它以单向链表的形式将区块串联起来,用于存放全网的交易、资产等数据。8 M: }( L+ I+ u8 k5 {
区块
9 c8 z! s; I# @: D+ W8 U$ W0 d" V
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
?*?Transactionstx[]交易列表
9 W6 s, \. j, e& c3 ~( K* B
在计算区块散列时,并不会把整个区块都计算在内,而是只计算区块头的前 7 个字段:Version, PrevBlock, MerkleRoot, Timestamp, Height, Nonce, NextMiner。由于 MerkleRoot 已经包含了所有交易的散列值,因此修改交易也会改变区块的散列值。- ?0 c2 ~1 p* Z" T" c
区块头的数据结构如下:8 ?8 K: e9 [1 V2 ~
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
1-uint8固定为 0

& D5 [( _/ S2 N0 `9 l每个区块的时间戳必须晚于前一个区块的时间戳,一般两个区块的时间戳相差 15 秒左右,但是也允许出现不精确的情况。区块的高度值必须恰好等于前一个区块的高度值加一。
$ G$ R9 P, q- C% T5 F; ?9 v; A% t交易
! e8 E8 t3 E. D. \3 I3 O
尺寸字段数据类型说明
1Typeuint8交易类型
1Versionuint8交易版本,目前为 0
?--特定于交易类型的数据
?*?Attributestx_attr[]该交易所具备的额外特性
34*?Inputstx_in[]输入
60*?Outputstx_out[]输出
?*?Scriptsscript[]用于验证该交易的脚本列表

' W' G$ m# p$ @, t6 [7 fNEO 系统中的一切事务都以交易为单位进行记录。交易有以下几种类型:
6 H7 X- {* s; v+ O! e
名称系统费用说明
0x00MinerTransaction0用于分配字节费的交易
0x01IssueTransaction500|0用于分发资产的交易
0x02ClaimTransaction0用于分配 NeoGas 的交易
0x20EnrollmentTransaction1000(已弃用) 用于报名成为共识候选人的特殊交易
0x40RegisterTransaction10000|0(已弃用) 用于资产登记的交易
0x80ContractTransaction0合约交易,这是最常用的一种交易
0xd0PublishTransaction500*n(已弃用)智能合约发布的特殊交易
0xd1InvocationTransaction0调用智能合约的特殊交易

$ R# S: n& J" t. p. s每一种类型的交易除了具有交易的公共字段之外,还会具有自己的专属字段。关于不同类型交易的专属字段,下文会有详细说明。
$ e( n2 y9 N7 i2 q4 e# d2 d3 u& RMinerTransaction
( b+ G  w! c; X% ~9 b5 O
尺寸字段数据类型说明
---交易的公共字段
4Nonceuint32随机数
---交易的公共字段
$ G  l& g- d# [/ P# R0 z
每一个区块的第一笔交易必然是 MinerTransaction。它用于将当前区块中所有的交易手续费奖励给记账人。* H9 y) X9 A4 J- l4 C+ N- f0 u7 n8 s
交易中的随机数用于防止出现散列冲突。6 K, T2 ?( i# J9 z! h; z
IssueTransaction' r! ]! g6 ^2 t. p
资产发行交易没有额外的特殊字段。$ p: z& k/ s+ R# K7 o- }  E
资产管理员可以通过资产发行交易,将已经登记过的资产在 NEO 区块链上制造出来,并发送到任意地址。
, l0 U6 p0 A- e3 j' w特别的,如果发行的资产是 NEO,那么这笔交易将可以免费发送。' P$ S. i7 e4 W; n
ClaimTransaction
# l$ {9 j* i& T6 V; Z
尺寸字段数据类型说明
---交易的公共字段
34*?Claimstx_in[]用于分配的 NEO
---交易的公共字段

* m- R+ ]2 G1 N: t/ a2 r$ EEnrollmentTransaction$ F$ p! d& Q- }
, Q/ ^% K6 ^* B7 r; `, q* ]/ R& |& ~) n
[!Warning]
1 ?; Y8 M/ J6 o已弃用,已被智能合约的 Neo.Blockchain.RegisterValidator 所替代。" a1 n1 s6 P+ \; W; z
2 H+ P4 Y* u5 |  |1 m
查看 替代的 .NET 智能合约框架
7 G" A' k  G5 H0 w8 g/ D查看 替代智能合约 API
0 U4 j# D# E" o# T/ f: k5 aRegisterTransaction" S/ T7 a8 x  U, d! _
3 V# o9 v0 K7 p- O- _4 O. G; x
[!Warning], b, T0 h* g( I5 r
已弃用,已被智能合约的 Neo.Blockchain.CreateAsset 所替代。
# G* F5 d- k$ l: F
1 V2 \' U9 D, C
查看 替代的 .NET 智能合约框架
/ f! R( r, ?- z查看 替代智能合约 API
. j' B+ u7 ~9 Z6 U! YContractTransaction, C) C! e* o& U: ]: a4 c9 k
合约交易没有任何特殊的地方。
$ n, s% H# L" A; K9 f( QPublishTransaction
  D6 o0 Z3 L: r3 d2 c5 c* K. J$ L4 [( ^7 Q3 i. {. R0 S% P
[!Warning]7 E6 _/ D/ E) [  t* S% w9 Y
已弃用,已被智能合约的 Neo.Blockchain.CreateContract 所替代。3 ~0 _0 |0 L8 [
: d# @& j" G, G  D
查看 替代的 .NET 智能合约框架- Z$ \& J# k- b0 j/ k( s+ N: Q
查看 替代智能合约 API
3 [+ q: ~- K6 A( d& T: lInvocationTransaction
" H% Q# Y/ |( b+ m6 g
尺寸字段数据类型说明
---交易的公共字段
?Scriptuint8[]所调用的智能合约的脚本
8Gasint64运行所调用的智能合约需要的费用
---交易的公共字段
  n% c3 Q0 A# c+ ]  s$ `5 w" A1 Z
交易特性
' e# q# C" s& O; B9 S6 Z) K
尺寸字段数据类型说明
1Usageuint8用途
0|1lengthuint8数据长度(特定情况下会省略)
lengthDatauint8[length]特定于用途的外部数据
0 l9 _5 q+ f+ N0 s4 O
有时候交易中会需要包含一些供外部使用的数据,这些数据将统一被放置在交易特性字段中。
1 ?% h0 i7 o5 }每个交易特性可以有不同的用途:3 M/ E" O! H  F+ `/ L
名称说明
0x00ContractHash外部合同的散列值
0x02-0x03ECDH02-ECDH03用于 ECDH 密钥交换的公钥
0x20Script用于对交易进行额外的验证
0x30Vote用于投票选出记账人
0x81DescriptionUrl外部介绍信息地址
0x90Description简短的介绍信息
0xa1-0xafHash1-Hash15用于存放自定义的散列值
0xf0-0xffRemark-Remark15备注
) l7 C" B3 b1 H! t- v
对于 ContractHash,ECDH 系列,Vote,Hash 系列,数据长度固定为 32 字节,length 字段省略;
* E# N  t1 N8 u/ p4 C对于 Script,数据长度固定为 20 字节,存放地址;
) Q( w" K0 O" a0 E* r, V对于 DescriptionUrl,必须明确给出数据长度,且长度不能超过 255 字节;% e4 K- |- a: B5 c% f1 n1 i
对于 Description 和 Remark 系列,必须明确给出数据长度, 且长度不能超过 65535 字节。
7 ^& U$ _0 G  `( U1 P交易输入
+ ^# V4 f: D$ k& z; p7 |% v0 D
尺寸字段数据类型说明
32PrevHashuint256引用交易的散列值
2PrevIndexuint16引用交易输出的索引

$ {+ N( E5 e  q交易输出4 P! L( V3 p; W" X
尺寸字段数据类型说明
32AssetIduint256资产编号
8Valueint64金额
20ScriptHashuint160收款地址
8 w: o; K0 r2 \, L  e" [3 j, ?
每个交易中最多只能包含 65536 个输出。
! X4 i# Z" s. R4 L4 p6 W" J验证脚本; \+ u% m* o7 _0 ^
尺寸字段数据类型说明
?StackScriptuint8[]栈脚本代码
?RedeemScriptuint8[]合约脚本代码

! D) q, r  ]) ]; m- _! ?2 D$ r$ |栈脚本中只能包含压栈操作指令,用于向合约脚本传递参数(如签名等)。脚本解释器会先执行栈脚本代码,然后执行合约脚本代码。! q5 j. c) K5 Q" k
在一笔交易中,合约脚本代码的散列值必须与交易输出中的一致,这是验证的一部分。关于脚本执行的过程,后文会详细阐述。+ `( b, }# N$ R$ x  j
网络消息& `5 s0 q7 j! J* \! o- d4 `
所有的网络消息都通过以下消息结构来发送:
# p$ Y/ G! }7 e  J6 E9 W8 C3 H: E7 C3 w
尺寸字段数据类型说明
4Magicuint32协议标识号
12Commandchar[12]命令
4lengthuint32Payload 的长度
4Checksumuint32校验和
lengthPayloaduint8[length]消息内容

0 f$ V7 N) A0 D6 K! v) c8 z$ m2 Z6 f已定义的 Magic 值:
: V( N* u  n0 a( n
说明
0x00746e41正式网
0x74746e41测试网

$ Q! y) L; n. g+ |$ jCommand 采用 utf8 编码,长度为 12 字节,多余部分用 0 填充。$ b2 i4 s' Z+ B9 Y- z( }- D
Checksum 是 Payload 两次 SHA256 散列后的前 4 个字节。) n2 W- m- K3 Q: c: L5 C8 @6 k, S
Payload 根据不同的命令有不同的详细格式,见下文。
  P+ X8 D, l# nversion
( \6 j+ F' P/ @+ q9 X
尺寸字段数据类型说明
4Versionuint32协议版本,目前为 0
8Servicesuint64节点提供的服务,目前为 1
4Timestampuint32当前时间
2Portuint16监听的端口,如果不监听则为 0
4Nonceuint32用于区分相同公网 IP 的节点
?UserAgentvarstr客户端标识
4StartHeightuint32区块链高度
1Relaybool是否接收并转发
5 z1 V  B1 ^4 `: i
一个节点收到连接请求时,它立即宣告其版本。在通信双方都得到对方版本之前,不会有其他通信。
3 G, }1 X' j* j( Lverack9 h# w1 z/ p8 K# Q" C+ ?
节点收到 version 消息后,立刻回复一个 verack 作为应答。2 C* i* d( i. F$ a
此消息没有 payload。
% J8 m& |- k* V* N: {getaddr& t, T+ s' D* M: L9 N
向一个节点请求一批新的活动节点,以增加自身的连接数。1 P$ u6 s. G; W
此消息没有 payload。5 N7 O3 ?  p( D5 w- G
addr1 T5 ]2 W1 `4 ]  B& O
尺寸字段数据类型说明
30*?AddressListnet_addr[]网络上其他节点的地址
% Q: [# ]' }7 q2 `2 g( o
节点收到 getaddr 消息后,返回一个 addr 消息作为应答,提供网络上已知节点的信息。
* N7 |6 Y; R+ q0 igetheaders+ D/ p! Z5 I9 |, i. I1 Y1 I
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列
+ C; p6 h' _8 `$ Z1 f# }
向一个节点请求包含编号 HashStart 到 HashStop 的至多 2000 个 block 的 header 包。要获取之后的 block 散列,需要重新发送 getheaders 消息。这个消息用于快速下载不包含相关交易的 blockchain。
5 a1 v/ Q1 r* \! d+ Oheaders  }# \# r9 G4 ]0 G4 d* I) ]
尺寸字段数据类型说明
?*?Headersheader[]区块头

! G+ o' {) e1 v2 F2 n5 N9 z节点收到 getheaders 消息后,返回一个 headers 消息作为应答,提供请求的区块头。* D) J7 R" p" z2 N# Z1 v+ g6 b# Y
getblocks6 X4 {/ Q$ _6 C9 v  ~
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列

$ u% ]% Q& H0 n0 v5 ^% S: _向一个节点请求包含编号从 HashStart 到 HashStop 的 block 列表的 inv 消息。若 HashStart 到 HashStop 的 block 数超过 500,则在 500 处截止。欲获取后面的 block 散列,需要重新发送 getblocks 消息。" |. e$ c' E( a3 |# b% s
inv  g! X  }+ D% B
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单

- y9 f- {, {; d% }/ O- R节点通过此消息可以广播它拥有的对象信息。这个消息可以主动发送,也可以用于应答 getbloks 消息。# z2 K( c' F9 Z
清单类型有以下几种:. f, Z2 T) X& t( {. l
名称说明
0x01TX交易
0x02Block区块
0xe0Consensus共识数据

8 n( a7 g1 O' Q3 k& \getdata2 K  j) j) J0 b9 T
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单
  m" g! t2 J0 G5 ^( g
向一个节点请求指定的对象,它通常在接收到 inv 包并滤去已知元素后发送。, h- N4 l1 x( Q( k% Q9 H) U
block
9 _7 g2 h8 ]# g, \3 W. e
尺寸字段数据类型说明
?Blockblock区块
! B1 t/ b$ T$ k1 d4 U$ {
向一个节点发送一个区块,用于响应请求数据的 getdata 消息。: K- {* T: ^3 Q( ]
tx3 ^) h8 e. p& h/ [* b
尺寸字段数据类型说明
?Transactiontx交易

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

本版积分规则

成为第一个吐槽的人

宠着祖宗 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    1