Transaction

https://jeiwan.cc/posts/building-blockchain-in-go-part-4/

什么是Transaction

区块链中的Transaction(交易)就是一批输入和输出的集合,比如A通过交易给B10个代币(token),那么交易就是A输入10代币,输出变成B得到10代币,这样A就减少10代币,B增加10代币,再将这个交易信息存储到区块链中固化后,A和B在区块链中的账号状态就发生了永久性不可逆的变化。

从定义可以看到Transaction就是输入和输出的集合,输入和输出的关系如下图: 

其中tx0,tx1,tx2等是独立的交易,每个交易通过输入产生输出,下面重点看看一个交易的输入和输出单位是怎么回事。

先看输出TXOutput:

Value : 表示这个输出中的代币数量

PubKeyHash : 存放了一个用户的公钥的hash值,表示这个输出里面的Value是属于哪个用户的

输入单元TXInput:

Txid : 交易ID(这个输入使用的是哪个交易的输出)

Vout : 该输入单元指向本次交易输出数组的下标,通俗讲就是,这个输入使用的是Txid中的第几个输出。

Signature : 输入发起方(转账出去方)的私钥签名本Transaction,表示自己认证了这个输入TXInput。

PubKey : 输入发起方的公钥

通俗来讲,一个TXInput结构表示 :

我要使用哪个交易(Txid)的哪个输出数组(Transaction.Vout)的下标(Vout)作为我本次输入的代币数值(TXOutput.Value)

1

因为交易的输入其实是需要指明要输入多少代币(Value),但是TXInput中并没有直接的代币字段,而唯一有代币字段的是在TXOuput中,所以这里使用的方式是在TXInput中指明了自己需要使用的代币在哪个TXOutput中。

TXInput中的Signature字段是发起用户对本次交易输入的签名,PubKey存放了用户的公钥,用于之前的验证(私钥签名,公钥验证)。

3.什么是UTXO

UTXO 是 Unspent Transaction Output 的缩写,意指“为花费的交易输出”,是中本聪最早在比特币中采用的一种技术方案。因为比特币中没有账户的概念,也就没有保存用户余额数值的机制。因为区块链中的历史交易都是被保存且不可修改的,而每一个交易(如前所述的Transaction)中又保存了“谁转移了多少给谁”的信息,所以要计算用户账户余额,只需要遍历所有交易进行累计即可。

从第三节的交易图可以看到,每笔交易的输入TXInput都是使用的是其他交易的输出TXOutput(只有输出中保存了该输出是属于哪个用户,价值多少)。如果一笔交易的输出被另外一个交易的输入引用了(TXInput中的Vout指向了该TXOutput),那么这笔输出就是“已花费”。如果一笔交易的输出没有被任何交易的输入引用,那么就是“未花费”。分析上图的tx3交易:

tx3有3个输入:

input 0 :来自tx0的output0,花费了这个tx0.output0.

input 1 :来自tx1的output1,花费了这个tx1.output1.

input 2 :来自了tx2的output0,花费了这个tx2.output0.

tx3有2个输出:

output 0 :没有被任何后续交易引用,表示“未花费”。

output 1 :被tx4的input1引用,表示已经被花费。

因为每一个output都包括一个value和一个公钥身份,所以遍历所有区块中的交易,找出其中所有“未花费”的输出,就可以计算出用户的账户余额。

4.查找未花费的Output

如果一个账户需要进行一次交易,把自己的代币转给别人,由于没有一个账号系统可以直接查询余额和变更,而在utxo模型里面一个用户账户余额就是这个用户的所有utxo(未花费的输出)记录的合集,因此需要查询用户的转账额度是否足够,以及本次转账需要消耗哪些output(将“未花费”的output变成”已花费“的output),通过遍历区块链中每个区块中的每个交易中的output来得到结果。

下面看看怎么查找一个特定用户的utxo,utxo_set.go相关代码如下:

FindSpendableOutputs查找区块链上pubkeyHash账户的utxo集合,直到这些集合的累计未花费金额达到需求的amount为止。

blockchain_go中使用嵌入式key-value数据库boltdb存储区块链和未花费输出等信息,其中utxoBucket是所有用户未花费输出的bucket,其中的key表示交易ID,value是这个交易中未被引用的所有output的集合。所以通过遍历查询本次交易需要花费的output,得到Transaction的txID和这个output在Transaction中的输出数组中的下标组合unspentOutputs。

另外一个重点是utxobucket中保存的未花费输出结合是关于所有账户的,要查询特定账户需要对账户进行判断,因为TXOutput中有pubkeyhash字段,用来表示该输出属于哪个用户,此处采用out.IsLockedWithKey(pubkeyHash)判断特定output是否是属于给定用户。

5.新建Transaction

需要发起一笔交易的时候,需要新建一个Transaction,通过交易发起人的钱包得到足够的未花费输出,构建出交易的输入和输出,完成签名即可

因为用户的总金额是通过若干未花费输出累计起来的,而每个output所携带金额不一而足,所以每次转账可能需要消耗多个不同的output,而且还可能涉及找零问题。以上查询返回了一批未花费输出列表validOutputs和他们总共的金额acc. 找出来的未花费输出列表就是本次交易的输入,并将输出结果构造output指向目的用户,并检查是否有找零,将找零返还。

如果交易顺利完成,转账发起人的“未花费输出”被消耗掉变成了花费状态,而转账接收人to得到了一笔新的“未花费输出”,之后他自己需要转账时,查询自己的未花费输出,即可使用这笔钱。

最后需要对交易进行签名,表示交易确实是由发起人本人发起(私钥签名),而不是被第三人冒充。

6.Transaction的签名和验证

6.1 签名

交易的有效性需要首先建立在发起人签名的基础上,防止他人冒充转账或者发起人抵赖,blockchain_go中交易签名实现如下:


交易输入的签名信息是放在TXInput中的signature字段,其中需要包括用户的pubkey,用于之后的验证。需要对每一个输入做签名。

6.2 验证

交易签名是发生在交易产生时,交易完成后,Transaction会把交易广播给邻居。节点在进行挖矿时,会整理一段时间的所有交易信息,将这些信息打包进入新的区块,成功加入区块链以后,这个交易就得到了最终的确认。但是在挖矿节点打包交易前,需要对交易的有效性做验证,以防虚假数据,验证实现如下:


可以看到验证的时候也是每个交易的每个TXInput都单独进行验证,和签名过程很相似,需要构造相同的交易数据txCopy,验证时会用到签名设置的TxInput.PubKeyHash生成一个原始的PublicKey,将前面的signature分拆后通过ecdsa.Verify进行验证。

7.总结

以上简单分析和整理了blockchain_go中的交易和UTXO机制的实现过程,加深了区块链中的挖矿,交易和转账的基础技术原理的理解。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,898评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,401评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,058评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,539评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,382评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,319评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,706评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,370评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,664评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,715评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,476评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,326评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,730评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,003评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,275评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,683评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,877评论 2 335

推荐阅读更多精彩内容