public inbox for bitcoindev@googlegroups.com
 help / color / mirror / Atom feed
From: Peter Todd <pete@petertodd•org>
To: Peter Grigor <peter@grigor•ws>
Cc: bitcoin-development@lists•sourceforge.net
Subject: Re: [Bitcoin-development] From block 0 to block 72499 the Merkle root is the same as the coinbase transaction id. Why is that?
Date: Sat, 20 Sep 2014 12:24:16 -0400	[thread overview]
Message-ID: <20140920162416.GA28251@muck> (raw)
In-Reply-To: <CAGpx8BUav93VTHyaBcuqk+FmsNBrq_ue8L4exfZ1iq8Om_WGiA@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2291 bytes --]

On Sat, Sep 20, 2014 at 08:38:15AM -0700, Peter Grigor wrote:
> From block 0 to block 72499 the Merkle root is the same as the
> coinbase transaction id. Why is that?

It's because of how the merkle tree algorithm works:

    uint256 CBlock::BuildMerkleTree() const
    {
        vMerkleTree.clear();

So here all the txids are pushed onto the vMerkleTree vector:

        BOOST_FOREACH(const CTransaction& tx, vtx)
            vMerkleTree.push_back(tx.GetHash());

For most of the early blocks there's just the coinbase transaction and
no other transactions.

        int j = 0;
        for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)

That means this for loop never executes! nSize = vtx.size() == 1, and
the loop terminates when nSize <= 1

        {
            for (int i = 0; i < nSize; i += 2)
            {
                int i2 = std::min(i+1, nSize-1);
                vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]),  END(vMerkleTree[j+i]),
                                           BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
            }
            j += nSize;
        }
        return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
    }

Thus the vMerkleTree still has only the coinbase txid in it, and and
vMerkleTree.back() returns that txid as the merkle root. There's no
problem with the merkle root algorithm working that way - to make a long
story short all this means is that the merkle tree algorithm
consistently uses the txid as the merkle root whenever there is only one
transaction. The contents of the block is still being securely committed
to by the merkleroot, which is the important thing, and there's no way
to lie about those contents.

There is however a serious flaw in the algorithm, unrelated to the case
of a single transaction, where the merkle tree is indistinguishable from
a merkle tree with duplicate txids if there are a non-power-of-two
number of items in the tree. For bitcoin we fixed this flaw with BIP30
and BIP34; for any other application you should *never* use the Satoshi
merkle root calculation code. Get it right on day one and do things
correctly.

-- 
'peter'[:-1]@petertodd.org
00000000000000000fbf83c9e14d8711e4b2264ceda0d1d06d169c811387eadd

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 650 bytes --]

      parent reply	other threads:[~2014-09-20 16:24 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-20 15:38 Peter Grigor
2014-09-20 16:22 ` Christophe Biocca
2014-09-20 16:24 ` Peter Todd [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140920162416.GA28251@muck \
    --to=pete@petertodd$(echo .)org \
    --cc=bitcoin-development@lists$(echo .)sourceforge.net \
    --cc=peter@grigor$(echo .)ws \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox