Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

NEO网络协议

宠着祖宗
95 0 0
网络协议
0 }3 o& Z8 I& z在网络结构上,NEO 采用点对点网络结构,并使用 TCP 协议进行通讯。. h8 i  b* b" P! e) Y5 G' Y2 E
网络中存在两种节点类型,分别是普通节点和共识节点。普通节点可以广播、接收和转发交易、区块等,而共识节点可以创建区块。& v' O9 I' W$ c; K$ F. O6 o
NEO 的网络协议规范与比特币的协议大致类似,但在区块、交易等的数据结构上有很大的不同。/ t3 q' Q% A& H* h+ ~# V7 F# s* _7 t
约定
0 |( m  u# e' J3 h1 \字节序  i7 j: x0 C: v9 w
NEO 系统中所有的整数类型都是采用小端序 (Little Endian) 编码,只有 IP 地址和端口号采用大端序 (Big Endian) 编码。
7 k/ _$ M5 \1 ~2 a8 M  I; A0 ?散列7 u0 d0 _7 b" a! p4 `) i7 ^: n
NEO 系统中会用到 2 种不同的散列函数:SHA256 和 RIPEMD160。前者用于生成较长的散列值,而后者用于生成较短的散列值。通常生成一个对象的散列值时,会运用两次散列函数,例如要生成区块或交易的散列时,会计算两次 SHA256;生成合约地址时,会先计算脚本的 SHA256 散列,然后再计算上一个散列的 RIPEMD160 散列。
/ _! y! O* x5 ~0 a( r  K* M此外,区块中还会用到一种散列树 (Merkle Tree) 的结构,它将每一笔交易的散列两两相接后再计算一次散列,并重复以上过程直到只剩下一个根散列 (Merkle Root)。: c7 V# N1 B& k% k  F: ^, ]* ?, c
变长类型
4 X2 j2 M+ U. E" d% zvarint:变长整数,可以根据表达的值进行编码以节省空间。. G3 H, y$ Q- P* D
长度格式
0xffffffff90xff + uint64
; R2 R1 k# V* F! ]6 S6 S
varstr:变长字符串,由一个变长整数后接字符串构成。字符串采用 UTF8 编码。
, r  d) A7 V  U1 p/ _: w
尺寸字段数据类型说明
?lengthvarint字符串的长度,以字节为单位
lengthstringuint8[length]字符串本身

$ s: P) Z* ~* |2 Karray:数组,由一个变长整数后接元素序列构成。
1 w4 ~1 u' t1 o7 ~0 s* W9 {7 v定点数  H' P7 R6 \& y5 n* x9 n1 r4 o$ G
NEO 系统中的金额、价格等数据,统一采用 64 位定点数,小数部分精确到 10-8,可表示的范围是:[-263/108, +263/108)
$ g& l9 m( J& D数据结构
1 b4 B7 v, i9 x, a" S区块链
: F1 R. X+ X& l$ ]: [" s区块链是一种逻辑结构,它以单向链表的形式将区块串联起来,用于存放全网的交易、资产等数据。, d* A( X# m. }/ E3 u
区块1 _) R+ R/ _" l$ y3 F! c) v
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
?*?Transactionstx[]交易列表

