区块链这个范畴里,以太坊是非常耀眼的。然而,它的那些基本要素比较复杂,像区块、账户、状态交易、费用等,就好像是神秘的密码似的。了解这些要素,是深入理解以太坊的关键,而这正是我们今天要讲述的内容。

区块

一个区块包含着多方面重要内容。一方面,它是由区块头、交易列表以及叔块所组成的。在以太坊的体系里,每一个区块就如同一个既具有独立性又与其他区块相互关联的单元。就好像多米诺骨牌中的一块那样,这个单元记录着以太坊网络在特定某个时刻的信息。以太坊当中的每一个新的区块都携带着上一个区块的哈希值,这种链式的结构保证了区块链的完整性。从最开始的创世区块开始,随着时间一直不断地向前推进,新的区块在持续地产生,并且没有终点。

另外,系统会对每生成一个区块的当前状态进行一次快照,并且将其存于区块头。孤块是一种特殊的存在,它最多能有 6 个高度。这就是为什么会有 6 个区块确认主链这一说法。同时,3)交易列表会把本区块里的交易内容存储起来。

账户

在以太坊中,账户是重要的基本元素。账户分为外部拥有账户与合约账户。以太坊网络中每个人的身份标识依赖于账户。每个账户都有独特的标识属性,比如 nonce 。从时间顺序角度看,nonce 可被简单理解为一个账户发起交易或创建合约的序号。例如在 2023 年 10 月这个特定时间,上海的张先生查看自己的以太坊账户时,能看到自己账户的交易序号。这对管理他自己的账户交易历史很重要。

"blocks" : [
            {
                "blockHeader" : {
                    "bloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
                    "coinbase" : "0x3535353535353535353535353535353535353535",
                    "difficulty" : "0x020000",
                    "extraData" : "",
                    "gasLimit" : "0x05f5e100",
                    "gasUsed" : "0x014fa1",
                    "hash" : "0x39f4659b079e257df8fd7e699528531e97a6b8a442ca0d11200c4a2f7433c483",
                    "mixHash" : "0x7379f33af4ae2db7e293f808a165135d0b1a99572cc96fb9f7d17ef64a751969",
                    "nonce" : "0x8e08d7aabeee8773",
                    "number" : "0x01",
                    "parentHash" : "0xadbef3bf0b3b7b14f6e7b1a45d240ecc863543a279a86c23f60170e8e7a6bcc3",
                    "receiptTrie" : "0xb21660268480338c0cd0613358315359b619bd527d5850949c4863cddaec316b",
                    "stateRoot" : "0xde4ce9b5b2f88ab1680962c64281224b1743bdf94bd6a9e390ea779ff616c1f7",
                    "timestamp" : "0x03e8",
                    "transactionsTrie" : "0x56445ba866f3e41851154fb8700dcec8556a178f1833021e030b8a47b494769d",
                    "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
                },
                "rlp" : "0xf90308f901f9a0adbef3bf0b3b7b14f6e7b1a45d240ecc863543a279a86c23f60170e8e7a6bcc3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347943535353535353535353535353535353535353535a0de4ce9b5b2f88ab1680962c64281224b1743bdf94bd6a9e390ea779ff616c1f7a056445ba866f3e41851154fb8700dcec8556a178f1833021e030b8a47b494769da0b21660268480338c0cd0613358315359b619bd527d5850949c4863cddaec316bb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018405f5e10083014fa18203e880a07379f33af4ae2db7e293f808a165135d0b1a99572cc96fb9f7d17ef64a751969888e08d7aabeee8773f90108f90105460183030d4094c305c901078781c232a2a521c2af7980f8385ee980b8a430c8d1da000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000230644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000001ba021a28cc82b40931239f8653ffa5300e1a506c0ef7fb79a663772cafe6558ab44a075af23441f7f176a2770af41142c77b671391209b15d59144e7a1332179b5e14c0",
                "transactions" : [
                    {
                        "data" : "0x30c8d1da000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000230644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000",
                        "gasLimit" : "0x030d40",
                        "gasPrice" : "0x01",
                        "nonce" : "0x46",
                        "r" : "0x21a28cc82b40931239f8653ffa5300e1a506c0ef7fb79a663772cafe6558ab44",
                        "s" : "0x75af23441f7f176a2770af41142c77b671391209b15d59144e7a1332179b5e14",
                        "to" : "0xc305c901078781c232a2a521c2af7980f8385ee9",
                        "v" : "0x1b",
                        "value" : "0x00"
                    }
                ],
                "uncleHeaders" : [
                ]
            }
        ]

