交易驗證

要驗證交易需要 serialize 函式,

serialize 指的是要把一串資訊變成電腦可以傳送和讀的格式

TxInserialize : (參考上面的 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

TxOutserialize : (參考上面的 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

Txserialize :(參考上面的 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

驗證的重點是

  1. 輸入是正確的 UTXO
  2. 輸入的比特幣數量大於等於要花出去的
  3. 簽名是正確的 (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 是對除了自己以外的交易進行簽名產生的

results matching ""

    No results matching ""