開源 Bitcoin P2P電子貨幣系統背後的技術 (三)

轉載:http://www.showmuch.com/article/article_120.html

前面講了交易單,接下來講講交易單的類型和交易驗證的實現細節。

交易的類型與驗證

交易單(Transaction)目前被bitcoin分爲3種:

  1. 按IP地址轉賬(Transfer)
  2. 按接收地址轉賬(Transfer)
  3. 造幣(Generation)

通過前面對交易單的描述,我想大家應該已經知道,交易的驗證是通過不斷的追溯交易單來完成的。那麼交易驗證的細節是如何實現的,bitcoin的交易驗證的實現細節是很意思的,它是通過腳本來實現驗證的,這樣bitcoin就實現了一個可被腳本擴展的行爲,更加廣義的”交易”,這可以保證足夠的靈活性和可擴展,可以想象也許以後會有真正的分佈式計算任務跑在上面作爲一筆交易。因此要想講清楚驗證的細節,就不得不從腳本系統講起了。

腳本系統

Bitcoin的腳本系統是使用類FORTH語言(FORTH在嵌入式設備中是我最喜歡的一種語言)實現的,FORTH系統是面向棧的“高級機器”語言,它兼具了高級語言的特性(面向WORD)和機器語言的高性能與小尺寸,唯一的缺點就是可讀性不高,基本上可以把FORTH當一種高級的機器語言吧。Bitcoin在實現上做了許多簡化和特殊實現,所以只能算是類FORTH的系統。

FORTH系統中所有的命令(函數)都被稱爲單詞(WORD),所有數據的處理都要壓入數據棧上進行,所以FORTH被稱爲面向棧的語言。
比如 1和2相加,在FORTH系統中則是 1 2 +,數字 1,2 表示將它們壓入到數據棧中(在FORTH解釋器執行後實際指令會有OP_PUSH),+的操作則是將棧頂和次棧頂的數字取出並相加,並將結果壓回數據棧。

Bitcoin的腳本系統的所有的操作指令(單詞)見後面的附錄,不是所有的操作指令都能被執行支持,因爲安全上的考慮有的操作指令被禁止掉了,比如大多數的字符串操作和乘除運算。

在FORTH系統中一般會定義該系統是8位FORTH, 16位FORTH還是32/64位FORTH,這和數據棧的值長有關。在Bitcoin中的腳本系統使用的堆棧是用(vector<vector<unsigned char> >)來模擬的,它在數據棧的每一項都是以字符串的形式存放,它的數值是統一用CBigNum來運算的(讀到這裏應該明白爲啥bitcoin會限制乘除運算了),每一次從數據棧中壓入(CBigNum.getvch())或者取出數值(CastToBigNum(stacktop[-1]))都要進行一次轉換。看着這樣的實現,讓我有點發怵,本能的不喜歡,怎麼能把高效的FORTH搞成這個樣子。Bitcoin的腳本系統與FORTH一樣,有兩個堆棧,一個數據棧,在Bitcoin中被稱爲main stack,一個返回棧,在Bitcoin中被稱爲alt stack(事實上在Bitcoin中將alt stack作爲數據棧的中轉而還沒有作爲FORTH意義上的返回棧). Bitcoin的腳本系統沒有實現單詞定義,流程跳轉,循環控制(FOR, WHILE),對IF的實現非常醜陋。事實上我對Bitcoin的腳本實現不是十分認可,堆棧採用變長的數據值,直接將big number 作爲opcode,導致每一次opcode執行開銷無法控制,由於沒有完整實現FORTH的控制指令,導致用trick的方式來實現IF指令,在bitcoin中也因此無法定義新的WORD。總之我很不喜歡bitcoin的這個腳本引擎實現(參見script.cpp)。

下一篇將接着介紹下和交易驗證相關的幾個操作符:OP_DUP, OP_HASH160, OP_EQUALVERIFY , OP_CHECKSIG 的功能,現在有點倦了。

enum opcodetype
{
    // push value
    OP_0=0,
    OP_FALSE=OP_0,
    OP_PUSHDATA1=76,
    OP_PUSHDATA2,
    OP_PUSHDATA4,
    OP_1NEGATE,
    OP_RESERVED,
    OP_1,
    OP_TRUE=OP_1,
    OP_2,
    OP_3,
    OP_4,
    OP_5,
    OP_6,
    OP_7,
    OP_8,
    OP_9,
    OP_10,
    OP_11,
    OP_12,
    OP_13,
    OP_14,
    OP_15,
    OP_16,
 
