github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/core/blocks/header_test.go (about) 1 package blocks_test 2 3 import ( 4 "context" 5 "io/ioutil" 6 "testing" 7 8 "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" 9 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 10 p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types" 11 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 12 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper" 13 "github.com/prysmaticlabs/prysm/shared/bls" 14 "github.com/prysmaticlabs/prysm/shared/bytesutil" 15 "github.com/prysmaticlabs/prysm/shared/params" 16 "github.com/prysmaticlabs/prysm/shared/testutil" 17 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 18 "github.com/prysmaticlabs/prysm/shared/testutil/require" 19 "github.com/sirupsen/logrus" 20 "google.golang.org/protobuf/proto" 21 ) 22 23 func init() { 24 logrus.SetOutput(ioutil.Discard) // Ignore "validator activated" logs 25 } 26 27 func TestProcessBlockHeader_ImproperBlockSlot(t *testing.T) { 28 validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) 29 for i := 0; i < len(validators); i++ { 30 validators[i] = ðpb.Validator{ 31 PublicKey: make([]byte, 32), 32 WithdrawalCredentials: make([]byte, 32), 33 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 34 Slashed: true, 35 } 36 } 37 38 state, err := testutil.NewBeaconState() 39 require.NoError(t, err) 40 require.NoError(t, state.SetSlot(10)) 41 require.NoError(t, state.SetValidators(validators)) 42 require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(ðpb.BeaconBlockHeader{ 43 Slot: 10, // Must be less than block.Slot 44 }))) 45 46 latestBlockSignedRoot, err := state.LatestBlockHeader().HashTreeRoot() 47 require.NoError(t, err) 48 49 currentEpoch := helpers.CurrentEpoch(state) 50 priv, err := bls.RandKey() 51 require.NoError(t, err) 52 pID, err := helpers.BeaconProposerIndex(state) 53 require.NoError(t, err) 54 block := testutil.NewBeaconBlock() 55 block.Block.ProposerIndex = pID 56 block.Block.Slot = 10 57 block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96) 58 block.Block.ParentRoot = latestBlockSignedRoot[:] 59 block.Signature, err = helpers.ComputeDomainAndSign(state, currentEpoch, block.Block, params.BeaconConfig().DomainBeaconProposer, priv) 60 require.NoError(t, err) 61 62 proposerIdx, err := helpers.BeaconProposerIndex(state) 63 require.NoError(t, err) 64 validators[proposerIdx].Slashed = false 65 validators[proposerIdx].PublicKey = priv.PublicKey().Marshal() 66 err = state.UpdateValidatorAtIndex(proposerIdx, validators[proposerIdx]) 67 require.NoError(t, err) 68 69 _, err = blocks.ProcessBlockHeader(context.Background(), state, wrapper.WrappedPhase0SignedBeaconBlock(block)) 70 assert.ErrorContains(t, "block.Slot 10 must be greater than state.LatestBlockHeader.Slot 10", err) 71 } 72 73 func TestProcessBlockHeader_WrongProposerSig(t *testing.T) { 74 75 beaconState, privKeys := testutil.DeterministicGenesisState(t, 100) 76 require.NoError(t, beaconState.SetLatestBlockHeader(testutil.HydrateBeaconHeader(ðpb.BeaconBlockHeader{ 77 Slot: 9, 78 }))) 79 require.NoError(t, beaconState.SetSlot(10)) 80 81 lbhdr, err := beaconState.LatestBlockHeader().HashTreeRoot() 82 require.NoError(t, err) 83 84 proposerIdx, err := helpers.BeaconProposerIndex(beaconState) 85 require.NoError(t, err) 86 87 block := testutil.NewBeaconBlock() 88 block.Block.ProposerIndex = proposerIdx 89 block.Block.Slot = 10 90 block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96) 91 block.Block.ParentRoot = lbhdr[:] 92 block.Signature, err = helpers.ComputeDomainAndSign(beaconState, 0, block.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx+1]) 93 require.NoError(t, err) 94 95 _, err = blocks.ProcessBlockHeader(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block)) 96 want := "signature did not verify" 97 assert.ErrorContains(t, want, err) 98 } 99 100 func TestProcessBlockHeader_DifferentSlots(t *testing.T) { 101 validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) 102 for i := 0; i < len(validators); i++ { 103 validators[i] = ðpb.Validator{ 104 PublicKey: make([]byte, 32), 105 WithdrawalCredentials: make([]byte, 32), 106 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 107 Slashed: true, 108 } 109 } 110 111 state, err := testutil.NewBeaconState() 112 require.NoError(t, err) 113 require.NoError(t, state.SetValidators(validators)) 114 require.NoError(t, state.SetSlot(10)) 115 require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(ðpb.BeaconBlockHeader{ 116 Slot: 9, 117 }))) 118 119 lbhsr, err := state.LatestBlockHeader().HashTreeRoot() 120 require.NoError(t, err) 121 currentEpoch := helpers.CurrentEpoch(state) 122 123 priv, err := bls.RandKey() 124 require.NoError(t, err) 125 sszBytes := p2ptypes.SSZBytes("hello") 126 blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, &sszBytes, params.BeaconConfig().DomainBeaconProposer, priv) 127 require.NoError(t, err) 128 validators[5896].PublicKey = priv.PublicKey().Marshal() 129 block := testutil.HydrateSignedBeaconBlock(ðpb.SignedBeaconBlock{ 130 Block: ðpb.BeaconBlock{ 131 Slot: 1, 132 ParentRoot: lbhsr[:], 133 }, 134 Signature: blockSig, 135 }) 136 137 _, err = blocks.ProcessBlockHeader(context.Background(), state, wrapper.WrappedPhase0SignedBeaconBlock(block)) 138 want := "is different than block slot" 139 assert.ErrorContains(t, want, err) 140 } 141 142 func TestProcessBlockHeader_PreviousBlockRootNotSignedRoot(t *testing.T) { 143 validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) 144 for i := 0; i < len(validators); i++ { 145 validators[i] = ðpb.Validator{ 146 PublicKey: make([]byte, 48), 147 WithdrawalCredentials: make([]byte, 32), 148 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 149 Slashed: true, 150 } 151 } 152 153 state, err := testutil.NewBeaconState() 154 require.NoError(t, err) 155 require.NoError(t, state.SetValidators(validators)) 156 require.NoError(t, state.SetSlot(10)) 157 bh := state.LatestBlockHeader() 158 bh.Slot = 9 159 require.NoError(t, state.SetLatestBlockHeader(bh)) 160 currentEpoch := helpers.CurrentEpoch(state) 161 priv, err := bls.RandKey() 162 require.NoError(t, err) 163 sszBytes := p2ptypes.SSZBytes("hello") 164 blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, &sszBytes, params.BeaconConfig().DomainBeaconProposer, priv) 165 require.NoError(t, err) 166 validators[5896].PublicKey = priv.PublicKey().Marshal() 167 pID, err := helpers.BeaconProposerIndex(state) 168 require.NoError(t, err) 169 block := testutil.NewBeaconBlock() 170 block.Block.Slot = 10 171 block.Block.ProposerIndex = pID 172 block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96) 173 block.Block.ParentRoot = bytesutil.PadTo([]byte{'A'}, 32) 174 block.Signature = blockSig 175 176 _, err = blocks.ProcessBlockHeader(context.Background(), state, wrapper.WrappedPhase0SignedBeaconBlock(block)) 177 want := "does not match" 178 assert.ErrorContains(t, want, err) 179 } 180 181 func TestProcessBlockHeader_SlashedProposer(t *testing.T) { 182 validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) 183 for i := 0; i < len(validators); i++ { 184 validators[i] = ðpb.Validator{ 185 PublicKey: make([]byte, 48), 186 WithdrawalCredentials: make([]byte, 32), 187 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 188 Slashed: true, 189 } 190 } 191 192 state, err := testutil.NewBeaconState() 193 require.NoError(t, err) 194 require.NoError(t, state.SetValidators(validators)) 195 require.NoError(t, state.SetSlot(10)) 196 bh := state.LatestBlockHeader() 197 bh.Slot = 9 198 require.NoError(t, state.SetLatestBlockHeader(bh)) 199 parentRoot, err := state.LatestBlockHeader().HashTreeRoot() 200 require.NoError(t, err) 201 currentEpoch := helpers.CurrentEpoch(state) 202 priv, err := bls.RandKey() 203 require.NoError(t, err) 204 sszBytes := p2ptypes.SSZBytes("hello") 205 blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, &sszBytes, params.BeaconConfig().DomainBeaconProposer, priv) 206 require.NoError(t, err) 207 208 validators[12683].PublicKey = priv.PublicKey().Marshal() 209 pID, err := helpers.BeaconProposerIndex(state) 210 require.NoError(t, err) 211 block := testutil.NewBeaconBlock() 212 block.Block.Slot = 10 213 block.Block.ProposerIndex = pID 214 block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96) 215 block.Block.ParentRoot = parentRoot[:] 216 block.Signature = blockSig 217 218 _, err = blocks.ProcessBlockHeader(context.Background(), state, wrapper.WrappedPhase0SignedBeaconBlock(block)) 219 want := "was previously slashed" 220 assert.ErrorContains(t, want, err) 221 } 222 223 func TestProcessBlockHeader_OK(t *testing.T) { 224 validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) 225 for i := 0; i < len(validators); i++ { 226 validators[i] = ðpb.Validator{ 227 PublicKey: make([]byte, 32), 228 WithdrawalCredentials: make([]byte, 32), 229 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 230 Slashed: true, 231 } 232 } 233 234 state, err := testutil.NewBeaconState() 235 require.NoError(t, err) 236 require.NoError(t, state.SetValidators(validators)) 237 require.NoError(t, state.SetSlot(10)) 238 require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(ðpb.BeaconBlockHeader{ 239 Slot: 9, 240 }))) 241 242 latestBlockSignedRoot, err := state.LatestBlockHeader().HashTreeRoot() 243 require.NoError(t, err) 244 245 currentEpoch := helpers.CurrentEpoch(state) 246 priv, err := bls.RandKey() 247 require.NoError(t, err) 248 pID, err := helpers.BeaconProposerIndex(state) 249 require.NoError(t, err) 250 block := testutil.NewBeaconBlock() 251 block.Block.ProposerIndex = pID 252 block.Block.Slot = 10 253 block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96) 254 block.Block.ParentRoot = latestBlockSignedRoot[:] 255 block.Signature, err = helpers.ComputeDomainAndSign(state, currentEpoch, block.Block, params.BeaconConfig().DomainBeaconProposer, priv) 256 require.NoError(t, err) 257 bodyRoot, err := block.Block.Body.HashTreeRoot() 258 require.NoError(t, err, "Failed to hash block bytes got") 259 260 proposerIdx, err := helpers.BeaconProposerIndex(state) 261 require.NoError(t, err) 262 validators[proposerIdx].Slashed = false 263 validators[proposerIdx].PublicKey = priv.PublicKey().Marshal() 264 err = state.UpdateValidatorAtIndex(proposerIdx, validators[proposerIdx]) 265 require.NoError(t, err) 266 267 newState, err := blocks.ProcessBlockHeader(context.Background(), state, wrapper.WrappedPhase0SignedBeaconBlock(block)) 268 require.NoError(t, err, "Failed to process block header got") 269 var zeroHash [32]byte 270 nsh := newState.LatestBlockHeader() 271 expected := ðpb.BeaconBlockHeader{ 272 ProposerIndex: pID, 273 Slot: block.Block.Slot, 274 ParentRoot: latestBlockSignedRoot[:], 275 BodyRoot: bodyRoot[:], 276 StateRoot: zeroHash[:], 277 } 278 assert.Equal(t, true, proto.Equal(nsh, expected), "Expected %v, received %v", expected, nsh) 279 } 280 281 func TestBlockSignatureSet_OK(t *testing.T) { 282 validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) 283 for i := 0; i < len(validators); i++ { 284 validators[i] = ðpb.Validator{ 285 PublicKey: make([]byte, 32), 286 WithdrawalCredentials: make([]byte, 32), 287 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 288 Slashed: true, 289 } 290 } 291 292 state, err := testutil.NewBeaconState() 293 require.NoError(t, err) 294 require.NoError(t, state.SetValidators(validators)) 295 require.NoError(t, state.SetSlot(10)) 296 require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(ðpb.BeaconBlockHeader{ 297 Slot: 9, 298 ProposerIndex: 0, 299 }))) 300 301 latestBlockSignedRoot, err := state.LatestBlockHeader().HashTreeRoot() 302 require.NoError(t, err) 303 304 currentEpoch := helpers.CurrentEpoch(state) 305 priv, err := bls.RandKey() 306 require.NoError(t, err) 307 pID, err := helpers.BeaconProposerIndex(state) 308 require.NoError(t, err) 309 block := testutil.NewBeaconBlock() 310 block.Block.Slot = 10 311 block.Block.ProposerIndex = pID 312 block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96) 313 block.Block.ParentRoot = latestBlockSignedRoot[:] 314 block.Signature, err = helpers.ComputeDomainAndSign(state, currentEpoch, block.Block, params.BeaconConfig().DomainBeaconProposer, priv) 315 require.NoError(t, err) 316 proposerIdx, err := helpers.BeaconProposerIndex(state) 317 require.NoError(t, err) 318 validators[proposerIdx].Slashed = false 319 validators[proposerIdx].PublicKey = priv.PublicKey().Marshal() 320 err = state.UpdateValidatorAtIndex(proposerIdx, validators[proposerIdx]) 321 require.NoError(t, err) 322 set, err := blocks.BlockSignatureSet(state, block.Block.ProposerIndex, block.Signature, block.Block.HashTreeRoot) 323 require.NoError(t, err) 324 325 verified, err := set.Verify() 326 require.NoError(t, err) 327 assert.Equal(t, true, verified, "Block signature set returned a set which was unable to be verified") 328 }