github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/forkchoice/protoarray/ffg_update_test.go (about) 1 package protoarray 2 3 import ( 4 "context" 5 "testing" 6 7 types "github.com/prysmaticlabs/eth2-types" 8 "github.com/prysmaticlabs/prysm/shared/params" 9 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 10 "github.com/prysmaticlabs/prysm/shared/testutil/require" 11 ) 12 13 func TestFFGUpdates_OneBranch(t *testing.T) { 14 balances := []uint64{1, 1} 15 f := setup(0, 0) 16 17 // The head should always start at the finalized block. 18 r, err := f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0) 19 require.NoError(t, err) 20 assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis") 21 22 // Define the following tree: 23 // 0 <- justified: 0, finalized: 0 24 // | 25 // 1 <- justified: 0, finalized: 0 26 // | 27 // 2 <- justified: 1, finalized: 0 28 // | 29 // 3 <- justified: 2, finalized: 1 30 require.NoError(t, f.ProcessBlock(context.Background(), 1, indexToHash(1), params.BeaconConfig().ZeroHash, [32]byte{}, 0, 0)) 31 require.NoError(t, f.ProcessBlock(context.Background(), 2, indexToHash(2), indexToHash(1), [32]byte{}, 1, 0)) 32 require.NoError(t, f.ProcessBlock(context.Background(), 3, indexToHash(3), indexToHash(2), [32]byte{}, 2, 1)) 33 34 // With starting justified epoch at 0, the head should be 3: 35 // 0 <- start 36 // | 37 // 1 38 // | 39 // 2 40 // | 41 // 3 <- head 42 r, err = f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0) 43 require.NoError(t, err) 44 assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 0") 45 46 // With starting justified epoch at 1, the head should be 2: 47 // 0 48 // | 49 // 1 <- start 50 // | 51 // 2 <- head 52 // | 53 // 3 54 r, err = f.Head(context.Background(), 1, indexToHash(2), balances, 0) 55 require.NoError(t, err) 56 assert.Equal(t, indexToHash(2), r, "Incorrect head with justified epoch at 1") 57 58 // With starting justified epoch at 2, the head should be 3: 59 // 0 60 // | 61 // 1 62 // | 63 // 2 <- start 64 // | 65 // 3 <- head 66 r, err = f.Head(context.Background(), 2, indexToHash(3), balances, 1) 67 require.NoError(t, err) 68 assert.Equal(t, indexToHash(3), r, "Incorrect head with justified epoch at 2") 69 } 70 71 func TestFFGUpdates_TwoBranches(t *testing.T) { 72 balances := []uint64{1, 1} 73 f := setup(0, 0) 74 75 r, err := f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0) 76 require.NoError(t, err) 77 assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis") 78 79 // Define the following tree: 80 // 0 81 // / \ 82 // justified: 0, finalized: 0 -> 1 2 <- justified: 0, finalized: 0 83 // | | 84 // justified: 1, finalized: 0 -> 3 4 <- justified: 0, finalized: 0 85 // | | 86 // justified: 1, finalized: 0 -> 5 6 <- justified: 0, finalized: 0 87 // | | 88 // justified: 1, finalized: 0 -> 7 8 <- justified: 1, finalized: 0 89 // | | 90 // justified: 2, finalized: 0 -> 9 10 <- justified: 2, finalized: 0 91 // Left branch. 92 require.NoError(t, f.ProcessBlock(context.Background(), 1, indexToHash(1), params.BeaconConfig().ZeroHash, [32]byte{}, 0, 0)) 93 require.NoError(t, f.ProcessBlock(context.Background(), 2, indexToHash(3), indexToHash(1), [32]byte{}, 1, 0)) 94 require.NoError(t, f.ProcessBlock(context.Background(), 3, indexToHash(5), indexToHash(3), [32]byte{}, 1, 0)) 95 require.NoError(t, f.ProcessBlock(context.Background(), 4, indexToHash(7), indexToHash(5), [32]byte{}, 1, 0)) 96 require.NoError(t, f.ProcessBlock(context.Background(), 4, indexToHash(9), indexToHash(7), [32]byte{}, 2, 0)) 97 // Right branch. 98 require.NoError(t, f.ProcessBlock(context.Background(), 1, indexToHash(2), params.BeaconConfig().ZeroHash, [32]byte{}, 0, 0)) 99 require.NoError(t, f.ProcessBlock(context.Background(), 2, indexToHash(4), indexToHash(2), [32]byte{}, 0, 0)) 100 require.NoError(t, f.ProcessBlock(context.Background(), 3, indexToHash(6), indexToHash(4), [32]byte{}, 0, 0)) 101 require.NoError(t, f.ProcessBlock(context.Background(), 4, indexToHash(8), indexToHash(6), [32]byte{}, 1, 0)) 102 require.NoError(t, f.ProcessBlock(context.Background(), 4, indexToHash(10), indexToHash(8), [32]byte{}, 2, 0)) 103 104 // With start at 0, the head should be 10: 105 // 0 <-- start 106 // / \ 107 // 1 2 108 // | | 109 // 3 4 110 // | | 111 // 5 6 112 // | | 113 // 7 8 114 // | | 115 // 9 10 <-- head 116 r, err = f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0) 117 require.NoError(t, err) 118 assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0") 119 120 // Add a vote to 1: 121 // 0 122 // / \ 123 // +1 vote -> 1 2 124 // | | 125 // 3 4 126 // | | 127 // 5 6 128 // | | 129 // 7 8 130 // | | 131 // 9 10 132 f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(1), 0) 133 134 // With the additional vote to the left branch, the head should be 9: 135 // 0 <-- start 136 // / \ 137 // 1 2 138 // | | 139 // 3 4 140 // | | 141 // 5 6 142 // | | 143 // 7 8 144 // | | 145 // head -> 9 10 146 r, err = f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0) 147 require.NoError(t, err) 148 assert.Equal(t, indexToHash(9), r, "Incorrect head with justified epoch at 0") 149 150 // Add a vote to 2: 151 // 0 152 // / \ 153 // 1 2 <- +1 vote 154 // | | 155 // 3 4 156 // | | 157 // 5 6 158 // | | 159 // 7 8 160 // | | 161 // 9 10 162 f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(2), 0) 163 164 // With the additional vote to the right branch, the head should be 10: 165 // 0 <-- start 166 // / \ 167 // 1 2 168 // | | 169 // 3 4 170 // | | 171 // 5 6 172 // | | 173 // 7 8 174 // | | 175 // 9 10 <-- head 176 r, err = f.Head(context.Background(), 0, params.BeaconConfig().ZeroHash, balances, 0) 177 require.NoError(t, err) 178 assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0") 179 180 r, err = f.Head(context.Background(), 1, indexToHash(1), balances, 0) 181 require.NoError(t, err) 182 assert.Equal(t, indexToHash(7), r, "Incorrect head with justified epoch at 0") 183 } 184 185 func setup(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice { 186 f := New(0, 0, params.BeaconConfig().ZeroHash) 187 f.store.nodesIndices[params.BeaconConfig().ZeroHash] = 0 188 f.store.nodes = append(f.store.nodes, &Node{ 189 slot: 0, 190 root: params.BeaconConfig().ZeroHash, 191 parent: NonExistentNode, 192 justifiedEpoch: justifiedEpoch, 193 finalizedEpoch: finalizedEpoch, 194 bestChild: NonExistentNode, 195 bestDescendant: NonExistentNode, 196 weight: 0, 197 }) 198 199 return f 200 }