bitcoin
脚本简介
比特币在交易中使用脚本系统,与FORTH(一种编译语言)一样,脚本是简单的、基于堆栈的、并且从左向右处理,它特意设计成非图灵完整,没有LOOP语句。
脚本语言是基于栈的,从左向右执行,无状态的,非图灵完备的语言;
- 无状态确保交易一旦被放到区块链上,就不会出现输出永远不能被花费的情况
- 非图灵完备(缺少循环和goto语句)让脚本语言更加灵活(flexible)和可预见,简化了安全模型
- 图灵完备 => 能够计算一切可计算问题
一个脚本本质上是众多指令的列表,这些指令记录在每个交易中,交易的接收者想花掉发送给他的比特币,这些指令就是描述接收者是如何获得这些比特币的。一个典型的发送比特币到目标地址D的脚本,要求接收者提供以下两个条件,才能花掉发给他的比特币:
(1)一个公钥,当进行HASH生成比特币地址时,生成的地址是嵌入在脚本中的目标地址D
(2)一个签名(私钥),证明接收者保存与上述公钥相对应的私钥。
脚本可以灵活改变花掉比特币的条件,举个例子,脚本系统可能会同时要求两个私钥、或几个私钥、或无需任何私钥等等。
如果联合脚本中未导致失败并且堆栈顶元素为真(非零),表明交易有效。
堆栈保存着字节向量,当用作数字时,字节向量被解释成小尾序的变长整数,最重要的位决定整数的正负号。这样0×81代表-1,0×80是0的另外一种表示方式(称之为负0)。正0用一个NULL长度向量表示。字节向量可以解析为布尔值,这里False表示为0,True表示为非0
交易标准
五种交易标准:P2PKH、P2PK、MS(限15个密钥)、P2SH和OP_Return。OP_Return将不会介绍,因为其存储的是信息(或者说只是字节),并非比特币货币。
交易的基本流程
- scriptPubKey => 发送方将自己的utxo使用锁定脚本锁定,锁定在接收方的地址上;
- scriptSig => 接收方使用解锁脚本进行解锁,才能提取BTC
P2PKH
Pay-to-Public-Key-Hash: 使用公钥hash锁定,现行主要的交易标准;
// 完成拼接的脚本内容
<Sig> <PubKey> OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG
//// 解锁脚本 scriptSig => <Sig> <PubKey>
// sig: 使用secp256k1 生成的签名
// PubKey:原生公钥
//// 锁定脚本 scriptPubKey => OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG
执行顺序
- 入栈:{ }
- OP_DUP => 复制栈顶: { }
- OP_HASH160 => 计算hash: { }
- 入栈 => 计算hash: { ,}
- OP_EQUALVERIFY 比较相等 => 计算hash: { }
- OP_CHECKSIG 校验签名=> { 0:失败,非0:成功}
sig签名是私钥与交易hash进行运算,验证签名OP_CHECKSIG是将公钥与签名进行运算,结果0则校验失败
P2PK
Pay-to-Public-Key: 使用公钥锁定脚本
<Signature from Private Key A> <Public Key A> OP_CHECKSIG
// 解锁脚本: <Signature from Private Key A>
// 锁定脚本: <Public Key A> OP_CHECKSIG
MS(限15个密钥)
Multiple Signatures:多重签名
// 锁定脚本,N是存档的公钥总数,M激活交易需要的最少公钥个数
M <Public Key 1> <Public Key 2> ... <Public Key N> N OP_CHECKMULTISIG
// 解锁脚本:op_0 占位符,无意义,是少M个,
// m=2
OP_0 <Signature 1> <Signature 2>
P2SH
pay-to-script-hash:是MS多重签名的简化版本:
// ms锁定脚本,m=2
2 <Public Key A> <Public Key B> <Public Key C> 5 OP_CHECKMULTISIG
// 对脚本依次进行SHA256,RIPEMD160 得到 hash: 8ac1d7a2fa204a16dc984fa81cfdf86a2a4e1731, 生成p2sh的锁定脚本
OP_HASH160 8ac1d7a2fa204a16dc984fa81cfdf86a2a4e1731 OP_EQUAL
// 解锁脚本(也叫回收脚本)
<Sig1> <Sig2> <2 PK1 PK2 PK3 PK4 PK5 5 OP_CHECKMULTISIG>
// 执行顺序,先判断相等,在校验签名
P2SH的特点是,将制作脚本的责任给了接收方,好处是可以暂缓节点存储的压力。
参考
- en.bitcoin.it/wiki/Script 较为全面的介绍了脚本语言