    // control
    OP_NOP,
    OP_VER,
    OP_IF,
    OP_NOTIF,
    OP_VERIF,
    OP_VERNOTIF,
    OP_ELSE,
    OP_ENDIF,
    OP_VERIFY,
    OP_RETURN,
 
    // stack ops
    OP_TOALTSTACK,
    OP_FROMALTSTACK,
    OP_2DROP,
    OP_2DUP,
    OP_3DUP,
    OP_2OVER,
    OP_2ROT,
    OP_2SWAP,
    OP_IFDUP,
    OP_DEPTH,
    OP_DROP,
    OP_DUP,
    OP_NIP,
    OP_OVER,
    OP_PICK,
    OP_ROLL,
    OP_ROT,
    OP_SWAP,
    OP_TUCK,
 
    // splice ops
    OP_CAT,
    OP_SUBSTR,
    OP_LEFT,
    OP_RIGHT,
    OP_SIZE,
 
    // bit logic
    OP_INVERT,
    OP_AND,
    OP_OR,
    OP_XOR,
    OP_EQUAL,
    OP_EQUALVERIFY,
    OP_RESERVED1,
    OP_RESERVED2,
 
    // numeric
    OP_1ADD,
    OP_1SUB,
    OP_2MUL,
    OP_2DIV,
    OP_NEGATE,
    OP_ABS,
    OP_NOT,
    OP_0NOTEQUAL,
 
    OP_ADD,
    OP_SUB,
    OP_MUL,
    OP_DIV,
    OP_MOD,
    OP_LSHIFT,
    OP_RSHIFT,
 
    OP_BOOLAND,
    OP_BOOLOR,
    OP_NUMEQUAL,
    OP_NUMEQUALVERIFY,
    OP_NUMNOTEQUAL,
    OP_LESSTHAN,
    OP_GREATERTHAN,
    OP_LESSTHANOREQUAL,
    OP_GREATERTHANOREQUAL,
    OP_MIN,
    OP_MAX,
 
    OP_WITHIN,
 
    // crypto
    OP_RIPEMD160,
    OP_SHA1,
    OP_SHA256,
    OP_HASH160,
    OP_HASH256,
    OP_CODESEPARATOR,
    OP_CHECKSIG,
    OP_CHECKSIGVERIFY,
    OP_CHECKMULTISIG,
    OP_CHECKMULTISIGVERIFY,
 
    // expansion
    OP_NOP1,
    OP_NOP2,
    OP_NOP3,
    OP_NOP4,
    OP_NOP5,
    OP_NOP6,
    OP_NOP7,
    OP_NOP8,
    OP_NOP9,
    OP_NOP10,
 
    // template matching params
    OP_PUBKEYHASH = 0xfd,
    OP_PUBKEY = 0xfe,
 
    OP_INVALIDOPCODE = 0xff,
};
 

附錄Bitcoin腳本系統單詞列表

參見:https://en.bitcoin.it/wiki/Script

常量

常量就是用來把數據壓入棧中的單詞:

單詞 虛擬指令(opcode) 輸入 輸出 Description
OP_0, OP_FALSE 0 Nothing. 0 壓入數字0到棧中
N/A 1-75 (special) data 將緊隨 opcode 的data數據 opcode個字節壓入到堆棧。opcode兼作數據長度指示。
OP_PUSHDATA1 76 (special) data 緊隨該指令的下一個字節是被壓入數據大小,然後是被壓入數據
OP_PUSHDATA2 77 (special) data 緊隨該指令的兩個字節是被壓入數據大小,然後是被壓入數據.
OP_PUSHDATA4 78 (special) data 緊隨該指令的4個字節是被壓入數據大小,然後是被壓入數據.
OP_1NEGATE 79 無. -1 壓入-1
OP_1, OP_TRUE 81 無. 1 壓入1.
OP_2-OP_16 82-96 無. 2-16 2-16被壓入.

控制流

