V神·以太坊上的分片

2023-10-28

译者序

本文是我应以太坊中文社区(Ethfans.org)之邀做的翻译稿,原文取自以太坊社区的Github: [https://github.com/ethereum/sharding/blob/develop/docs/doc.md] 。原文最后更新于2018年1月5日。

2017年8月,比特币网络进行了硬分叉,产生了比特币现金(Bitcoin Cash),这个硬分叉的技术解释就是对比特币网络进行“扩容”。比特币现金网络中的区块大小为8M,是比特币网络区块大小的8倍(比特币网络区块大小为1M),从而提高了每个区块的交易容量,反映为网络整体吞吐量的提高。而其他使用了与比特币网络类似的数据存储形式的加密货币网络,也必将伴随交易量的增加逐渐开始需要面对“扩容”的问题。“分片”(Sharding)就是以太坊网络为了解决扩容问题而设计的一种技术方案。

“分片”的大致设计思路是:将区块链网络中的每个区块变为一个子区块链,子区块链中可以容纳若干(目前为100个)打包了交易数据的Collation(大概可以称为“校验块”,为了在分片的情景中将其与区块的概念区分开),这些Collation最终组成一个在主链上区块;因为这些Collation是整体作为区块存在的,所以其数据必定是全部由某个特定的矿工所打包生成,本质上和现有协议中的区块没有区别,所以不再需要增加额外的网络确认。这样,每个区块的交易容量就大概扩大了100倍;而且这种设计还有利于未来的继续扩展,整个扩展计划目前也被大致分为4个阶段;本文所介绍的仅仅是第一阶段的相关实现细节。

这是一篇关于以太坊的“分片”技术改进的细节说明文档,供以太坊开发者和有兴趣的技术同行参考。

(编者注:本文于 2018 年 6 月 12 日经过重新编辑,同步了译者在 5 月 18 日完成的新译本。)


目录

序言

本文的目的是为那些希望理解分片建议详情,乃至去实现它的朋友提供一份相对完整的细节说明和介绍。本文仅作为二次方分片(quadratic sharding)的第一阶段的描述;第二、三、四阶段目前不在讨论范围,同样,超级二次方分片(super-quadratic sharding)(“Ethereum 3.0”) 也不在讨论范围。

假设用变量 c 来表示一个节点的有效计算能力,那么在一个普通的区块链里,交易容量就被限定为 O(c),因为每个节点都必须处理所有的交易。二次方分片的目的,就是通过一种双层的设计来增加交易容量。第一层不需要硬分叉,主链就保持原样。不过,一个叫做 校验器管理和约(validator manager contract,VMC)的合约需要被发布到主链上,它用来维持分片系统。这个合约中会存在 O(c) 个 分片 (目前为 100),每个分片都像是个独立的“银河”:它具有自己的账户空间,交易需要指定它们自己应该被发布到哪个分片中,并且分片间的通信是受限的(事实上,在第一阶段,不存在这种通信能力)。

分片运行在一个普通的符合最长链规则的权益证明系统中,权益数据将保存在主链上(具体来说,是在 VMC 中)。所有分片共享一个通用验证器池,这也意味着:任何通过 VMC 注册的验证器,理论上都可以在任意时间被授权来在任意分片上创建区块。每个分片会有一个 O(c) 的区块大小 / gas 上限(block size/gas limit),这样,系统的整体容量就变成了 O(c^2) 。

分片系统中的大多数用户都会运行两部分程序。(i) 一个在主链上的全节点(需要 O(c) 资源)或轻量节点(需要 O(log(c)) 资源)。 (ii) 一个通过 RPC 与主链交互的“分片客户端”(由于这个客户端同样运行在当前用户的计算机中,所以它被认为是可信的);它也可以作为任意分片的轻客户端、作为特定分片的全客户端(用户需要指定他们正在“监视”某个特定的分片),或者作为一个验证器节点。在这些情况下,一个分片客户端的存储和计算需求也将不会超过 O(c) (除非用户指定他们正在监视 每个 分片;区块浏览器和大型的交易所可能会这么做)。

在本文中,术语 Collation 被用来与 Block(区块)相区别,因为: (i) 它们是不同的 RLP(Recursive Length Prefix)对象:交易是第 0 层的对象,collation 是用来打包交易的第一层的对象,而 block 则是用来打包 collation(header)的第二层的对象; (ii) 在分片的情景中这更加清晰。通常,Collation 必须由 CollationHeader 和 TransactionList(交易列表)组成;Collation 的详细格式和 Witness(见证人)会在 无状态客户端 那节定义。Collator(即用来打包 transaction 生成 collation 的某个地址,译者注)是由主链上 验证器管理合约 的 getEligibleProposer 函数所生成的示例。算法会在随后的章节中介绍。

Main Chain Shard Chain
Block Collation
BlockHeader CollationHeader
Block Proposer (or Miner in PoW chain) Collator

二次方分片(Quadratic Sharding)

常量

  • LOOKAHEAD_PERIODS: 4
  • PERIOD_LENGTH: 5
  • COLLATION_GASLIMIT: 10,000,000 gas
  • SHARD_COUNT: 100
  • SIG_GASLIMIT: 40000 gas
  • COLLATOR_REWARD: 0.001 ETH

验证器管理合约(Validator Manager Contract,VMC)

我们假定 VMC 存在于地址 VALIDATOR_MANAGER_ADDRESS 上(在已有的“主分片”上),它支持下列函数:

  • deposit() returns uint256:添加一个验证器到验证器集合中,验证器的大小就是函数调用时的 msg.value(也就是存入的以太币数量)。这个函数会返回验证器的索引序号。
  • withdraw(uint256 validator_index) returns bool:验证 msg.sender == validators[validator_index].addr,如果相等,它会将验证器从验证器集合中移除,并退还存入的以太币。
  • get_eligible_proposer(uint256 shard_id, uint256 period) returns address:使用一个区块哈希(block hash)作为种子,基于预设的算法从验证器集合中选择一个签名者(signer)。验证器被选中几率应该与其存款数量成正比。这个函数应该可以返回一个当前周期内的值或者以 LOOKAHEAD_PERIODS 为上限的任意未来周期内的值。
  • add_header(uint256 shard_id, uint256 expected_period_number, bytes32 period_start_prevhash, bytes32 parent_hash, bytes32 transaction_root, address coinbase, bytes32 state_root, bytes32 receipt_root, uint256 number) returns bool:尝试处理一个 collation header,成功时返回 true,失败时返回 false。
  • get_shard_head(uint256 shard_id) returns bytes32:返回验证器管理合约内由参数所指定的分片的 header 哈希。

这里也有一个日志类型:

  • CollationAdded(indexed uint256 shard_id, bytes collation_header_bytes, bool is_new_head, uint256 score)

其中的 collation_header_bytes 可以用 vyper 语言来构造:

    collation_header_bytes = concat(
        as_bytes32(shard_id),
        as_bytes32(expected_period_number),
        period_start_prevhash,
        parent_hash,
        transaction_root,
        as_bytes32(collation_coinbase),
        state_root,
        receipt_root,
        as_bytes32(collation_number),
    )

注意:因为 coinbase 和 number 在 vyper 语言中是保留字,所以它们被重命名为 collation_coinbase 和 collation_number

Collation Header

我们首先以一个有下列内容的 RLP 列表来定义一个“collation header”:

[
shard_id: uint256,
expected_period_number: uint256,
period_start_prevhash: bytes32,
parent_hash: bytes32,
transaction_root: bytes32,
coinbase: address,
state_root: bytes32,
receipt_root: bytes32,
number: uint256,
]

这里:

  • shard_id 分片的ID;
  • expected_period_number 是 collation 希望被包含进的周期序号,这是由 period_number = floor(block.number / PERIOD_LENGTH) 计算出来的;
  • period_start_prevhash 前一区块,即区块 PERIOD_LENGTH * expected_period_number - 1 的区块哈希(这其实就是希望被包含进的周期起始区块之前的最后一个区块的哈希)。分片中使用区块数据的操作码(例如 NUMBER 和 DIFFICULTY)会使用这个区块的数据;只有 COINBASE 操作码会使用分片的 coinbase;
  • parent_hash 是父 collation 的哈希;
  • transaction_root 是包含了当前 collation 中的所有交易数据的树(trie)的根哈希;
  • state_root 是分片中当前 collation 之后的新状态根;(也就是当前 collation 中包含的所有交易执行之后,且记账收益分配之后得到的状态树根节点哈希,译者注)
  • receipt_root 是收据树(receipt trie)根哈希;
  • number 是 collation 编号,现在也是分叉选择规则中的分值;且

当 addHeader(header) 的调用返回 true 时, collation header 有效。验证器管理合约会在满足下列条件时这么做:

  • shard_id 是 0 到 SHARD_COUNT 之间的数值;
  • expected_period_number 与当前周期号相等(即 floor(block.number / PERIOD_LENGTH)
  • 在相同的分片中,一个具有 parent_hash 的 collation 已经被接受;(即当前 collation 的父 collation 已经被接受,译者注)
  • 在相同分片中,当前周期内还没有一个同样的 collation 被提交;(也就是检查要添加的 collation 是否已经添加过了,译者注)
  • add_header 函数调用者的地址与 get_eligible_proposer(shard_id, expected_period_number) 所返回的地址相同。(即判断要添加这个 collation 的 proposer 是否是给定分片、给定周期的合法记账人,译者注)

当满足以下条件时, collation 有效: (i) 它的“collation header”有效; (ii) 在 parent_hash 的 state_root 上执行 collation 的结果为给定的 state_root 和 receipt_root;并且 (iii) 总共使用的 gas 小于等于 COLLATION_GASLIMIT 。

Collation 状态转换函数

执行一个 collation 时的状态转换处理如下:

  • 按顺序执行由 transaction_root 所指定的树上的每个交易;并且
  • 将 COLLATOR_REWARD 的奖励分配给 coinbase。

`getEligibleProposer` 的细节

这里是用 Viper 写的一个简单实现:

def getEligibleProposer(shardId: num, period: num) -> address:
    assert period >= LOOKAHEAD_PERIODS
    assert (period - LOOKAHEAD_PERIODS) * PERIOD_LENGTH < block.number
    assert self.num_validators > 0

    h = as_num256(
        sha3(
            concat(
                blockhash((period - LOOKAHEAD_PERIODS) * PERIOD_LENGTH),
                as_bytes32(shardId)
            )
        )
    )
    return self.validators[
        as_num128(
            num256_mod(
                h,
                as_num256(self.num_validators)
            )
        )
    ].addr

无状态客户端(Stateless Clients)

当验证器被要求在一个给定的分片上创建区块时,一个验证器仅会被给予数分钟的通知(准确地说,就是持续 LOOKAHEAD_PERIODS * PERIOD_LENGTH 个区块的通知)。在 Ethereum 1.0 中,创建一个区块需要为验证交易而访问全部的状态。这里,我们的目标是避免需要验证器保留整个系统的状态(因为这样就将使运算资源需求变为 O(c^2) 了)。取而代之,我们允许验证器在仅知晓根状态(state root)的情况下创建 collation,而将其他责任交给交易发送者,由他们提供“见证数据”(witness data)(也就是 Merkle 分支),以此来验证交易对账户产生影响的“前状态”(pre-state),并提供足够的信息来计算交易执行后的“后状态根”(post-state root)。

(应该注意到,使用非无状态范式(non-stateless paradigm)来实现分片,理论上是可能的;然而,这需要: (i) 租用存储空间来保持存储的有界性;并且 (ii) 验证器需要使用 O(c) 的时间在一个分片中创建区块。上述方案避免了对这些牺牲的需求。)

数据格式

我们修改了交易的格式,以使交易必须指定一个 访问列表 来列举出它可以访问的状态(后边我们会更精确的描述这点,这里不妨把它想象为是一个地址列表)。任何在 VM 执行过程中试图读写交易所指定的访问列表以外的状态,都会返回一个错误。这可以防止这样的攻击:某人发送了一个消耗 500 万 gas 的随机执行,然后试图访问一个交易发送者和 collator 都没有见证人的随机账户;也可以防止 collator 包含进像这样浪费 collator 时间的交易。

交易发送者必须指定“见证人”(witness),这在被签名的交易体 之外 ,但也被打包进交易。这里的见证人是一个 Merkle 树节点的 RLP 编码的列表(RLP-encoded list),它是由交易在其访问列表中所指定的状态的组成部分。这使 collator 仅使用状态根就可以处理交易。在发布 collation 的时候,collator 也会发送整个 collation 的见证人。

交易打包格式

    [
        [nonce, acct, data....],    # transaction body (see below for specification)
        [node1, node2, node3....]   # witness
    ]

Collation格式

    [
        [shard_id, ... , sig],   # header
        [tx1, tx2 ...],          # transaction list
        [node1, node2, node3...] # witness
    ]

也请参考 ethresearch 上的帖子 无状态客户端的概念 。

无状态客户端状态转换函数

通常,我们可以将传统的“有状态”客户端执行状态转换的函数描述为: stf(state, tx) -> state'(或 stf(state, block) -> state')。在无状态客户端模型中,节点不保存状态,所以 apply_transaction 和 apply_block 可以写为:

apply_block(state_obj, witness, block) -> state_obj', reads, writes

这里,state_obj 是一个数据元组,包含了状态根和其他 O(1) 大小的状态数据(已使用的 gas、receipts、bloom filter 等等);witness 就是见证人;block 就是区块的余下部分。其返回的输出是:

  • 一个新的 state_obj 包含了新的状态根和其他变量;
  • 从见证人那里读取的对象集合(用于区块创建);和
  • 为了组成新的状态树(state trie)而被创建的一组新的状态对象。

这使得函数是“单纯性的”(pure),仅处理小尺寸对象(small-sized objects)(相反的例子就是现行的以太坊状态数据,现在已经 数百G字节 ),从而使他们可以方便地在分片中使用。

客户端逻辑

一个客户端应该有一个如下格式的配置:

{
    validator_address: "0x..." OR null,
    watching: [list of shard IDs],
    ...
}

如果指定了 validator 地址,那么客户端会在主链上检查这个地址是否是有效的 validator。如果是,那么在每次在主链上开始一个新周期时(例如,当 floor(block.number / PERIOD_LENGTH) 变化的时候),客户端将为所有分片的周期 floor(block.number / PERIOD_LENGTH) + LOOKAHEAD_PERIODS 调用 getEligibleProposer。如果这个调用返回了某个分片 i 的验证器地址,客户端会运行算法 CREATE_COLLATION(i)(参考下文)。

对于 watching 列表中的每个分片 i,每当一个新 collation header 出现在主链上,它就会从分片网络中下载完整的 collation,并对其进行校验。它将内部保持追踪所有有效的 header(这里的有效性是回溯的,也就是说,一个 header 如果是有效的,那么他的父 header 也应该是有效的),并且将 head 具有最高得分的分片链接受为主分片链,同时从创世(genesis)collation 到 head 的所有 collation 都是有效的和可用的。注意,这表示主链的重组  分片链的重组都将影响分片的 head。

逆向匹配候选 head

为了实现监视分片的算法和创建 collation,我们要做的第一件事就是使用下面的算法来按由高到低的顺序匹配候选 head。首先,假设存在一个(非单纯的、有状态的)方法 getNextLog(),它可以取得某个还没有被匹配的给定分片的最新的 CollationAdded 日志。这可以通过逆向匹配最新的区块的所有日志来达成,即从 head 开始,反方向扫描 receipt 中的每个区块。我们定义一个有状态的方法 fetch_candidate_head

unchecked_logs = []
current_checking_score = None

def fetch_candidate_head():
    # Try to return a log that has the score that we are checking for,
    # checking in order of oldest to most recent.
    for i in range(len(unchecked_logs)-1, -1, -1):
        if unchecked_logs[i].score == current_checking_score:
            return unchecked_logs.pop(i)
    # If no further recorded but unchecked logs exist, go to the next
    # isNewHead = true log
    while 1:
        unchecked_logs.append(getNextLog())
        if unchecked_logs[-1].isNewHead is True:
            break
    o = unchecked_logs.pop()
    current_checking_score = o.score
    return o

用普通的语言重新表述,这里就是反向扫描 CollationAdded 日志(对正确的分片),直到获得一个 isNewHead = True 的日志。首先返回那个日志,然后用从老到新的顺序返回所有与那个日志分值相同的且 isNewHead = False 的所有最新日志。随后到前一个 isNewHead = True 的日志(即确保分值会比前一个 NewHead 低,但比其他人高),再到这个日志之后的所有具有该分值的最新 collation,而后到第四个。

这就是说这个算法确保了首先按照分值的由高到低、然后按照从老到新的顺序检查潜在的候选 head。

例如,假定 CollationAdded 日志具有以下哈希和分值:

... 10 11 12 11 13 14 15 11 12 13 14 12 13 14 15 16 17 18 19 16

那么,isNewHead 将被按如下赋值:

... T T T F T T T F F F F F F F F T T T T F

如果我们将 collation 命名为 A1..A5、 B1..B5、 C1..C5 和 D1..D5 ,那么精确的返回顺序将是:

D4 D3 D2 D1 D5 B2 C5 B1 C1 C4 A5 B5 C3 A3 B4 C2 A2 A4 B3 A1

监视一个分片

如果一个客户端在监视一个分片,它应该去尝试下载和校验那个分片中的所有 collation(检查任何给定的 collation,仅当其父 collation 已经被校验过)。要取得 head,需要持续调用 fetch_candidate_head(),直到它返回一个被校验过的 collation,也就是 head。通常情况下它会立即返回一个有效的 collation,或者最多因为网络延迟或小规模的攻击导致生成过几个无效或者不可用的 collation,而需要稍微尝试几次。只有在遭遇一个真正长时间运行的 51% 攻击时,这个算法会恶化到 O(N) 的时间。

`CREATE_COLLATION`

这个处理由三部分组成,第一部分可以被叫做 GUESS_HEAD(shard_id),其示意代码如下:

# Download a single collation and check if it is valid or invalid (memoized)
validity_cache = {}
def memoized_fetch_and_verify_collation(c):
    if c.hash not in validity_cache:
        validity_cache[c.hash] = fetch_and_verify_collation(c)
    return validity_cache[c.hash]


def main(shard_id):
    head = None
    while 1:
        head = fetch_candidate_head(shard_id)
        c = head
        while 1:
            if not memoized_fetch_and_verify_collation(c):
                break
            c = get_parent(c)

fetch_and_verify_collation(c) 包含了从分片网络取得 c 的所有数据(包括见证人信息)并校验它们的处理。上述算法等价于“选取最长有效链,尽可能的检查有效性,如果其数据无效,则转而处理已知的次长链”。这个算法应该仅当校验器执行超时时才会停止,这就是该创建 collation 的时候了。每个 fetch_and_verify_collation 的执行都应该返回一个“写集合”(参考上文的“无状态客户端”那节)。保存所有这些“写集合”,把它们组合在一起,就构成了 recent_trie_nodes_db 。

我们现在可以来定义 UPDATE_WITNESS(tx, recent_trie_nodes_db) 了。在运行 GUESS_HEAD的过程中,某节点会接收到一些交易。当它要把交易(尝试)包含进 collation 的时候,这个算法需要先运行交易。假定交易有一个访问列表 [A1 ... An] 和一个见证人 W,对于每个 Ai 使用当前状态树的根取得 Ai 的 Merkle 分支,使用 recent_trie_nodes_db 和 W 一起作为数据库。如果原始的 W 正确,并且交易不是在客户端做这些检查之前就已经发出的话,那么这个取得 Merkle 分支的操作总是会成功的。在将交易包含进 collation 之后,状态变动的“写集合”也应该被添加到 recent_trie_nodes_db 中。

下面我们就要来 CREATE_COLLATION 了。作为例证,这里是这个方法中可能的、收集交易信息处理的完整示意代码。

# Sort by descending order of gasprice
txpool = sorted(copy(available_transactions), key=-tx.gasprice)
collation = new Collation(...)
while len(txpool) > 0:
    # Remove txs that ask for too much gas
    i = 0
    while i < len(txpool):
        if txpool[i].startgas > GASLIMIT - collation.gasused:
            txpool.pop(i)
        else:
            i += 1
    tx = copy.deepcopy(txpool[0])
    tx.witness = UPDATE_WITNESS(tx.witness, recent_trie_nodes_db)
    # Try to add the transaction, discard if it fails
    success, reads, writes = add_transaction(collation, tx)
    recent_trie_nodes_db = union(recent_trie_nodes_db, writes)
    txpool.pop(0)

最后,有一个额外的步骤,最终确定collation(给 collator 发放奖励,也就是 COLLATOR_REWARD的 ETH)。这需要询问网络以获得 collator 账户的 Merkle 分支。当得到网络对此的回应之后,发放奖励之后的“后状态根”(post-state root)就可以被计算出来了。Collator 就可以用 (header, txs, witness) 的形式打包这个 collation 了。这里,见证人(witness)就是由所有交易的见证和 collator 账户的 Merkle 分支组成的。

协议变动

交易的格式

交易的格式现在将变为(注意这里包含了 账户抽象 和 读/写列表 ):

    [
        chain_id,      # 1 on mainnet
        shard_id,      # the shard the transaction goes onto
        target,        # account the tx goes to
        data,          # transaction data
        start_gas,     # starting gas
        gasprice,      # gasprice
        access_list,   # access list (see below for specification)
        code           # initcode of the target (for account creation)
    ]

完成交易的处理过程也将变为:

  • 校验 chain_id 和 shard_id 是正确的;
  • 从 target 账户中减去 start_gas * gasprice wei;
  • 检查目标 account 是否有代码,如果没有,校验 sha3(code)[12:] == target ;
  • 如果目标账户为空,使用 code 作为初始代码,在 target 中执行一个合约的创建;否则,跳过这个步骤;
  • 执行一个消息,使用:剩余的气作为 startgas,target 作为地址,0xff...ff 作为发送者,0 作为 value,以及当前交易的 data 作为 data;
  • 如果上述任何一个执行失败,并且消耗了 <= 200000 的 gas(即 start_gas - remaining_gas <= 200000),那么这个交易是无效的;
  • 否则,remaining_gas * gasprice 将被退还,已支付的交易费将被添加到一个交易费计数(注意:交易费 不会 被直接加入 coinbase 余额,而是在区块最终确认时立即添加)。

双层树(two-layer trie)重新设计

现存的账户模型将被替换为:在一个单层树中收录进所有账户的余额、代码和存储。具体来讲,这个映射为:

  • 账户 X 的余额:sha3(X) ++ 0x00
  • 账户 X 的代码:sha3(X) ++ 0x01
  • 账户 X 的存储键值 K:sha3(X) ++ 0x02 ++ K

请参考 ethresearch 上的帖子 单层树中的双层账户树 。

此外,这个树现在有了一个新的二进制设计: https://github.com/ethereum/research/tree/master/trie_research 。

访问列表

一个账号的访问列表看起来大概像这样:

[[address, prefix1, prefix2...], [address, prefix1, prefix2...], ...]

从根本上说,这意味着:“这个交易可以访问这里给定的所有账户的余额和代码,并且账户列表中给出的每个账户的前缀中至少有一个是该账户存储的一个键的前缀”。我们可以将其转换为“前缀列表格式”,基本上就是一个账户的内部存储树(storage trie)的前缀列表(参考前面的章节):

def to_prefix_list_form(access_list):
    o = []
    for obj in access_list:
        addr, storage_prefixes = obj[0], obj[1:]
        o.append(sha3(addr) + b'\x00')
        o.append(sha3(addr) + b'\x01')
        for prefix in storage_prefixes:
            o.append(sha3(addr) + b'\x02' + prefix)
    return o

我们可以通过取得交易的访问列表,将其变换为前缀列表格式,然后对前缀列表中的每个前缀执行 get_witness_for_prefix,并将这些调用结果组成一个集合;以此来计算某个交易见证人。

get_witness_for_prefix 会返回树节点中可以访问以指定前缀开始的所有键值的一个最小集合。参考这里的实现: https://github.com/ethereum/research/blob/b0de8d352f6236c9fa2244fed871546fabb016d1/trie_research/new_bintrie.py#L250 。

在 EVM 中,任何尝试对访问列表以外的账户的访问(直接调用、SLOAD 或者通过类似 BALANCE 或 EXTCODECOPY 的 opcode 的操作)都会导致运行这种代码的 EVM 实例抛出异常。

请参考 ethresearch 上的帖子 账户读/写列表 。

Gas 的消耗

待定。

后续的阶段

通过分离区块 proposer 和 collator,我们实现了二次方扩展,这是一种快速、不彻底的中等安全权益证明分片,以此在不对协议或软件架构做太多更改的情况下增加了大约 100 倍的吞吐量。这也被用来作为一个完整的二次方分片多阶段计划的第一阶段,后续阶段大致如下:

  • 第二阶段(two-way pegging,即双向限定) :参考 USED_RECEIPT_STORE 章节,仍在撰写;
  • 第三阶段,选项a :将 collation header 作为 uncle 加入,而不是交易;
  • 第三阶段,选项b :将 collation header 加入一个数组,数组中的元素 i 必须为分片 i 的 collation header 或者空字符串,并且额外的数据必须为这个数组的哈希(软分叉);
  • 第四阶段(tight coupling,即紧耦合) :如果区块指向无效或不可用的 collation,那么区块也将变为无效;增加数据可用性证明。

原文链接: https://github.com/ethereum/sharding/blob/develop/docs/doc.md
作者: Vitalik
翻译: 风静縠纹平

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

V神·以太坊上的分片 的相关文章

  • 51行代码实现简单的PHP区块链

    本文原始地址 php区块链demo 今年区块链特别火 我也很火啊 我火什么呢 前几年 公众平台出现 还得花时间去学去看 后来小程序出现 又得花时间精力去学去看 现在比特币 以太坊等去中心化货币带起了区块链的发展 还得学 没办法 技术改变师姐
  • 以太坊智能合约部署与交互

    启动容器来执行geth命令 root ubu blockchain2 docker run i blockchain101 ethereum geth 1 6 5 geth attach http 45 32 252 88 8201 Wel
  • 以太坊智能合约安全监测工具 Oyente

    金色财经讯 2017年6月19日 数字资产管理公司Melonport AG与Oyente的开发者们合作 发布了一个测试版分析工具 旨在检查可执行的分布式代码合同 EDCC 的缺陷 Melonport和Oyente发布Bug检查工具 来源 金
  • 最新区块链开发教程汇总

    区块链的重要性已经毋庸置疑 但对大多数跃跃欲试的开发者而言 去中心化思想 非对称加密 共识算法等技术点的理解和运用 都是入门区块链开发的挑战 合适的区块链开发教程可以极大地缩短区块链开发的学习周期 因此 本文汇总整理了以太坊 比特币 EOS
  • 以太坊学习笔记(三)——搭建以太坊私链

    以太坊私链的搭建可以直接通过下载程序进行安装 也可以通过编译源码安装 本文介绍通过编译源码进行安装 编译源码 1 准备环境 我们下载的是go语言的源码 首先需要正确的安装go语言环境 如何正确安装go语言环境 大家可以去网上找教程 2 下载
  • 以太坊json rpc

    Contents Hash List JSON RPC support HEX value encoding The default block parameter Curl Examples Explained JSON RPC meth
  • 关于智能合约开发的真相

    就像 区块链 AI 和 云 这样的词语一样 智能合约 也是那些得到大量炒作的短语之一 毕竟 没有什么比不通过司法系统而让人们能够相信发生了什么更有意思的了 智能合约的承诺包括 自动 无须信任和公正地执行合约 在合约构建 合约执行和合约执行环
  • 笔记:以太坊geth客户端命令及参数

    geth命令的参数 nodiscover 使用此选项可确保未手动添加您的人员无法发现您的节点 否则 如果您的节点具有相同的创世纪文件和网络ID 则可能无意中将您的节点添加到陌生人的区块链中 maxpeers 0 如果您不希望任何其他人连接到
  • 通过python构建一个区块链来学习区块链

    了解区块链Blockchains如何工作的最快方法就是构建一个区块链 你来到这里是因为 和我一样 你对加密钱币的崛起感到很兴奋 而且你想知道区块链是如何工作的 想了解它们背后的基本技术 但理解区块链并不容易 或者至少不适合我 我在密集的视频
  • 不要再在以太坊和Metamask开发web时使用密码

    我在ConsenSys为各种客户构建了大量的概念证明 通常他们想要利用以太坊区块链来解决某些业务用例 奇怪的是 这些系统通常设计有标准的网络登录 即用户名和密码 我总是问自己为什么我还在这样做设计 毕竟 这是今天以太网目前可以解决每个烦人的
  • 用Go构建一个简单的区块链

    在本教程中 我将尝试通过帮助你在Go中编写简单的区块链来揭开区块链的广义概念 在本教程中 你应该能够 理解区块链术语 创建自己的简单区块链 了解什么是区块以及如何创建块 了解如何维护区块链的完整性 区块链 一种数字分类帐 以较小的集合排列
  • 以太坊智能合约教程(一)搭建以太坊私有链搭建

    环境说明 win10 64位 geth1 6 5 1 安装geth 安装完成以后 先创建2个账号 geth account new 然后建立 mygenesis json nonce 0x0000000000000042 difficult
  • 使用Go语言和以太坊智能合约交互

    尽管最近遇到了些麻烦 但以太坊仍然是区块链领域内智能合约的最大参与者 这似乎不会很快改变 在我看来 技术本身具有很大的潜力 是从学术的角度看很有意思 但正如上面提到的问题和之前的许多问题是区块链技术方面的 智能合约 特别是具有Solidit
  • 读取本地文件到读出p.node涉及的函数

    这里是读取本地文件的所调用的函数 func ParseNode rawurl string Node error if m incompleteNodeURL FindStringSubmatch rawurl m nil id err H
  • 搭建第一个Dapp应用(4)——搭建SmartDev-Scaffold——2021.5.3

    搭建第一个Dapp应用 4 搭建SmartDev Scaffold 一丶环境配置 Java gt JDK 1 8 Solidity 0 4 25 Git 下载安装包需要使用Git Gradle 大于6 小于7 使用gradle7会报错 二丶
  • FISCO BCOS——SmartDev-Contract——MarriageEvidence结婚证书合约案例分析

    MarriageEvidence结婚证书合约案例分析 一 合约场景分析 二丶基础合约介绍 1 角色合约 1 功能说明 2 接口说明 3 使用说明 2 存证合约 1 功能说明 2 接口说明 3 使用说明 三丶业务合约介绍 1 结婚证书合约 1
  • 区块链数据库

    大家好 这里是链客区块链技术问答社区 链客 有问必答 区块链是互联网未来十年中举足轻重的技术 区块链 Blockchain 或者说分布式账本 DLT Distributed Ledger Technology 最早是起源于比特币的一个重要概
  • 区块链的几大模块

    共识的分类 POW POW的一般理解 根据难度做SHA256哈希运算 不停寻找Nonce 特定的HASH 前导0的个数越多 代表难度越大 优点是难于计算 一旦收到网络上的区块 能快速验证 难度算法按高度动态调整 维持出块时间不变 POW规范
  • EOS智能合约安全开发终极指南

    EOS智能合约安全终极指南 当世界上最大的ICO EOS于2018年6月推出时 加密社区变得持怀疑态度 并且由于软件错误而被冻结了2天 但快进4个月 EOS今天占了以太网今天所做交易的两倍以上 通过免费和更快速交易的承诺 EOS最顶级的Da
  • 以太坊区块链学习之在私链上部署合约

    上一篇博客介绍了如何搭建私链并在私链上创建账户 挖矿 查看余额 本篇将介绍在私链上部署合约并与之交互 本篇开发环境为MacOS 10 12 建议读者使用macOS系统或者Ubuntu系统 第一步 进入geth客户端 启动私链 进入geth客

随机推荐

  • Pyecharts Graph 关系图示例

    关系可视化 from pyecharts import options as opts from pyecharts charts import Graph from pyecharts globals import ThemeType i
  • 实现一个函数,判断一个数是不是素数。

    我们先来看一下素数的定义 素数定义为在大于1的自然数中 除了1和它本身以外不再有其他因数 用普通代码实现 define CRT SECURE NO WARNINGS include
  • vs2010中引入boost库

    引言 在vs2010中无法使用C 11中的大多数特性 像mutex互斥锁 要想使用需要引入boost库 下面记录一下boost库引入到vs2010中 实现 分为以下几步 下载boost压缩包 可以采用下面的地址下载适合自己的版本 下载地址
  • List转Map的三种方法

    for循环 import com google common base Function import com google common collect Maps import java util ArrayList import jav
  • 补 day10算法打卡

    232 用栈实现队列 代码 class MyQueue Stack
  • BugkuWeb:game1

    进去后发现是一款游戏 思路就是直接结束游戏 然后去看信息 发现网络监视器中多了score php 发现了可疑的参数score IP sign 这个sign应该在后台代码中被控制的 去审计代码 发现了sign的算法 这个游戏的得分是25 ba
  • 梦幻模拟战手游服务器维护,梦幻模拟战手游无法登陆游戏 服务器异常登录解决方法_游侠手游...

    梦幻模拟战手游 异常登录怎么办 无法登陆游戏怎么办 还没解决的玩家 下面小编就为玩家带来 梦幻模拟战手游 服务器异常登录无法登录解决方法 一起来看看吧 服务器异常登录无法登录解决方法 各位指挥官 真的非常抱歉 服务器目前不稳定 会有部分指挥
  • oracle 创建数据库 create database,使用create database语句创建数据库的详细操作步骤...

    使用create database语句创建数据库的步骤如下 1 指定一个实例标识符SID 2 确保设置了必要的环境变量 3 选择一个数据库管理员验证方法 4 创建一个初始化参数文件 5 只用于windows平台 创建一个实例 6 连接实例
  • 2022全国大学生数学建模竞赛C题思路模型

    1 比赛报名与思路解析 持续更新750967193 2 比赛时间 2022年9月15日18点到2022年9月18日20点 如下为C题思路 C 题 古代玻璃制品的成分分析与鉴别 丝绸之路是古代中西方文化交流的通道 其中玻璃是早期贸易往来的宝贵
  • Java异常, 性能有多差

    在 Java 中 异常通常被认为是成本昂贵的 不应该用于控制控制 本文将证明这个观点的正确性 并验证导致性能问题的原因 Java微基准测试框架 在编写代码评估Java异常的性能成本之前 我们需要搭建一个基准测试环境 测量异常的成本开销 并不
  • 04C++11多线程编程之创建多个线程和数据共享问题分析

    04C 11多线程编程之创建多个线程和数据共享问题分析 1 thread循环创建多个子线程 思想就是使用容器创建多个线程 推荐 以后工作中会使用到 具有实际意义 方便统一管理线程 include
  • Staple 跟踪: Complementary Learners for Real-Time Tracking

    目标跟踪算法 Staple Complementary Learners for Real Time Tracking 小小菜鸟一只 2017 03 25 09 26 42 15110 收藏 14 分类专栏 目标跟踪 版权 文章下载链接 文
  • 辨析Java与Javascript

    首先 它们是两个公司开发的不同的两个产品 Java是SUN公司推出的新一代面向对象的程序设计语言 特别适合于Internet应用程序开发 而JavaScript是Netscape公司的产品 其目的是为了扩展Netscape Navigato
  • 人才供应链(17年12月)

    库克来中国访问时说 高质量的人才是Apple公司最需要的 而苹果商店的开发者中 中国有200万开发者在支持应用商店 其中大部分是在广州 苹果的供应链也在中国 配套的零部件 面对高要求和近似到极限的品质要求 只有在中国才能满足 IT行业的人才
  • 压缩/减小VirtualBox虚拟硬盘文件占用空间

    文章目录 网上的做法 导出虚拟电脑 再导入 网上的做法 网上有两种压缩空间的做法 1 在虚拟机中 使用 SDelete 例如 sdelete c z 经本人实测 不仅不能压缩 因为SDelete 扫描了整个c 盘 而 VirtualBox
  • 【多模态】7、DINO

    文章目录 一 背景 二 方法 2 1 Contrastive DeNoising Training 2 3 Mixed Query Selection 2 4 Look Forward Twice 三 效果 论文 DINO DETR wit
  • 联想E450c下vmware安装ubuntu " Intel VT-x 处于禁用状态"

    实验环境 lenovo E450c 报错信息 解决办法 按F12进入BIOS 选择Security下的Virtualization 在Intel R 的行 设置Enabled 按F10保存 重新打开虚拟机 参考链接 vmware安装ubun
  • linux 挂载以及初始化硬盘

    linux 挂载以及初始化硬盘 简述 过多的赘述就不说了 一般使用linux完成一些像iscsi服务存储配置啥的 都需要用到硬盘的挂载来扩充服务器的存储空间 这里就简简单单给大家讲一下linux如何挂载初始化新的硬盘 我这里使用的是linu
  • CRC编码计算方法及C语言实现

    CRC编码计算方法及C语言实现 CRC Cyclic Redundancy Check 是一种常用的错误校验码 用于检测和纠正传输过程中的错误 在数据通信和存储中 CRC编码被广泛应用 因为它能够高效地检测错误 并且实现简便 CRC编码计算
  • V神·以太坊上的分片

    译者序 本文是我应以太坊中文社区 Ethfans org 之邀做的翻译稿 原文取自以太坊社区的Github https github com ethereum sharding blob develop docs doc md 原文最后更新