Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

NEO网络协议

宠着祖宗
163 0 0
网络协议
) g2 O" {& V# @) Z/ \6 K在网络结构上,NEO 采用点对点网络结构,并使用 TCP 协议进行通讯。
4 b  a3 C( @# F, Y* I! F9 ~网络中存在两种节点类型,分别是普通节点和共识节点。普通节点可以广播、接收和转发交易、区块等,而共识节点可以创建区块。
. a5 o6 A4 m) ]* U- oNEO 的网络协议规范与比特币的协议大致类似,但在区块、交易等的数据结构上有很大的不同。
  J+ Q1 B7 J' E/ A# u; ^8 Z约定
" h: k) ?3 l& ]0 T7 i字节序
& d' l8 Y9 {' Z3 MNEO 系统中所有的整数类型都是采用小端序 (Little Endian) 编码,只有 IP 地址和端口号采用大端序 (Big Endian) 编码。& z3 j# z2 q1 l5 p" j$ l
散列
" W* q" N9 ?- H0 Y: I- O' yNEO 系统中会用到 2 种不同的散列函数:SHA256 和 RIPEMD160。前者用于生成较长的散列值,而后者用于生成较短的散列值。通常生成一个对象的散列值时,会运用两次散列函数,例如要生成区块或交易的散列时,会计算两次 SHA256;生成合约地址时,会先计算脚本的 SHA256 散列,然后再计算上一个散列的 RIPEMD160 散列。, _/ \8 a: L! c
此外,区块中还会用到一种散列树 (Merkle Tree) 的结构,它将每一笔交易的散列两两相接后再计算一次散列,并重复以上过程直到只剩下一个根散列 (Merkle Root)。
6 b1 {2 k  _4 r变长类型
' f5 C8 X3 r  E% O5 V4 N2 Ivarint:变长整数,可以根据表达的值进行编码以节省空间。
/ v. ]: S& z7 m% {
长度格式
0xffffffff90xff + uint64

, I) z* ?7 R1 p' l; svarstr:变长字符串,由一个变长整数后接字符串构成。字符串采用 UTF8 编码。
; S0 I9 k4 W% U; Q1 X$ T- r) H
尺寸字段数据类型说明
?lengthvarint字符串的长度,以字节为单位
lengthstringuint8[length]字符串本身

9 b' B4 [" j- ^1 u2 ]) ^7 K+ ?8 ^array:数组,由一个变长整数后接元素序列构成。
7 `+ V& y% Y% i( w  I定点数
- o3 X2 b2 j% X; D( w% ~NEO 系统中的金额、价格等数据,统一采用 64 位定点数,小数部分精确到 10-8,可表示的范围是:[-263/108, +263/108). s: b2 I! C' ?: h' |* N0 o
数据结构' o, j1 W% i5 g; J9 o
区块链
6 e6 F% e' o# ?: y区块链是一种逻辑结构,它以单向链表的形式将区块串联起来,用于存放全网的交易、资产等数据。
& i6 p! `; i. t) z区块0 |* @6 i, g& ]1 p7 E; u! C& V
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
?*?Transactionstx[]交易列表

7 N  c# c4 b3 c! x- y在计算区块散列时,并不会把整个区块都计算在内,而是只计算区块头的前 7 个字段:Version, PrevBlock, MerkleRoot, Timestamp, Height, Nonce, NextMiner。由于 MerkleRoot 已经包含了所有交易的散列值,因此修改交易也会改变区块的散列值。  R, i5 c' Q6 T$ O1 H5 I+ W
区块头的数据结构如下:
) I+ q- n" P, ^& y
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
1-uint8固定为 0

2 n! N% P' Q* Q# j0 O每个区块的时间戳必须晚于前一个区块的时间戳,一般两个区块的时间戳相差 15 秒左右,但是也允许出现不精确的情况。区块的高度值必须恰好等于前一个区块的高度值加一。$ w) S( n+ L; w% j: P3 e# y' D- ~& N
交易- c$ u2 @6 S( k$ x. m  P0 _* i) w
尺寸字段数据类型说明
1Typeuint8交易类型
1Versionuint8交易版本,目前为 0
?--特定于交易类型的数据
?*?Attributestx_attr[]该交易所具备的额外特性
34*?Inputstx_in[]输入
60*?Outputstx_out[]输出
?*?Scriptsscript[]用于验证该交易的脚本列表
  t. l- a5 a- M; g
