Skip to content

比特币:点对点电子现金论文 ​

原始发布页

打开来源页面
查看 1 个交叉存档

哈尔·芬尼写道:

文中提到,如果一笔广播交易没有到达所有节点,也没关系,因为它不久就会进入区块链。这是怎样发生的——如果创建“下一个”区块的节点(第一个找到 hashcash 碰撞的节点)没有听说这笔交易,而接下来又有几个区块也由没有听说这笔交易的节点添加,会怎么样?所有听说了这笔交易的节点是否会一直保留它,希望自己足够幸运,成为找到下一个碰撞的节点,从而把它纳入一个区块?

没错,节点会把交易保留在工作集中,直到它们进入一个区块。如果一笔交易到达了 90% 的节点,那么每次找到新区块时,它有 90% 的机会被纳入其中。

或者举例说,如果一个节点在等待观察哪条链增长得最快时保留着两条或更多条链,而链 A 收到的一个区块会包含对链 B 中某枚币的双重支付,会怎么样?这种情况会被检查吗?(如果有人进行了双重支付,而两组不同的节点分别听说了使用同一枚币的两笔不同交易,就可能发生这种情况。)

不需要检查这种情况。最终取得领先的那个分支中的交易会成为有效交易,另一个则无效。如果有人尝试这样进行双重支付,始终只会有一笔支付成为有效支付,其他支付都会无效。

交易接收方通常需要持有交易大约一小时或更久,以留出时间解决这类可能性。他们仍然可以立即再次花掉这些币,但在采取诸如发货之类的行动前应当等待。

我也不完全明白,一个能够调集比所有诚实参与者更多计算能力的强大攻击者,究竟如何实现双重支付或取消交易。我明白他可以创建新区块并把它们添加进去形成最长链,但他如何擦除或添加链中的旧交易?当攻击者发出新区块时,诚实节点难道不会执行一致性检查,以确保没有任何内容被擦除吗?为了判断攻击者从中获得的收益,与其直接利用计算能力诚实地铸造新币相比如何,更详细地解释这种攻击会很有帮助。

攻击者不是把区块添加到末尾。他必须回到过去,重做包含其交易的那个区块及其后的所有区块,还要重做网络在他这样做时不断添加到末尾的所有新区块。他是在重写历史。一旦他的分支更长,它就会成为新的有效分支。

这涉及一个关键点。即使所有在场的人都能看到其中的把戏,也没有办法利用这一事实。

最长链必须始终被视为有效链,这是绝对必要的。在场的节点可能记得某个分支先出现、后来被另一个分支取代,但它们没有办法让当时不在场的人相信这一点。我们不能让一部分节点固守它们认为最先出现的分支,另一部分节点固守它们最先看到的另一个分支,还有一些节点后来才加入,从未看到发生了什么。CPU 算力的工作量证明投票必须拥有最终决定权。所有人保持一致的唯一方式,就是相信最长链始终是有效链,无论发生什么。

至于支付交易,一枚币的接收方需要执行哪些检查?她需要回溯这枚币的全部转移历史,并确保列表中的每笔交易确实都链接到了“时间戳”区块链中吗?还是只需检查最近一笔?

接收方只需向后验证到区块链中足够深的位置,通常只需要达到 2 笔交易的深度。此前的所有交易都可以丢弃。

时间戳节点会检查交易,确保一枚币的上一笔交易位于链中,从而强制执行链中所有交易都代表有效币这一规则吗?

对,正是这样。节点收到一个区块时,会根据区块中的先前交易,检查其中每笔交易的签名。区块只能包含依赖于先前区块或同一区块中有效交易的交易。交易 C 可以依赖同一区块中的交易 B,而 B 依赖更早区块中的交易 A。

抱歉问了这么多问题,但正如我所说,这确实是一个很有前景且原创的想法,我期待看到这个概念得到进一步发展。如果能看到一份更面向过程的构想描述,具体说明各种对象(币、区块、交易)的数据结构、消息中包含的数据,以及处理这个系统中可能发生的各种事件的算法过程,会很有帮助。你提到正在进行实现,但我认为下一步如果能有一份更正式的系统文字描述,会很有帮助。

