Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

NEO网络协议

宠着祖宗
154 0 0
网络协议; B1 {5 n/ N& K, Y/ K# c
在网络结构上,NEO 采用点对点网络结构,并使用 TCP 协议进行通讯。; e( y5 {. X2 |' B& ?; G: a
网络中存在两种节点类型,分别是普通节点和共识节点。普通节点可以广播、接收和转发交易、区块等,而共识节点可以创建区块。
  b* }; M5 Q: P# H! n9 XNEO 的网络协议规范与比特币的协议大致类似,但在区块、交易等的数据结构上有很大的不同。0 F3 p' J- u" N+ ^" V, D! B4 j
约定5 j% |9 v! G9 j9 k- h4 J  |
字节序9 j+ G8 f3 ]) V' q. \/ g, k. F7 ~, ~
NEO 系统中所有的整数类型都是采用小端序 (Little Endian) 编码,只有 IP 地址和端口号采用大端序 (Big Endian) 编码。
+ h+ S5 j- V& P0 Q- E散列& `' a+ z  j$ l, m7 u
NEO 系统中会用到 2 种不同的散列函数:SHA256 和 RIPEMD160。前者用于生成较长的散列值,而后者用于生成较短的散列值。通常生成一个对象的散列值时,会运用两次散列函数,例如要生成区块或交易的散列时,会计算两次 SHA256;生成合约地址时,会先计算脚本的 SHA256 散列,然后再计算上一个散列的 RIPEMD160 散列。
* E% V8 J0 E& ~/ ]% I9 |# p. w5 W! q此外,区块中还会用到一种散列树 (Merkle Tree) 的结构,它将每一笔交易的散列两两相接后再计算一次散列,并重复以上过程直到只剩下一个根散列 (Merkle Root)。% s8 ^, U8 g. q5 k  i. q! m
变长类型$ h7 W1 `2 K" u# K
varint:变长整数,可以根据表达的值进行编码以节省空间。
' F: M; G: a- ?7 N
长度格式
0xffffffff90xff + uint64

