Hi 游客

更多精彩,请登录!

比特池塘 区块链前沿 正文

剖析以太坊的存储成本

灵宝雄起滴
168 0 0
当我们开发智能合约时,我们有几种不同类型的可用存储:
$ T' c* ^" B8 U2 P$ X
& S. L. |1 Q$ {2 J6 p! F5 ]    易失性栈访问:堆栈(Stack)
$ I! S1 r6 j8 Y# D; Y6 H
2 K$ `+ A! B. W: K* @( E6 {- ?! r    易失性存储器访问:内存(Memory)2 }' W  G2 a: I: U; y+ C  d

: Y, b* R5 a: x# i2 V4 q9 \$ j    非易失性:存储(Storage)
  p7 P: Q7 g3 ~2 z2 H4 s3 z
8 g/ [; O, q" y3 `    此外,我们还提供了背景信息:: g$ b0 l, u$ j* a
" v+ v; C3 E9 k* _
    与合约相关的代码* r0 p" w: z( b8 N1 n# \
8 ~, J0 d5 c' B' ?8 E  _
    访问交易的数据字段% S1 ~! l- p1 F# [( J
6 `5 x7 ?  M1 Z) z
    ##如何使用不同的存储类型
" t, m9 W/ Y4 }( z+ A. q; k  a0 e3 ~  }/ L
    堆栈
8 F% a4 J) O9 y4 R& v6 o8 n8 A4 G: ?: L8 T4 Y+ I7 ^
    除了STOP,JUMPDEST和INVALID操作以外,所有以太坊虚拟机操作(EVM操作码)都使用堆栈来读取或写入。但是,还有能够在不执行任何计算的情况下进行读取或写入数据的操作:
2 G' P8 `, d6 K( J+ ]* _% u  Y4 `
    堆栈深度范围从0到最大值1024! `8 [, E! X( L& `- X
# j' c* i( x0 Q
    POP:获取栈顶的值(级别0)
9 ]9 v4 q7 n3 A' a; u7 a% I7 k7 {- N9 @
    PUSH1…PUSH32(PUSHX):在栈顶插入X个字节
3 f9 d8 v9 S. w8 H  n1 b4 z- v$ v2 j& f8 Q& u
    DUP1…DUP16(DUPX):复制栈顶X处的值+ R5 l, Y& z1 }' A5 [$ d- O
$ k7 R0 n* y: J1 ^9 l- {
    SWAP1…SWAP16(SWAPX):交换X处和栈顶的值0 N2 N, S7 X/ s

' v# r! E$ p/ g0 u. L: o' r    内存
( y/ \# a. N1 S. d7 D4 N$ ^& B
; V5 |3 d- h& D3 I1 `    访问此内存(读取或写入)的操作有:
( U4 M6 B$ C4 Y* z* J+ E# t# u2 ^' J: e& q; i' t6 I/ k  Z) {
    CALLDATACOPY:读取交易的数据字段并将其加载到内存中/ ^# J' v' J. O  b& n- a4 o

) n4 [: j! n1 e, c    CODECOPY:读取与当前合约相关联的代码并将其加载到内存中7 e) E* f! v  \& F

' ]- K  K* l, V' j+ u    EXTCODECOPY:读取与外部合约相关联的代码并将其加载到内存中
: T* L) W6 f, J# I8 ?7 f. ^& J: p  z: ~& L9 ~
    MLOAD:从内存读取一个值9 x2 L3 q4 V+ x+ _& O

8 T) b+ Z/ x2 G8 \8 A1 y    MSTORE:在内存中存储一个词或32字节的值
; n3 a9 q- h' R/ C6 T4 w/ a: S3 a) `1 d* P
    MSTORE8:在内存中存储一个8字节的值2 L* N0 d! w5 d& D

