<blockquote>
  <p>How can i tell if the block is official / not orphaned and that it will not be replaced by a 'better' block?</p>
</blockquote>

<p>As Nate notes, there's no guarantee that any block will be part of the best chain in the future. Here's what you should ask: Is this block part of the highest-work valid blockchain?</p>

<p>Here's how you determine that: you get the blocks, and connect them together. You sum up the work in each block in the blockchain. You check that they form a valid blockchain, and don't break any rules. You constantly look for more blocks, and try to assemble better, higher-work, valid blockchains.</p>

<blockquote>
  <p>I'm not knowledgeable enough to to tell for sure if the is_valid is doing more like (determining that the block is official)</p>
</blockquote>

<p>Here's a list of things that code doesn't check:</p>

<ul>
<li>Does a transaction spend more money than exists in an address?</li>
<li>Do transactions inputs actually exist?</li>
<li>Does this block connect to anything?</li>
</ul>

<p>In fact, you can provide it a difficulty-1 block that doesn't connect to anything, and it will tell you that the block is valid.</p>

CC BY-SA 3.0
2016-09-26T18:46:22.210Z
Does this block connect to anything? wouldn't you have to wait for the next block to do this?
Ben Muircroft
CC BY-SA 3.0
2016-09-26T19:33:29.643Z
@BenMuircroft To check if it has children, yes. To check if it has parents, no. I can look at all of the blocks I already have, and see if the new block's prevBlock matches any block's hash.
Nick ODell
CC BY-SA 3.0
2016-09-26T19:36:56.720Z
@BenMuircroft Also, note that orphan blocks typically have parents: http://bitcoin.stackexchange.com/questions/32110/is-there-a-correct-way-to-refer-to-orphan-blocks (Yes, that doesn't make any sense.)
Nick ODell
CC BY-SA 4.0
2021-02-11T18:30:18.560Z
Just a note on the terminology: "orphan" is used despite orphan blocks having parents. In the real world, orphans have (biological) parents; the distinction is that their parents have *abandoned them*. Thus, orphan blocks are blocks who have been cast aside by their parents, no longer being part of the canonical blockchain.
Jivan Pal
CC BY-SA 3.0
2016-09-25T02:00:05.523Z
2016-09-25T02:00:05.523Z
Nick ODell
<p>I have a giant hole in my understanding!</p>
<p>I recently started using <a href="https://github.com/sebicas/bitcoin-sniffer" rel="nofollow noreferrer">https://github.com/sebicas/bitcoin-sniffer</a></p>
<p>which is a Python script that lets you connect to any node on the Bitcoin Network and triggers events:</p>
<ul>
<li>new_block_event(block): Triggered when a Block is found</li>
<li>new_tx_event(tx): Triggered when a Transactions is found</li>
</ul>
<hr />
<p>On inspecting a new block I was quite surprised to find that the object does not include <code>block.height</code>!</p>
<p>Then I found this question: <a href="https://bitcoin.stackexchange.com/questions/24309/is-block-height-always-sequential">Is block height always sequential?</a></p>
<p>Quote:</p>
<blockquote>
<p>Block height is by definition sequential in the sense that adjacent blocks will always have heights that differ by 1. But there is a chicken-and-egg problem: in order to compute the height, you have to have access to all the blocks in between the genesis block and the current one. (The height is not recorded in the block itself.)</p>
<p>There's also the issue that multiple blocks can have the same height, if they are on different branches of the chain. So just because you have one block at every height, doesn't mean you have all the blocks on the main chain; some of them might be on orphan branches.</p>
</blockquote>
<hr />
<h2>So my Question is</h2>
<p>How can i tell if the block is official / not orphaned and that it will not be replaced by a 'better' block?</p>
<hr />
<p>I see that each block contains a previous block hash so my reasoning is that if a block was orphaned then the next blocks previous block hash would not be that blocks hash but another. But using that as a test to see If the last block became part of the network would put the check (time) back by one block... which is not realtime nor ideal</p>
<p>The bitcoin-sniffer does have one curious function for a block message called <strong>block.is_valid</strong> at the end of the CBlock class:</p>
<pre><code>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(&quot;&lt;i&quot;, f.read(4))[0]
        self.hashPrevBlock = deser_uint256(f)
        self.hashMerkleRoot = deser_uint256(f)
        self.nTime = struct.unpack(&quot;&lt;I&quot;, f.read(4))[0]
        self.nBits = struct.unpack(&quot;&lt;I&quot;, f.read(4))[0]
        self.nNonce = struct.unpack(&quot;&lt;I&quot;, f.read(4))[0]
        self.vtx = deser_vector(f, CTransaction)
    def serialize(self):
        r = &quot;&quot;
        r += struct.pack(&quot;&lt;i&quot;, self.nVersion)
        r += ser_uint256(self.hashPrevBlock)
        r += ser_uint256(self.hashMerkleRoot)
        r += struct.pack(&quot;&lt;I&quot;, self.nTime)
        r += struct.pack(&quot;&lt;I&quot;, self.nBits)
        r += struct.pack(&quot;&lt;I&quot;, self.nNonce)
        r += ser_vector(self.vtx)
        return r
    def calc_sha256(self):
        if self.sha256 is None:
            r = &quot;&quot;
            r += struct.pack(&quot;&lt;i&quot;, self.nVersion)
            r += ser_uint256(self.hashPrevBlock)
            r += ser_uint256(self.hashMerkleRoot)
            r += struct.pack(&quot;&lt;I&quot;, self.nTime)
            r += struct.pack(&quot;&lt;I&quot;, self.nBits)
            r += struct.pack(&quot;&lt;I&quot;, 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 &gt; 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) &gt; 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 &quot;CBlock(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x nTime=%s nBits=%08x nNonce=%08x vtx=%s)&quot; % (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot, time.ctime(self.nTime), self.nBits, self.nNonce, repr(self.vtx))
