Hi Guest

More contents, please log on!

Bitmere.com 区块链前沿 Content
stateDB用来存储合约状态及账户余额,和indexDB类似,底层存储通过levelDB的kv存储来实现。和indexDB不同的是stateDB为了能够支持快速的状态回滚操作,实现了多版本,每个版本的kv数据会关联状态对应的快照高度,这样当快照回滚的时候,可以非常快速的恢复到目标高度的状态。

1.key设计
不管是账户余额还是合约都有唯一的地址,因此可以以地址为key来做空间划分,对于同一个地址的访问更容易实现更高的读写效率。另外为了区分不同数据类型,在地址的前面会有一个字节用来标记key对应的是账户余额还是合约状态,以及其他预定义的数据类型。

stateDB key的具体实现如上图示
key type:key的类型,用来区分账户余额,合约状态,账户余额历史,合约状态历史等
address:状态所属的普通地址或合约地址
user key:对除了账户余额外的其他key type有效
version/sb height:通过快照高度来区分不同版本的状态

2.高度回滚
因为stateDB支持多版本的数据,因此可以实现对历史数据的遍历,这里只保留一个高度窗口内的多个数据版本,满足回滚的需求,同时也能避免数据过度膨胀。
由于只存储了历史快照数据,没有存储用户在两次快照之间的数据变动的细节信息,所以假如没有引入其他的机制,在数据回滚时,只能回滚到数据的某个历史快照状态,无法回滚到两个快照之间的某个细节状态。举个例子,假如在快照块高度为10000时,用户A1拥有数据k1=v1,在快照块高度为10001时,用户A1的数据变更为k1=v3,假设在快照高度为10000之后,k1的值变换了两次,从v1变化到了v3(v1->v2->v3),这表明在快照块10000与10001之间,用户A1产生了多于1个account block(一个account block会导致一个用户的数据集合发生原子变更),而stateDB只记录了快照块高度为10000和快照块高度为10001是用户A1的两个版本的数据,不会记录两个快照之间的account block产生的数据变动的细节信息,因而在发生数据回滚时,只能回滚到某个历史快照的数据状态。为了解决这个问题,引入了state redo机制,state redo中记录了最近写入的account block产生的数据变化的细节信息,那么在发生较近的数据回滚时,可以回滚到某个account block出现后的数据版本。但是如果发生较远的数据回滚时(如回滚了5000个快照块,实践中这样回滚的概率非常小),state redo机制就不起作用了,启动兜底方案,即只回滚到历史的快照数据版本,同时回滚这个快照块之后的所有account block。

3.缓存
合约的更新操作并不会直接写入底层存储,而是会把操作本身依序记录在内存的unsaved数据结构,待合约执行成功后,通过redo操作记录写入stateDB,这个过程和accountBlock写入blockDB是作为一个整体进行操作的。
stateDB为最近读写入的账户余额、内置合约的状态及外置合约的元数据这些常用的数据建立了缓存,方便进行快速的读取。
BitMere.com is Information release platform,just provides information storage space services.
The opinions expressed are solely those of the author,Does not constitute advice, please treat with caution.
You have to log in before you can reply Login | 立即注册

Points Rules

Write the first review

一身似水厝 初中生
  • Follow

    0

  • Following

    0

  • Articles

    21

币圈江左盟
Promoted