交易模型介绍
比特币的实现使用的是区块链技术,所以比特币账本里面存储的都是一个个连接起来的区块数据。而区块数据里面存储的都是一笔笔交易数据,所以可以理解为比特币里面没有任何其它数据,只有一笔笔交易。
每一笔交易包含交易的唯一id,交易的输入,交易的输出三部分内容:
id: 非常好理解,就是一个唯一标识,我们可以简单理解为和数据库的主见id一样;
交易输入: 交易输入数据记录的是本次交易转账人的信息,包含了转账人的账号,转账金额,还有本次转账的钱来自以前的哪一次交易的id,最后是交易签名,加签名是为了防止被篡改
交易输出: 交易收款人账号,交易结余金额
上面的交易模型简单来说,就是记账,通过交易输入可以看到此次转账需要用到前面的哪些交易输出的余额,通过交易输出可以计算本次交易剩余了多少钱的结余,并转给自己,也方便下一次的交易输入的使用。
所有的交易输出其实就是自己账户上的一笔笔结余余额,所有的交易输入其实就是记录了此次交易花费使用了以前哪些交易输出,如果有结余,再记录为新的交易输出。
比特币的交易模型也简称为UTXO(unspent transaction output),全称是未花费的交易输出,一次交易如果有余额,就有未花费的交易输出,如果没有余额,那么交易输入中存的就都是已花费的交易输出。所以,所有未花费的交易输出加起来,就是当前账户的余额。
同理可以推断出,如果是挖矿操作,那么记账时交易输入一定是0,交易输出就是系统奖励给账户的比特币数量。如果是转账,那么交易输入就会记录本次转账花费的是前面的哪些交易输出,如果刚好花完,那么交易输出就是0,如果没有花完,那么剩余的钱再转为交易输出。
代码实现
从上面的介绍中可以看出,交易输出的数据模型设计最简单,我们来看一下:
交易输出的数据模型只有三个属性,一个是金额,另外两个就是收钱方的钱包地址和公钥。交易输入的数据模型我们定义类 TransactionInput ,交易的数据模型我们定义类 Transaction ,先来看交易的数据模型:
虽然交易模型包含了交易输入和交易输出,但是从整体上看,交易模型也很简单,只包含一个交易id,一个交易输入,一个交易输出。
这里需要说明一下,一次交易转账因为金额不固定,用到的交易输出应该是一个list模型,但是这里的比特币因为是简单实现,因此后面我们交易时金额会固定,这样用单个交易输出也可以实现。
看完交易输出模型和交易模型,下面来看一下交易输入模型:
交易输入模型略微复杂一些,除了定义正常的交易金额和收钱方地址及公钥之外,还定义了交易签名字段,和交易id字段,这个id指向的就是引用输出的那次交易id。
交易输入模型 TransactionInput 中还有一个方法需要定义,在系统挖矿生成的交易中,没有交易输入,我们可以简单把交易输入引用的交易id设置为0,并且把交易输入的金额设置为-1,以此来判断是否为系统交易:
因此,在交易模型类 Transaction 中,需要定义一个判断的方法:
这样,交易输入模型类 TransactionInput 也设计完成了。
下面继续看交易模型类Transaction 。接下来是交易的签名和验证签名的设计,首先,设计两个工具方法,一个是交易对象的克隆方法,另一个是把整体交易对象进行哈希的方法:
上面的克隆方法发送方公钥为空,是为了在签名的时候直接配置引用的交易的交易输出的地址。接下来是给交易进行签名:
签名方法完成后,验证签名的方法就简单了:
上面就是交易模型UTXO的简单设计,用到的加密技术都是前面提到的。比特币的交易模型与普通的支付软件的交易并不一样,需要用记账的思想去理解。
交易id的生成,我们直接使用uuid即可,这里不再演示。
测试
来看一下测试代码,首先测试一下系统交易:
测试结果:
再来测试一下转账交易:
测试结果:
项目代码:https://gitee.com/blueses/btc-demo