使用GO语言构建区块链 - 第4部分:交易1

2019/07/26 栏目:行业资讯
原文标题:使用GO语言构建区块链 - 第4部分:交易1

 前言
     交易是比特币的核心,区块链的唯一目的是以安全可靠的方式存储交易,因此在创建交易后没有人可以修改它。今天我们开始实施交易。但由于这是一个相当大的话题,我将其分为两部分:第一部分,我们将实施一般的交易机制;在第二部分,我们将处理细节。
此外,由于代码变化很大,所以在这里描述所有代码是没有意义的。您可以在此处查看所有更改。

鸟   如果您曾经开发过Web应用程序,则可以在数据库中为付款创建这些表:accounts和transac蒸发散。该帐户将存储有关用户的信息,包括他们的个人信息和余额,并且交易将存储从一个帐户转移到另一个帐户的钱的信息。在比特币中,付款以完全不同的方式实施。有:
      1. 没有说明。
      2. 没有余额。
      3. 没有地址。
      没有硬币。
      5. 没有发件人和收件人。

因为区块链是公开的,所以根据图书馆,我们不想存储有关钱包所有者的敏感信息。帐户中不会收集任何硬币。交易不会将资金从一个地址转移到另一个地址。没有包含帐户余额的字段或属性。只交易,但交易中有什么?


比特币交易

交易是组合输入和输出:

输入上一个事务的新事务参考输出(虽然有例外,我们稍后会讨论)。输出是硬币实际存储的地方。下图说明了交易的互连:

     请注意:
 与国家统计局磷;   1. 有些输出与输入无关。
鸟    2. 在事务中,输入可以引用多个事务的输出。
鸟    3. 输入必须参考输出。


在整篇文章中,我们将使用诸如“钱”,“硬币”,“花”,“发送”,“帐户”等词语等。但比特币中没有这样的概念。事务只是用脚本锁定值,只能由锁定它们的人解锁。


  交易产出

[ 123]

让我们从输出开始: ]


实际上,它存储“硬币”的输出(注意上面的字段值)。存储意味着用谜题锁定它们,谜题存储在ScriptPubKey中。在内部,比特币使用名为Script的脚本语言来定义输出锁定和解锁逻辑。这种语言非常原始(故意这是为了避免可能的黑客攻击和滥用),但我们不会详细讨论。你可以在这里找到它的详细解释。
在比特币中,值字段存储satoshis的数量而不是BTC的数量。 satoshi是比特币(0.00000001 BTC),百万分之一,所以这是比特币在货币中的最小单位(例如百分比)。
由于我们没有实现地址,我们现在将避免使用与sc相关的整个逻辑RIPT。 ScriptPubKey将存储任何字符串(用户定义的钱包地址)。
相同的脚本语言意味着比特币也可以用作智能合约平台。

关于产出的一个重要观点是它们是不可分割的,这意味着你不能引用它的一部分价值。当您在新事务中引用输出时,它将作为一个整体使用。如果其值大于要求,则会生成更改并将其发送回发件人。这类似于现实世界的情况。当您支付5美元的账单时,当您购买1美元的商品时,您将获得4美元的更改。



交易输入

这是输入:


作为男人之前,输入引用了前一个输出:Txid存储此类事务的ID,Vout存储事务中输出的索引。 ScriptSig是一个脚本,它提供要在输出中使用的数据ScriptPubKey。如果数据正确,则可以解锁输出,并且可以使用其值生成新输出;如果不正确,则无法在输入中引用输出。这是一种确保用户不能花费属于其他人的硬币的机制。
同样,由于我们尚未实现地址,因此ScriptSig仅存储任何用户定义的钱包地址。我们将在下一篇文章中实现公钥和签名检查。
让我们总结一下:输出是存储“硬币”的地方。每一个出来put附带一个解锁脚本,用于确定解锁输出的逻辑。每个新事务必须至少有一个输入和输出。输入引用上一个事务的输出,并提供ScriptSig在输出的解锁脚本中使用的数据(字段)以解锁它并使用其值创建新输出。

但首先:输入还是输出?


上一项产出
   在比特币中,首先是输出,然后是输入。逻辑可以指经典的“鸡或蛋”问题:输入产生输出,输出使输入成为可能。在比特币中,输出在输入之前。
鸟   当一个矿工开始挖掘一个区块时,它会添加一个coinbase处理它。 coinbase事务是一种特殊类型的事务,不需要预先存在的输出。它创造了输出(即“硬币”无处不在,这是矿工开采新区块的奖励。
   如您所知,区块链的开头有一个Genesis区块正是这个区块产生区块链中的第一个输出。并且不需要先前的输出,因为没有先前的交易就没有这样的损失。输出。
    ;让我们创建一个coinbase事务:


coinbase事务只有一个输入。在我们的实现中,它的Txid是空的和Vout等于-1。此外,coinbase事务不存储脚本ScriptSigtead,存储任意数据。
鸟   在比特币中,第一笔基于硬币的交易包含以下信息:“时代03 / Jan / 2009财政大臣即将面临银行的第二轮救助”。
鸟   补贴是奖金金额。在比特币中,这个数字不存储在任何地方,仅基于块的总数:块数除以210000是补贴。挖掘产生的块产生50 BTC,并且在每挖掘210,000个块之后奖励减半。在我们的实施中,我们将奖励存储为常数(至少到现在为止)。


      在区块链中存储交易
     从现在开始,每个集团k必须存储至少一个事务,并且不能在没有事务的情况下挖掘块。这意味着我们应该删除块中的数据字段并存储事务:


NewBlock和NewGenesisBlock也必须是相应地改变:


接下来要改变的是创建一个新的区块链:

]