4 X; U: T( n; U( [1 ]( j+ Cvarstr:变长字符串,由一个变长整数后接字符串构成。字符串采用 UTF8 编码。
# q  I, b3 n' e3 B# p' Z4 o
尺寸字段数据类型说明
?lengthvarint字符串的长度,以字节为单位
lengthstringuint8[length]字符串本身
, O5 P2 V3 o, Z- E9 M
array:数组,由一个变长整数后接元素序列构成。
. @* x6 Q* w( n: @6 S$ J# |定点数# z) R2 s6 Y3 I' E" t) R
NEO 系统中的金额、价格等数据,统一采用 64 位定点数,小数部分精确到 10-8,可表示的范围是:[-263/108, +263/108)
' J& S! o. ^7 A2 x7 |& {( L数据结构: V) u4 q. z, [' |8 g* l
区块链
8 R5 @3 y+ o8 T$ r5 ~6 m0 P( H4 P区块链是一种逻辑结构,它以单向链表的形式将区块串联起来,用于存放全网的交易、资产等数据。7 F" _+ N$ r1 S  }
区块
, D# j7 s, h1 z
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
?*?Transactionstx[]交易列表
9 v5 N5 O) r$ |. D* L; ?2 v3 ]
在计算区块散列时,并不会把整个区块都计算在内,而是只计算区块头的前 7 个字段:Version, PrevBlock, MerkleRoot, Timestamp, Height, Nonce, NextMiner。由于 MerkleRoot 已经包含了所有交易的散列值,因此修改交易也会改变区块的散列值。& D" i5 j" k4 A
区块头的数据结构如下:1 d4 f0 s1 r! A& D! b
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
1-uint8固定为 0
' I+ y' a+ B. }
每个区块的时间戳必须晚于前一个区块的时间戳,一般两个区块的时间戳相差 15 秒左右,但是也允许出现不精确的情况。区块的高度值必须恰好等于前一个区块的高度值加一。6 N( w" B, Q. L" I3 P/ s0 z
交易  P5 G( |# \: r
尺寸字段数据类型说明
1Typeuint8交易类型
1Versionuint8交易版本,目前为 0
?--特定于交易类型的数据
?*?Attributestx_attr[]该交易所具备的额外特性
34*?Inputstx_in[]输入
60*?Outputstx_out[]输出
?*?Scriptsscript[]用于验证该交易的脚本列表

: M! `9 o2 m6 xNEO 系统中的一切事务都以交易为单位进行记录。交易有以下几种类型:& R9 |3 Q! R0 A$ ~) V) o' E# Z: q+ h/ `
名称系统费用说明
0x00MinerTransaction0用于分配字节费的交易
0x01IssueTransaction500|0用于分发资产的交易
0x02ClaimTransaction0用于分配 NeoGas 的交易
0x20EnrollmentTransaction1000(已弃用) 用于报名成为共识候选人的特殊交易
0x40RegisterTransaction10000|0(已弃用) 用于资产登记的交易
0x80ContractTransaction0合约交易,这是最常用的一种交易
0xd0PublishTransaction500*n(已弃用)智能合约发布的特殊交易
0xd1InvocationTransaction0调用智能合约的特殊交易

" ?0 ], i; }% A* @& r  C& c: J每一种类型的交易除了具有交易的公共字段之外,还会具有自己的专属字段。关于不同类型交易的专属字段,下文会有详细说明。# w$ ]3 r0 K) s3 ~6 v8 H
MinerTransaction) U  M! y# f) c  [2 b) j4 Q
尺寸字段数据类型说明
---交易的公共字段
4Nonceuint32随机数
---交易的公共字段
' P! w: t# O9 r; V# ^! a
每一个区块的第一笔交易必然是 MinerTransaction。它用于将当前区块中所有的交易手续费奖励给记账人。5 \% z0 H* f, s) p& i+ e
交易中的随机数用于防止出现散列冲突。
$ i- m# E# m+ C! d2 HIssueTransaction3 h5 o8 P" I2 ^% M9 l' x) {$ ?
资产发行交易没有额外的特殊字段。
. F0 Z1 |) V+ N; ~1 l! E资产管理员可以通过资产发行交易,将已经登记过的资产在 NEO 区块链上制造出来,并发送到任意地址。
* e" n3 q+ y' W6 @4 E特别的,如果发行的资产是 NEO,那么这笔交易将可以免费发送。
7 {& G3 E8 c, s: oClaimTransaction
! W& G9 [  v- S% |- ~; ~1 f
尺寸字段数据类型说明
---交易的公共字段
34*?Claimstx_in[]用于分配的 NEO
---交易的公共字段

  j5 e% o/ k8 }5 N# ]' ^- o# HEnrollmentTransaction
2 A" s2 _9 p: `8 w/ C- y7 J, a0 ^6 A
[!Warning]
0 a$ V3 @  j/ m- W9 K已弃用,已被智能合约的 Neo.Blockchain.RegisterValidator 所替代。6 z% v; P& U" {2 F* I1 Q
5 y/ a; U. n0 q" d$ V! D, b$ q! Z- U# e* i
查看 替代的 .NET 智能合约框架
2 f) r* H5 f. v0 r( n查看 替代智能合约 API 2 L( Q" k; v- J2 Y# a% B
RegisterTransaction
+ U; u  Q& W0 V# d  B7 s! B: @; F# S9 z4 U( W, w* C1 w4 F- x: o- H
[!Warning]0 j4 a1 G+ K6 A4 W: B) w. [2 k; v
已弃用,已被智能合约的 Neo.Blockchain.CreateAsset 所替代。
  `& T5 X7 _" h
* H0 r) a7 `+ ?. H2 M7 S
查看 替代的 .NET 智能合约框架
8 W. i3 _. [- S4 N! e查看 替代智能合约 API
3 P$ z% u! M( w; d1 W& X$ F8 _ContractTransaction" t: V* X* d. N
合约交易没有任何特殊的地方。
# C* s% U$ ~8 q8 O, dPublishTransaction6 h$ U+ w; v# b1 {! A# P

6 e0 @# {0 G6 S5 D[!Warning]+ y- w# V( \: E: b$ A1 l
已弃用,已被智能合约的 Neo.Blockchain.CreateContract 所替代。
# D% o# j% [; e4 d
) r; J( B+ P6 T# F' N
查看 替代的 .NET 智能合约框架
( [& i% e( l/ Z4 M' t2 [0 Z* S' R查看 替代智能合约 API
* b8 y  f$ p1 d) xInvocationTransaction
6 m/ e" o6 g, M9 c2 D! T1 D3 W4 O
尺寸字段数据类型说明
---交易的公共字段
?Scriptuint8[]所调用的智能合约的脚本
8Gasint64运行所调用的智能合约需要的费用
---交易的公共字段
$ ?* P) N4 \+ ?
交易特性
+ o8 e* D- B: \8 f, g& U
尺寸字段数据类型说明
1Usageuint8用途
0|1lengthuint8数据长度(特定情况下会省略)
lengthDatauint8[length]特定于用途的外部数据
) `2 j1 ?6 e! ^( W
有时候交易中会需要包含一些供外部使用的数据,这些数据将统一被放置在交易特性字段中。+ a) \% i$ _% X
每个交易特性可以有不同的用途:
% F8 x5 e7 [6 o, o8 ]
名称说明
0x00ContractHash外部合同的散列值
0x02-0x03ECDH02-ECDH03用于 ECDH 密钥交换的公钥
0x20Script用于对交易进行额外的验证
0x30Vote用于投票选出记账人
0x81DescriptionUrl外部介绍信息地址
0x90Description简短的介绍信息
0xa1-0xafHash1-Hash15用于存放自定义的散列值
0xf0-0xffRemark-Remark15备注

! y' [6 p7 Q3 y7 A9 E! S3 b对于 ContractHash,ECDH 系列,Vote,Hash 系列,数据长度固定为 32 字节,length 字段省略;2 ?. M( Q4 W0 `2 F: T5 s* o
对于 Script,数据长度固定为 20 字节,存放地址;
/ }1 M; `5 a. Z, Z' Y6 b7 l对于 DescriptionUrl,必须明确给出数据长度,且长度不能超过 255 字节;
# I* x$ D2 K2 j% M: T对于 Description 和 Remark 系列,必须明确给出数据长度, 且长度不能超过 65535 字节。
" j0 B4 i  A* ~交易输入
6 v- P; W  @7 H$ u2 Z
尺寸字段数据类型说明
32PrevHashuint256引用交易的散列值
2PrevIndexuint16引用交易输出的索引
. k9 |' N9 V+ p* `1 p
交易输出& H& J3 E1 O, u9 O8 d$ Y
尺寸字段数据类型说明
32AssetIduint256资产编号
8Valueint64金额
20ScriptHashuint160收款地址

8 @& m6 q* t2 b7 Z9 `每个交易中最多只能包含 65536 个输出。3 p5 H2 B2 H& x, R1 X; T
验证脚本
5 j; h- G* F  M6 r' n
尺寸字段数据类型说明
?StackScriptuint8[]栈脚本代码
?RedeemScriptuint8[]合约脚本代码

* I+ k- h* t" t( h5 V栈脚本中只能包含压栈操作指令,用于向合约脚本传递参数(如签名等)。脚本解释器会先执行栈脚本代码,然后执行合约脚本代码。
" w  R2 H9 b3 r  v, U5 {6 q6 i在一笔交易中,合约脚本代码的散列值必须与交易输出中的一致,这是验证的一部分。关于脚本执行的过程,后文会详细阐述。7 F5 B  O# r2 g$ ?+ S
网络消息7 |" q" r9 }. x4 X( o& z+ m
所有的网络消息都通过以下消息结构来发送:7 R* @+ s, V6 h4 N: C# R
尺寸字段数据类型说明
4Magicuint32协议标识号
12Commandchar[12]命令
4lengthuint32Payload 的长度
4Checksumuint32校验和
lengthPayloaduint8[length]消息内容

9 }1 }- d$ s* E9 P6 |% H) \已定义的 Magic 值:9 A' \* B& a+ r1 Q: E; ~$ g/ p
说明
0x00746e41正式网
0x74746e41测试网

- ?7 d& l9 q7 H' @8 K& a! \- \Command 采用 utf8 编码,长度为 12 字节,多余部分用 0 填充。
& W2 `) I  ]- r, pChecksum 是 Payload 两次 SHA256 散列后的前 4 个字节。/ W& J5 p: u% @0 a8 W. a8 B
Payload 根据不同的命令有不同的详细格式,见下文。
. `& f$ _  ]  p$ s2 f) s+ `+ Mversion
# ?! h0 s( s) m9 t" \! h+ v8 s+ f
尺寸字段数据类型说明
4Versionuint32协议版本,目前为 0
8Servicesuint64节点提供的服务,目前为 1
4Timestampuint32当前时间
2Portuint16监听的端口,如果不监听则为 0
4Nonceuint32用于区分相同公网 IP 的节点
?UserAgentvarstr客户端标识
4StartHeightuint32区块链高度
1Relaybool是否接收并转发
; o; S; @6 J  p& I$ q6 l' R5 `
一个节点收到连接请求时,它立即宣告其版本。在通信双方都得到对方版本之前,不会有其他通信。' E& x! A% C! o% r
verack
5 L) _9 f: T4 s: j4 X节点收到 version 消息后,立刻回复一个 verack 作为应答。
  i) `7 t0 \1 S$ ?此消息没有 payload。& N8 Q% T  i4 b0 g# D# p
getaddr
3 _5 @6 ?. B9 k: B4 d& g向一个节点请求一批新的活动节点,以增加自身的连接数。
3 A/ y2 F% L- t$ i此消息没有 payload。2 N" `& X9 l! S
addr0 ^2 |% |- f: S6 i1 L# E
尺寸字段数据类型说明
30*?AddressListnet_addr[]网络上其他节点的地址