單詞 Opcode 輸入 輸出 描述
OP_NOP 97 空指令.
OP_IF 99 <expression> if [statements] [else [statements]] endif If 判斷指令,取出棧頂值,如果棧頂值爲1, 則if後面的語句被執行,否則else中的語句被執行。
OP_NOTIF 100 <expression> ifnot [statements] [else [statements]] endif Ifnot 判斷指令,取出棧頂值,如果棧頂值爲0, 則if後面的語句被執行,否則else中的語句被執行。
OP_ELSE 103 <expression> if [statements] [else [statements]] endif 放置在 OP_IF 或OP_NOTIF 後的指令,當前面的條件不滿足的時候執行
OP_ENDIF 104 <expression> if [statements] [else [statements]] endif 結束  if/else 執行塊.
OP_VERIFY 105 True / false Nothing / False 標記交易單無效
如果棧頂值不爲真。當棧頂值爲真,移除該棧頂值,否則保留該值。
OP_RETURN 106 Nothing Nothing 標記交易單無效.

堆棧操作

Word Opcode Input Output Description
OP_TOALTSTACK 107 x1 (alt)x1 從數據棧中彈出棧頂 數據,壓入輔助棧。
OP_FROMALTSTACK 108 (alt)x1 x1 從輔助棧彈出棧頂數據壓入到數據棧
OP_IFDUP 115 x x / x x 如果棧頂非0則複製棧頂
OP_DEPTH 116 Nothing <Stack size> 獲取堆棧數據個數
OP_DROP 117 x Nothing 丟棄棧頂數據.
OP_DUP 118 x x x 複製棧頂數據.
OP_NIP 119 x1 x2 x2 丟棄次棧頂數據
OP_OVER 120 x1 x2 x1 x2 x1 複製次棧頂數據到棧頂.
OP_PICK 121 xn … x2 x1 x0 <n> xn … x2 x1 x0 xn 複製第n項數據到棧頂.
OP_ROLL 122 xn … x2 x1 x0 <n> … x2 x1 x0 xn 將第n項數據移到棧頂.
OP_ROT 123 x1 x2 x3 x2 x3 x1 棧頂3項數據向左旋轉.
OP_SWAP 124 x1 x2 x2 x1 棧頂2項數據交換.
OP_TUCK 125 x1 x2 x2 x1 x2 棧頂數據複製並插入到次棧頂數據前
OP_2DROP 109 x1 x2 Nothing 同 DROP,只是數據項是2項.
OP_2DUP 110 x1 x2 x1 x2 x1 x2 同 DUP,只是數據項是2項.
OP_3DUP 111 x1 x2 x3 x1 x2 x3 x1 x2 x3 同 DUP,只是數據項是3項.
OP_2OVER 112 x1 x2 x3 x4 x1 x2 x3 x4 x1 x2 同 OVER,只是數據項是2項.
OP_2ROT 113 x1 x2 x3 x4 x5 x6 x3 x4 x5 x6 x1 x2 同 ROT,只是數據項是2項.
OP_2SWAP 114 x1 x2 x3 x4 x3 x4 x1 x2 同 SWAP,只是數據項是2項.

字符串處理

字符串處理的大多數指令都被禁止了。

Word Opcode Input Output Description
OP_CAT 126 x1 x2 out Concatenates two strings. [禁止]
OP_SUBSTR 127 in begin size out Returns a section of a string. [禁止]
OP_LEFT 128 in size out Keeps only characters left of the specified point in a string. [禁止]
OP_RIGHT 129 in size out Keeps only characters right of the specified point in a string. [禁止]
OP_SIZE 130 in in size 返回字符串長度

位運算

Word Opcode Input Output Description
OP_INVERT 131 in out Flips all of the bits in the input. [禁止]
OP_AND 132 x1 x2 out Boolean and between each bit in the inputs. [禁止]
OP_OR 133 x1 x2 out Boolean or between each bit in the inputs. [禁止]
OP_XOR 134 x1 x2 out Boolean exclusive or between each bit in the inputs. [禁止]
OP_EQUAL 135 x1 x2 True / false Returns 1 if the inputs are exactly equal, 0 otherwise.
OP_EQUALVERIFY 136 x1 x2 True / false Same as OP_EQUAL, but runs OP_VERIFY afterward.

數學運算

