Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

NEO网络协议

宠着祖宗
97 0 0
网络协议
$ K4 ]& c+ x$ |0 g在网络结构上,NEO 采用点对点网络结构,并使用 TCP 协议进行通讯。
4 a4 U( F2 V6 J. C# G( N9 ~+ y9 U网络中存在两种节点类型,分别是普通节点和共识节点。普通节点可以广播、接收和转发交易、区块等,而共识节点可以创建区块。
( B$ V% o) H: M+ bNEO 的网络协议规范与比特币的协议大致类似,但在区块、交易等的数据结构上有很大的不同。: g  i$ O9 _; d- v2 ?
约定
9 j! t' ]. \) e% }0 H% J& l字节序+ j' k: F) c/ l
NEO 系统中所有的整数类型都是采用小端序 (Little Endian) 编码,只有 IP 地址和端口号采用大端序 (Big Endian) 编码。
: k. c$ h. L* U8 G" b( v7 z散列( E% P) C: O& p' y% V% V- ]7 H7 ^
NEO 系统中会用到 2 种不同的散列函数:SHA256 和 RIPEMD160。前者用于生成较长的散列值,而后者用于生成较短的散列值。通常生成一个对象的散列值时,会运用两次散列函数,例如要生成区块或交易的散列时,会计算两次 SHA256;生成合约地址时,会先计算脚本的 SHA256 散列,然后再计算上一个散列的 RIPEMD160 散列。
. b0 G0 L/ Q& j) w* O此外,区块中还会用到一种散列树 (Merkle Tree) 的结构,它将每一笔交易的散列两两相接后再计算一次散列,并重复以上过程直到只剩下一个根散列 (Merkle Root)。7 {' O9 K% v2 Y- F2 ?
变长类型' Q! u# K0 L1 e4 B1 t4 h% E& h
varint:变长整数,可以根据表达的值进行编码以节省空间。; K( c4 ?( R& r9 O! s1 B
长度格式
0xffffffff90xff + uint64

) T. G% @, V0 t  @& Y  M, M* Ovarstr:变长字符串,由一个变长整数后接字符串构成。字符串采用 UTF8 编码。
) f8 Q+ \* K  C  L( s
尺寸字段数据类型说明
?lengthvarint字符串的长度,以字节为单位
lengthstringuint8[length]字符串本身
5 J8 u, l/ ?" `: b/ `2 V
array:数组,由一个变长整数后接元素序列构成。9 ^9 c0 r( J! j8 U- e3 j6 k9 O
定点数9 u( m! p  Z5 [
NEO 系统中的金额、价格等数据,统一采用 64 位定点数,小数部分精确到 10-8,可表示的范围是:[-263/108, +263/108)
& a# |# C) ?2 r3 t7 _) J" R数据结构; p0 n8 I" U% Z
区块链
3 X4 J, _! D. {& }4 Y区块链是一种逻辑结构,它以单向链表的形式将区块串联起来,用于存放全网的交易、资产等数据。
: X- H, }' s( h0 }: M# \区块
- a4 b4 }$ S  r# l
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
?*?Transactionstx[]交易列表

% L! L" l3 ?: d' Y1 i; e0 j0 ?, i在计算区块散列时,并不会把整个区块都计算在内,而是只计算区块头的前 7 个字段:Version, PrevBlock, MerkleRoot, Timestamp, Height, Nonce, NextMiner。由于 MerkleRoot 已经包含了所有交易的散列值,因此修改交易也会改变区块的散列值。
% r! e( O2 Y8 Z区块头的数据结构如下:9 x% u7 h, L4 ^, s
尺寸字段数据类型说明
4Versionuint32区块版本,目前为 0
32PrevBlockuint256前一个区块的散列值
32MerkleRootuint256交易列表的根散列
4Timestampuint32时间戳
4Indexuint32区块高度(区块索引) = 区块数量 - 1
8ConsensusDatauint64共识数据(共识节点生成的伪随机数)
20NextConsensusuint160下一个区块的记账合约的散列值
1-uint8固定为 1
?Scriptscript用于验证该区块的脚本
1-uint8固定为 0
9 \, s" K! f, |% Z( f/ N9 m
每个区块的时间戳必须晚于前一个区块的时间戳,一般两个区块的时间戳相差 15 秒左右,但是也允许出现不精确的情况。区块的高度值必须恰好等于前一个区块的高度值加一。" g" _1 X! C1 _% {2 N% w
交易6 M$ [# L( E, A; q0 G
尺寸字段数据类型说明
1Typeuint8交易类型
1Versionuint8交易版本,目前为 0
?--特定于交易类型的数据
?*?Attributestx_attr[]该交易所具备的额外特性
34*?Inputstx_in[]输入
60*?Outputstx_out[]输出
?*?Scriptsscript[]用于验证该交易的脚本列表

- W- v( V$ ]2 j$ x0 n4 ENEO 系统中的一切事务都以交易为单位进行记录。交易有以下几种类型:$ X+ G' a: N- ^4 s. e/ I2 J
名称系统费用说明
0x00MinerTransaction0用于分配字节费的交易
0x01IssueTransaction500|0用于分发资产的交易
0x02ClaimTransaction0用于分配 NeoGas 的交易
0x20EnrollmentTransaction1000(已弃用) 用于报名成为共识候选人的特殊交易
0x40RegisterTransaction10000|0(已弃用) 用于资产登记的交易
0x80ContractTransaction0合约交易,这是最常用的一种交易
0xd0PublishTransaction500*n(已弃用)智能合约发布的特殊交易
0xd1InvocationTransaction0调用智能合约的特殊交易

1 k% _2 j7 U! {; F每一种类型的交易除了具有交易的公共字段之外,还会具有自己的专属字段。关于不同类型交易的专属字段,下文会有详细说明。
# C: L; I$ I" I! o" o3 O, ]9 ]% yMinerTransaction% U& g7 C2 X& E; V6 Z) o+ K$ A
尺寸字段数据类型说明
---交易的公共字段
4Nonceuint32随机数
---交易的公共字段

+ b" J4 P/ n) }6 p3 A5 I每一个区块的第一笔交易必然是 MinerTransaction。它用于将当前区块中所有的交易手续费奖励给记账人。. N- E  h+ n( S( a7 `/ ]' ^, [3 L, ]
交易中的随机数用于防止出现散列冲突。
! B( Z: e- ]& P  `3 R8 mIssueTransaction
0 Z) _$ G0 N4 V* N3 M2 Q资产发行交易没有额外的特殊字段。
: P- L6 l7 _0 _) P& d/ ]资产管理员可以通过资产发行交易,将已经登记过的资产在 NEO 区块链上制造出来,并发送到任意地址。
0 n3 Q: I9 b& u8 x: L0 n  X特别的,如果发行的资产是 NEO,那么这笔交易将可以免费发送。' G3 i( T0 G( O! r& u& _
ClaimTransaction
" W- _1 C5 P/ o
尺寸字段数据类型说明
---交易的公共字段
34*?Claimstx_in[]用于分配的 NEO
---交易的公共字段
5 K3 ]+ x4 D5 |- E( O( p  c/ ?3 r/ y
EnrollmentTransaction* L- K7 l1 u! g3 w0 Q) i- z

1 c5 `2 h! a5 h5 d3 K8 q[!Warning]
5 F" q) D- q5 D8 i% s! D  }已弃用,已被智能合约的 Neo.Blockchain.RegisterValidator 所替代。( B$ U' l8 f  ~3 z

( o; |1 i( W% C查看 替代的 .NET 智能合约框架) x& r  g) y& J  }' {, Q* Z& ?5 J
查看 替代智能合约 API 5 p" E& o- r* G) c% V  t) t
RegisterTransaction
5 r  p3 i' g+ r# V3 q- o8 n
2 P& h% P* U' N- T  P[!Warning]) |  M1 L* [' g$ Q" ]* {; `
已弃用,已被智能合约的 Neo.Blockchain.CreateAsset 所替代。
6 I* F* e  p4 N
5 h: Z2 |  I& w
查看 替代的 .NET 智能合约框架( v; p  r4 `/ R" @) `
查看 替代智能合约 API
) ?: e9 U6 a8 O1 A" o3 NContractTransaction
9 \! L% P: Y2 E( d9 i2 ^合约交易没有任何特殊的地方。* {$ Q$ M7 X: J" K
PublishTransaction( z& @+ V9 H+ F( w

% |3 E2 e, L4 h8 [[!Warning], Y4 S. g" B" @6 _
已弃用,已被智能合约的 Neo.Blockchain.CreateContract 所替代。
! E3 \$ I: G( L. r+ P6 N
, y0 P! d0 E) M
查看 替代的 .NET 智能合约框架, R' f. S; k. H" E: v1 P9 [
查看 替代智能合约 API
  U0 v; K" B4 f* k  T3 W9 HInvocationTransaction: K  ?5 S) @0 s# n% a1 P; m+ U
尺寸字段数据类型说明
---交易的公共字段
?Scriptuint8[]所调用的智能合约的脚本
8Gasint64运行所调用的智能合约需要的费用
---交易的公共字段
5 R8 o! L# S* _  n" N
交易特性
' o4 d7 }  ^( p- @2 U! h% e
尺寸字段数据类型说明
1Usageuint8用途
0|1lengthuint8数据长度(特定情况下会省略)
lengthDatauint8[length]特定于用途的外部数据

: y9 t2 W) h- U- v有时候交易中会需要包含一些供外部使用的数据,这些数据将统一被放置在交易特性字段中。
2 z: R# k0 e- v# n  \. J每个交易特性可以有不同的用途:
) K1 K& S- p; y# O$ w; m3 z
名称说明
0x00ContractHash外部合同的散列值
0x02-0x03ECDH02-ECDH03用于 ECDH 密钥交换的公钥
0x20Script用于对交易进行额外的验证
0x30Vote用于投票选出记账人
0x81DescriptionUrl外部介绍信息地址
0x90Description简短的介绍信息
0xa1-0xafHash1-Hash15用于存放自定义的散列值
0xf0-0xffRemark-Remark15备注
0 a) h1 D2 T. U' T  W; ?
对于 ContractHash,ECDH 系列,Vote,Hash 系列,数据长度固定为 32 字节,length 字段省略;: [" F& F2 b# n5 G" p9 \
对于 Script,数据长度固定为 20 字节,存放地址;
1 L# ^. c) n( W+ S, ~对于 DescriptionUrl,必须明确给出数据长度,且长度不能超过 255 字节;
3 h$ y2 [  d- }% J8 k5 N8 h: q7 I# _对于 Description 和 Remark 系列,必须明确给出数据长度, 且长度不能超过 65535 字节。
9 s: w$ v3 }' ?% S5 o交易输入4 q% v% w, C3 l7 [/ Q0 n
尺寸字段数据类型说明
32PrevHashuint256引用交易的散列值
2PrevIndexuint16引用交易输出的索引

# {, L' O. Y, P4 G/ A) E; P交易输出
0 E5 {9 n, }$ I+ B6 p+ R
尺寸字段数据类型说明
32AssetIduint256资产编号
8Valueint64金额
20ScriptHashuint160收款地址
5 J; d" Y' J$ {& q. c
每个交易中最多只能包含 65536 个输出。
1 U+ M( J3 ~6 z验证脚本1 s! ~6 ?0 Y3 j, j1 T2 ]
尺寸字段数据类型说明
?StackScriptuint8[]栈脚本代码
?RedeemScriptuint8[]合约脚本代码
7 k- H4 X. K- I* r
栈脚本中只能包含压栈操作指令,用于向合约脚本传递参数(如签名等)。脚本解释器会先执行栈脚本代码,然后执行合约脚本代码。
3 `* E# S. O, o在一笔交易中,合约脚本代码的散列值必须与交易输出中的一致,这是验证的一部分。关于脚本执行的过程,后文会详细阐述。
4 X6 k3 x' C2 w' Z. s! z0 Z网络消息
& J, ?8 v/ L1 Y& Q+ ^" x! F2 N所有的网络消息都通过以下消息结构来发送:
- C' n) |& F( `+ W0 K2 D
尺寸字段数据类型说明
4Magicuint32协议标识号
12Commandchar[12]命令
4lengthuint32Payload 的长度
4Checksumuint32校验和
lengthPayloaduint8[length]消息内容

$ c( `* T; V6 j# {已定义的 Magic 值:- |2 V/ x* t# ^+ z$ N+ q
说明
0x00746e41正式网
0x74746e41测试网

2 p; i- R! X6 p- PCommand 采用 utf8 编码,长度为 12 字节,多余部分用 0 填充。6 v  ~' I7 F- R, E
Checksum 是 Payload 两次 SHA256 散列后的前 4 个字节。
% h  V& P7 n6 }/ O, LPayload 根据不同的命令有不同的详细格式,见下文。- r% T( R: `/ U
version% u2 b, D$ x1 F) a) B% q  |* Q
尺寸字段数据类型说明
4Versionuint32协议版本,目前为 0
8Servicesuint64节点提供的服务,目前为 1
4Timestampuint32当前时间
2Portuint16监听的端口,如果不监听则为 0
4Nonceuint32用于区分相同公网 IP 的节点
?UserAgentvarstr客户端标识
4StartHeightuint32区块链高度
1Relaybool是否接收并转发

9 ?% h' I( a: v) D% z一个节点收到连接请求时,它立即宣告其版本。在通信双方都得到对方版本之前,不会有其他通信。/ A4 H8 o+ A# u
verack6 `% Q5 o( g; s5 T4 B" d- ^
节点收到 version 消息后,立刻回复一个 verack 作为应答。
, A3 c% o! Q" b! j) B! m5 \, c此消息没有 payload。
1 p6 J; Y2 P) Q3 {getaddr2 T0 H: ?4 j' E# e
向一个节点请求一批新的活动节点,以增加自身的连接数。* y3 j, u, }2 Z0 b4 D
此消息没有 payload。
! P2 I( Z/ j* O+ E6 d0 Z% Z, {  kaddr5 k% Z1 J" a0 q; f
尺寸字段数据类型说明
30*?AddressListnet_addr[]网络上其他节点的地址
! ]3 V! ~3 e3 h2 \3 S6 v: m
节点收到 getaddr 消息后,返回一个 addr 消息作为应答,提供网络上已知节点的信息。3 o2 r  Y) X  p% Z8 [
getheaders
0 V+ _: E2 ^8 u5 V- @! k
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列
7 ?5 [3 U; ~# C# x+ s0 g! o
向一个节点请求包含编号 HashStart 到 HashStop 的至多 2000 个 block 的 header 包。要获取之后的 block 散列,需要重新发送 getheaders 消息。这个消息用于快速下载不包含相关交易的 blockchain。
1 ^6 I$ {' v% D4 Z/ t* F$ z7 m5 bheaders
, ~3 z5 X$ @: \1 p+ W" R5 k- {
尺寸字段数据类型说明
?*?Headersheader[]区块头
" [$ d7 w# v+ u
节点收到 getheaders 消息后,返回一个 headers 消息作为应答,提供请求的区块头。3 F$ n/ o( q& u  t* Y) _% M; y
getblocks1 i0 V# w" i6 S: q8 p# t
尺寸字段数据类型说明
32*?HashStartuint256[]节点已知的最新 block 散列
32HashStopuint256请求的最后一个 block 的散列
/ w: `( K) S7 g% V* H, r. g8 M/ X
向一个节点请求包含编号从 HashStart 到 HashStop 的 block 列表的 inv 消息。若 HashStart 到 HashStop 的 block 数超过 500,则在 500 处截止。欲获取后面的 block 散列,需要重新发送 getblocks 消息。
* C8 W. ^( i6 ~' O; L7 C, C9 _inv$ e1 Y! j: v( \% u' l: `2 p
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单
+ u, s( k8 e+ u& Z( f
节点通过此消息可以广播它拥有的对象信息。这个消息可以主动发送,也可以用于应答 getbloks 消息。2 t8 n8 [* I/ h' p* o1 S0 Y& N
清单类型有以下几种:' R$ r( v6 {( J( x
名称说明
0x01TX交易
0x02Block区块
0xe0Consensus共识数据
3 b9 x# U1 |: U9 w& u$ A; d8 d
getdata1 w1 ~2 A5 X/ R& `5 k
尺寸字段数据类型说明
1Typeuint8清单类型
32*?Hashesuint256[]清单

% Q: q3 I9 I  J5 f8 J+ J" {- z; Z向一个节点请求指定的对象,它通常在接收到 inv 包并滤去已知元素后发送。/ g  f) W  K" g/ ~# H: L) P
block
: V" m- ~2 F( \
尺寸字段数据类型说明
?Blockblock区块

2 T. Q3 S# s; d. l3 ^; ]& Z向一个节点发送一个区块,用于响应请求数据的 getdata 消息。1 n  F' u. j8 c& u
tx: g, T) t1 H  ]" p* D) @. [
尺寸字段数据类型说明
?Transactiontx交易

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

本版积分规则

成为第一个吐槽的人

宠着祖宗 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    1