MalukChain-交易 Part1

区块链的一个重要目的就是为了能够安全可靠的存储数据,而这里面应用最广泛的是交易数据。

在区块链中,交易一旦被创建,就不能够被修改或者删除。

由于交易的引入将会大大改变原有的代码结构,我们将分两部分来实现,这一次我们来实现引入交易概念的第一部分,再下一次来补充完成整个交易过程的代码。

UXTO

在介绍交易框架之前,我们先来简单介绍一下 UXTO(Unspent Transaction Output,未花费输出),比特币采用的正是这种交易模型,那什么是 UXTO 呢?

首先比特币中的钱包不存余额的概念,所有的交易都是基于 UXTO 的。

举个简单的例子,你的钱包里面有一个 10 元,有一个 5 元和一个 1 元,一共 16 元,这里所有的钱都是 UXTO,当你花费 13 元去买东西的时候,会得到一个 2 元的找零,这时候 10 元和 5 元花费出去了,就不再是 UXTO 了,新得到的 2 元会成为一个新的 UXTO,加上之前你的 1 元 UXTO,你一共还剩 3 元。这个新的 2元 UXTO 会被记录在区块链上,但不会改变历史的区块数据。

比特币正是用这种前后链接的区块链来记录所有交易记录的,当之前的 UXTO 出现在后续交易时,这个 UXTO 就被花费掉了,就不再是 UXTO 了。

一笔交易包含一些输入和一些输出,每一笔交易都会引用之前一笔交易的输出(将之前的一笔交易输出包含在另一笔交易的输入当中,也就是花费之前的交易输出),每一笔交易的输出其实就是币的存储地址,用一张图来看就是酱的。

从上面我们还能够发现一下特点

一些输出并没有被别的输入引用,废话,你钱包里的钱全都用光了吗

一笔交易的输入可以引用之前多笔输出,嗯,你一元,他一元,我就是亿万富翁了。

一个输入必须引用一个输出

这里有一种特殊交易叫做 coinbase,也就是挖矿,挖矿获得的收入过程是没有输入的~

每一个交易都会创造输出,这个输出都会被比特币记录下来,给某人发比特币,实际上就是给创建一个 UXTO 把输出设置为这个人的钱包地址。

ok,那我们先定义一个交易结构体,这个结构体应该包含一个序号,一系列输入和输出:

交易输出

一个交易输出包括输出的比特币值和一个“解锁”脚本:

这里的 Value 就是比特币值,用的是比特币最小度量 单位 (1 亿分之一 BTC ) 的数量(有点像咱们的 1 分硬币)。

那这个 ScriptPubKey 是什么呢?比特币中用了一种 Script 的脚本语言来定义锁定和解锁的输出,也就是说这个交易不是说谁都能得到,而是谁能解锁这个脚本谁就能获得这个比特币。这里我们简化一下,ScriptPubKey 就当做是用户的钱包地址。

对于 UXTO 这种交易模型来说,输出是不可再分的,换句话说,你无法从一个输出中拿一部分,必须全部花费,如果你想拿一部分,就必须再生成一个 UXTO 把剩下的返还。

现实生活中就是这样啊,你给别人一个 10 元纸币买 5 元的东西,别人再找一个 5 元的给你

交易输入

一个交易输入引用了之前交易的一个输出,所以首先要包含之前那笔交易的 ID,同时要知道是哪一个输出,所以需要一个从之前交易输出列表定位那个输出的索引,再加上一个用于解锁交易输出的数据,如果解锁数据正确,那么输出就可以解锁,被解锁的值就可以用于产生新的输出,如果不正确则不能被输入引用。

这种方式保证你不能花费其他人的币

我们来定义一下交易输入的结构体:

其中,Txid 为交易 id,Vout 为上一笔交易输出的索引,ScriptSig 表示解锁数据。

交易过程

到这里我们在来总结一下上面那几个概念:

输出,就是 “币” 存储的地方。每个输出都会带有一个解锁脚本,这个脚本定义了解锁该输出的逻辑。

每笔新的交易,必须至少有一个输入和输出。

一个输入引用了之前一笔交易的输出,并提供了解锁数据(也就是 字段),该数据会被用在输出的解锁脚本中解锁输出,解锁完成后即可使用它的值去产生新的输出。

第一笔交易

按照上面所说,交易输入引用交易输出,最先有输出,才有输入。

那么我们第一笔交易从何而来?第一笔交易没有输出啊,在区块链中,第一笔交易叫做 coinbase 交易,也就是咱们常听到的挖矿。coinbase 是一种特殊交易,它不需要引用之前的交易输出,也可以理解成发行了 “新币”。

ok,我们来创建一个 coinbase 交易:

我们这里简化实现思路是,把这笔交易的交易输入 (TXInput) 中标识引用的输出 Vout 值设为 -1 表示它不引用交易输出,解锁脚本 ScriptSig 也随意设置成一个字符串, 交易 Id (Transaction 的 Id) 设为空,并且设置奖励金 subsidy 和奖励对象 to。

将交易保存到区块链

我们之前用区块链存储了一些很简单的信息,而现在,我们要用它来存储交易信息啦。从现在开始,每一个区块都必须存储至少一笔交易。

ok,我们移除之前 Block 结构体中的 Data,将它替换成 Transaction:

因此,我们也要修改一下 NewBlock 方法和 NewGenesisBlock 方法:

接下来,我们要修改创建区块链的函数 NewBlockChain:

现在,这个函数会接受一个地址作为参数,这个地址将会被用来接收挖出创世块的奖励。

交易的工作量证明

之前工作量证明的实现仅仅是计算 data 的 hash 值,现在我们要把存储在区块中的交易信息进行 hash 计算。

我们实现一个计算 Transaction 列表 hash 的方法:

然后修改一下之前我们在进行工作量证明时的 prepareData 方法,之前我们是直接用的字符串,现在我们要用上面计算交易 hash 的方法。

来挖一个矿试试

这里我们修改了一些 CLI,具体可以请看代码。

小结

截止目前,我们对我们的区块链项目引入了交易的概念,但目前还没有余额,发送交易等功能,接下来我们会进一步改造我们的区块链,完成上面的功能。

MalukChain 的代码地址:

https://git.coding.net/MrNullPoint/MalukChain.git

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181001G10KLI00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码关注腾讯云开发者

领取腾讯云代金券