共计 4944 个字符,预计需要花费 13 分钟才能阅读完成。
区块链入门 ③ – 交易
交易
概述
比特币交易实质上蕴含交易参与者价值转移的相干信息数据结构。比特币区块链是一本寰球复式记账总账簿,每笔交易都是在比特币区块链上的一个公开记录。
本章中应用术语“钱包”时,咱们指的是构建交易的软件,而不仅仅是蕴含密钥的数据库。
前置常识
UTXO
UTXO,即“未破费的交易输入”(unspent transaction outputs)。所有 UTXO 的汇合被称为 UTXO 集。UTXO 集大小在新的 UTXO 减少时而增长,并在 UTXO 被耗费时而放大。每一个交易都代表 UTXO 集中的变动(状态转换)。
- UTXO 的最小单位是八位小数的“聪”。
- UTXO 是面值为“聪”的离散且不可分割的价值单位,一个 UTXO 只能在一次交易中 作为一个整体 被耗费。如果一个 UTXO 面值大于一笔交易所需,它依然必须作为整体全副应用,但同时会在交易中生成零头。比特币利用能够应用一些策略来满足付款需要:组合若干小额 UTXO,并算出精确的找零;或者应用一个比交易额大的 UTXO 而后进行找零。
- 交易会耗费先前记录的未应用的 UTXO,并创立可供将来交易应用的新的 UTXO。通过这种形式,大量的比特币在生产和创立 UTXO 的交易链中在所有者之间进行转移。
- “币基交易”(Coinbase Transaction):每个区块中的第一笔交易,这笔交易由“获胜”矿工设置,创立全新比特币并领取给该矿工作为采矿处分。币基交易并不生产 UTXO,相同,它有一种称为“coinbase”的非凡类型的输出。
余额
用户的比特币“余额”是指用户钱包中可用的 UTXO总和,它们可能扩散在数百个交易和区块中。比特币钱包通过扫描区块链并汇聚所有属于该钱包管制的私钥的 UTXO 来计算该用户的余额。
比特币脚本语言
比特币的脚本语言是一种基于栈的语言。脚本语言通过从左到右解决每个我的项目来执行脚本。
- 数字(数据常量)被推到栈上。操作码(Operators)从栈中推送或弹出一个或多个参数,对其执行操作,并可能将后果推送到栈上。例如,操作码 OP_ADD 将从栈中弹出两个我的项目,增加它们,并将后果的总和推送到栈上。
- 条件操作码(Conditional operators)对一个条件进行计算,产生一个 TRUE 或 FALSE 的布尔后果(boolean result)。例如,OP_EQUAL 从栈中弹出两个我的项目,如果它们相等,则推送为 TRUE(由数字 1 示意),否则推送为 FALSE(由数字 0 示意)。
比特币数字签名
数字签名是一种由两局部组成的数学计划:第一局部是应用私钥对数据创立签名的算法;第二局部是容许在给定数据和公钥时验证签名合法性的算法。比特币中应用的数字签名算法是椭圆曲线数字签名算法(Elliptic Curve Digital Signature Algorithm,ECDSA)
- 创立签名
在比特币的 ECDSA 算法的实现中,被签名的“音讯”是交易,或更确切地说是交易中特定数据子集的哈希值。签名密钥是用户的私钥,后果就是签名,签名 Sig 由两个值组成,称为 R 和 S:Sig = (R, S)。
具体流程如下:
- 签名算法首先生成一个长期密钥对。长期密钥对基于随机数 k,用作长期私钥。如果应用雷同的值 k 在不同的音讯(交易)上生成两个签名,那么任何人都能够计算出签名私钥!!!
- 利用 k,咱们生成相应的长期公钥 P(以 P=k*G 计算,与派生比特币公钥雷同)。
- 数字签名的 R 值则是长期公钥 P 的 x 轴坐标。
-
数字签名的 S 值:
$$
S = k^{-1}(Hash(m) + dA * R) mod n
$$
其中:
- k是长期私钥
- R是长期公钥的 x 坐标
- dA是签名私钥
- m是交易数据(或其局部)
- n是椭圆曲线的阶
- 验证签名
验证应用数据(交易或其局部的哈希值),签名者的公钥和签名(R 和 S 值)来计算值 P,该值是椭圆曲线上的一个点,如果计算出的点 P 的x坐标等于R,则签名无效。
$$
P = S^{-1} Hash(m)*G + S^{-1}*R*Qa
$$
其中:
- R和 S 是签名值
- Qa是签名者的公钥
- m是交易数据(或其局部)
- G是椭圆曲线生成点
-
数字签名的用处:
- 身份认证性 : 签名证实私钥的所有者,即资金所有者,曾经受权收入这些资金。
- 不可否认性 : 受权证实是不可否认的(不可否认性)。
- 完整性 : 签名证实交易(或交易的特定局部)在签名之后没有也不能被任何人批改。
交易输入
每一笔比特币交易都会发明输入,并被比特币账簿(区块链)记录下来。除特例之外,简直所有的输入都能发明 UTXO。
交易输入蕴含两局部:
- “value”:一定量的比特币,面值为“聪”(satoshis)。
- “scriptPubKey”:作为破费输入所需条件的加密难题(cryptographic puzzle),也被称为锁定脚本(locking script)、见证脚本(witness script),或脚本公钥(scriptPubKey)。
{
...
"vout": [
{
"value": 0.01500000,
"scriptPubKey": "OP_DUP OP_HASH160 ab68025513c3dbd2f7b92a94e0581f5d50f654e7 OP_EQUALVERIFY OP_CHECKSIG"
},
{
"value": 0.08450000,
"scriptPubKey": "OP_DUP OP_HASH160 7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8 OP_EQUALVERIFY OP_CHECKSIG"
}
]
}
交易输出
交易输出将 UTXO(通过被援用)标记为将被生产,并通过解锁脚本提供所有权证实。
交易输出蕴含四局部:
- “txid”:一个交易 ID,援用蕴含正在应用的 UTXO 的 交易(不是 UTXO)。
- “vout”:一个输入索引,用于标识来自该 交易中的第几个 UTXO被援用(一个交易可能存在多个输入,第一个为零)。
- “scriptSig”:一个解锁脚本,钱包构建它是为了满足 UTXO 中设置的生产条件,满足搁置在 UTXO 上的领取条件,解锁收入。
- “scriptSig”:一个序列号,与工夫锁无关。
{
...
"vin": [
{
"txid": "7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18",
"vout": 0,
"scriptSig": "3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813[ALL]0484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc5412336376789d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adf",
"sequence": 4294967295
}
]
}
- 留神:交易输出中仅蕴含了“txid”,须要首先从区块链中检索援用的 UTXO,来获取该 UTXO 的面值和锁定条件。
交易脚本
比特币网络解决的大多数交易破费的是由“付款至公钥散列”(Pay-to-Public-Key-Hash,P2PKH)脚本锁定的输入。
相应的锁定脚本和解锁脚本如下:
- 锁定脚本(scriptPubKey):锁定脚本是一个搁置在输入上的破费条件:它指定了今后破费这笔输入必须要满足的条件。其蕴含一个公钥散列(hash)值,即咱们常说的比特币地址。
- 解锁脚本(scriptSig):解锁脚本是“解决”或满足输入上锁定脚本设定的破费条件并容许破费输入的脚本。解锁脚本是交易输出的一部分,其蕴含散列值对应的公钥和由相应私钥创立的数字签名。
每个比特币验证节点将通过一起执行锁定和解锁脚本来验证交易。
- 每个输出都蕴含一个解锁脚本,并援用先前存在的 UTXO。
- 验证软件将复制解锁脚本,检索输出援用的 UTXO,并从该 UTXO 复制锁定脚本。
- 而后按程序执行解锁和锁定脚本。如果解锁脚本满足锁定脚本条件,则输出无效。所有输出都是独立验证的,作为交易整体验证的一部分。
例子:
- 锁定脚本
OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG
- 解锁脚本
<Cafe Signature> <Cafe Public Key>
- 组合验证脚本
<Cafe Signature> <Cafe Public Key> OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG
- 验证流程
签名散列类型
比特币签名有一种办法,用于通过应用 SIGHASH 标记来批示交易数据的 某一部分 蕴含在由私钥签名的散列中。
每个输出可能在其解锁脚本中蕴含一个签名。因而,蕴含多个输出的交易能够领有具备不同 SIGHASH 标记的多个签名,这些标记在每个输出中承诺交易的不同局部。
有三个 SIGHASH 标记:ALL,NONE 和 SINGLE。
SIGHASH flag | Value | Description |
---|---|---|
ALL | 0x01 | 签名利用到所有输入输出 |
NONE | 0x02 | 签名只利用到所有输出,不包含任何输入 |
SINGLE | 0x03 | 签名利用到所有输出和与签名输出具备雷同索引号的那个输入 |
另外还有一个修饰符标记 SIGHASH_ANYONECANPAY,它能够与后面的每个标记组合应用。
当设置 ANYONECANPAY 时,只有以后输出被签名,其余的(及其序列号)放弃凋谢以进行批改。ANYONECANPAY 的值为 0x80,并通过按位 OR 运算,失去如下表所示组合标记:
SIGHASH flag | Value | Description |
---|---|---|
ALL | ANYONECANPAY | 0x81 |
NONE | ANYONECANPAY | 0x82 |
SINGLE | ANYONECANPAY | 0x83 |
利用 sighash 标记的形式:
- 依据应用的 SIGHASH 标记,生成交易的正本并截断其中的某些字段(设置为零长度并清空)。
- 序列化交易正本,将 SIGHASH 标记被增加到序列化交易的结尾。
- 将序列化交易正本 +SIGHASH 标记散列,失去的散列值即是被签名的“音讯”。
- 因为在散列化前,SIGHASH 作为最初一步被蕴含在内,签名也会对 SIGHASH 类型进行签订,因而不能被更改(例如,不能被矿工批改)。
利用:
- ALL|ANYONECANPAY:这种标记能够用来做“众筹”交易,众筹发起人能够用单笔输入来构建一个交易,这笔输入将“指标”金额付给众筹发起人。这样的交易显然是有效的,因为它没有输出。然而当初其他人能够通过增加本人的输出作为捐献来批改它们,他们用 ALL|ANYONECANPAY 签订本人的输出,直到收集到足够的输出以达到输入的指标金额前,交易有效,每一笔捐款都是一种“承诺”,在募集够整个指标金额之前,筹款不能发出。
- NONE:该构造可用于创立特定金额的“不记名支票”或“空白支票”。它对输出进行承诺,但容许输入锁定脚本被更改。任何人都能够将本人的比特币地址写入输入锁定脚本并兑换交易。
- NONE|ANYONECANPAY:这种结构能够用来建造一个“吸尘器”。在钱包中领有渺小 UTXO 的用户无奈破费这些费用,因为手续费超过了这些渺小 UTXO 的价值。借助这种类型的签名,渺小 UTXO 能够捐献给任何违心募集的人并由他们随时破费。
交易费
交易费是指输出和输入之间的差值。从所有输出中扣掉所有输入之后的残余的金额是矿工收取的交易费。
- 交易的数据结构自身没有交易费这个字段。
- 交易费是以千字节为单位计算的,而不是比特币交易的金额,这意味着如果把大量小型 UTXO 作为输出可能须要领取更高的交易费。
- 交易费作为矿工打包(挖矿)一笔交易到下一个区块中的一种激励;同时作为一种克制因素,通过对每一笔交易收取小额费用来避免对系统的滥用。胜利挖到某区块的矿工将失去该区内蕴含的交易费,并将该区块增加至区块链中。
- 大多数状况下,交易费影响解决优先级,这意味着有足够费用的交易费更可能被打包进下一个挖出的区块中;任何创立交易的比特币服务,包含钱包、交易所、批发利用等,都必须实现交易费动静计算性能。