以太坊网络运行时,账户之间的交互具有重要性。账户会开展交易,同时会与合约账户进行交互,而这些交互都是按照账户的标识来予以执行的。

type Header struct {
        ParentHash  common.Hash    //Hp,上一区块全部内容的hash,区块因它而成链!
        UncleHash   common.Hash    //Ho,本区块的ommers(所有叔块)列表的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组合证明出块执行了足够的计算
        Nonce       BlockNonce     //Hn,64位的hash,与MixDigest组合证明出块执行了足够的计算
}

状态

系统状态被称为 world state,它呈现为一种 trie 结构。这个结构就像系统的中枢神经一样。因为它承担着整个以太坊网络中所有账户的状态。不过,只有它的根哈希存在于区块头的 Root 中。每当一个区块被挖出并且被确认的那一瞬间,区块头里的 Root 就仿佛是这个时刻系统状态的一张照片,把当时系统的情况给记录了下来。

任意两个账户之间进行交易,这种交易能引起 world state 的改变,就像涟漪一样。相邻区块之间的状态差别比较小。但由于 trie 结构很高效,所以能够很好地应对账户状态持续变化的情况。

交易

交易在以太坊网络中占据重要地位。从定义上来说,交易是由外部拥有账户发出的,经过了加密签名并且序列化的指令。每一笔交易都有其特定的规则。比如,Tn 必须和发起交易账户的 nonce 保持相等。以 2022 年美国的某一个以太坊交易为例,如果一个投资者想要发起交易,就一定要按照这个规则来进行。

type Account struct {
    Nonce    uint64      // σ[a]n ,若为EOA是发送的交易序号,如为CA是合约创建的序号。
    Balance  *big.Int    // σ[a]b ,这个地址的余额。
     //merkle root of the storage trie
    Root     common.Hash // σ[a]s ,账户自身内容RPL编码组成的Merkle Trie的根哈希
    CodeHash []byte      // σ[a]c ,账户绑定的EVM Code,账户一经创建不可修改。
}

根据交易类型的不同,我们会把 Td 和 Ti 区分开来。如果交易属于消息调用类型,那么 Td 就表示输入数据。像在使用注册域名的合约服务时,Td 就是该服务所需要的那些参数。要是交易是创建合约类型,Ti 就代表一段初始化代码,并且这段代码只会被执行一次。

费用

在以太坊中,费用的概念较为特别。这里存在 gas 和 eth 这两个概念。gas 是具有固定衡量标准的价值,它的状态较为稳定。eth 是在市场上会迅速变化的价格。就像在商店里,gas 如同商品的固定标价,而 eth 可能会因市场的供需关系而产生波动。许多以太坊虚拟机的操作指令消耗的费用是以 gas 来计价的,并且 gas 的最小单位是 wei。另外,之所以有存储收费,是因为一旦合约使状态数据库的存储增大,所有节点都需要增加存储,这是有成本的。

存储器的成本在不同地区的节点是有差异的。像在欧洲的数据中心节点,由于电力成本以及硬件成本等因素的作用,存储器收费的权重会比较高。

type txdata struct {
    AccountNonce uint64          //Tn
    Price        *big.Int        //Tp
    GasLimit     uint64          //Tg
    Recipient    *common.Address //Tt
    Amount       *big.Int        //Tv
    Payload      []byte          //Td || Ti 
    V *big.Int
    R *big.Int
    S *big.Int
    // This is only used when marshaling to JSON.
    Hash *common.Hash
}

交互中的状态转换

当我们与以太坊交互时,就如同一个人在复杂机器上对零件进行操作。我们进行的行为是执行交易,通过这种方式来改变系统的状态。我们用Υ表示状态转换函数,用 T 代表交易,用σ表示初始状态,用σ′表示经过转换后的状态。我们持续发起交易,就像流水线上不断组装零件一样。从创世区块开始,无穷无尽的交易一直在刷新系统状态,就像河流中的水不断流动推动水车转动一样。

如果你想深入了解以太坊,那么这些基本元素是入门的基础。你是否对以太坊的这些基本元素有了自己的新想法?欢迎大家点赞、分享并留下评论。