為什麼比特幣礦工不能修改交易輸出?
我通過閱讀比特幣開發者參考文件來學習比特幣協議。
據我所知,原始交易包括:
版本(始終為 1)
輸入。每個輸入包含:
- 包含我們將在此處花費的輸出的交易雜湊
- 該事務中的輸出索引
- 滿足引用輸出腳本中的條件的腳本。
輸出。每個輸出包含:
- satoshis 中的值的 8 個字節
- 具有必須滿足才能使用此輸出的條件的腳本。
鎖定時間(通常為 0)
我不太確定輸入的腳本包含什麼,但我猜它應該包含公鑰和簽名消息。
我的問題是,如果這些腳本不是真實使用者必須簽名的消息的一部分,為什麼礦工不能修改輸出中的腳本(用他們自己的地址替換)?
或者也許這個問題最好這樣問:輸入腳本中的簽名是什麼?
輸入腳本中的簽名是什麼?
要看。
在 P2PKH 支出交易的情況下,
scriptSig
每個輸入的(輸入腳本)將包含一個 ECDSA 簽名和一個字節,該字節捐贈了被稱為SIGHASH
標誌的確切簽名內容。在幾乎所有情況下都是SIGHASH_ALL
,這意味著簽名涵蓋了整個交易輸出和輸入,而不是其他簽名。如果交易輸出腳本被修改並且任何輸入已經用SIGHASH_ALL
簽名,則該簽名將無效並且交易不能包含在塊中。其他標誌可能會產生您描述的效果,如果我進行的交易僅對單個輸入進行
SIGHASH_NONE
簽名(此簽名僅涵蓋輸入),那麼網路中的任何人都可以在輸出被掩埋之前隨意修改輸出在一個街區。正是因為這個原因,沒有人像那樣使用它。今天還有另外兩個可用的標誌
SIGHASH_SINGLE
和SIGHASH_ANYONECANPAY
. 前者允許您僅簽署其中一個輸出而忽略其餘的(例如 vin:1 僅簽署 vout:1),但這是有問題的,而且一點也不直覺。後者允許您在輸入為萬用字元的情況下進行交易,將此輸出用於此腳本,並使用您想要的任何其他輸入來彌補赤字。一般來說,沒有人使用
SIGHASH
標誌,所有交易中的大多數都是嚴格的SIGHASH_ALL
。我不太確定輸入的腳本包含什麼,但我猜它應該包含公鑰和簽名消息。
這完全取決於所使用的輸出類型,但我們假設這是一個非常典型的 Pay to Pubkey Hash(地址)交易。在這種情況下,
scriptSig
非常簡單。304402204bc6ed9b0122fc145031d4d9f6a30fbb28b63d152e3848c785a65f1e0b97ea8d02205a99bc13ba9293526ed175947cb756c5e3fca0a98890b88551e3e6c4c0bb6f5601 04988b34239b2f1c2441db4d50911b0550350414ce00b88f8dd39964f1a8631824db8e78b61d0ea6f3d9fcffcf2cd20be7d88a1583854682db4d136acd08542c3d
我們有兩個數據項,第一個是DER格式的 ECDSA 簽名,以及我們花費的 P2PKH 輸出的公共點數。簽名的最後一個字節是
SIGHASH
標誌,在這種情況下是0x01
orSIGHASH_ALL
。如果你想了解這些結構是如何工作的,webbtc.com 有一個很棒的腳本視覺化工具,可以讓你看到這些結構是如何結合在一起的。特別是這裡是一個合理的範例交易,只有一個輸入和輸出,這裡是一個腳本執行的遊戲,它很好地解釋了它如何以及為什麼是有效的。