I’ve an enormous gap in my understanding!
I just lately began utilizing https://github.com/sebicas/bitcoin-sniffer
which is a Python script that allows you to hook up with any node on the Bitcoin Community and triggers occasions:
- new_block_event(block): Triggered when a Block is discovered
- new_tx_event(tx): Triggered when a Transactions is discovered
On inspecting a brand new block I used to be fairly stunned to search out that the article doesn’t embrace block.peak
!
Then I discovered this query: Is block peak all the time sequential?
Quote:
Block peak is by definition sequential within the sense that adjoining blocks will all the time have heights that differ by 1. However there’s a chicken-and-egg downside: so as to compute the peak, it’s important to have entry to all of the blocks in between the genesis block and the present one. (The peak just isn’t recorded within the block itself.)
There’s additionally the problem that a number of blocks can have the identical peak, if they’re on completely different branches of the chain. So simply because you’ve gotten one block at each peak, doesn’t suggest you’ve gotten all of the blocks on the principle chain; a few of them is likely to be on orphan branches.
So my Query is
How am i able to inform if the block is official / not orphaned and that it’ll not get replaced by a ‘higher’ block?
I see that every block incorporates a earlier block hash so my reasoning is that if a block was orphaned then the following blocks earlier block hash wouldn’t be that blocks hash however one other. However utilizing that as a take a look at to see If the final block turned a part of the community would put the test (time) again by one block… which isn’t realtime nor ideally suited
The bitcoin-sniffer does have one curious perform for a block message referred to as block.is_valid on the finish of the CBlock class:
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.learn(4))[0]
self.hashPrevBlock = deser_uint256(f)
self.hashMerkleRoot = deser_uint256(f)
self.nTime = struct.unpack("<I", f.learn(4))[0]
self.nBits = struct.unpack("<I", f.learn(4))[0]
self.nNonce = struct.unpack("<I", f.learn(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()
goal = uint256_from_compact(self.nBits)
if self.sha256 > goal:
return False
hashes = []
for tx in self.vtx:
if not tx.is_valid():
return False
tx.calc_sha256()
hashes.append(ser_uint256(tx.sha256))
whereas 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))
The perform is ‘way-over-my-head’ to be trustworthy but it surely appears prefer it is likely to be attempting to find out climate the block might be trusted (as in; not tampered with as its querying the hashMerkleRoot
which is a a method hash mechanism) however, I am not educated sufficient to to inform for certain if the is_valid
is doing extra like (figuring out that the block is official)
The very last thing I wish to do is:
- push a tx to the community
- hearken to
new_tx_event(tx)
get my tx hash - hearken to
new_block_event(block)
discover my tx hash is accepted within the block - begin to affirm fee counting new blocks as confirmations
- discover out later that the block received changed/turned orphaned
Your ideas?