Bitcoin-Core

你能解釋一下這個JS程式碼嗎?

  • June 21, 2018

有人可以向我解釋一下這個JS程式碼嗎?

也許一行一行?我試圖理解並從中學習。此程式碼是否基於現有的兌換腳本創建原始交易?或者它實際上是創建一個redeemScript,然後基於它進行交易?

我在安裝了比特幣核心和節點的 Windows 伺服器 2016 上

特別是這條線我不明白。

var scriptSig = bitcore.Script.fromASM('04678afd04678a ' + redeemScript.toHex())

什麼是04678afd04678a?:

他是整個程式碼,在 2 年前的一些 JS 範例中找到了它。這是關於創建不安全的 P2SH 交易。

> var bitcore = require('bitcore');                                              
undefined                                                                        
> var redeemScript = bitcore.Script.fromASM('OP_SHA256 894eeb82f9a851f5d1cb1be324
9f58bc8d259963832c5e7474a76f7a859ee95c OP_EQUAL');                               
undefined                                                                        
> var scriptPubKey = redeemScript.toScriptHashOut();                             
undefined                                                                        
> scriptPubKey                                                                   
<Script: OP_HASH160 20 0x028d07ac41994c915b76e00490289f5933454f90 OP_EQUAL>      
> scriptPubKey.toAddress()                                                       
<Address: 31vWDrvuRXaEaymhyuZqkbNBkPrVzw6DBc, type: scripthash, network: livenet>
> scriptPubKey.toHex()                                                           
'a914028d07ac41994c915b76e00490289f5933454f9087'                                 
> var utxo = new bitcore.Transaction.UnspentOutput({                             
...   "txId" : "a0a08e397203df68392ee95b3f08b0b3b3e2401410a38d46ae0874f74846f2e9"
, //fake, don't try!                                                             
...   "outputIndex" : 0,                                                         
...   "script" : "a914028d07ac41994c915b76e00490289f5933454f9087",               
...   "satoshis" : 60000,                                                        
...   "address" : "31vWDrvuRXaEaymhyuZqkbNBkPrVzw6DBc"                           
... });                                                          
> var address = '13mDYExLFx7stcYJN5uJRhzxwLuTEKNJbg';                            
undefined                                                                        
> var tx = new bitcore.Transaction().from(utxo).to(address, 50000);              
undefined                                                                        
> tx.inputs[0]                                                                   
{ output: <Output (60000 sats) <Script: OP_HASH160 20 0x028d07ac41994c915b76e0049
0289f5933454f90 OP_EQUAL>>,                                                      
 prevTxId: <Buffer a0 a0 8e 39 72 03 df 68 39 2e e9 5b 3f 08 b0 b3 b3 e2 40 14 1
0 a3 8d 46 ae 08 74 f7 48 46 f2 e9>,                                             
 outputIndex: 0,                                                                
 sequenceNumber: 4294967295,                                                    
 _script: <Script: >,
                  _scriptBuffer: <Buffer > }                                                     
> tx.outputs                                                                     
[ <Output (50000 sats) <Script: OP_DUP OP_HASH160 20 0x1e4d054693c02c60e3f77f87f5
ba79a281bf9141 OP_EQUALVERIFY OP_CHECKSIG>> ]                                    
> var scriptSig = bitcore.Script.fromASM('04678afd04678a ' + redeemScript.toHex()
)                                                                                
undefined                                                                        
> tx.inputs[0].setScript(scriptSig);                                             
{ output: <Output (60000 sats) <Script: OP_HASH160 20 0x028d07ac41994c915b76e0049
0289f5933454f90 OP_EQUAL>>,                                                      
 prevTxId: <Buffer a0 a0 8e 39 72 03 df 68 39 2e e9 5b 3f 08 b0 b3 b3 e2 40 14 1
0 a3 8d 46 ae 08 74 f7 48 46 f2 e9>,                                             
 outputIndex: 0,                                                                
 sequenceNumber: 4294967295,                                                    
 _script: <Script: 7 0x04678afd04678a 35 0xa820894eeb82f9a851f5d1cb1be3249f58bc8
d259963832c5e7474a76f7a859ee95c87>,
            _scriptBuffer: <Buffer 07 04 67 8a fd 04 67 8a 23 a8 20 89 4e eb 82 f9 a8 51 f5
d1 cb 1b e3 24 9f 58 bc 8d 25 99 63 83 2c 5e 74 74 a7 6f 7a 85 9e e9 5c 87> }   
> var rawTx = tx.toString('hex');                                                
undefined                                                                        
> rawTx                                                                          
'0100000001e9f24648f77408ae468da3101440e2b3b3b0083f5be92e3968df0372398ea0a0000000
002c0704678afd04678a23a820894eeb82f9a851f5d1cb1be3249f58bc8d259963832c5e7474a76f7
a859ee95c87ffffffff0150c30000000000001976a9141e4d054693c02c60e3f77f87f5ba79a281bf
914188ac00000000'                                                                
>                                                                             

我不是 JS 開發人員,但可以閱讀和理解程式碼。所以這是我在 tx 中看到的總結。我嘗試專注於重要的行,並將腳本與wiki 中的資訊進行比較:

> var redeemScript = bitcore.Script.fromASM('OP_SHA256 894eeb82f9a851f5d1cb1be324
9f58bc8d259963832c5e7474a76f7a859ee95c OP_EQUAL');

這看起來像是 P2SH tx 的準備工作。需要注意的是:它以 OP_SHA256 (0xA8) 開頭,而“普通”p2sh 腳本以 OP_HASH160 (0xA9) 開頭 - 請參閱下一節“scriptPubKey”。查看腳本執行的方式,SHA256 操作員會嘗試對堆棧上的前一項執行 sha256 操作……因為 sha256 不容易可逆,我們不知道什麼字元串被轉換為某個雜湊值,即然後可以評估為 TRUE,因此交易仍然有效……肯定是您要求解釋的字元串(04678afd04678a)。

> scriptPubKey 
<Script: OP_HASH160 20 0x028d07ac41994c915b76e00490289f5933454f90 OP_EQUAL>

這是一個標準腳本,它將堆棧上的前一項與 hash160 (0x028d07ac…) 進行比較。這通常在 P2SH 中使用,以將公鑰與其雜湊值進行比較。

> var tx = new bitcore.Transaction().from(utxo).to(address, 50000);

為交易準備一個資料結構,包含目標地址和金額

> tx.inputs[0]

添加輸入(使用腳本)

> tx.outputs

創建輸出

> var scriptSig = bitcore.Script.fromASM('04678afd04678a ' + redeemScript.toHex()

最有趣的線路!我在下面跟進它,但首先解碼 tx:

VERSION 01000000
TX_IN COUNT hex=01, decimal=1
 TX_IN[0] OutPoint hash A0A08E397203DF68392EE95B3F08B0B3B3E2401410A38D46AE0874F74846F2E9
 TX_IN[0] OutPoint index hex=00000000, reversed=00000000, decimal=0
 TX_IN[0] Script Length hex=2C, decimal=44
 TX_IN[0] Script Sig 0704678AFD04678A23A82...C8D259963832C5E7474A76F7A859EE95C87
 TX_IN[0] Sequence FFFFFFFF
TX_OUT COUNT, hex=01, decimal=1
 TX_OUT[0] Value hex=50C3000000000000, reversed_hex=C350, dec=50000 Satoshi
 TX_OUT[0] PK_Script Length hex=19, dec=25
 TX_OUT[0] pk_script 76A9141E4D054693C02C60E3F77F87F5BA79A281BF914188AC
LOCK_TIME 00000000

所以現在分析創建的腳本信號:

0704678AFD04678A23A820894EEB82F9A851F5D1CB1BE3249F58BC8D259963832C5E7474A76F7A859EE95C87

首先我們有“07”,它將“下一個操作碼字節”(十六進制 07)壓入堆棧。所以堆棧得到

04678AFD04678A

然後跟隨一個以 0x23 開頭的字元串。這意味著接下來的 35 個字節進入堆棧,所以腳本的其餘部分。堆棧看起來像這樣:

04678AFD04678A
OP_SHA256 20894EEB82F9A851F5D1CB1BE3249F58BC8D259963832C5E7474A76F7A859EE95C OP_EQUAL

所以字元串

04678afd04678a

散列到 32 個字節(十六進制 0x20):

894EEB82F9A851F5D1CB1BE3249F58BC8D259963832C5E7474A76F7A859EE95C

當它在堆棧上執行時,它是相等的,因此 tx 是有效的。我沒有 Windows 系統,但在 unixoide 系統上,可以在命令行或使用 openssl 進行驗證:

printf $( echo 04678AFD04678A | sed 's/[[:xdigit:]]\{2\}/\\x&/g' ) > tmp_hex_fn
hexdump -C tmp_hex_fn
openssl dgst -sha256 <tmp_hex_fn

注意:在主網上使用這樣的腳本可能會失去資金。礦工可以更改 tx,並將“他的”腳本放入 sigscript 部分,並將資金轉移到他自己的地址。僅在測試網上使用此類不安全的 tx。

引用自:https://bitcoin.stackexchange.com/questions/76370