# beacon_chain # Copyright (c) 2018 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). # * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). # at your option. This file may not be copied, modified, or distributed except according to those terms. # import ../interpreter # included to be able to use "suiteReport" proc setup_finality_02(): tuple[fork_choice: ForkChoice, ops: seq[Operation]] = var balances = @[Gwei(1), Gwei(1)] let GenesisRoot = fakeHash(0) # Initialize the fork choice context result.fork_choice = initForkChoice( finalized_block_slot = Slot(0), # Metadata unused in fork choice finalized_block_state_root = default(Eth2Digest), # Metadata unused in fork choice justified_epoch = Epoch(1), finalized_epoch = Epoch(1), finalized_root = GenesisRoot ).get() # ---------------------------------- # Head should be genesis result.ops.add Operation( kind: FindHead, justified_epoch: Epoch(1), justified_root: GenesisRoot, finalized_epoch: Epoch(1), justified_state_balances: balances, expected_head: GenesisRoot ) # Build the following tree. # # 0 # / \ # just: 0, fin: 0 -> 1 2 <- just: 0, fin: 0 # | | # just: 1, fin: 0 -> 3 4 <- just: 0, fin: 0 # | | # just: 1, fin: 0 -> 5 6 <- just: 0, fin: 0 # | | # just: 1, fin: 0 -> 7 8 <- just: 1, fin: 0 # | | # just: 2, fin: 0 -> 9 10 <- just: 2, fin: 0 # Left branch result.ops.add Operation( kind: ProcessBlock, root: fakeHash(1), parent_root: GenesisRoot, blk_justified_epoch: Epoch(0), blk_finalized_epoch: Epoch(0) ) result.ops.add Operation( kind: ProcessBlock, root: fakeHash(3), parent_root: fakeHash(1), blk_justified_epoch: Epoch(1), blk_finalized_epoch: Epoch(0) ) result.ops.add Operation( kind: ProcessBlock, root: fakeHash(5), parent_root: fakeHash(3), blk_justified_epoch: Epoch(1), blk_finalized_epoch: Epoch(0) ) result.ops.add Operation( kind: ProcessBlock, root: fakeHash(7), parent_root: fakeHash(5), blk_justified_epoch: Epoch(1), blk_finalized_epoch: Epoch(0) ) result.ops.add Operation( kind: ProcessBlock, root: fakeHash(9), parent_root: fakeHash(7), blk_justified_epoch: Epoch(2), blk_finalized_epoch: Epoch(0) ) # Build the following tree. # # 0 # / \ # just: 0, fin: 0 -> 1 2 <- just: 0, fin: 0 # | | # just: 1, fin: 0 -> 3 4 <- just: 0, fin: 0 # | | # just: 1, fin: 0 -> 5 6 <- just: 0, fin: 0 # | | # just: 1, fin: 0 -> 7 8 <- just: 1, fin: 0 # | | # just: 2, fin: 0 -> 9 10 <- just: 2, fin: 0 # Right branch result.ops.add Operation( kind: ProcessBlock, root: fakeHash(2), parent_root: GenesisRoot, blk_justified_epoch: Epoch(0), blk_finalized_epoch: Epoch(0) ) result.ops.add Operation( kind: ProcessBlock, root: fakeHash(4), parent_root: fakeHash(2), blk_justified_epoch: Epoch(0), blk_finalized_epoch: Epoch(0) ) result.ops.add Operation( kind: ProcessBlock, root: fakeHash(6), parent_root: fakeHash(4), blk_justified_epoch: Epoch(0), blk_finalized_epoch: Epoch(0) ) result.ops.add Operation( kind: ProcessBlock, root: fakeHash(8), parent_root: fakeHash(6), blk_justified_epoch: Epoch(1), blk_finalized_epoch: Epoch(0) ) result.ops.add Operation( kind: ProcessBlock, root: fakeHash(10), parent_root: fakeHash(8), blk_justified_epoch: Epoch(2), blk_finalized_epoch: Epoch(0) ) # Ensure that if we start at 0 we find 10 (just: 0, fin: 0). # # 0 <-- start # / \ # 1 2 # | | # 3 4 # | | # 5 6 # | | # 7 8 # | | # 9 10 <-- head result.ops.add Operation( kind: FindHead, justified_epoch: Epoch(0), justified_root: GenesisRoot, finalized_epoch: Epoch(0), justified_state_balances: balances, expected_head: fakeHash(10) ) # Same with justified_epoch 2 result.ops.add Operation( kind: FindHead, justified_epoch: Epoch(2), justified_root: GenesisRoot, finalized_epoch: Epoch(0), justified_state_balances: balances, expected_head: fakeHash(10) ) # Justified epoch 3 is invalid result.ops.add Operation( kind: InvalidFindHead, justified_epoch: Epoch(3), # <--- Wrong epoch justified_root: GenesisRoot, finalized_epoch: Epoch(0), justified_state_balances: balances ) # Add a vote to 1. # # 0 # / \ # +1 vote -> 1 2 # | | # 3 4 # | | # 5 6 # | | # 7 8 # | | # 9 10 result.ops.add Operation( kind: ProcessAttestation, validator_index: ValidatorIndex(0), block_root: fake_hash(1), target_epoch: Epoch(0) ) # Ensure that if we start at 0 we find 9 (just: 0, fin: 0). # # 0 <-- start # / \ # 1 2 # | | # 3 4 # | | # 5 6 # | | # 7 8 # | | # head -> 9 10 result.ops.add Operation( kind: FindHead, justified_epoch: Epoch(0), justified_root: GenesisRoot, finalized_epoch: Epoch(0), justified_state_balances: balances, expected_head: fakeHash(9) ) # Same with justified_epoch 2 result.ops.add Operation( kind: FindHead, justified_epoch: Epoch(2), justified_root: GenesisRoot, finalized_epoch: Epoch(0), justified_state_balances: balances, expected_head: fakeHash(9) ) # Justified epoch 3 is invalid result.ops.add Operation( kind: InvalidFindHead, justified_epoch: Epoch(3), # <--- Wrong epoch justified_root: GenesisRoot, finalized_epoch: Epoch(0), justified_state_balances: balances ) # Add a vote to 2. # # 0 # / \ # 1 2 <- +1 vote # | | # 3 4 # | | # 5 6 # | | # 7 8 # | | # 9 10 result.ops.add Operation( kind: ProcessAttestation, validator_index: ValidatorIndex(1), block_root: fake_hash(2), target_epoch: Epoch(0) ) # Ensure that if we start at 0 we find 10 again (just: 0, fin: 0). # # 0 <-- start # / \ # 1 2 # | | # 3 4 # | | # 5 6 # | | # 7 8 # | | # 9 10 <-- head result.ops.add Operation( kind: FindHead, justified_epoch: Epoch(0), justified_root: GenesisRoot, finalized_epoch: Epoch(0), justified_state_balances: balances, expected_head: fakeHash(10) ) # Same with justified_epoch 2 result.ops.add Operation( kind: FindHead, justified_epoch: Epoch(2), justified_root: GenesisRoot, finalized_epoch: Epoch(0), justified_state_balances: balances, expected_head: fakeHash(10) ) # Justified epoch 3 is invalid result.ops.add Operation( kind: InvalidFindHead, justified_epoch: Epoch(3), # <--- Wrong epoch justified_root: GenesisRoot, finalized_epoch: Epoch(0), justified_state_balances: balances ) # Ensure that if we start at 1 (instead of 0) we find 9 (just: 0, fin: 0). # # 0 # / \ # start-> 1 2 # | | # 3 4 # | | # 5 6 # | | # 7 8 # | | # head -> 9 10 result.ops.add Operation( kind: FindHead, justified_epoch: Epoch(0), justified_root: fakeHash(1), finalized_epoch: Epoch(0), justified_state_balances: balances, expected_head: fakeHash(9) ) # Same with justified_epoch 2 result.ops.add Operation( kind: FindHead, justified_epoch: Epoch(2), justified_root: fakeHash(1), finalized_epoch: Epoch(0), justified_state_balances: balances, expected_head: fakeHash(9) ) # Justified epoch 3 is invalid result.ops.add Operation( kind: InvalidFindHead, justified_epoch: Epoch(3), # <--- Wrong epoch justified_root: fakeHash(1), finalized_epoch: Epoch(0), justified_state_balances: balances ) # Ensure that if we start at 2 (instead of 0) we find 10 (just: 0, fin: 0). # # 0 # / \ # 1 2 <- start # | | # 3 4 # | | # 5 6 # | | # 7 8 # | | # 9 10 <- head result.ops.add Operation( kind: FindHead, justified_epoch: Epoch(0), justified_root: fakeHash(2), finalized_epoch: Epoch(0), justified_state_balances: balances, expected_head: fakeHash(10) ) # Same with justified_epoch 2 result.ops.add Operation( kind: FindHead, justified_epoch: Epoch(2), justified_root: fakeHash(2), finalized_epoch: Epoch(0), justified_state_balances: balances, expected_head: fakeHash(10) ) # Justified epoch 3 is invalid result.ops.add Operation( kind: InvalidFindHead, justified_epoch: Epoch(3), # <--- Wrong epoch justified_root: fakeHash(2), finalized_epoch: Epoch(0), justified_state_balances: balances ) proc test_ffg02() = timedTest "fork_choice - testing finality #02": # for i in 0 ..< 12: # echo " block (", i, ") hash: ", fakeHash(i) # echo " ------------------------------------------------------" var (ctx, ops) = setup_finality_02() ctx.run(ops) test_ffg02()