Objective 11a: Naughty/Nice List with Blockchain Investigation Part 1

Even though the chunk of the blockchain that you have ends with block 129996, can you predict the nonce for block 130000? Talk to Tangle Coalbox in the Speaker UNpreparedness Room for tips on prediction and Tinsel Upatree for more tips and tools. (Enter just the 16-character hex value of the nonce)

This Objective is split into two because of the fact that I am going to work on the same file for both challenges. This first challenge was considerably easier than the second, and this is mostly because of what I've built so far in previous challenges. Utilizing PRNG prediction that I've used for Kiosk 11, I can also predict the nonce it mentions. But before I get into that, I'll discuss the structure of the Naughty/Nice blockchain.

Structure

From the slide provided by Professor Qwerty Petabyte, the basic structure is as follows:

Structure

With the provided python code for working with the blockchain, I can load up the provided blockchain...however there was a couple of things necessary for this to work. First, this isn't the entire blockchain. This is only a very small sampling of it. It's also not the beginning of the blockchain either, so there is no true genesis block. Since each block contains a hash of the previous block, this should fail because the genesis block is not the first block here. I have to utilize the code provided to get the hash of first block here and sort of fool the code into thinking that the first block is the genesis block. Luckily, a variable was created to do exactly that: genesis_block_fake_hash

Fake Genesis

When I make that slight change, I can now load the blockchain in and read as expected!

To verify the blockchain is valid, I load the blockchain in and run the verify_chain() function to ensure that it's copacetic:

Valid chain

And we have a valid chain! We can work with each block within the blockchain by accessing each via c.blocks[50] to reference the 50th block in the chain, and so on. So based on that, I can return the nonce of the 50th block with c.blocks[50].nonce:

Nonce

...which itself is a 64-bit integer, not a 32-bit integer like I've been working with for the Snowball Fight Challenge. Luckily the mt19937predictor library had a means to ingest it anyway. Based on that, I was able to spin up a quick python script to determine the nonce for block 130000:

from naughty_nice import *
from mt19937predictor import MT19937Predictor

c = Chain(load=True, filename='blockchain.dat')
p = MT19937Predictor()
for block in c.blocks[:-1]:
    p.setrandbits(block.nonce, 64)

# Ensure it's working
assert p.getrandbits(64) == c.blocks[-1].nonce

# If you got here, we are able to predict the PRNG
for _ in range(3):
    p.getrandbits(64)

print(f"Predicted nonce for 130000: {p.getrandbits(64)}")

I even ingested all but the last block, then used an assert() function to ensure that it was predicting properly. Then I just threw away the next 3 potential blocks, and dumped the predicted nonce for block 130000:

Predicted nonce for 130000: 6270808489970332317

Objective 11b! Once more unto the breach, dear friends, once more!