我如何才能信任在網路上傳播的新區塊?
我的理解有一個巨大的洞!
我最近開始使用<https://github.com/sebicas/bitcoin-sniffer>
這是一個 Python 腳本,可讓您連接到比特幣網路上的任何節點並觸發事件:
- new_block_event(block): 找到塊時觸發
- new_tx_event(tx): 找到交易時觸發
在檢查一個新塊時,我很驚訝地發現該對像不包括
block.height
!然後我發現了這個問題:塊高度是否總是連續的?
引用:
塊高度按照定義是連續的,因為相鄰塊的高度總是相差 1。但是有一個先有雞還是先有蛋的問題:為了計算高度,您必須訪問其間的所有塊創世區塊和目前區塊。(高度不記錄在塊本身中。)
還有一個問題是多個塊可以具有相同的高度,如果它們位於鏈的不同分支上。所以僅僅因為你在每個高度都有一個區塊,並不意味著你擁有主鏈上的所有區塊;其中一些可能在孤兒分支上。
所以我的問題是
我如何判斷該塊是否是官方的/不是孤立的,並且它不會被“更好”的塊取代?
我看到每個塊都包含一個前一個塊散列,所以我的推理是,如果一個塊是孤立的,那麼下一個塊的前一個塊散列將不是那個塊散列而是另一個塊散列。但是使用它作為測試來查看最後一個塊是否成為網路的一部分會將檢查(時間)推遲一個塊……這不是實時的,也不是理想的
比特幣嗅探器確實有一個奇怪的功能,用於在 CBlock 類的末尾呼叫block.is_valid塊消息:
class CBlock(object): def __init__(self): self.nVersion = 1 self.hashPrevBlock = 0 self.hashMerkleRoot = 0 self.nTime = 0 self.nBits = 0 self.nNonce = 0 self.vtx = [] self.sha256 = None self.hash = None def deserialize(self, f): self.nVersion = struct.unpack("<i", f.read(4))[0] self.hashPrevBlock = deser_uint256(f) self.hashMerkleRoot = deser_uint256(f) self.nTime = struct.unpack("<I", f.read(4))[0] self.nBits = struct.unpack("<I", f.read(4))[0] self.nNonce = struct.unpack("<I", f.read(4))[0] self.vtx = deser_vector(f, CTransaction) def serialize(self): r = "" r += struct.pack("<i", self.nVersion) r += ser_uint256(self.hashPrevBlock) r += ser_uint256(self.hashMerkleRoot) r += struct.pack("<I", self.nTime) r += struct.pack("<I", self.nBits) r += struct.pack("<I", self.nNonce) r += ser_vector(self.vtx) return r def calc_sha256(self): if self.sha256 is None: r = "" r += struct.pack("<i", self.nVersion) r += ser_uint256(self.hashPrevBlock) r += ser_uint256(self.hashMerkleRoot) r += struct.pack("<I", self.nTime) r += struct.pack("<I", self.nBits) r += struct.pack("<I", self.nNonce) self.sha256 = uint256_from_str(hash256(r)) self.hash = hash256(r)[::-1].encode('hex_codec') def is_valid(self): self.calc_sha256() target = uint256_from_compact(self.nBits) if self.sha256 > target: return False hashes = [] for tx in self.vtx: if not tx.is_valid(): return False tx.calc_sha256() hashes.append(ser_uint256(tx.sha256)) while len(hashes) > 1: newhashes = [] for i in xrange(0, len(hashes), 2): i2 = min(i+1, len(hashes)-1) newhashes.append(hash256(hashes[i] + hashes[i2])) hashes = newhashes if uint256_from_str(hashes[0]) != self.hashMerkleRoot: return False return True def __repr__(self): return "CBlock(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x nTime=%s nBits=%08x nNonce=%08x vtx=%s)" % (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot, time.ctime(self.nTime), self.nBits, self.nNonce, repr(self.vtx))
老實說,該功能*“超出我的想像”*,但看起來它可能正在嘗試確定可以信任該塊的天氣(如;在查詢時不會被篡改,
hashMerkleRoot
這是一種單向雜湊機制)但是,我沒有足夠的知識來確定它是否is_valid
更像(確定該塊是官方的)我想做的最後一件事是:
- 將 tx 推送到網路
- 聽
new_tx_event(tx)
得到我的 tx 雜湊- 聽,
new_block_event(block)
發現我的 tx 雜湊在塊中被接受- 開始確認付款,將新塊計算為確認
- 稍後發現該塊被替換/成為孤兒
你的意見?
我如何判斷該塊是否是官方的/不是孤立的,並且它不會被“更好”的塊取代?
正如 Nate 所說,不能保證任何區塊都將成為未來最佳鏈的一部分。這就是你應該問的問題:這個區塊是最高工作有效區塊鏈的一部分嗎?
以下是您確定的方法:您獲取塊,並將它們連接在一起。你總結了區塊鏈中每個區塊的工作。您檢查它們是否形成了有效的區塊鏈,並且不違反任何規則。你不斷地尋找更多的區塊,並嘗試組裝更好、工作量更高、有效的區塊鏈。
我沒有足夠的知識來確定 is_valid 是否更像(確定該塊是官方的)
以下是程式碼不檢查的內容列表:
- 交易花費的錢是否比地址中存在的錢多?
- 交易輸入是否真的存在?
- 這個塊是否連接到任何東西?
事實上,你可以為它提供一個不連接任何東西的難度為 1 的塊,它會告訴你該塊是有效的。