账户结构

以太坊基本数据单元(Metadata):Account

不同于Bitcoin 基于 UTXO 的 Blockchain/Ledger 系统,Ethereum是以 Account/State 模型为核心的基于交易驱动的状态机(Transaction-based State Machine),我们常说的世界状态(State),其根本是反应了某一账户(Account)在某一时刻下的属性。

其中,State 对应的基本数据结构,称为 stateObject(内部维护,不可导出)。当 stateObject 的值由Transaction 的执行而触发数据更新/删除/创建而发生了变化时,我们称为状态转移

即stateObject 的状态从当前的 State 转移到另一个 State

// core/state/state_object.go
type stateObject struct {
  address  common.Address
  addrHash common.Hash // hash(address)
  
  // account state
  data     types.StateAccount
  // 指向stateDB: 真正存储数据的地方
  // 方便调用 StateDB 相关的API对Account所对应的stateObject进行CRUD操作
  db       *StateDB

  // DB error.
  // State objects are used by the consensus core and VM which are
  // unable to deal with database-level errors. Any error that occurs
  // during a database read is memoized here and will eventually be returned
  // by StateDB.Commit.
  dbErr error

  // 内存缓存相关逻辑
  trie Trie // storage trie
  code Code // contract bytecode, 缓存代码当代码被从DB storage中加载出来 

  // 在执行 Transaction 的时候缓存合约修改的持久化数据
  // EOA账户为空
  originStorage  Storage 
  pendingStorage Storage 
  dirtyStorage   Storage 
  fakeStorage    Storage 

  dirtyCode bool // true: 当code被更新
  suicided  bool
  deleted   bool
}

1)EOA账户

的创建:包含本地创建链上注册(stateDB进行链上账户管理),入口函数NewAccount

passphrase入参仅用于加密本地保存私钥的Keystore文件(使用对称加密算法来加密私钥生成),与生成账户的私钥、地址的生成无关。

私钥泄露、助记词泄露、Keystore+密码泄露都会导致账户控制权丢失

  • 账号创建

    这里实际上只进行了ecdsa计算和keystore存储,实际账户在以太坊世界状态中存储,只需要等待有相关联的Transaction发生,若不存在就会自动通过newObject() //core/state/state_object.go创建

  • 算法生成过程:

    • 第一步:32字节,私钥 (private key)

      伪随机数产生的256bit私钥示例(256bit)

      18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725

    • 第二步:64字节,公钥 (public key)

      采用椭圆曲线数字签名算法ECDSA-secp256k1将私钥(32字节)映射成公钥(算上前缀65字节)

    ​ (前缀04+X公钥+Y公钥),公钥是椭圆曲线上的一点,故有(X, Y)

      04   50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352   2cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6

    ​ (去掉04前缀)计算公钥的 Keccak-256 哈希值(32bytes):

      fc12ad814631ba689f7abe67 1016f75c54c607f082ae6b0881fac0abeda21781

    • 第三步:20字节,地址 (address)

      取上一步hash值的后20bytes,加上前缀0x,即以太坊地址:

      0x 1016f75c54c607f082ae6b0881fac0abeda21781

    比特币地址生成过程,在上述第三步之后还有其他操作:

    1. 计算RIPEMD-160哈希: 对上一步得到的SHA-256哈希值执行RIPEMD-160哈希运算。这将会得到一个20字节的值。

    2. 添加地址版本前缀: 为了区分主网和测试网的地址,会在RIPEMD-160哈希的前面添加一个字节的版本。例如,比特币主网地址的版本前缀是0x00。

    3. 计算双重SHA-256哈希校验和: 对前一步得到的结果执行两次SHA-256哈希,并取哈希的前4个字节作为校验和。

    4. 组合并进行Base58编码: 将前缀、RIPEMD-160哈希和校验和组合在一起,然后使用Base58编码得到比特币地址。

  • 签名Sign(65字节)

密码学技术分类

虽然以太坊签名算法也采样了 secp256k1(与比特币相同) ,但是在签名的格式上有所差异,比特币在 BIP66中对签名数据格式采用严格的DER(Distinguished Encoding Rules,可辨别编码规则)编码格式。

ECDSA.spec256k1椭圆曲线签名算法

使用公钥叫加密数据,使用私钥叫签名,签名通过公钥验签

以太坊的签名格式是r+s+vrs是ECDSA签名的原始输出,而末尾的一个字节为恢复id(recovery id简称recid) ,在以太坊中用v表示,是签名的最后一个字节。 65 字节的序列:r 有 32 个字节,s 有 32 个字节,v 有一个字节。

recid称为恢复标识符。因为我们使用的是椭圆曲线算法,仅凭 r 和 s 可计算出曲线上的多个点,因此会恢复出两个不同的公钥(及其对应地址)。v 会告诉我们应该使用这些点中的哪一个(也可以理解为查找次数)。在大多数实现中,v =recid,在内部只是 0 或 1。

在以太坊中区块中的数据需要签名的仅有交易Transaction

注意:EIP-155后,在交易签名时,v值不再是recid, 而是 v = recid+ chainID*2+ 35(旧为v = recid+27)

2)CA账户

Storage是一个 key 和 value 都是common.Hash类型的 map 结构,account code 实际存储位置,与EOA账户相比合约账户额外保存了一个存储层(Storage)用于存储合约代码中持久化的变量的数据

对应solidity智能合约的状态变量

Storage 层的基本组成单元称为槽 (Slot)。若干个 Slot 按照Stack的方式顺序集合在一起就构造成了 Storage 层。每个 Slot 的大小是 256 bits(32 bytes)的数据。

Slot 作为基本的存储单元,通过地址索引的方式被上层函数访问。Slot的地址索引的长度同样是32 bytes(256 bits),寻址空间从 0x00000000000000000000000000000000000000000000000000000000000000000xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF。因此在理论状态下,一个 合约 可以最多保存 2^256 bytes (0 - 2^256-1) 的数据,这是个相当大的数字。

可观测宇宙中约有2^272个原子

为了更好的管理数据,Contract 同样使用 MPT(会对slot[key] = value中key值(即slot position)进行hash存储) 作为索引树(Account stroage trie)来管理 Storage 层的Slot。

值得注意的是,合约 Storage 层的数据并不会跟随交易一起,被打包进入 Block 中。只有Account storage Trie root 被保存在 account state 结构体中,而account state构成世界状态state。

因此,当某个 Contract 的 Storage 层的数据发生变化时,任一叶子结点account state的改变会使account storage tire root改变,进而使世界状态state其中的一个叶子结点发生改变,进而改变state root,从而记录到Chain链上(包含在block header中)。

Storage 的数据读取和修改,具体是在执行相关 Transaction 的时候,通过 EVM opcodes中sloadsstore来实际执行的

Last updated