现在,函数获取一个地址,该地址将获得挖掘生成的块的奖励。


      工作负载证明算法

工作负载证明算法必须考虑存储在块中的事务,以确保一致性和可靠性区块链作为交易商店。所以现在我们必须修改ProofOfWork.prepareData方法:



]


而不是之前使用的pow.block.Data,现在我们使用的是pow.block.HashTransactions():


     我们使用哈希来提供我们之前遇到的数据的唯一表示。我们想要用一个哈希来识别块中的所有事务。为此,我们获取每个事务的哈希值,关联它们,并获得连接的组合哈希值。

鸟   比特币使用更复杂的技术:它代表块中包含的所有交易,如Merklet 树,并在证明中使用树工作制度。根哈希。此方法允许您快速检查块是否包含特定事务,仅具有根哈希并且不下载所有事务。
鸟   我们现在检查了一切:




好!我们获得了第一个采矿奖。但是我们如何检查平衡?


未用交易产出
     我们需要找到所有未使用的事务输出(UTXO)。未使用意味着在任何输入中都不引用这些输出。在上图中,这些是:
      1 tx0,输出1;
      2 TX1,输出0;
鸟    3。 tx3,输出0;
鸟    4。 tx4,输出0.
     当然,当我们检查余额时,我们不需要知道所有这些,只需要注意UTXO可以用我们拥有的密钥解锁(我们目前没有实现秘密)密钥,但是用户 - 定义的地址)。首先,让我们在输入和输出上定义锁定解锁方法:


这里我们只比较脚本字段unlockingData。在我们基于私钥实现地址之后,我们将在以后的文章中改进这些部分。
鸟    Next - 使用未使用的输出查找交易非常困难:


由于交易存储在一个区块中,我们必须检查区块链中的每个区块。让我们从输出开始:


如果输出被同一地址锁定,我们正在搜索未使用的事务输出那么这就是我们想要的输出。但在采用之前,我们需要检查输入中是否已引用输出:


我们跳过参考输入那些(它们的值被移动到其他输出,所以我们无法计算它们)。检查输出后,我们收集所有可以使用提供的地址锁定输出锁定的输入(这不适用于coinbase事务,因为它们不解锁输出):


此函数返回包含未使用输出的事务列表。为了计算余额,我们需要另一个函数来获取事务并仅返回输出:


这就是它!现在我们可以实现getbalance命令:


     帐户余额是帐户地址被锁定的所有未使用的交易输出的值的总和。
鸟   在挖掘Genesis区块之后,让我们检查一下我们的平衡:




]

这是我们的第一笔钱!


发送硬币
     现在我们必须这样发送我硬币给别人。为此,我们需要创建一个新事务,将其放在一个块中,然后挖掘该块。到目前为止,我们只实施了coinbase交易(这是一种特殊类型的交易),现在我们需要一般交易:


]

在创建新输出之前,我们必须首先找到所有未使用的输出并确保它们存储足够的值,这是FindSpendableOutputs方法的要求。之后,对于找到的每个输出,创建一个引用它的输入。接下来,我们创建两个输出:
      1. 一个用收件人地址锁定,这是硬币实际转移到另一个地址。
鸟    2. 一位锁定发件人'的地址。这是仅在未使用的输出的值保持超过新事务所需的值时创建的更改。请记住:输出没有细分。
鸟    FindSpendableOutputs方法基于FindUnspentTransactions方法:


此方法遍历所有未花费的事务并累积其值。当累计值大于或等于我们要转移的金额时,它会停止并返回按交易ID分组的累计值和输出索引。我们不想超支。
鸟   现在我们可以修改Blockchain.MineBlock方法:


[123最后,让我们实现发送命令:


发送硬币意味着创建一个交易并将其添加到通过区块链。但比特币没有立即做到(就像我们一样)。相反,它将所有新事务放入内存池(或mempool)。当矿工准备挖掘块时,只有当包含它们的块被挖掘并添加到块中时,它才从内存池中获取所有事务并创建候选块。当链在链中时,将确认交易。

让我们检查发送硬币是否有效:


太棒了!现在让我们创建更多交易,并确保从多个输出发送工作正常:


现在,海伦的硬币锁定在两个输出中:一个来自Pedro,一个来自Ivan。让我们把它们发给别人:


看起来很棒!现在让我们测试失败:


结论

即使这不容易,但我们现在达成协议!然而,像比特币这样的加密货币有一些关键特征:

      1
。我们还没有真正的基于私钥的地址。 鸟    2
奖励。矿区绝对没有利润! 鸟    3。
UTXO设置。获得平衡需要扫描整个区块链,这可能需要很长时间得到很多块。此外,如果我们想验证未来的交易,可能需要很长时间。 UTXO集旨在解决这些问题并使事务快速进行。 鸟    4。
内存池。这是在打包块之前存储事务的位置。在我们当前的实现中,块只包含一个事务,效率非常低。   编辑:但原作