Skip to content

[0.17] blockheaders include block height, nodes validate it - #431

Merged
instagibbs merged 2 commits into
ElementsProject:elements-0.17from
instagibbs:height_in_header
Nov 27, 2018
Merged

[0.17] blockheaders include block height, nodes validate it#431
instagibbs merged 2 commits into
ElementsProject:elements-0.17from
instagibbs:height_in_header

Conversation

@instagibbs

@instagibbs instagibbs commented Oct 12, 2018

Copy link
Copy Markdown
Contributor

The feature is enabled by default in custom chains; cannot be activated in legacy chains.

@jtimon jtimon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, could use a rebase and move the -con_blockheightinheader to chainparams.

Comment thread src/chain.h
Comment thread src/chainparams.cpp
Comment thread src/primitives/block.h Outdated
READWRITE(hashPrevBlock);
READWRITE(hashMerkleRoot);
READWRITE(nTime);
if (gArgs.GetBoolArg("-con_blockheightinheader", true)) {

ghost Oct 16, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need g_block_height_in_header here too

@instagibbs

ghost commented Oct 16, 2018

Copy link
Copy Markdown
Contributor Author

forgot to push my fixes that I believe fixed things. Will switch to chainparams setup next.

@instagibbs

ghost commented Oct 18, 2018

Copy link
Copy Markdown
Contributor Author

Feature complete now, just no tests.

@instagibbs
instagibbs force-pushed the height_in_header branch 2 times, most recently from 04c8fe5 to 97b714f Compare October 18, 2018 20:59
Comment thread src/chainparams.cpp Outdated
genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"));
consensus.blockheight_in_header = gArgs.GetBoolArg("-con_blockheightinheader", false);

ghost Oct 19, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, just don't use -con_blockheightinheader at all outside of CCustomParams and you shouldn't need to touch neither CMainParams, CTestNetParams or CRegTestParams, specially not their asserts.
Perhaps it would be interesting to rebase on top of #436 and add a test like this:

{
    'memo': 'default_style with height in header',
    'genesis': 'c03f16ae9e2980de2b61fd6dc84af8ac4a37bea928af632166a6b36c5c871ddd',
    'args': [
            '-con_genesis_style=default_style',
            '-con_blockheightinheader',
    ],
},

ghost Oct 22, 2018

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It creates a new style genesis block for each network when iterating through network types during load, then hits the assert.

ghost Oct 22, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That means blockheight_in_header is not really acting as false for main, test and regtest, no?

ghost Oct 22, 2018

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, if you don't set -con_blockheightinheader to true

@instagibbs

ghost commented Oct 22, 2018

Copy link
Copy Markdown
Contributor Author

I'm getting build failures for windows and other builds due to gArgs in block.h.

@instagibbs

ghost commented Oct 22, 2018

Copy link
Copy Markdown
Contributor Author

tricked PR to refresh by closing/opening

@instagibbs instagibbs changed the title [WIP, 0.17] blockheaders include block height, nodes validate it [WIP] blockheaders include block height, nodes validate it Oct 25, 2018
@instagibbs instagibbs changed the title [WIP] blockheaders include block height, nodes validate it [0.17] blockheaders include block height, nodes validate it Oct 25, 2018
@instagibbs

ghost commented Oct 25, 2018

Copy link
Copy Markdown
Contributor Author

Took essential fixes from #442 and squashed.

@instagibbs

ghost commented Oct 26, 2018

Copy link
Copy Markdown
Contributor Author

Rebased, fixed some tests.

@instagibbs
instagibbs force-pushed the height_in_header branch 4 times, most recently from e4a3331 to 977ea1a Compare October 29, 2018 19:29
@instagibbs

ghost commented Oct 29, 2018

Copy link
Copy Markdown
Contributor Author

Finally resolves all issues and tests. Ready for review.

@mword

ghost commented Oct 31, 2018

Copy link
Copy Markdown

Note that for me many tests fail with test/functional/test_runner.py --extended . The extended functional tests pass on the elements-0.17 branch.

@instagibbs

ghost commented Oct 31, 2018

Copy link
Copy Markdown
Contributor Author

@mword ah good catch. Will take a look.

@instagibbs

ghost commented Nov 1, 2018

Copy link
Copy Markdown
Contributor Author

Looks like upstream moved all but two tests into the normal testing regime. We should probably mirror that if possible.

@instagibbs

ghost commented Nov 5, 2018

Copy link
Copy Markdown
Contributor Author

rebased onto tip to catch most extended failures

@instagibbs

ghost commented Nov 5, 2018

Copy link
Copy Markdown
Contributor Author

All builds passing, squashed.

@mword

ghost commented Nov 6, 2018

Copy link
Copy Markdown

tACK with one caveat: I ran test_runner.py twice once with --extended and then once without, the second run (without --extended) the rpc_rawtransaction.py test failed. I could not reproduce the failure. I ran test_runner.py again several with no problems and I ran the rpc_rawtransaction.py test by itself a number of times with no failures.

@stevenroose

ghost commented Nov 6, 2018

Copy link
Copy Markdown
Contributor

tACK a8c6fcd

@instagibbs

ghost commented Nov 13, 2018

Copy link
Copy Markdown
Contributor Author

will cherry-pick Blockstream/liquid#3 when merged

@stevenroose

ghost commented Nov 15, 2018

Copy link
Copy Markdown
Contributor

ACK when you merge liquid#3 :)

@instagibbs

ghost commented Nov 15, 2018

Copy link
Copy Markdown
Contributor Author

@stevenroose oh it appears I already mirror this logic in liquid#3, great minds yada yada

@instagibbs

ghost commented Nov 19, 2018 via email

Copy link
Copy Markdown
Contributor Author

Comment thread src/chain.h
READWRITE(hashPrev);
READWRITE(hashMerkleRoot);
READWRITE(nTime);
READWRITE(block_height);

ghost Nov 19, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why this doesn't need to be conditional. Bitcoin block indexes sure won't have height here...

ghost Nov 22, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure myself, but Greg discussed it with Jorge here: #431 (comment)

Comment thread src/chainparams.cpp
// No subsidy for custom chains by default
consensus.genesis_subsidy = args.GetArg("-con_blocksubsidy", 0);

// Note: This global is needed to avoid circular dependency

ghost Nov 19, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

ghost Nov 22, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with chainparams (ie if the global was a field in chainparams), because chainparams depends on block.

Comment thread src/miner.cpp
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
if (g_con_blockheightinheader) {
pblock->block_height = nHeight;

ghost Nov 19, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assignment probably doesn't need to be conditional.

WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed"

def create_block(hashprev, coinbase, ntime=None):
def create_block(hashprev, coinbase, block_height, ntime=None):

ghost Nov 19, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modifying the function signature like this is begging for silent bugs.

Instead, add block_height to the end, and always specify it by name (enforce with PEP 3102; ie, (hashprev, coinbase, ntime=None, *, block_height)).

ghost Nov 22, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah that's what the random asterixes are for! :) Thanks

ghost Nov 22, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option is to make ntime non optional.

WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed"

def create_block(hashprev, coinbase, ntime=None):
def create_block(hashprev, coinbase, block_height, ntime=None):

ghost Nov 19, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that block_height is provided here, suggest making coinbase optional since almost all uses just call create_coinbase(block_height). Probably doesn't matter much unless/until this goes upstream...

ghost Nov 26, 2018

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd have to implement a CScriptNum encoder in python.... sigh I'll do it :)

ghost Nov 26, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh? create_coinbase (and serialize_script_num) already exists..

ghost Nov 26, 2018

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

de-serialize*. I want to grab it directly from the coinbase.

@luke-jr

ghost commented Nov 19, 2018

Copy link
Copy Markdown
Contributor

It's never (de)serialed as non zero if not active.

Why wouldn't it take an existing CBlockIndex serialisation, and turn that bits into height, and nonce into bits?

Comment thread src/chainparamsbase.cpp Outdated
gArgs.AddArg("-seednode=<ip>", "Use specified node as seed node. This option can be specified multiple times to connect to multiple nodes. (custom only)", true, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-con_blocksubsidy", "Defines the amount of block subsidy to start with, at genesis block.", false, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-con_connect_coinbase", "Connect outputs in genesis block to utxo database.", false, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-con_blockheightinheader", "Whether the chain includes the block height directly in the header, for easier validation of block height in low-resource environments.", false, OptionsCategory::CHAINPARAMS);

ghost Nov 22, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps indicate that defaults to true here?

@jtimon

ghost commented Nov 22, 2018

Copy link
Copy Markdown
Contributor

I dislike that this modifies many unrelated tests (because the new option defaults to true) instead of just copying or creating a specific one to test this. That's bad for rebases.
Is it really necessary to default to true?

@instagibbs

ghost commented Nov 22, 2018 via email

Copy link
Copy Markdown
Contributor Author

@jtimon

ghost commented Nov 22, 2018

Copy link
Copy Markdown
Contributor

Or you can just change the default to false, no? Perhaps duplicate and modify some tests if that has value, but run all of them with this set to true.
What am I missing?

@instagibbs

ghost commented Nov 22, 2018 via email

Copy link
Copy Markdown
Contributor Author

@instagibbs

ghost commented Nov 26, 2018

Copy link
Copy Markdown
Contributor Author

Pushed an update that is able to extract the block height directly from the coinbase input, and places it in the header. This shrinks the test diff by quite a bit.

@instagibbs

ghost commented Nov 26, 2018

Copy link
Copy Markdown
Contributor Author

squashed, passing tests, and ready for final review

Gregory Sanders added 2 commits November 27, 2018 09:45
The block height validation is gated by the startup option
`con_blockheightinheader`, accesible in custom chains only
using option `chain=<name>`. Only if set to true will this
field be (de)serialized and evaluated in consensus logic.
Otherwise the field is simply ignored, other than being
stored in memory as the default value 0.
@instagibbs

ghost commented Nov 27, 2018

Copy link
Copy Markdown
Contributor Author

rebased and added default value message in help of true(assuming custom chains since that will be default later)

@stevenroose

ghost commented Nov 27, 2018

Copy link
Copy Markdown
Contributor

cool, tACK 2bfabb3!

@instagibbs
instagibbs merged commit 2bfabb3 into ElementsProject:elements-0.17 Nov 27, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants