(廖雪峰)分析比特币交易数据

http://lib.csdn.net/article/blockchain/45826 比特币交易测试
作者:wuzh1230

做实验之前使用-txindex=1(索引所有交易)和-reindex(重新索引block)来启动Daemon程序bitcoind

./bitcoind -datadir=/root/harrywu/temp/bitcoin-v0.9.1/ -gen -daemon -reindex -txindex=1

标准交易实验部分:
1)创建交易

createrawtransaction [{\"txid\":\"94ab03c82d036454c0b733094b306997eebee297af1684f905b3a74a4092efbc\",\"vout\":0}] {\"PN3h88Az7oyt4oRkGQov6KgHhT2U4BQbgH\":50}

输出:0100000001bcef92404aa7b305f98416af97e2beee9769304b0933b7c05464032dc803ab940000000000ffffffff0100f2052a010000001976a914939d776145ae6e35a9be0592361938683bb5756188ac00000000

2)签名交易

signrawtransaction 0100000001bcef92404aa7b305f98416af97e2beee9769304b0933b7c05464032dc803ab940000000000ffffffff0100e40b54020000001976a914939d776145ae6e35a9be0592361938683bb5756188ac00000000
输出:{ "hex" : "0100000001bcef92404aa7b305f98416af97e2beee9769304b0933b7c05464032dc803ab94000000006b4830450221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022008795f8428c19977e5f0ba0cbef4432b5a291c3e03df0ab194652750e3142ba80121032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501fffffffff0100e40b54020000001976a914939d776145ae6e35a9be0592361938683bb5756188ac00000000", "complete" : true}

decoderawtransaction 0100000001bcef92404aa7b305f98416af97e2beee9769304b0933b7c05464032dc803ab94000000006b4830450221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022008795f8428c19977e5f0ba0cbef4432b5a291c3e03df0ab194652750e3142ba80121032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501fffffffff0100e40b54020000001976a914939d776145ae6e35a9be0592361938683bb5756188ac00000000
输出:{    "txid" : "cd488764b6a87e9aacbec021ba678ea262890dfed400594931aa3856bcaa59e2",    "version" : 1,    "locktime" : 0,    "vin" : [        {            "txid" : "94ab03c82d036454c0b733094b306997eebee297af1684f905b3a74a4092efbc",            "vout" : 0,            "scriptSig" : {                "asm" : "30450221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022008795f8428c19977e5f0ba0cbef4432b5a291c3e03df0ab194652750e3142ba801 032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501f",                "hex" : "4830450221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022008795f8428c19977e5f0ba0cbef4432b5a291c3e03df0ab194652750e3142ba80121032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501f"            },            "sequence" : 4294967295        }    ],    "vout" : [        {            "value" : 100.00000000,            "n" : 0,            "scriptPubKey" : {                "asm" : "OP_DUP OP_HASH160 939d776145ae6e35a9be0592361938683bb57561 OP_EQUALVERIFY OP_CHECKSIG",                "hex" : "76a914939d776145ae6e35a9be0592361938683bb5756188ac",                "reqSigs" : 1,                "type" : "pubkeyhash",                "addresses" : [                    "PN3h88Az7oyt4oRkGQov6KgHhT2U4BQbgH"                ]            }        }    ]}

玩一下:修改签名(r,s)中的s部,使得s’=n-s, n是椭圆曲线多项式方程的order,(p,a,b,G,n,h)中n,对于secp256k1的koblitz曲线,

n = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141

decoderawtransaction 0100000001bcef92404aa7b305f98416af97e2beee9769304b0933b7c05464032dc803ab94000000006c4930460221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022100f786a07bd73e66881a0f45f3410bbcd36085c0a8ab69958a2b6d373bed2215990121032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501fffffffff0100e40b54020000001976a914939d776145ae6e35a9be0592361938683bb5756188ac00000000
输出:{ "txid" : "4d391c500dd247eb6c78fc069d876ed0833f92c2581adca5e454406a79535001", "version" : 1, "locktime" : 0, "vin" : [ { "txid" : "94ab03c82d036454c0b733094b306997eebee297af1684f905b3a74a4092efbc", "vout" : 0, "scriptSig" : { "asm" : "30460221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022100f786a07bd73e66881a0f45f3410bbcd36085c0a8ab69958a2b6d373bed22159901 032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501f", "hex" : "4930460221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022100f786a07bd73e66881a0f45f3410bbcd36085c0a8ab69958a2b6d373bed2215990121032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501f" }, "sequence" : 4294967295 } ], "vout" : [ { "value" : 100.00000000, "n" : 0, "scriptPubKey" : { "asm" : "OP_DUP OP_HASH160 939d776145ae6e35a9be0592361938683bb57561 OP_EQUALVERIFY OP_CHECKSIG", "hex" : "76a914939d776145ae6e35a9be0592361938683bb5756188ac", "reqSigs" : 1, "type" : "pubkeyhash", "addresses" : [ "PN3h88Az7oyt4oRkGQov6KgHhT2U4BQbgH" ] } } ]}

3)发送交易

sendrawtransaction 0100000001bcef92404aa7b305f98416af97e2beee9769304b0933b7c05464032dc803ab94000000006c4930460221008dc53e7535ae67045cc996293534c2f349fbea39ee6bd43cf4f622ac81eb9e50022100f786a07bd73e66881a0f45f3410bbcd36085c0a8ab69958a2b6d373bed2215990121032a1d1fcb50c09fd0356ace15f71981209df6af6cbc6a4929541accf5a583501fffffffff0100e40b54020000001976a914939d776145ae6e35a9be0592361938683bb5756188ac00000000
输出:4d391c500dd247eb6c78fc069d876ed0833f92c2581adca5e454406a79535001

提示:
1)createrawtransaction 的参数格式要求:转义,无空格
2)需要了解der编码
3)做实验的客户端我修改了部分参数的,地址前缀是P(官方是1),但是不影响实验

Byte-map of Transaction with each type of TxIn and TxOut

以下内容来自 Wiki

A transaction is a signed section of data that is broadcast to the network and collected into blocks. It typically references previous transaction(s) and dedicates a certain number of bitcoins from it to one or more new public key(s) (Bitcoin address). It is not encrypted (nothing in Bitcoin is encrypted).

A block chain browser is a site where every transaction included within the block chain can be viewed. This is useful for seeing the technical details of transaction in action, and for payment verification purposes.

general format of a Bitcoin transaction (inside a block)
Field
Description
Size

Version no
currently 1
4 bytes

In-counter
positive integer VI = VarInt
1 – 9 bytes

list of inputs
the first input of the first transaction is also called “coinbase” (its content was ignored in earlier versions)
<in-counter>-many inputs

Out-counter
positive integer VI = VarInt
1 – 9 bytes

list of outputs
the outputs of the first transaction spend the mined bitcoins for the block
<out-counter>-many outputs

lock_time
if non-zero and sequence numbers are < 0xFFFFFFFF: block height or timestamp when transaction is final
4 bytes

Principle example of a Bitcoin transaction with 1 input and 1 output only
Data

Input:Previous-tx(64Byte): f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6
Index(1Byte): 0
scriptSig(144Byte): 304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d1090db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501
Output-Value(108Byte): 5000000000scriptPubKey: OP_DUP OP_HASH160 404371705fa9bd789a2fcd52d2c580b65d35549dOP_EQUALVERIFY OP_CHECKSIG

Explanation
The input in this transaction imports 50 BTC from output #0 in transaction f5d8… Then the output sends 50 BTC to a Bitcoin address (expressed here in hexadecimal 4043… instead of the normal base58). When the recipient wants to spend this money, he will reference output #0 of this transaction in an input of his own transaction.
Input
An input is a reference to an output in a different transaction. Multiple inputs are often listed in a transaction. The values of the referenced outputs are added up, and the total is usable in the outputs of this transaction. Previous tx is a hash of a previous transaction. Index is the specific output in the referenced transaction. ScriptSig is the first half of a script (discussed in more detail later).
The script contains two components, a signature and a public key. The public key must match the hash given in the script of the redeemed output. The public key is used to verify the redeemers signature, which is the second component. More precisely, the second component is an ECDSA signature over a hash of a simplified version of the transaction. It, combined with the public key, proves the transaction was created by the real owner of the address in question. Various flags define how the transaction is simplified and can be used to create different types of payment.
Output
An output contains instructions for sending bitcoins. Value is the number of Satoshi (1 BTC = 100,000,000 Satoshi) that this output will be worth when claimed. ScriptPubKey is the second half of a script (discussed later). There can be more than one output, and they share the combined value of the inputs. Because each output from one transaction can only ever be referenced once by an input of a subsequent transaction, the entire combined input value needs to be sent in an output if you don’t want to lose it. If the input is worth 50 BTC but you only want to send 25 BTC, Bitcoin will create two outputs worth 25 BTC: one to the destination, and one back to you (known as “change“, though you send it to yourself). Any input bitcoins not redeemed in an output is considered a transaction fee; whoever generates the block will get it.