+ R3 E2 q+ u5 m" v8 X, v, x' i在计算区块散列时,并不会把整个区块都计算在内,而是只计算区块头的前 7 个字段:Version, PrevBlock, MerkleRoot, Timestamp, Height, Nonce, NextMiner。由于 MerkleRoot 已经包含了所有交易的散列值,因此修改交易也会改变区块的散列值。
4 C9 z4 e& v8 o: h6 `, q+ y7 w+ p区块头的数据结构如下:: o3 A) u5 V7 C& @
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
1-uint8固定为 0
1 [6 n# S; N8 ?/ V/ ~
每个区块的时间戳必须晚于前一个区块的时间戳,一般两个区块的时间戳相差 15 秒左右,但是也允许出现不精确的情况。区块的高度值必须恰好等于前一个区块的高度值加一。
6 [1 c8 Z- p+ r" i8 ]交易) x, e) z. r7 B0 p  Q7 |0 J
尺寸字段数据类型说明
1Typeuint8交易类型
1Versionuint8交易版本,目前为 0
?--特定于交易类型的数据
?*?Attributestx_attr[]该交易所具备的额外特性
34*?Inputstx_in[]输入
60*?Outputstx_out[]输出
?*?Scriptsscript[]用于验证该交易的脚本列表

4 F- }8 U! X* P7 H& o& W4 INEO 系统中的一切事务都以交易为单位进行记录。交易有以下几种类型:% q5 U: W/ X& c0 q
名称系统费用说明
0x00MinerTransaction0用于分配字节费的交易
0x01IssueTransaction500|0用于分发资产的交易
0x02ClaimTransaction0用于分配 NeoGas 的交易
0x20EnrollmentTransaction1000(已弃用) 用于报名成为共识候选人的特殊交易
0x40RegisterTransaction10000|0(已弃用) 用于资产登记的交易
0x80ContractTransaction0合约交易,这是最常用的一种交易
0xd0PublishTransaction500*n(已弃用)智能合约发布的特殊交易
0xd1InvocationTransaction0调用智能合约的特殊交易
5 X3 o4 D( \  J; }6 J- c
每一种类型的交易除了具有交易的公共字段之外,还会具有自己的专属字段。关于不同类型交易的专属字段,下文会有详细说明。
7 H; u8 H+ o7 ~' J7 r- S% R: ~" PMinerTransaction
( u6 J) f8 H  y* y% [/ K( e2 }
尺寸字段数据类型说明
---交易的公共字段
4Nonceuint32随机数
---交易的公共字段
. N0 S' x* ~! c$ |2 R
每一个区块的第一笔交易必然是 MinerTransaction。它用于将当前区块中所有的交易手续费奖励给记账人。
' d1 O- i% v) ]9 l! v" Y交易中的随机数用于防止出现散列冲突。0 B& P+ Q: F- O# }  @+ U
IssueTransaction- u4 Y" A- m7 H+ ^
资产发行交易没有额外的特殊字段。
* c- G: G# X, k% [+ E4 a( s资产管理员可以通过资产发行交易,将已经登记过的资产在 NEO 区块链上制造出来,并发送到任意地址。( _9 y! k' T. f' S2 h) _
特别的,如果发行的资产是 NEO,那么这笔交易将可以免费发送。
+ @/ R, G. a( M0 P) S: i0 g6 l+ eClaimTransaction' ~1 ]4 q7 z% n" y, D3 Q8 U) t
尺寸字段数据类型说明
---交易的公共字段
34*?Claimstx_in[]用于分配的 NEO
---交易的公共字段
, ]. l) J& l) Y$ Y; c
EnrollmentTransaction! M1 N9 l3 ]3 D2 g- L- P
, c9 ]# C' @" W1 j7 u! L
[!Warning]
) L$ m8 j6 b0 b) b: t' e: g0 D: Z5 N已弃用,已被智能合约的 Neo.Blockchain.RegisterValidator 所替代。: {( f9 |+ k  Y  q. g8 I
7 C. K  q, p3 t) r
查看 替代的 .NET 智能合约框架
# r9 [, Q+ s3 w/ x- d$ Y查看 替代智能合约 API
4 P# Q1 s$ ]* ]+ w! o. H7 E  [RegisterTransaction
! ^- i& S9 M6 Q) z
9 K( o# s; ?$ d  g% j: E[!Warning]
# H9 h( S0 C- R: t0 N% f已弃用,已被智能合约的 Neo.Blockchain.CreateAsset 所替代。
4 N. H" e# @* e- f
* d% L/ G, u$ `
查看 替代的 .NET 智能合约框架
: ]: E8 F7 B7 N$ A! c: ^* k查看 替代智能合约 API $ f: `5 w6 g; j. _
ContractTransaction
+ n$ s, s9 N. t. g6 f合约交易没有任何特殊的地方。
! }8 ~6 E6 y: E: l2 _) IPublishTransaction
4 ^/ I! j$ s0 C$ J2 w% s$ r5 T, y8 y+ v5 f
[!Warning]
2 b) p/ O) U& s! S# V已弃用,已被智能合约的 Neo.Blockchain.CreateContract 所替代。" H( c  }* G1 v( V2 `