</code></pre>
<p>The function is <em>'way-over-my-head'</em> to be honest but it looks like it might be trying to determine weather the block can be trusted (as in; not tampered with as its querying the <code>hashMerkleRoot</code> which is a one way hash mechanism) but, I'm not knowledgeable enough to to tell for sure if the <code>is_valid</code> is doing more like (determining that the block is official)</p>
<p>The last thing I want to do is:</p>
<ol>
<li>push a tx to the network</li>
<li>listen to <code>new_tx_event(tx)</code> get my tx hash</li>
<li>listen to <code>new_block_event(block)</code> find my tx hash is accepted in the block</li>
<li>start to confirm payment counting new blocks as confirmations</li>
<li>find out later that the block got replaced/became orphaned</li>
</ol>
<p>Your thoughts?</p>

CC BY-SA 3.0
2016-09-24T21:15:31.480Z
This is an issue you cannot avoid.  It is always possible for a block to be replaced or orphaned at a later time.  However, after several confirmations, it is unlikely.
Nate Eldredge
<network><stale-block><block>
How can I trust a new block broadcated on the network?
Ben Muircroft
# How can I trust a new block broadcated on the network?

(Asked by: username_0 on 2016-09-24)

I have a giant hole in my understanding!

I recently started using <https://github.com/sebicas/bitcoin-sniffer>

which is a Python script that lets you connect to any node on the Bitcoin Network and triggers events:

* new\_block\_event(block): Triggered when a Block is found
* new\_tx\_event(tx): Triggered when a Transactions is found

---

On inspecting a new block I was quite surprised to find that the object does not include `block.height`!

Then I found this question: [Is block height always sequential?](https://bitcoin.stackexchange.com/questions/24309/is-block-height-always-sequential)

Quote:

> Block height is by definition sequential in the sense that adjacent blocks will always have heights that differ by 1. But there is a chicken-and-egg problem: in order to compute the height, you have to have access to all the blocks in between the genesis block and the current one. (The height is not recorded in the block itself.)
>
> There's also the issue that multiple blocks can have the same height, if they are on different branches of the chain. So just because you have one block at every height, doesn't mean you have all the blocks on the main chain; some of them might be on orphan branches.

---

## So my Question is

How can i tell if the block is official / not orphaned and that it will not be replaced by a 'better' block?

---

I see that each block contains a previous block hash so my reasoning is that if a block was orphaned then the next blocks previous block hash would not be that blocks hash but another. But using that as a test to see If the last block became part of the network would put the check (time) back by one block... which is not realtime nor ideal

The bitcoin-sniffer does have one curious function for a block message called **block.is\_valid** at the end 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.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))

```

The function is *'way-over-my-head'* to be honest but it looks like it might be trying to determine weather the block can be trusted (as in; not tampered with as its querying the `hashMerkleRoot` which is a one way hash mechanism) but, I'm not knowledgeable enough to to tell for sure if the `is_valid` is doing more like (determining that the block is official)

The last thing I want to do is:

1. push a tx to the network
2. listen to `new_tx_event(tx)` get my tx hash
3. listen to `new_block_event(block)` find my tx hash is accepted in the block
4. start to confirm payment counting new blocks as confirmations
5. find out later that the block got replaced/became orphaned

Your thoughts?

**Tags:** network, stale-block, block

> **Comments:**
> **username_1**: This is an issue you cannot avoid.  It is always possible for a block to be replaced or orphaned at a later time.  However, after several confirmations, it is unlikely.  

---

## 1 answers

### Answer by username_2 on 2016-09-25. Score: 3 | Accepted answer

> How can i tell if the block is official / not orphaned and that it will not be replaced by a 'better' block?

As username_1 notes, there's no guarantee that any block will be part of the best chain in the future. Here's what you should ask: Is this block part of the highest-work valid blockchain?

Here's how you determine that: you get the blocks, and connect them together. You sum up the work in each block in the blockchain. You check that they form a valid blockchain, and don't break any rules. You constantly look for more blocks, and try to assemble better, higher-work, valid blockchains.

> I'm not knowledgeable enough to to tell for sure if the is\_valid is doing more like (determining that the block is official)

Here's a list of things that code doesn't check:

* Does a transaction spend more money than exists in an address?
* Do transactions inputs actually exist?
* Does this block connect to anything?

In fact, you can provide it a difficulty-1 block that doesn't connect to anything, and it will tell you that the block is valid.

> **Comments:**
> **username_0**: Does this block connect to anything? wouldn't you have to wait for the next block to do this?  
> **username_2**: @username_0 To check if it has children, yes. To check if it has parents, no. I can look at all of the blocks I already have, and see if the new block's prevBlock matches any block's hash.  
> **username_2**: @username_0 Also, note that orphan blocks typically have parents: http://bitcoin.stackexchange.com/questions/32110/is-there-a-correct-way-to-refer-to-orphan-blocks (Yes, that doesn't make any sense.)  
> **username_3**: Just a note on the terminology: "orphan" is used despite orphan blocks having parents. In the real world, orphans have (biological) parents; the distinction is that their parents have *abandoned them*. Thus, orphan blocks are blocks who have been cast aside by their parents, no longer being part of the canonical blockchain.  

---

