- Merged mining 合并挖矿;联合挖矿
- Aux 辅助
注意:这个标准由Namecoin使用,但是新的合并挖掘数据可能会提出一个新的BIP来代替它,使用基于p2pool合并挖掘的东西。
内容
- 术语
- 辅助工作量证明块
- merkle分支
- 合并挖矿coinbase
- 人造山楂树
- 例子
- 笔记
术语
Auxiliary Proof-of-Work (POW)
a.k.“AuxPOW”。这就是合并挖掘存在的方式;这是两个区块链之间的关系,一个区块链信任另一个区块链的工作,并接受AuxPOW区块。
Merged Mining
在多个链上使用一个区块链所做的工作的行为,使用辅助POW。
Auxiliary Blockchain
altcoin接受在交替链上所做的工作,并将其作为在自己的链上有效的工作。必须修改客户端应用程序才能接受辅助POW。
Parent Blockchain
实际挖矿工作发生的区块链。这个链不需要知道辅助POW逻辑,因为提交给这个链的AuxPOW块仍然是有效的块。
Parent Block
不要与“前一个块”混淆。这是一个为父区块链构造的块(即prev_block散列指向父区块链上的前一个块)。该块的头部是辅助区块链中的AuxPOW块的一部分。
AuxPOW Block
这是一种与标准区块链块类似的新型块,但有两个重要区别。首先,块头的哈希不满足区块链的难度级别(因此,如果被一个简单的客户端解释为不满足难度级别,那么将被抛出)。其次,它还有额外的数据元素,表明创建这个块的矿工实际上在父区块链上进行了挖掘活动(散列),并且该工作满足辅助区块链的难度级别,这就是为什么应该接受这个块。
Aux proof-of-work block
这是用来证明对辅助区块链的功。在vinced的原始实现中,它是通过调用父区块链客户机(bitcoind)上的getworkaux RPC方法生成的,然后通过将其作为getauxblock的第二个参数传递给辅助链客户机(namecoind)来提交工作。
当在“块”网络消息中接收一个Aux工作验证块时,接收到的数据与标准块类似,但是在nonce和txn_count元素之间插入了额外的数据。下表中,阴影行与标准块定义相同:
Field Size | Description | Data type | Comments | |
---|---|---|---|---|
4 | version | uint32_t | ||
32 | prev_block | char[32] | ||
32 | merkle_root | char[32] | ||
4 | timestamp | uint32_t | ||
4 | bits | uint32_t | ||
4 | nonce | uint32_t | ||
? | coinbase_txn | txn | 位于父块中的Coinbase事务,将AuxPOW块链接到其父块 | |
32 | block_hash | char[32] | parent_block头的散列 | |
? | coinbase_branch | merkle branch | merkle分支将coinbase_txn链接到父块的merkle_root | |
? | blockchain_branch | Merkle branch | merkle分支将这个辅助区块链连接到其他的区块链,当在合并了多个辅助链的挖掘设置中使用时 | |
80 | parent_block | Block header | 父块头 | |
? | txn_count | var_int | ||
? | txns | tx[] |
coinbase_branch merkle分支,因为块中的coinbase事务是第一个事务(如果使用比特币作为父链,即散列在下面的例子中# 7),branch_side_mask总是都是0,因为分支总是会散列哈希的“右边”工作。
当只处理一个辅助区块链时,blockchain_branch链接是不需要的,它被表示为5个字节的零(解释为一个一个字节的var_int,表示一个零的branch_length,以及一个32位(4字节)的branch_side_mask)。
注意,
block_hash元素是不需要的,因为您有完整的parent_block头元素,可以从中计算散列。当前的Namecoin客户端没有检查这个字段的有效性,因此有些AuxPOW块使用little-endian,有些使用big-endian。
Merkle Branch
假设Alice创建了一个Merkle树,它的根元素是公开可用的。例如:
现在她想向Bob证明一个给定的hash(#10)是树的一部分,但是Bob没有完整的树(只有公共根;散列# 0)。
- Alice可以向Bob发送她最初用来生成树的所有散列(散列#7-#14,总共有7个额外的散列),因此Bob可以构建整个树来验证根是相同的,但是这需要大量的数据。
- 相反,她可以给Bob提供#9、#3和#2哈希值(从树的每一层都有一个哈希值,从#10返回到根)。在Bob不知道树的结构的情况下,Alice还必须告诉Bob应用散列的顺序(因为散列(#9,#10)== #4,而散列(#10,#9)!= #4)。
- 因此,Alice告诉Bob“left, left, right”来指示#9、#3和#2分别是哪个操作数。它可以被编码为位掩码,并且只占用很少的数据来传输。因此,Alice没有向Bob传输7个哈希值,而是传输了3个哈希值和一个位掩码。如果merkle树变得更大,数据节省就会更加明显。
这是整体的前提,特别是对于AuxPOW协议,它被称为“merkle branch”(因为它是merkle树的一个通路),并被传输如下:
Field Size | Description | Data type | Comments | |
---|---|---|---|---|
? | branch_length | var_int | 组成分支的哈希数 | |
? | branch_hash[] | char[32] | 分支中的单个散列;重复分支长度次数 | |
4 | branch_side_mask | int32_t | 位掩码merkle哈希函数的哪一侧的branch_hash元素应该继续。0表示在右边,1表示在左边。它等于这个merkle分支的merkle树最宽级别内的起始散列的索引。 |
备注:
branch_hash[] 个长度和branch_side_mask的长度是一致的。
首先使用第一个branch_hash, branch_side_mask的最小有效位决定它的hash位置。然后将第二个branch_hash应用于branch_side_mask的第二个最小有效位,以此类推。对于Alice的例子,branch_length是3,散列的顺序是#9 #3 #2,branch_side_mask是0b011 = 3(等于merkle树中最宽级别的#10的索引)。
联合挖矿coinbase
在父块中的coinbase事务的scriptSig中插入其中一个头部。
Field Size | Description | Data type | Comments | |
---|---|---|---|---|
4 | magic | char[4] | 0xfa、0xbe、'm'、'm'(仅当脚本开始后超过20个字节时才需要;可选的其他) | |
32 | block_hash | char[32] | 链merkle分支的AuxPOW块头/根的散列 | |
4 | merkle_size | int32_t | 在辅助工作merkle树的条目数。(必须是2的幂) | |
4 | merkle_nonce | int32_t | Nonce用于计算索引到辅助工作merkle树;你还是把这个值设为零为好 |
这个包含44个字节的字符串是coinbase脚本的一部分,这意味着矿工在创建coinbase之前构造了AuxPOW块。
Aux work merkle tree
如果您只是挖掘一个辅助链并使用getauxblock,那么您不必担心这个问题—只需将coinbase中的merkle树散列设置为由getauxblock提供的aux链块的散列,merkle大小为1,merkle nonce为0。如果你开采了不止一个,这个就有点坏了。它使用以下算法将链ID转换为merkle树底部的一个槽,其中链的块哈希必须槽:
unsigned int rand = merkle_nonce;
rand = rand * 1103515245 + 12345;
rand += chain_id;
rand = rand * 1103515245 + 12345;
slot_num = rand % merkle_size
其思想是,您可以增加merkle_nonce,直到您挖掘的链不会与相同的槽发生冲突。问题是这不起作用;因为它只是将merkle_nonce派生的一个数字添加到chain_id,如果两个链冲突为一个nonce,那么它们仍然会冲突为所有可能的nonces。
- [1]新实现:请选择您的chain_id,这样就不会与现有的链冲突,需要尽可能小的merkle_size值,或者使用更好的算法来计算链的槽id。
一旦知道了merkle树中不同链的位置,按照getauxblock提供的方法将每个链的块散列的字节倒转(这样开始的字节就会移动到末尾,等等),并插入到适当的槽中,用任意数据填充未使用的槽。现在像往常一样构建merkle树,取初始行中的每一对值,并对它们进行双SHA-256哈希,得到新的哈希行,重复这个过程,直到只有一个哈希。最后一个散列是merkle根。在将其插入coinbase之前,您需要再次反转这个字节。如果没有使用getauxblock来获得块散列,可以跳过第一次反转,但是在将最终的merkle根添加到coinbase时,仍然需要反转它。
aux工作证明还需要一个merkle分支,其构建过程如下:查找块的散列在merkle树中的位置,并添加构建merkle树时使用的散列值。现在添加对结果进行散列的值。一直这样做,直到你到达根。merkle树本身从来不包括在merkle枝。如果您只有一个aux链,则可以将其完全空出来。(似乎也不需要反转这些散列。)
例子
这是Namecoin链中高度为19200的AuxPOW块(第一个允许AuxPOW身份验证的块)。它的散列是d8a7c3e01e1e95bcee015e6fcc7583a2ca60b79e5a3aa0a171eddd344ada903d,并且只有一个Namecoin事务(coinbase将50个NMC发送到矿工的地址)。被用作工作证明的父块的哈希值比当时Namecoin的难度目标小,但比特币的目标则不同:
0000000000003d47277359fb969c43e3c7e7c0306a17f6444b8e91e19def03a9 -- parent block hash
000000000000b269000000000000000000000000000000000000000000000000 -- Namecoin difficulty target
00000000000009ee5d0000000000000000000000000000000000000000000000 -- Bitcoin difficulty target
因此,这个AuxPOW块在Namecoin区块链中是有效的,但在比特币区块链中无效(您将发现没有一个以3d47277359fb969c开头的散列的比特币块。如果是,那么它就在4a59b7deb5c4e01b之后,因为这是使用的前vious_block散列)
Block Header:
01 01 01 00 // Version
36 90 9a c0 7a 16 73 da f6 5f a7 d8 28 88 2e 66 c9 e8 9f 85 46 cd d5 0a 9f b1 00 00 00 00 00 00 // Previous block hash
0f 5c 65 49 bc d6 08 ab 7c 4e ac 59 3e 5b d5 a7 3b 2d 43 2e b6 35 18 70 8f 77 8f c7 dc df af 88 // Merkle root
8d 1a 90 4e // Timestamp
69 b2 00 1b // Bits
00 00 00 00 // Nonce
Parent Block Coinbase Transaction:
01 00 00 00 // Version
01 // TxIn Count
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // Previous Out
00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ff
35 // Script size
04 5d ee 09 1a 01 4d 52 2c fa be 6d 6d d8 a7 c3 e0 1e 1e 95 bc ee 01 5e 6f cc 75 83 a2 ca 60 b7 // Script
9e 5a 3a a0 a1 71 ed dd 34 4a da 90 3d 01 00 00 00 00 00 00 00
ff ff ff ff // Sequence Number
01 // TxOut Count
60 a0 10 2a 01 00 00 00 // Amount
43 // Script Size
41 04 f8 bb e9 7e d2 ac bc 5b ba 11 c6 8f 6f 1a 03 13 f9 18 f3 d3 c0 e8 47 50 55 e3 51 e3 bf 44 // Script
2f 8c 8d ce e6 82 d2 45 7b dc 53 51 b7 0d d9 e3 40 26 76 6e ba 18 b0 6e ae e2 e1 02 ef d1 ab 63
46 67 ac
00 00 00 00 // Lock Time
Coinbase Link:
a9 03 ef 9d e1 91 8e 4b 44 f6 17 6a 30 c0 e7 c7 e3 43 9c 96 fb 59 73 27 47 3d 00 00 00 00 00 00 // Hash of parent block header
05 // Number of links in branch
05 0a c4 a1 a1 e1 bc e0 c4 8e 55 5b 1a 9f 93 52 81 96 8c 72 d6 37 9b 24 72 9c a0 42 5a 3f c3 cb // Hash #1
43 3c d3 48 b3 5e a2 28 06 cf 21 c7 b1 46 48 9a ef 69 89 55 1e b5 ad 23 73 ab 61 21 06 0f 30 34 // Hash #2
1d 64 87 57 c0 21 7d 43 e6 6c 57 ea ed 64 fc 18 20 ec 65 d1 57 f3 3b 74 19 65 18 3a 5e 0c 85 06 // Hash #3
ac 26 02 df e2 f5 47 01 2d 1c c7 50 04 d4 8f 97 ab a4 6b d9 93 0f f2 85 c9 f2 76 f5 bd 09 f3 56 // Hash #4
df 19 72 45 79 d6 5e c7 cb 62 bf 97 94 6d fc 6f b0 e3 b2 83 9b 7f da b3 7c db 60 e5 51 22 d3 5b // Hash #5
00 00 00 00 // Branch sides bitmask
Aux Blockchain Link:
00 // Number of links in branch
00 00 00 00 // Branch sides bitmask
Parent Block Header:
01 00 00 00 // Version
08 be 13 29 5c 03 e6 7c b7 0d 00 da e8 1e a0 6e 78 b9 01 4e 5c eb 7d 9b a5 04 00 00 00 00 00 00 // Previous block hash
e0 fd 42 db 8e f6 d7 83 f0 79 d1 26 be a1 2e 2d 10 c1 04 c0 92 7c d6 8f 95 4d 85 6f 9e 81 11 e5 // Merkle root
9a 23 90 4e // Timestamp
5d ee 09 1a // Bits
1c 65 50 86 // Nonce
Transactions:
01 // Tx Count
01 00 00 00 // Version
01 // TxIn Count
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // Previous Out
00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ff
08 // Script size
04 69 b2 00 1b 01 01 52 // Script
ff ff ff ff // Sequence number
01 // TxOut Count
00 f2 05 2a 01 00 00 00 // Amount
43 // Script size
41 04 89 fe 91 e6 28 47 57 5c 98 de ea b0 20 f6 5f df f1 7a 3a 87 0e bb 05 82 0b 41 4f 3d 80 97 // Script
21 8e c9 a6 5f 1e 0a e0 ac 35 af 72 47 bd 79 ed 1f 2a 24 67 5f ff b5 aa 6f 96 20 e1 92 0a d4 bf
5a a6 ac
00 00 00 00 // Lock Time
Notes
https://bitcointalk.org/index.php?topic=51069.0
本文由Rebase社区的River进行整理和翻译:
原文链接:https://en.bitcoin.it/wiki/Merged_mining_specification