7 E3 s+ {* }6 p+ W3 k查看 替代的 .NET 智能合约框架% P; k& q6 ]7 G7 o, N
查看 替代智能合约 API
3 S2 ?+ @! X" r$ E  sInvocationTransaction) X8 T* O0 a. P  t. w7 B
尺寸字段数据类型说明
---交易的公共字段
?Scriptuint8[]所调用的智能合约的脚本
8Gasint64运行所调用的智能合约需要的费用
---交易的公共字段
0 t6 Y: Y0 \  p/ S1 k* N8 q
交易特性
' R& M# T7 h4 M1 _) o' P& z
尺寸字段数据类型说明
1Usageuint8用途
0|1lengthuint8数据长度(特定情况下会省略)
lengthDatauint8[length]特定于用途的外部数据
+ L1 o" S0 P5 s  ~3 `
有时候交易中会需要包含一些供外部使用的数据,这些数据将统一被放置在交易特性字段中。
' f. F* w/ i) t' X- E8 p' y每个交易特性可以有不同的用途:
  _& T- j# s' Y* F0 M+ q9 }
名称说明
0x00ContractHash外部合同的散列值
0x02-0x03ECDH02-ECDH03用于 ECDH 密钥交换的公钥
0x20Script用于对交易进行额外的验证
0x30Vote用于投票选出记账人
0x81DescriptionUrl外部介绍信息地址
0x90Description简短的介绍信息
0xa1-0xafHash1-Hash15用于存放自定义的散列值
0xf0-0xffRemark-Remark15备注
2 X# U# P$ o0 R) Z3 A
对于 ContractHash,ECDH 系列,Vote,Hash 系列,数据长度固定为 32 字节,length 字段省略;- k! l, O, F7 j
对于 Script,数据长度固定为 20 字节,存放地址;
" Q  {6 W! e' u+ ~对于 DescriptionUrl,必须明确给出数据长度,且长度不能超过 255 字节;# u2 T" ]* z. S8 I; |
对于 Description 和 Remark 系列,必须明确给出数据长度, 且长度不能超过 65535 字节。- h, s  \/ M( Z/ \. I8 F) C5 ~# z
交易输入
( i( o* f+ o2 s6 H9 C
尺寸字段数据类型说明
32PrevHashuint256引用交易的散列值
2PrevIndexuint16引用交易输出的索引

7 h3 v5 ^/ r0 Q! g8 C+ i/ N交易输出$ h9 ?! c) ^7 k% h* r
尺寸字段数据类型说明
32AssetIduint256资产编号
8Valueint64金额
20ScriptHashuint160收款地址
" `7 S. S; R6 P( I0 U
每个交易中最多只能包含 65536 个输出。0 ]) Q1 C5 T( s; Z2 r
验证脚本: z! P3 D% n! I" c- V/ d* z6 n
尺寸字段数据类型说明
?StackScriptuint8[]栈脚本代码
?RedeemScriptuint8[]合约脚本代码

. j, e8 |0 q3 D6 u# o1 D& I栈脚本中只能包含压栈操作指令,用于向合约脚本传递参数(如签名等)。脚本解释器会先执行栈脚本代码,然后执行合约脚本代码。
# r, \& t4 {8 U6 u* s3 i在一笔交易中,合约脚本代码的散列值必须与交易输出中的一致,这是验证的一部分。关于脚本执行的过程,后文会详细阐述。& W9 S% R* ]/ @3 p: a
网络消息
  d* `; i  L8 P( A  p所有的网络消息都通过以下消息结构来发送:  L5 j* k8 d3 k1 p: w. ]
尺寸字段数据类型说明
4Magicuint32协议标识号
12Commandchar[12]命令
4lengthuint32Payload 的长度
4Checksumuint32校验和
lengthPayloaduint8[length]消息内容

7 S9 j. i; H: B4 K8 O已定义的 Magic 值:
! Y+ K7 P% D6 }! g  ~5 g! P
说明
0x00746e41正式网
0x74746e41测试网

3 B4 Q$ t9 h4 H3 W, Y, NCommand 采用 utf8 编码,长度为 12 字节,多余部分用 0 填充。
9 z. w& U  @- r: J7 m. ?8 d( \' ^Checksum 是 Payload 两次 SHA256 散列后的前 4 个字节。
% o( h. W/ J6 ]) l* TPayload 根据不同的命令有不同的详细格式,见下文。( h7 ~1 A& Y7 P5 C
version# N' `4 r, _! Z( i; T
尺寸字段数据类型说明
4Versionuint32协议版本,目前为 0
8Servicesuint64节点提供的服务,目前为 1
4Timestampuint32当前时间
2Portuint16监听的端口,如果不监听则为 0
4Nonceuint32用于区分相同公网 IP 的节点
?UserAgentvarstr客户端标识
4StartHeightuint32区块链高度
1Relaybool是否接收并转发
5 H8 b. c. u" k8 D
一个节点收到连接请求时,它立即宣告其版本。在通信双方都得到对方版本之前,不会有其他通信。
) A/ f) [( g# i1 t. W1 `/ L+ M- yverack
2 o# ?6 f9 q( `+ y节点收到 version 消息后,立刻回复一个 verack 作为应答。
: M; u! _2 t8 w! a& F. M" ^此消息没有 payload。
$ c! `) U$ O$ S; B% kgetaddr
  `: H$ w) C! {; T5 ^5 Z向一个节点请求一批新的活动节点,以增加自身的连接数。
- Z; \- i# j! a$ F. R0 q此消息没有 payload。2 R/ J' \) }' H+ d  H- R8 n
addr
) i5 X/ R" B) O
尺寸字段数据类型说明
30*?AddressListnet_addr[]网络上其他节点的地址

( t. j/ X) A0 ]9 u节点收到 getaddr 消息后,返回一个 addr 消息作为应答,提供网络上已知节点的信息。; T) S; P. u; v7 p
getheaders2 q0 ]/ |$ M4 M; Y- Q; R3 J  }# l- v
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列

