Transaction签名的流程
在Bitcoin里transaction分成5类,但跟上一篇提过Gcoin所谓的7种transaction type是不一样的,Gcoin的7种transaction是因为Gcoin为联盟制架构,且拥有多货币功能的区块链,导致在transaction的型态上可以有7种分类。而Bitcoin里transaction的五个分类指的是5种Standard transaction,这5个分类的依据则是因为transaction script的不同,所以Gcoin也享有这五个分类,而他们分别是Pay-to-Public_Key_Hash(P2PKH )Pay-to-Public-Key(P2PK)Multi-SignaturePay-to-Script-Hash(P2SH)和Data Output(OP_RETURN),如果你想要了解这五种的差异,可以参考强者我同学做的笔记
而这篇我比较想要专注在transaction签名的流程,会用最常见的P2PKH 来当范例。
前言
还记得在拆解transaction的过程中有提过,在transaction output有一个script叫做locking script,它的意义在于定义这个output可以被花掉的条件,而在transaction input有另一个script叫做unlocking script,他的任务就是去满足他要花掉的那个output的locking script,一旦input的unlocking script经过验证是符合上一笔transaction output的locking script,这笔transaction才会被解锁且认为是合法的。而最常见的P2PKH transaction script就长得像下图这样
在Bitcoin script里,他们采用一种语言叫做script language,他是一个stack-based的语言,从左向右执行,所以当你看到Bitcoin script时,不管是locking script还是unlocking script,都建议搭配这个一起看才会知道这个script的动作到底是什么,例如当我在script里面出现63,我就要对表知道他代表OP_IF这个动作。
现在我们回想一下上一篇的raw transaction,locking script 的值长的像这样
76a9149dd353a079ad3b149e00dcc9f6a62f399d3d1c8f88ac
透过Bitcoin script 对照表我们就可以把它翻译成
OP_DUP OP_HASH160 9dd353a079ad3b149e00dcc9f6a62f399d3d1c8f OP_EQUALVERIFY OP_CKECHSIG
会发现他跟上图结构上长一样了!但如果有看仔细你会发现76a9后面的14被我偷渡掉了,他在对照表上没有实质的动作,他表明了接下来这么多bytes会被放上去stack,而0x14就是20 bytes,所以接下来的20 bytes9dd353a079ad3b149e00dcc9f6a62f399d3d1c8f才会是我的重点,在执行时会被放上去stack,而这串就是上图的PubKHash,他其实就是public key去做hash160的结果,也可以从address推过去,另外因为这个locking script里面含public key,所以又称为scriptPubKey。而他的用处到底是什么以及为什么unlocking script还长的跟上图不一样,等等会介绍。
签名
transaction 的签名意思就是我去把input 的unlocking script 换掉,换成可以满足我要花掉的那个output 的locking script,所以可以预期做完之后,我们的unlocking script 结构也要长的跟上图一样。还记得我们上一篇的raw transaction 吗
01000000018eff490c3dac592caf4954ad1e142e6e8d8fbb427909bb18d7271e7d66dcf9d4000000001976a9149dd353a079ad3b149e00dcc9f6a62f399d3d1c8f88acffffffff0200e40b54020000001976a9144400e18b93766b106220343dbd37d4135501d6da88ac01000000003bbf15f08623001976a9149dd353a079ad3b149e00dcc9f6a62f399d3d1c8f88ac010000000000000000000000
首先我们先暂时的在raw transaction后面挂上4 bytes的hash type code,一般的transaction来说都用SIGHASH_ALL (0x00000001),要记得因为也是用little endian表示所以是01000000 然后我们把整串raw transaction 复制一份之后拿去做两次SHA256 接着把两次SHA256 的结果连同我自己的private key 一起送去ECDSA 签名,会得到一个signature 再来把signature后面再挂上1 byte的hash code type,在这边一样是01的SIGHASH_ALL 最后把上一步的signature 连同我自己的public key 去取代这个raw transaction 原本的input unlocking script,记得也要符合script language,所以signature 和public key 前面都需要加他们的长度
步骤上看起来很少,但是第3步的ECDSA到底是怎么签名的在这之前我们需要先回忆一下public key是怎么产生的,Bitcoin用的椭圆曲线是secp256k1如下图
图中的G 为generator point,在Bitcoin 里面是一个满足此方程式的点
G * k = K
其中k 为你的private key,而产生的K 就是你的public key,而椭圆曲线的乘法如左边显示,所以可以知道其实public key 也是曲线上的一个点,只是一般我们看到都是把他的两个座标接在一起而已。
回到我们的signature,他其实也是由G 去乘上一个k 所产生的一个座标,只是这个k 并不只是private key 了,他是由private key 和传进来的message (两次SHA256 的raw transaction)和一个random number 所组成的,因此要签名一个transaction 还是一定要有private key 才能产生。
但如果要验证transaction 的signature 是不是合法除了要有本来的message 之外,则只需要用到public key 就可以了,而message 很容易可以再次创建一个,因为毕竟他只是一个空有input output 的raw transaction 在做两次sha256 而已,所以这就是为什么我们的unlocking script 是由signature 和public key 两个所组成的就好,因为等等验证transaction 时并不需要其他的东西了。
ECDSA详细的内容我也没有很懂,可能要问问数学系的了。
总而言之,以下就是我们新的unlocking script,他会用来取代旧的
上面拆解有几个比较特别的地方,signature 和public key 明明都是一个座标,但他们表示的方式竟然不一样,signature 是用一个叫做DER encoding 的方式来编码,而public key 就比较正常,但前面有一个byte 的type 要写在前面。另外要注意signature 后面也有挂一个byte 的hash type code,他并不是真正signature 的一部分。
验证
先来看一眼我们签名过的transaction 长什么样子
01000000018eff490c3dac592caf4954ad1e142e6e8d8fbb427909bb18d7271e7d66dcf9d4000000008b4830450221009227b2e4f8c36518049bafc88839c19c5597a7a5cfd1e133b84bd6ff8046c6c50220077fdcbb210f4361f20cbe4c056982a798b1d009c391a1447ccef11ea7a1675c0141046036a0a8f54895704ac5cba5b642153331bc2d13dda142665c6a501a606e2099a61d22d22a5cbe8c966672e2a353631f05014157ae37659238381b59bbbcce80ffffffff0200e40b54020000001976a9144400e18b93766b106220343dbd37d4135501d6da88ac01000000003bbf15f08623001976a9149dd353a079ad3b149e00dcc9f6a62f399d3d1c8f88ac010000000000000000000000
虽然感觉变长了,但仔细解析其实会发现只有input 的unlocking script 改过了,而真正的unlocking script 是由一个signature 和一个public key 所组成,又称为scriptSig。现在我们的transaction 已经准备好了,当我们一把它broadcast 到网路上,就会进行transaction 的验证流程,一但验证成功了,他就会被收到block 里面去,现在我们来看看验证是怎么进行的。
因为这笔transaction 的input 会记载着我是要花哪一个transaction 的哪一个output,所以就会去拿出那个output 的locking script,长得像这样
OP_DUP OP_HASH160 9dd353a079ad3b149e00dcc9f6a62f399d3d1c8f OP_EQUALVERIFY OP_CHECKSIG
接着我们就要拿我们这笔transaction 的input unlocking script 去解锁他,而我们的unlocking script 长这样
30450221009227b2e4f8c36518049bafc88839c19c5597a7a5cfd1e133b84bd6ff8046c6c50220077fdcbb210f4361f20cbe4c056982a798b1d009c391a1447ccef11ea7a1675c01 046036a0a8f54895704ac5cba5b642153331bc2d13dda142665c6a501a606e2099a61d22d22a5cbe8c966672e2a353631f05014157ae37659238381b59bbbcce80
其实就是两个字串,分别是signature 和public key。接着记得上面提过Bitcoin 的script language 是一个stack-based 的语言吗下面就是stack 的操作,如果最后出来是对的,那就验证成功代表我们可以花这笔钱,如果是错的当然就会交易失败。
将前一个output 的locking script 和我们input 的unlocking script 接在一起 把signature 和public key 都push 到stack 上 把stack 顶部的东西复制一份,所以现在stack 上又多了一个public key 把刚刚复制的public key 做OP_HASH160,这边要注意的是,如果你是自己在电脑上做验证,要记得把public key 从hex 转成bytes 才能丢进去HASH160,出来才会跟你看到的pubKeyHash长一样 把原本locking script 的pubKeyHash 也push 到stack 上,并比较他和本来在stack 上的pubKeyHash 是否一样,如果一样就把他们两个都pop 出来继续操作,但如果不一样,就代表这个locking script 根本不是你可以掌控的,也就是说你想要花的那个output 根本不是你的钱,所以transaction 验证就会失败 最后把signature 和我们的public key 拿去ECDSA 验证看看是不是符合,而前面提过,验证transaction 只需要public key 就可以了
当以上的步骤都成功之后,transaction 的验证也就完成了,虽然这长长的一个范例只有P2PKH,但其实其他的概念上也差不多,有空也会再介绍其他的,或可以看看最上面我贴的强者我朋友的文章。
声明:本站所提供的资讯信息不代表任何投资暗示, 本站所发布文章仅代表个人观点,仅供参考。