gen_hash256(7,1,0) "0000000ae82798beaba5537ef3b0dd551fef80af1e0239f061f33248589d801c"
gen_hash256(6,1,0) "0000008ae82798beaba5537ef3b0dd551fef80af1e0239f061f33248589d801c"
gen_hash256(5,1,0) "00000f8ae82798beaba5537ef3b0dd551fef80af1e0239f061f33248589d801c"
gen_hash256(4,1,0) "0000cf8ae82798beaba5537ef3b0dd551fef80af1e0239f061f33248589d801c"
gen_hash256(3,1,0) "0007cf8ae82798beaba5537ef3b0dd551fef80af1e0239f061f33248589d801c"
gen_hash256(2,1,0) "00a7cf8ae82798beaba5537ef3b0dd551fef80af1e0239f061f33248589d801c"
gen_hash256(1,1,0) "0da7cf8ae82798beaba5537ef3b0dd551fef80af1e0239f061f33248589d801c"
gen_hash256(0,1,0) "6da7cf8ae82798beaba5537ef3b0dd551fef80af1e0239f061f33248589d801c"
Oh, so that's how hashes are made!
gen_hash256(0,1,0x00000000) "6da7cf8ae82798beaba5537ef3b0dd551fef80af1e0239f061f33248589d801c"
gen_hash256(0,1,0xffffffff) "ef4ac5a4b4aed0339758c8af0811423763b64e534c85cc2d9c6ef3fbab87dcff"
There are only 2^32 possible outcomes, and everything is simply masked, to get the final value. Nice!
Yep, that function is the core of how "faking" the proof of work hashes is done. Internally, the parameters are essentially
bias (the number of leading zeroes),
odds,
seed. The function will then sample a hash using the
seed from a distribution where the expected value of
bias is 1/
odds. It sounds a little complicated, but you can get a visual idea by using the sample_distribution(bias, odds, n_samples) function that's already in there. For example:

You can see that the number of hashes generated with 10 leading zeroes was 1074/100000, which is roughly 1% (equal to 1/odds) and it has a somewhat realistic/nice overall distribution. That is what is actually going on when you buy devices and increase your hashrate, the game just tweaks your bias/odds values in such a way that your hashes line up with the hashes you
should be generating if you actually had that hashrate.
By the way, that also means, that after mining around 64k blocks, there would be block hash collisions! I wonder, if some things would crash because of that, or not. For example: what if there would be two or more block hashes, generated out of the same seeds? How getting block by hash would behave?
I haven't tested that, it would take too long

. However, finding a block by it's hash is done by searching downwards from the set of chaintips, meaning if two blocks have the same hash, it'll retrieve the one most recently added to the chain. Theoretically nothing else should actually break since blocks are usually identified by their actual BlockNode object in the JS and not their hash, but I'll have to test it at some point.
Edit:
for(var i=0;i<10000;++i) cb_P2PK("1teDcUjNzJdjiBesXDfsSUeeQUQYLQdQ5M")
Whoops! 500k coins generated just like that? Well, it seems the supply is no longer limited to 50k coins, if such things are possible.
After Value Overflow Incident, more checks were put in place. In general, no transaction should be able to send more coins than MAX_MONEY (which is 21 million coins in BTC, but could be 50k coins in SAT). Also, making a single output like that should be disallowed, as well as sending more coins than that in a single block. But, as you can easily see, the source of this bug leads to the simple fact, that coinbase amount is never checked anywhere, so it is trivially hackable. I wonder, if it should be that easy, it is single player by the way, so maybe it should be allowed? I don't know.
Indeed, since the game never allows for more than one coinbase transaction to exist in a block, I didn't place a check to explicitly prevent it. I think it's mostly fine, games like Cookie Clicker are also trivially hackable like this. Cookie Clicker actually has messages that you will see if you open the console, such as the following:
[=== About to cheat in some cookies or just checking for bugs? ===]
or
[=== Hey, Orteil here. Cheated cookies taste awful... or do they? ===]
Maybe I'll just add something like that as a light hearted deterrent