Word Opcode Input Output Description
OP_1ADD 139 in out 1 is added to the input.
OP_1SUB 140 in out 1 is subtracted from the input.
OP_2MUL 141 in out The input is multiplied by 2. [禁止]
OP_2DIV 142 in out The input is divided by 2. [禁止]
OP_NEGATE 143 in out The sign of the input is flipped.
OP_ABS 144 in out The input is made positive.
OP_NOT 145 in out If the input is 0 or 1, it is flipped. Otherwise the output will be 0.
OP_0NOTEQUAL 146 in out Returns 1 if the input is 0. 0 otherwise.
OP_ADD 147 a b out a is added to b.
OP_SUB 148 a b out b is subtracted from a.
OP_MUL 149 a b out a is multiplied by b. [禁止]
OP_DIV 150 a b out a is divided by b. [禁止]
OP_MOD 151 a b out Returns the remainder after dividing a by b. [禁止]
OP_LSHIFT 152 a b out Shifts a left b bits, preserving sign. [禁止]
OP_RSHIFT 153 a b out Shifts a right b bits, preserving sign. [禁止]
OP_BOOLAND 154 a b out If both a and b are not 0, the output is 1. Otherwise 0.
OP_BOOLOR 155 a b out If a or b is not 0, the output is 1. Otherwise 0.
OP_NUMEQUAL 156 a b out Returns 1 if the numbers are equal, 0 otherwise.
OP_NUMEQUALVERIFY 157 a b out Same as OP_NUMEQUAL, but runs OP_VERIFY afterward.
OP_NUMNOTEQUAL 158 a b out Returns 1 if the numbers are not equal, 0 otherwise.
OP_LESSTHAN 159 a b out Returns 1 if a is less than b, 0 otherwise.
OP_GREATERTHAN 160 a b out Returns 1 if a is greater than b, 0 otherwise.
OP_LESSTHANOREQUAL 161 a b out Returns 1 if a is less than or equal to b, 0 otherwise.
OP_GREATERTHANOREQUAL 162 a b out Returns 1 if a is greater than or equal to b, 0 otherwise.
OP_MIN 163 a b out Returns the smaller of a and b.
OP_MAX 164 a b out Returns the larger of a and b.
OP_WITHIN 165 x min max out Returns 1 if x is within the specified range (left-inclusive), 0 otherwise.

加密相關

Word Opcode Input Output Description
OP_RIPEMD160 166 in hash The input is hashed using RIPEMD-160.
OP_SHA1 167 in hash The input is hashed using SHA-1.
OP_SHA256 168 in hash The input is hashed using SHA-256.
OP_HASH160 169 in hash The input is hashed twice: first with SHA-256 and then with RIPEMD-160.
OP_HASH256 170 in hash The input is hashed two times with SHA-256.
OP_CODESEPARATOR 171 Nothing Nothing All of the signature checking words will only match signatures to the data after the most recently-executed OP_CODESEPARATOR.
OP_CHECKSIG 172 sig pubkey True / false The entire transaction’s outputs, inputs, and script (from the most recently-executed OP_CODESEPARATOR to the end) are hashed. The signature used by OP_CHECKSIG must be a valid signature for this hash and public key. If it is, 1 is returned, 0 otherwise.
OP_CHECKSIGVERIFY 173 sig pubkey True / false Same as OP_CHECKSIG, but OP_VERIFY is executed afterward.
OP_CHECKMULTISIG 174 sig1 sig2 … <number of signatures> pub1 pub2 <number of public keys> True / False For each signature and public key pair, OP_CHECKSIG is executed. If more public keys than signatures are listed, some key/sig pairs can fail. All signatures need to match a public key. If all signatures are valid, 1 is returned, 0 otherwise.
OP_CHECKMULTISIGVERIFY 175 sig1 sig2 … <number of signatures> pub1 pub2 … <number of public keys> True / False Same as OP_CHECKMULTISIG, but OP_VERIFY is executed afterward.

僞詞(Pseudo-words)

下列詞彙用於在內部使用,在腳本系統中實際上不存在的詞。

Word Opcode Description
OP_PUBKEYHASH 253 表示OP_HASH160 後的公開密鑰散列
OP_PUBKEY 254 表示一個公開密鑰(可以被 OP_CHECKSIG).
OP_INVALIDOPCODE 255  

保留詞(Reserved words)

沒有被定義的opcode被保留以後使用,如果在腳本中使用這些保留詞,要麼被忽略,要麼使得交易無效。

Word Opcode When used…
OP_RESERVED 80 Transaction is invalid
OP_VER 98 Transaction is invalid
OP_VERIF 101 Transaction is invalid
OP_VERNOTIF 102 Transaction is invalid
OP_RESERVED1 137 Transaction is invalid
OP_RESERVED2 138 Transaction is invalid
OP_NOP1-OP_NOP10 176-185 The word is ignored.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章