感谢你的这些问题。实际上,我做这件事的顺序有些颠倒。我必须先写完所有代码,才能说服自己可以解决每个问题,然后才写了论文。我想我发布代码的时间会早于写出详细规范。你在填补空白时所作的大多数假设已经是对的。

Satoshi Nakamoto

英文原文 ​

展开英文原文

Hal Finney wrote:

it is mentioned that if a broadcast transaction does not reach all nodes, it is OK, as it will get into the block chain before long. How does this happen - what if the node that creates the "next" block (the first node to find the hashcash collision) did not hear about the transaction, and then a few more blocks get added also by nodes that did not hear about that transaction? Do all the nodes that did hear it keep that transaction around, hoping to incorporate it into a block once they get lucky enough to be the one which finds the next collision?

Right, nodes keep transactions in their working set until they get into a block. If a transaction reaches 90% of nodes, then each time a new block is found, it has a 90% chance of being in it.

Or for example, what if a node is keeping two or more chains around as it waits to see which grows fastest, and a block comes in for chain A which would include a double-spend of a coin that is in chain B? Is that checked for or not? (This might happen if someone double-spent and two different sets of nodes heard about the two different transactions with the same coin.)

That does not need to be checked for. The transaction in whichever branch ends up getting ahead becomes the valid one, the other is invalid. If someone tries to double spend like that, one and only one spend will always become valid, the others invalid.

Receivers of transactions will normally need to hold transactions for perhaps an hour or more to allow time for this kind of possibility to be resolved. They can still re-spend the coins immediately, but they should wait before taking an action such as shipping goods.

I also don't understand exactly how double-spending, or cancelling transactions, is accomplished by a superior attacker who is able to muster more computing power than all the honest participants. I see that he can create new blocks and add them to create the longest chain, but how can he erase or add old transactions in the chain? As the attacker sends out his new blocks, aren't there consistency checks which honest nodes can perform, to make sure that nothing got erased? More explanation of this attack would be helpful, in order to judge the gains to an attacker from this, versus simply using his computing power to mint new coins honestly.

The attacker isn't adding blocks to the end. He has to go back and redo the block his transaction is in and all the blocks after it, as well as any new blocks the network keeps adding to the end while he's doing that. He's rewriting history. Once his branch is longer, it becomes the new valid one.

This touches on a key point. Even though everyone present may see the shenanigans going on, there's no way to take advantage of that fact.

It is strictly necessary that the longest chain is always considered the valid one. Nodes that were present may remember that one branch was there first and got replaced by another, but there would be no way for them to convince those who were not present of this. We can't have subfactions of nodes that cling to one branch that they think was first, others that saw another branch first, and others that joined later and never saw what happened. The CPU power proof-of-work vote must have the final say. The only way for everyone to stay on the same page is to believe that the longest chain is always the valid one, no matter what.

As far as the spending transactions, what checks does the recipient of a coin have to perform? Does she need to go back through the coin's entire history of transfers, and make sure that every transaction on the list is indeed linked into the "timestamp" block chain? Or can she just do the latest one?

The recipient just needs to verify it back to a depth that is sufficiently far back in the block chain, which will often only require a depth of 2 transactions. All transactions before that can be discarded.

Do the timestamp nodes check transactions, making sure that the previous transaction on a coin is in the chain, thereby enforcing the rule that all transactions in the chain represent valid coins?

Right, exactly. When a node receives a block, it checks the signatures of every transaction in it against previous transactions in blocks. Blocks can only contain transactions that depend on valid transactions in previous blocks or the same block. Transaction C could depend on transaction B in the same block and B depends on transaction A in an earlier block.

Sorry about all the questions, but as I said this does seem to be a very promising and original idea, and I am looking forward to seeing how the concept is further developed. It would be helpful to see a more process oriented description of the idea, with concrete details of the data structures for the various objects (coins, blocks, transactions), the data which is included in messages, and algorithmic descriptions of the procedures for handling the various events which would occur in this system. You mentioned that you are working on an implementation, but I think a more formal, text description of the system would be a helpful next step.

I appreciate your questions. I actually did this kind of backwards. I had to write all the code before I could convince myself that I could solve every problem, then I wrote the paper. I think I will be able to release the code sooner than I could write a detailed spec. You're already right about most of your assumptions where you filled in the blanks.

Satoshi Nakamoto

为历史保存,为中文读者整理。每篇档案均附来源与英文原文。