https://webbtc.com/block/00000000152340ca42227603908689183edc47355204e7aca59383b0aaac1fd8
https://webbtc.com/tx/1a0126b4e734e6e64095ac1f75de47d375e218ff6cf3a0800586b2befba7900d
https://blockchain.info/tx/1a0126b4e734e6e64095ac1f75de47d375e218ff6cf3a0800586b2befba7900d?show_adv=true

Output Scripts
OP_RETURN 4f4101000280919206a0f73600
OP_HASH160 3406ff2f8c18a44cbd10e0d44fc5248480d21b8a OP_EQUAL
OP_HASH160 479b3711de29b02df87ea5b3d116352b3a33a7fc OP_EQUAL
OP_HASH160 479b3711de29b02df87ea5b3d116352b3a33a7fc OP_EQUAL
OP_DUP OP_HASH160 4bafd3780031cae8b9f8e419fa5352e4e0e639ac OP_EQUALVERIFY OP_CHECKSIG

2017年1月12 廖雪峰 揭秘比特币和区块链(五):深入理解比特币交易的脚本

本文作者为火币区块链研究中心技术专家廖雪峰,他有十年软件开发经验,精通Java/Python/Ruby/Visual Basic/Objective C/Lisp等编程语言,对开源框架有深入研究,著有《Spring 2.0核心技术与最佳实践》一书,并有多个业余开源项目托管在GitHub。本文中廖雪峰详细地介绍了比特币及比特币区块链的相关知识。

在比特币区块链中,每一个区块都指向上一个区块,这些通过SHA256计算的区块哈希链就是比特币账本不可篡改的基础。

在一个区块中,比特币系统用交易(Transaction)来表示一笔比特币交易。一个区块包含至少一笔交易。这些Transaction的Hash通过Merkle Tree计算出所有交易的Merkle Hash,并被包含至区块Hash中,从而实现交易的不可修改。

如果我们仔细观察每一笔交易,可以发现,除了第一笔交易是矿工的挖矿所得外,每一笔交易都拥有一个或多个输入(TxIn),以及一个或多个输出(TxOut):

《(廖雪峰)分析比特币交易数据》

第一笔矿工挖矿的收入交易通常被称为Coinbase,它没有输入,所以TxIn的Hash总是被标记为00000000…0000

其他的交易,任何一个TxIn都会唯一追溯到区块链上在本区块之前的某个交易Hash,以及索引:

《(廖雪峰)分析比特币交易数据》

通过交易Hash和索引(从0开始),即可唯一确定一个未花费的交易输出——UTXO(Unspent Transaction Output)。这样,每一个Tx Input都和之前的某个Tx Output关联了起来。

我们假设在上一笔交易中,Bob给Alice支付了0.15个BTC。由于比特币并没有账户的概念,这一笔交易的输出并没有写上Alice的名字,也没有写上Alice的公钥。那么,Alice想要花费这0.15个BTC,她应该如何证明自己拥有这个UTXO,并且,其他人无法假冒Alice来花费这个UTXO呢?

答案是比特币的交易创建的输出其实并非一个简单的公钥地址,而是一个脚本。在Bob给Alice支付0.15个BTC的这个交易中,Bob创建的输出脚本类似:

OP_DUP OP_HASH160 abcd1234…9876 OP_EQUALVERIFY OP_CHECKSIG

其中,abcd1234…9876是Alice的公钥Hash。整个脚本的意思是,谁能够提供一个签名和一个公钥,让这个脚本运行通过,谁就能花费这笔交易的1.5个BTC。由于创建签名只能使用Alice的私钥,非Alice的私钥创建的签名将无法通过这个脚本的验证,所以,其他人无法假冒Alice来花费这笔输出。一旦Alice提供了一个签名和自己的公钥,她实际上已经创建了另一笔交易来花费这个输出。

所有人都可以验证Alice创建的这个新交易是否有效。如果有效,该交易就会被矿工打包进新的区块,从而成为区块链上不可更改的一部分。

我们以著名的 Pizza Transaction 为例,来验证一个交易是否是有效的。

在交易cca75078…4d79中,唯一的TxIn输入提供的sigScript是:

原始数据:8b4830450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e0141042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb

分析数据:
前缀:8b48
签名:30450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e-01
未知:41
公钥:042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb)

该sigScript实际上由两部分构成:

  • 签名:30450221…ee0e01(71字节+1字节签名类型),实际签名是去掉最后一个字节01的30450221…ee0e,签名类型是SIGHASH_ALL(0x01)。
  • 公钥:042e930f…cabb(65字节)

为了验证该交易是否有效,我们首先要根据TxIn所声明的Previous Output Hash:a1075db5…d48d和索引0找到上一笔交易的输出:

https://webbtc.com/tx/a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d