$ m. ^$ `( |* f- F! p* r    存储' e! {# y+ H) F
1 r3 [/ a& i1 Z# P8 Y* x8 k" l+ d
    与堆栈和内存不同,存储在此内存中的数据在交易访问的合约地址上是永久的。维护此内存的操作有:( L- Y4 {2 ?# O/ ^) _6 W+ [
7 q" a/ S# M9 p6 ~/ u# J0 n" ~, c
    SLOAD; E- O, N  s! o/ n
' s& G- z# e$ t" t2 j5 u
    SSTORE/ \+ u) W) I9 ]' F: o8 N; w
  I& q( o0 d" _1 r. t( z
    要注意分别代表存储(Storage)和内存(Memory)的“S”和“M”。
! s) F) w- `& u- ?) Z5 z0 E" R+ A6 ?, t2 k& ?" c* [
    ##成本
( ]  T& `  ]7 Q5 ~1 m! D" Y2 v
" Z) a* {) z6 A% ]    上述所有的操作都有以Gas为单位的操作成本。当用户发起一笔交易时,他/她都会以ETH计价给出单位Gas的价格。矿工已经配置了最低的Gas价格,较高的最低Gas价格会给矿工带来更多的利润,但是会需要放弃更多的交易。这就形成了一个用单位Gas来交易ETH的市场。代码消耗的Gas越少,执行代码所需的资源就会越有效率。下表根据数据的大小,展示了不同操作码的Gas开销:
3 X1 C3 d! J8 Y4 u- j
9 J  z3 X, u( w; l- V6 `: F8 D    其中最昂贵的是非易失性存储。当数据大小为几KB时,使用内存操作与使用堆栈操作的Gas成本是差不多的,但当数据大小增加时,成本呈指数级增加。这种关系如下图所示:
7 B7 i( A( u9 W$ e
: Q# p6 t+ @  U    -3*+ROUND(POWER(,2)/512,0)-* {6 a$ j3 c6 Q' f& H* z- S

3 \" q  [. F. p* s3 @    如果我们基于https://ethgasstation.info网站设置Gas的ETH价格:
0 h4 e. J) r- a1 ~! h; a' b: U
1 Q% v; i0 F: n: d    -2018/01/1412:17AM-. Z- h( s# ~+ J. L. n7 y

* Q3 R3 b8 N; S    我们就可以用ETH价格来估算出每种存储类型的成本:
* s8 V; C& G# K* {: y, f- j0 n: R0 N4 n+ D0 B  C& A6 m) x
    STD=5gwei,FAST=50gwei-
& D' V7 Q1 E8 Z: i9 m
4 S, V7 G( X% B( a2 W: V  ?6 h% m    上表的值是以ETH为单位的价格。矿工将打包价格更高的交易,因此当用户为单位Gas支付更多的ETH时,他/她的交易就会被更快地打包进区块中。9 B$ B& }9 S' ^' K0 ^6 |
6 @+ `1 H( J- [! z
    最后,我们可以设置一个美元对ETH的汇率,例如,1356.30美元:: b, C' f8 Z" b% O; ^5 j
* r: i# @. `6 ^! _) D
    -1356.3$=1ETH,2018/01/1412:17AM-0 m* c4 R( o% [

/ S9 M$ S% L+ X2 c, v2 C1 x    结论5 P( `: q0 O* l3 l
- S3 v8 A: F* W  r5 l+ C% A$ u  |
    将数据永久存储在以太坊中是极其昂贵的。使用以太坊存储数据没有任何意义。以太坊应该只存储正常运行所需要的数据,并将数据存储委托给其他解决方案:如Swarm、Filecoin、IPFS等等。一个不错的主意是将默克尔树的根哈希值作为数据篡改证明存储在外部服务器中。
* n" ?' [/ \+ M
/ r: U, S9 M* `, b, A* ]    此外,ETH价格不可预知,可能的快速增长会导致操作的开销(以法定货币为单位)增长到更高的级别。如果发生这种情况,矿工必须调整单位Gas的最低ETH价格,以重新调整开销。3 q2 ^) l$ t9 E1 T
. B1 B8 I  o3 \+ l+ v) Y: j4 j' k
    通过分析智能合约的Gas开销来控制操作的成本是非常重要的。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

灵宝雄起滴 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    5