NEO 系统中的一切事务都以交易为单位进行记录。交易有以下几种类型:
9 [3 u; L- x) I! o2 m! D
名称系统费用说明
0x00MinerTransaction0用于分配字节费的交易
0x01IssueTransaction500|0用于分发资产的交易
0x02ClaimTransaction0用于分配 NeoGas 的交易
0x20EnrollmentTransaction1000(已弃用) 用于报名成为共识候选人的特殊交易
0x40RegisterTransaction10000|0(已弃用) 用于资产登记的交易
0x80ContractTransaction0合约交易,这是最常用的一种交易
0xd0PublishTransaction500*n(已弃用)智能合约发布的特殊交易
0xd1InvocationTransaction0调用智能合约的特殊交易

3 |; f6 Z! [8 Q$ Z每一种类型的交易除了具有交易的公共字段之外,还会具有自己的专属字段。关于不同类型交易的专属字段,下文会有详细说明。
5 \( @8 H' x7 D- @- hMinerTransaction
% Z9 P* ^1 I* z7 [6 z  ?
尺寸字段数据类型说明
---交易的公共字段
4Nonceuint32随机数
---交易的公共字段

9 O8 t/ l; A) Y$ b% V每一个区块的第一笔交易必然是 MinerTransaction。它用于将当前区块中所有的交易手续费奖励给记账人。
, E1 t& v, j. \1 @5 u8 e1 K交易中的随机数用于防止出现散列冲突。; N9 x8 U! J: i2 s& f! n
IssueTransaction2 B0 m7 l% A8 D  l9 W3 m3 e
资产发行交易没有额外的特殊字段。5 i! k; i& f& T( `& A; j0 y
资产管理员可以通过资产发行交易,将已经登记过的资产在 NEO 区块链上制造出来,并发送到任意地址。
" U% y& b+ V7 X特别的,如果发行的资产是 NEO,那么这笔交易将可以免费发送。6 R7 \! j) d6 |9 X
ClaimTransaction
, l. h0 v# I0 v- |. |" t# ?
尺寸字段数据类型说明
---交易的公共字段
34*?Claimstx_in[]用于分配的 NEO
---交易的公共字段

$ S! I( Y$ p# S( k9 pEnrollmentTransaction
  k. S8 {/ E3 E: T- E
$ P7 p( }+ a9 U. G- }" I8 r[!Warning]) `6 p+ d, @! y% o8 R, m. Y5 J
已弃用,已被智能合约的 Neo.Blockchain.RegisterValidator 所替代。
6 D) G2 C( @6 q+ _2 S
- T( @* X9 [: i, p3 `* W, K3 N
查看 替代的 .NET 智能合约框架
; C% `# o4 u+ W5 K* A# t- v" [查看 替代智能合约 API
0 {1 ~! L1 o9 TRegisterTransaction
4 _5 D/ }8 C  y, W- {; ~7 K' f" p8 Q1 `0 V; [
[!Warning]1 u0 R1 W! j) O: N2 T( X
已弃用,已被智能合约的 Neo.Blockchain.CreateAsset 所替代。4 Q9 w% c% d" h7 w

* i0 }2 z5 _" U. g, s" u6 s' l查看 替代的 .NET 智能合约框架# y, k* j% L  r; U- a) S! _6 v
查看 替代智能合约 API " y: H4 z/ P$ r2 {6 q4 S& h4 O. \3 v( H
ContractTransaction$ s& @1 j' V$ b6 v  ?' e* u8 E
合约交易没有任何特殊的地方。; X' |8 _2 e3 j$ Z% d
PublishTransaction
1 |1 D/ e9 q. T) G9 R5 W/ }
' f# o/ a+ Q7 v, W3 B& \8 I- l[!Warning]" h% u1 l9 J* M5 M
已弃用,已被智能合约的 Neo.Blockchain.CreateContract 所替代。
8 X+ r+ ~) d; b- t
! z3 y5 w- I7 k( T/ K
查看 替代的 .NET 智能合约框架
, f1 U- D0 N9 @# \- ?& F查看 替代智能合约 API
" G" K2 ~" v1 I! CInvocationTransaction
. u  F$ Z/ Y, w
尺寸字段数据类型说明
---交易的公共字段
?Scriptuint8[]所调用的智能合约的脚本
8Gasint64运行所调用的智能合约需要的费用
---交易的公共字段
4 r* v( ~  V7 j' t
交易特性
( |3 ]; S/ u  J
尺寸字段数据类型说明
1Usageuint8用途
0|1lengthuint8数据长度(特定情况下会省略)
lengthDatauint8[length]特定于用途的外部数据

5 B0 d/ [9 n+ I( n. `有时候交易中会需要包含一些供外部使用的数据,这些数据将统一被放置在交易特性字段中。( A; o. _1 o# }% v" X2 E" y
每个交易特性可以有不同的用途:7 q7 ^. M7 u5 n' x1 r8 ^" U2 n
名称说明
0x00ContractHash外部合同的散列值
0x02-0x03ECDH02-ECDH03用于 ECDH 密钥交换的公钥
0x20Script用于对交易进行额外的验证
0x30Vote用于投票选出记账人
0x81DescriptionUrl外部介绍信息地址
0x90Description简短的介绍信息
0xa1-0xafHash1-Hash15用于存放自定义的散列值
0xf0-0xffRemark-Remark15备注
! ~  D- Y; G! k, W4 Y  k. H2 E. \
对于 ContractHash,ECDH 系列,Vote,Hash 系列,数据长度固定为 32 字节,length 字段省略;
; I+ V' X9 `' H* b对于 Script,数据长度固定为 20 字节,存放地址;: F. y/ g7 b' a
对于 DescriptionUrl,必须明确给出数据长度,且长度不能超过 255 字节;
0 d$ F. ?6 L% P. Y9 ~$ p3 e( m对于 Description 和 Remark 系列,必须明确给出数据长度, 且长度不能超过 65535 字节。
+ X6 u$ i  D) I" G. }% |% W! g交易输入& q3 q4 G2 i, i" R
尺寸字段数据类型说明
32PrevHashuint256引用交易的散列值
2PrevIndexuint16引用交易输出的索引
4 I' [2 u" ?+ E; d5 ?1 _7 H1 `; E
交易输出
7 x6 ~! w0 g0 Y% c& ?9 R1 S' _
尺寸字段数据类型说明
32AssetIduint256资产编号
8Valueint64金额
20ScriptHashuint160收款地址

5 v& S5 V5 t4 I* E+ C- [& d5 D每个交易中最多只能包含 65536 个输出。
* L4 W1 ?) N" O. P& B验证脚本
- h. k0 e. I* G  p: R0 r
尺寸字段数据类型说明
?StackScriptuint8[]栈脚本代码
?RedeemScriptuint8[]合约脚本代码
. O3 s9 a- W. B. ]% B8 B; R
栈脚本中只能包含压栈操作指令,用于向合约脚本传递参数(如签名等)。脚本解释器会先执行栈脚本代码,然后执行合约脚本代码。
& g, y# n3 l2 t$ a& h0 X8 K在一笔交易中,合约脚本代码的散列值必须与交易输出中的一致,这是验证的一部分。关于脚本执行的过程,后文会详细阐述。
; N; J8 G6 p- r4 |8 y+ {2 P网络消息
' N3 v9 s/ B! F# y, G所有的网络消息都通过以下消息结构来发送:
* X5 U# _  G' s( w6 h
尺寸字段数据类型说明
4Magicuint32协议标识号
12Commandchar[12]命令
4lengthuint32Payload 的长度
4Checksumuint32校验和
lengthPayloaduint8[length]消息内容
3 u1 z' B) k3 G( C$ a: K: R
已定义的 Magic 值:
; [% \6 G( v  R0 D- n& u* }
说明
0x00746e41正式网
0x74746e41测试网

' H2 R. \7 Q7 l1 [! s- b1 m5 i  wCommand 采用 utf8 编码,长度为 12 字节,多余部分用 0 填充。" ]0 H0 a. O# r; C2 J
Checksum 是 Payload 两次 SHA256 散列后的前 4 个字节。
- T& i3 [" K& o7 q2 p$ t; ePayload 根据不同的命令有不同的详细格式,见下文。
7 `% q3 I& P% y* ]" Pversion
, i1 m* l( Q4 ]% d6 a' k
尺寸字段数据类型说明
4Versionuint32协议版本,目前为 0
8Servicesuint64节点提供的服务,目前为 1
4Timestampuint32当前时间
2Portuint16监听的端口,如果不监听则为 0
4Nonceuint32用于区分相同公网 IP 的节点
?UserAgentvarstr客户端标识
4StartHeightuint32区块链高度
1Relaybool是否接收并转发
4 r7 \  }' l' K7 z
一个节点收到连接请求时,它立即宣告其版本。在通信双方都得到对方版本之前,不会有其他通信。' \  z5 ^: ]! R" d* Z
verack
  v( |5 Y" ?  s8 V( M9 {节点收到 version 消息后,立刻回复一个 verack 作为应答。
& d8 I: C3 K  V此消息没有 payload。8 C) y9 W) o' o* H1 o
getaddr
9 P% Q( f- Y0 P, l) s4 ?向一个节点请求一批新的活动节点,以增加自身的连接数。6 _3 z: P! z& |% Y: T) }3 ]/ P8 H( }
此消息没有 payload。
. _3 H, R$ x7 x5 r7 u) \& p7 [4 Qaddr
7 B" K8 J5 k$ I
尺寸字段数据类型说明
30*?AddressListnet_addr[]网络上其他节点的地址

) y* x! X7 m9 o! E2 i6 ], K* |节点收到 getaddr 消息后,返回一个 addr 消息作为应答,提供网络上已知节点的信息。' t( Q2 Z1 e) g8 Y: ]5 ]
getheaders
! Y% p5 M1 i3 n) M3 s# v, K
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列

" c$ w5 J/ {. ~6 m! K向一个节点请求包含编号 HashStart 到 HashStop 的至多 2000 个 block 的 header 包。要获取之后的 block 散列,需要重新发送 getheaders 消息。这个消息用于快速下载不包含相关交易的 blockchain。8 L3 |' N( |& L, E; z* u- v1 N
headers
3 O+ q0 \9 I/ |& x& A* u
尺寸字段数据类型说明
?*?Headersheader[]区块头

' J% e. @- m: c. a# H; u# H1 _* o节点收到 getheaders 消息后,返回一个 headers 消息作为应答,提供请求的区块头。6 C$ k) t7 L0 K/ ?% N7 ^: r& {* U
getblocks5 q) [: s* j0 l* n% f! ^
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列
( h  k2 e0 a* X, O
向一个节点请求包含编号从 HashStart 到 HashStop 的 block 列表的 inv 消息。若 HashStart 到 HashStop 的 block 数超过 500,则在 500 处截止。欲获取后面的 block 散列,需要重新发送 getblocks 消息。' {9 {. m: R; Q. }1 }
inv) M! N, i2 Y. ^& k5 {+ v, A' x; p/ U
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单

  n2 D% \! f" h4 ?& N" v节点通过此消息可以广播它拥有的对象信息。这个消息可以主动发送,也可以用于应答 getbloks 消息。
% M! I" \! R( N) D- r  d9 Q& B清单类型有以下几种:
4 q( n7 k' G( s% N) F
名称说明
0x01TX交易
0x02Block区块
0xe0Consensus共识数据

* E$ `6 F( L# _& q5 n0 k( dgetdata
' V1 ?1 K  _+ H
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单
* H% q% x' V# {/ k( p
向一个节点请求指定的对象,它通常在接收到 inv 包并滤去已知元素后发送。$ R( C0 u& m: S
block3 F8 {5 k& p9 d. \- l) {- S
尺寸字段数据类型说明
?Blockblock区块
% n0 Z- Q2 I4 H
向一个节点发送一个区块,用于响应请求数据的 getdata 消息。  W5 g6 `+ ?% X+ M: P  n
tx/ j) J- G6 {. K3 s6 @6 T
尺寸字段数据类型说明
?Transactiontx交易

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

本版积分规则

成为第一个吐槽的人

宠着祖宗 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    1