这笔交易输出的脚本是:

1976a91446af3fb481837fadbb421727f9959c2d32a3682988ac

比特币的脚本由一系列指令和数据构成,每个指令占用一个字节,数据由数据头部的长度决定。上述二进制脚本翻译后的比特币指令如下:

OP_DUP OP_HASH160 46af3fb481837fadbb421727f9959c2d32a36829 OP_EQUALVERIFY OP_CHECKSIG

现在,我们有了签名,公钥和脚本,就可以运行这个脚本来验证交易是否有效。

sig: 30450221…ee0e01
pubkey: 042e930f…cabb
OP_DUP OP_HASH160 46af3fb4…6829 OP_EQUALVERIFY OP_CHECKSIG

比特币脚本被设计成以栈来运行的虚拟机指令,它只有有限的几种指令,并且故意被设计成没有循环、条件跳转,所以,比特币脚本不是图灵完备的语言。

比特币脚本的执行非常简单。我们首先要准备一个空栈,然后把签名和公钥入栈:

《(廖雪峰)分析比特币交易数据》

紧接着,我们就可以执行TxOut的脚本:

OP_DUP OP_HASH160 46af3fb481837fadbb421727f9959c2d32a36829 OP_EQUALVERIFY OP_CHECKSIG

首先执行OP_DUP,这条指令把栈顶的元素复制一份,所以结果变成:

《(廖雪峰)分析比特币交易数据》

紧接着执行OP_HASH160,它对栈顶元素计算SHA256/RipeMD160,实际上是计算公钥Hash,所以运行结果变成:

《(廖雪峰)分析比特币交易数据》

接下来的指令实际上是一个数据,我们直接把数据入栈:

《(廖雪峰)分析比特币交易数据》

然后,执行OP_EQUALVERIFY,这条指令会比较栈顶的两个元素是否相等,如果不等,整个脚本就执行失败了,如果相等,脚本会继续执行,所以运行结果变成:

《(廖雪峰)分析比特币交易数据》 Paste_Image.png

最后,执行指令OP_CHECKSIG,这条指令会验证签名。首先,我们根据签名类型SIGHASH_ALL(0x01)对整个交易进行验证。验证方法是:
把当前Transaction的所有TxIn的scriptSig去掉(红色部分),并把当前TxIn的scriptSig替换为UTXO的script(蓝色部分),调整长度字段(绿色部分):

《(廖雪峰)分析比特币交易数据》

最后加上小端序4字节的签名类型0x01(灰色部分),计算两次SHA256,我们得到:

c2d48f45…2669

现在,使用ECDSA算法对签名进行验证:

 boolean ecdsa_verify_signature(byte[] message, byte[] signature, byte[] pubkey);

根据签名的验证结果,我们即可确认该交易是否有效。

由于引入了脚本,我们可以看到,比特币实际上通过编程脚本实现了一个严格以计算机程序验证为基础的数字货币所有权的转移机制。由于计算机程序的可扩展性,比特币支付其实并不限定在必须支付给某一个公钥地址。利用脚本,我们可以构造出各种支付条件,例如,多重签名验证条件:

2 <public-key1> <public-key2> <public-key3> 3 OP_CHECKMULTISIGN

这种提供多个公钥地址,并且需要多个签名验证的多重签名脚本,允许在M个签名种至少给出N个签名即可使用。上述脚本允许提供3个公钥地址中的任意两个有效签名。

当我们把比特币托管在某个第三方的在线钱包中时,就可以使用多重签名来保证只有自己和第三方钱包共同签名后才可动用输出,这样保证了黑客在攻击了第三方钱包后也无法花掉用户的比特币。

通过OP_CHECKLOCKTIMEVERIFY,我们可以指定一个交易的锁定时间,在此之前,该交易输出无法被花掉。这个指令其实实现了支付宝的7天资金锁定然后再支付给卖家的功能。

还有一些交易并没有指定一个公钥Hash,例如,这个交易的脚本如下:

OP_HASH256 6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000 OP_EQUAL

它的意思是说,谁能够提供一个数据,它的SHA256是6fe28c0a…0000,谁就可以花费这笔交易。

(注:该交易已经被花费了,有人找到了符合条件的数据)

从比特币的脚本,我们可以看到,基于区块链的数字货币支付实际上是数字货币所有权的安全转移。如果我们把金融资产或者实物资产以数字化的形式登记在区块链上,通过脚本就可以安全实现各种条件下的所有权转移,这正是智能合约在区块链上的应用。

出处:火币区块链研究中心。转载需注明来源!

    原文作者:大圣2017
    原文地址: https://www.jianshu.com/p/d326e6e21cc0
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