$ @" h7 K: x' z9 B9 Y节点收到 getaddr 消息后,返回一个 addr 消息作为应答,提供网络上已知节点的信息。( x8 i# M7 Q7 H+ U* S9 x! r  P
getheaders
: O/ g9 l+ H/ u& X1 S1 A
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列
+ A' P" o' R, p1 e* t
向一个节点请求包含编号 HashStart 到 HashStop 的至多 2000 个 block 的 header 包。要获取之后的 block 散列,需要重新发送 getheaders 消息。这个消息用于快速下载不包含相关交易的 blockchain。
4 S. z* d+ M3 R6 z/ T2 [0 P2 jheaders9 C5 A. I0 w8 j5 g
尺寸字段数据类型说明
?*?Headersheader[]区块头
- B- ~1 }3 }8 {% ]* L
节点收到 getheaders 消息后,返回一个 headers 消息作为应答,提供请求的区块头。
( \+ K0 k' N$ ?getblocks
, w5 C8 w$ A" @/ o. g, h6 l0 z
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列

  k+ t2 x3 l6 a7 s向一个节点请求包含编号从 HashStart 到 HashStop 的 block 列表的 inv 消息。若 HashStart 到 HashStop 的 block 数超过 500,则在 500 处截止。欲获取后面的 block 散列,需要重新发送 getblocks 消息。2 [& V' n, g8 i
inv0 |+ U" }8 \# O
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单

& e# p( i, o4 Q5 e- }7 ^& Y  ^  J. x节点通过此消息可以广播它拥有的对象信息。这个消息可以主动发送,也可以用于应答 getbloks 消息。- J( C6 M6 M+ }) X  p
清单类型有以下几种:- b, J. G) \% F$ u* R) `; H2 @& y" B
名称说明
0x01TX交易
0x02Block区块
0xe0Consensus共识数据

; a/ X9 v9 r: \  E- T# W; f4 }0 Rgetdata
8 _+ [3 E3 h4 l3 R: ]
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单
$ Q( A# N3 y/ @) O) u& |; Q  `0 ~# }
向一个节点请求指定的对象,它通常在接收到 inv 包并滤去已知元素后发送。
9 {  F1 ~% I# _8 }' l6 G9 {# Iblock9 C% x8 |- I6 b; Y# E3 |
尺寸字段数据类型说明
?Blockblock区块

& H. y5 v: J  d. _+ B+ n0 i. Y向一个节点发送一个区块,用于响应请求数据的 getdata 消息。* \4 F+ n9 z/ I$ e
tx% B. E# v; c2 D- w9 b
尺寸字段数据类型说明
?Transactiontx交易

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

本版积分规则

成为第一个吐槽的人

宠着祖宗 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    1