原文链接-石匠的Blog
1.背景在去中心化的区块链中进行交易(转账)是怎么实现的呢?本篇通过blockchain_go来分析一下。需要进行交易,首先就需要有交易的双方以及他们的认证机制,其次是各自的资金账户规则。在分布式账本系统里面,需要有机制能够准确验证一个用户身份以及对账户资金的精确计算,不能出现一丁点差错。在区块链中交易通过Transaction表示,而账户的自己并不是在每个节点上保存每个用户的一个余额的数字,而是通过历史交易信息计算而来(历史交易不可篡改),其中的关键机制是UTXO。
2.身份认证在区块链身份认证是采用RSA非对称加密体系完成,每个用户在会拥有一个“钱包”,钱包是通过安全的椭圆曲线加密算法生成,其中包括一对公私钥。私钥自己保留不能暴露,用作加密,签名等,公钥公开给所有人,用于信息验证等。只要是用私钥签名的信息,就可以通过配对的公钥解码认证,不可抵赖。在blockchain_go中,钱包实现如下:
// Wallet stores private and public keys type Wallet struct { PrivateKey ecdsa.PrivateKey PublicKey []byte } // NewWallet creates and returns a Wallet func NewWallet() *Wallet { private, public := newKeyPair() wallet := Wallet{private, public} return &wallet } func newKeyPair() (ecdsa.PrivateKey, []byte) { curve := elliptic.P256() //椭圆曲线 private, err := ecdsa.GenerateKey(curve, rand.Reader) //生成私钥 if err != nil { log.Panic(err) } pubKey := append(private.PublicKey.X.Bytes(),private.PublicKey.Y.Bytes()...) //合成公钥 return *private, pubKey }钱包最重要的功能就是为用户提供身份认证和加解密的公私钥对。
3.什么是Transaction区块链中的Transaction(交易)就是一批输入和输出的集合,比如A通过交易给B10个代币(token),那么交易就是A输入10代币,输出变成B得到10代币,这样A就减少10代币,B增加10代币,再将这个交易信息存储到区块链中固化后,A和B在区块链中的账号状态就发生了永久性不可逆的变化。
在blockchain_go中transaction的定义如下:
// TXInput represents a transaction input type TXInput struct { Txid []byte Vout int Signature []byte PubKey []byte } // TXOutput represents a transaction output type TXOutput struct { Value int PubKeyHash []byte } type Transaction struct { ID []byte //交易唯一ID Vin []TXInput //交易输入序列 Vout []TXOutput //交易输出序列 }从定义可以看到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)因为交易的输入其实是需要指明要输入多少代币(Value),但是TXInput中并没有直接的代币字段,而唯一有代币字段的是在TXOuput中,所以这里使用的方式是在TXInput中指明了自己需要使用的代币在哪个TXOutput中。
TXInput中的Signature字段是发起用户对本次交易输入的签名,PubKey存放了用户的公钥,用于之前的验证(私钥签名,公钥验证)。
3.什么是UTXOUTXO 是 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引用,表示已经被花费。