3 R, n! M" O( b% Q' \向一个节点请求包含编号 HashStart 到 HashStop 的至多 2000 个 block 的 header 包。要获取之后的 block 散列,需要重新发送 getheaders 消息。这个消息用于快速下载不包含相关交易的 blockchain。  h1 ?6 t  |* T* T) \8 D0 c
headers  {: X% \2 H" X: X% J7 O
尺寸字段数据类型说明
?*?Headersheader[]区块头

: B9 |5 e2 v& U% v* Z- i: [: `/ D节点收到 getheaders 消息后,返回一个 headers 消息作为应答,提供请求的区块头。
2 z3 L5 h: h. c( V/ ~: b( y1 _getblocks
; |! s2 @9 B8 u, c  D
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列
3 O' o. r# j6 p' t; a! e+ u
向一个节点请求包含编号从 HashStart 到 HashStop 的 block 列表的 inv 消息。若 HashStart 到 HashStop 的 block 数超过 500,则在 500 处截止。欲获取后面的 block 散列,需要重新发送 getblocks 消息。0 G) ?* h" ~  K* q( Q( t/ ]
inv
- W) f$ p/ r$ Z) D8 H& i$ ?
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单
9 n; o; }2 s0 P# s: _6 Q
节点通过此消息可以广播它拥有的对象信息。这个消息可以主动发送,也可以用于应答 getbloks 消息。; ]5 J. h$ w! `' r# G
清单类型有以下几种:2 l- x6 D9 W3 W* i" w, F: o
名称说明
0x01TX交易
0x02Block区块
0xe0Consensus共识数据
$ V+ o7 W  F" R2 d# P% m
getdata
/ @% `* \6 g  L/ v  E8 f/ @* v
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单

; Z( ~" ^- @2 u向一个节点请求指定的对象,它通常在接收到 inv 包并滤去已知元素后发送。! y* N. ?- r. a; D6 E" p! x
block
1 {' L' R8 B" y8 C  S3 i" [
尺寸字段数据类型说明
?Blockblock区块

# J( P3 ?9 K7 x! Q& V$ ?: g7 o7 {向一个节点发送一个区块,用于响应请求数据的 getdata 消息。
2 f/ s- c4 a: ~* w8 B5 Ltx
$ {2 n4 ^" O! M
尺寸字段数据类型说明
?Transactiontx交易
# O3 Q; C. Y8 k. C9 b
向一个节点发送一笔交易,用于响应请求数据的 getdata 消息。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

宠着祖宗 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    1