以太坊账户模型分析

1、引言

       区块链的本质是一个分布式的数据库。因此不同时刻的用户数据的写入对应着不同的状态。比特币使用UTXO来表示状态的转移,而以太坊使用账来表示状态的转移。

2、账户

       以太坊中存在两种账户,分别是外部账户和合约账户。

  • 外部账户EOA:一般自然人分配的账户,被私钥控制且没有任何代码与之关联。
  • 合约账户CA:给智能合约分配的账户,被合约代码控制且有代码与之关联。

    账户在源码中的定义如下:

    typeAccountstruct{

            Nonce    uint64

            Balance  *big.Int

            Root     common.Hash//merklerootofthestoragetrie

            CodeHash[]byte }

  • Nonce:如果当前账户为EOA,则Nonce为发送的交易序号;如果当前账户为CA,则Nonce为合约创建的序号。
  • Balance:账户余额,表示账户所对应地址的余额。
  • Root:存储为状态树的根hash,在EOA中,此字段为空。
  • CodeHash:账户绑定的EVM code,在EOA中,此字段为空。
以太坊账户模型分析_第1张图片
图1 此图片来自网络

    EOA账户只能发起交易,例如转移以太币或者触发合约代码。CA账户不能发起交易,可以被触发执行合约代码。

    外部账户对应转账地址,由用户创建;合约账户在以太坊中由EVM根据合约地址创建(在代码vm文件夹下evm.go文件中)。

3、交易

typeTransactionstruct{

    datatxdata

    //caches

    hashatomic.Value

    sizeatomic.Value

    fromatomic.Value

}

typetxdatastruct{

    AccountNonceuint64         

    Price        *big.Int       

    GasLimit     uint64         

    Recipient    *common.Address

    Amount       *big.Int       

    Payload      []byte         

 

    //Signaturevalues

    V*big.Int`json:"v"gencodec:"required"`

    R*big.Int`json:"r"gencodec:"required"`

    S*big.Int`json:"s"gencodec:"required"`


    //ThisisonlyusedwhenmarshalingtoJSON.

    Hash*common.Hash`json:"hash"rlp:"-"`

}

 

  • AccountNonce:发起者发起的交易总数量        
  • Price:此次交易的gas price
  • GasLimit:本交易允许消耗的最大gas数 
  • Recipient:交易接收者的地址
  • Amount:此次交易转移的以太币数量 
  • Payload:其中每个byte对应一个单独虚拟机指令
  • V签名数据
  • R签名数据
  • S签名数据
  • hash交易的hash
  • size交易数据的大小
  • from交易的发起地址

3、区块头

typeHeaderstruct {

        ParentHash common.Hash    //Hp,上一区块全部内容的hash           

        UncleHash  common.Hash    //Ho,本区块的所有叔块列表的hash

        Coinbase   common.Address //Hc,成功挖出本区块的矿工地址

        Root       common.Hash    //Hr,本区块所有交易的状态tree的根hash

        TxHash     common.Hash    //Ht,本区块所有交易tree的根hash

        ReceiptHash common.Hash   //He,本区块所有交易收据tree的根hash

        Bloom      Bloom          //Hb,交易收据日志组成的Bloom过滤器

        Difficulty    *big.Int      //Hd,本区块难度级别

        Number     *big.Int       //Hi,区块序号,从创世块0递增

        GasLimit     uint64         //Hl,每个区块当前的gas limit

        GasUsed     uint64         //Hg,本区块交易消耗的总gas

        Time        *big.Int       //Hs,本区块创建时的Unix时间戳

        Extra        []byte         //Hx,区块附加数据,<=32字节

        MixDigest    common.Hash   //Hm,256位的hash

        Nonce       BlockNonce     //Hn,64位的hash

 }

以太坊账户模型分析_第2张图片

图2 此图片来自网络

Root(状态hash):整个系统状态的hash,也就是所有账户状态树的根hash

TxHash(交易列表hash):本区块中所有交易默克尔树的根hash

ReceiptHash(收据列表hash):收据默克尔树的根hash

        状态树并不存在于链上,而存在于节点的 levelDB 中。只有它的根 hash 存在于区块头 Root 中,每一个区块头里的 Root 都是区块被挖出确认时的快照。

补充(此内容来自于网络)

三棵树允许轻客户端轻松地进行并核实以下类型的查询答案:

1)        这笔交易被包含在特定的区块中了么?

2)        告诉我这个地址在过去30天中,发出X类型事件的所有实例(例如,一个众筹合约完成了它的目标)

3)        目前我的账户余额是多少?

4)        这个账户是否存在?

5)        假装在这个合约中运行这笔交易,它的输出会是什么?

       第一种是由交易树(transaction tree)来处理的;第三和第四种则是由状态树(state tree)负责处理,第二种则由收据树(receipt tree)处理。计算前四个查询任务是相当简单的。服务器简单地找到对象,获取梅克尔分支,并通过分支来回复轻客户端。第五种查询任务同样也是由状态树处理,但它的计算方式会比较复杂。

总结

  • 整个以太坊维持一个所有账户状态的树,这棵树的hash会打包在整个链上;
  • 账户状态树本身的信息不会上链,保存在leveldb中;
  • 交易(狭义的)、消息等相关信息通过交易(广义的)的方式打包在区块上;
  • 交易的执行可大致分为内外两层结构第一层是虚拟机外,包括执行前将Transaction类型转化成Message,创建虚拟机(EVM)对象,计算一些Gas消耗,以及执行交易完毕后创建收据(Receipt)对象并返回等;第二层是虚拟机内,包括执行转帐,和创建合约并执行合约的指令数组;
  • 合约账户在创建合约时生成,不管是合约还是交易,都会和账户(EOACA)相关,所以区块中交易树hash、状态树hash、收据树hash三者能保证链的一致性。



你可能感兴趣的:(以太坊,区块链)