交易驗證
要驗證交易需要 serialize 函式,
serialize 指的是要把一串資訊變成電腦可以傳送和讀的格式
TxIn
的 serialize
: (參考上面的 raw 格式)
def serialize(self):
# reverse order
result = self.prev_tx[::-1]
result += int_to_little_endian(self.prev_index, 4)
raw_script_sig = self.script_sig.serialize()
result += encode_varint(len(raw_script_sig))
result += raw_script_sig
result += int_to_little_endian(self.sequence, 4)
return result
TxOut
的 serialize
: (參考上面的 raw 格式)
def serialize(self):
result = int_to_little_endian(self.amount)
raw_script_pubkey = self.script_pubkey.serialize()
result += encode_varint(len(raw_script_pubkey))
result += raw_script_pubkey
return result
Tx
的 serialize
:(參考上面的 raw 格式)
def serialize(self):
result = int_to_little_endian(self.version, 4)
result += encode_varint(len(self.tx_ins))
for tx_in in self.tx_ins:
result += tx_in.serialize()
result += encode_varint(len(self.tx_outs))
for tx_out in self.tx_outs:
result += tx_out.serialize()
result += int_to_little_endian(self.locktime, 4)
return result
驗證的重點是
- 輸入是正確的 UTXO
- 輸入的比特幣數量大於等於要花出去的
- 簽名是正確的 (scriptSig 可以解鎖 scriptPubkey)
在談輸入是正確之前,首先要知道比特幣的交易都是以「UTXO」方式儲存在整個系統裡,
我們談的輸入,就是從「UTXO」池裡挑出交易,所以在說輸入是正確的這件事,
是在說你要使用的UTXO是存在的,以及被全網認可
步驟一是要確認所有的交易不能被「雙花」,這是比特幣之前的電子貨幣都做不到的事
因此要確認 UTXO 存在,要透過自己的全節點,或是透過別人的節點來檢查
我們用別人的節點:
@classmethod
def get_url(cls, testnet=False):
if testnet:
return 'https://testnet.blockexplorer.com/api'
else:
return 'https://blockexplorer.com/api'
再用 python 的 requests 來獲得 rawtx,然後放到 cache
裡
def fetch_tx(self, testnet=False):
if self.prev_tx not in self.cache:
url = self.get_url(testnet) + '/rawtx/{}'.format(self.prev_tx.hex())
response = requests.get(url)
try:
js_response = response.json()
if 'rawtx' not in js_response:
raise RuntimeError('got from server: {}'.format(js_response))
except:
raise RuntimeError('got from server: {}'.format(response.text))
raw = bytes.fromhex(js_response['rawtx'])
stream = BytesIO(raw)
tx = Tx.parse(stream)
self.cache[self.prev_tx] = tx
return self.cache[self.prev_tx]
步驟二可以參考交易裡的手續費部分
要驗證輸入的話,複習一下輸入包含什麼,
輸入有
- prev_tx
- prev_index
- scriptSig
- sequence
我們要確定 scriptSig 裡面的 signature 是正確的,
這個 signature 是對除了自己以外的交易進行簽名產生的