github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/state/v1/state_trie_test.go (about) 1 package v1_test 2 3 import ( 4 "bytes" 5 "context" 6 "testing" 7 8 types "github.com/prysmaticlabs/eth2-types" 9 "github.com/prysmaticlabs/go-bitfield" 10 iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface" 11 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" 12 pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 13 eth "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 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 ) 20 21 func TestInitializeFromProto(t *testing.T) { 22 testState, _ := testutil.DeterministicGenesisState(t, 64) 23 pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) 24 require.NoError(t, err) 25 type test struct { 26 name string 27 state *pbp2p.BeaconState 28 error string 29 } 30 initTests := []test{ 31 { 32 name: "nil state", 33 state: nil, 34 error: "received nil state", 35 }, 36 { 37 name: "nil validators", 38 state: &pbp2p.BeaconState{ 39 Slot: 4, 40 Validators: nil, 41 }, 42 }, 43 { 44 name: "empty state", 45 state: &pbp2p.BeaconState{}, 46 }, 47 { 48 name: "full state", 49 state: pbState, 50 }, 51 } 52 for _, tt := range initTests { 53 t.Run(tt.name, func(t *testing.T) { 54 _, err := v1.InitializeFromProto(tt.state) 55 if tt.error != "" { 56 assert.ErrorContains(t, tt.error, err) 57 } else { 58 assert.NoError(t, err) 59 } 60 }) 61 } 62 } 63 64 func TestInitializeFromProtoUnsafe(t *testing.T) { 65 testState, _ := testutil.DeterministicGenesisState(t, 64) 66 pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) 67 require.NoError(t, err) 68 type test struct { 69 name string 70 state *pbp2p.BeaconState 71 error string 72 } 73 initTests := []test{ 74 { 75 name: "nil state", 76 state: nil, 77 error: "received nil state", 78 }, 79 { 80 name: "nil validators", 81 state: &pbp2p.BeaconState{ 82 Slot: 4, 83 Validators: nil, 84 }, 85 }, 86 { 87 name: "empty state", 88 state: &pbp2p.BeaconState{}, 89 }, 90 { 91 name: "full state", 92 state: pbState, 93 }, 94 } 95 for _, tt := range initTests { 96 t.Run(tt.name, func(t *testing.T) { 97 _, err := v1.InitializeFromProtoUnsafe(tt.state) 98 if tt.error != "" { 99 assert.ErrorContains(t, tt.error, err) 100 } else { 101 assert.NoError(t, err) 102 } 103 }) 104 } 105 } 106 107 func TestBeaconState_HashTreeRoot(t *testing.T) { 108 testState, _ := testutil.DeterministicGenesisState(t, 64) 109 110 type test struct { 111 name string 112 stateModify func(beaconState iface.BeaconState) (iface.BeaconState, error) 113 error string 114 } 115 initTests := []test{ 116 { 117 name: "unchanged state", 118 stateModify: func(beaconState iface.BeaconState) (iface.BeaconState, error) { 119 return beaconState, nil 120 }, 121 error: "", 122 }, 123 { 124 name: "different slot", 125 stateModify: func(beaconState iface.BeaconState) (iface.BeaconState, error) { 126 if err := beaconState.SetSlot(5); err != nil { 127 return nil, err 128 } 129 return beaconState, nil 130 }, 131 error: "", 132 }, 133 { 134 name: "different validator balance", 135 stateModify: func(beaconState iface.BeaconState) (iface.BeaconState, error) { 136 val, err := beaconState.ValidatorAtIndex(5) 137 if err != nil { 138 return nil, err 139 } 140 val.EffectiveBalance = params.BeaconConfig().MaxEffectiveBalance - params.BeaconConfig().EffectiveBalanceIncrement 141 if err := beaconState.UpdateValidatorAtIndex(5, val); err != nil { 142 return nil, err 143 } 144 return beaconState, nil 145 }, 146 error: "", 147 }, 148 } 149 150 var err error 151 var oldHTR []byte 152 for _, tt := range initTests { 153 t.Run(tt.name, func(t *testing.T) { 154 testState, err = tt.stateModify(testState) 155 assert.NoError(t, err) 156 root, err := testState.HashTreeRoot(context.Background()) 157 if err == nil && tt.error != "" { 158 t.Errorf("Expected error, expected %v, recevied %v", tt.error, err) 159 } 160 pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) 161 require.NoError(t, err) 162 genericHTR, err := pbState.HashTreeRoot() 163 if err == nil && tt.error != "" { 164 t.Errorf("Expected error, expected %v, recevied %v", tt.error, err) 165 } 166 assert.DeepNotEqual(t, []byte{}, root[:], "Received empty hash tree root") 167 assert.DeepEqual(t, genericHTR[:], root[:], "Expected hash tree root to match generic") 168 if len(oldHTR) != 0 && bytes.Equal(root[:], oldHTR) { 169 t.Errorf("Expected HTR to change, received %#x == old %#x", root, oldHTR) 170 } 171 oldHTR = root[:] 172 }) 173 } 174 } 175 176 func TestBeaconState_HashTreeRoot_FieldTrie(t *testing.T) { 177 testState, _ := testutil.DeterministicGenesisState(t, 64) 178 179 type test struct { 180 name string 181 stateModify func(iface.BeaconState) (iface.BeaconState, error) 182 error string 183 } 184 initTests := []test{ 185 { 186 name: "unchanged state", 187 stateModify: func(beaconState iface.BeaconState) (iface.BeaconState, error) { 188 return beaconState, nil 189 }, 190 error: "", 191 }, 192 { 193 name: "different slot", 194 stateModify: func(beaconState iface.BeaconState) (iface.BeaconState, error) { 195 if err := beaconState.SetSlot(5); err != nil { 196 return nil, err 197 } 198 return beaconState, nil 199 }, 200 error: "", 201 }, 202 { 203 name: "different validator balance", 204 stateModify: func(beaconState iface.BeaconState) (iface.BeaconState, error) { 205 val, err := beaconState.ValidatorAtIndex(5) 206 if err != nil { 207 return nil, err 208 } 209 val.EffectiveBalance = params.BeaconConfig().MaxEffectiveBalance - params.BeaconConfig().EffectiveBalanceIncrement 210 if err := beaconState.UpdateValidatorAtIndex(5, val); err != nil { 211 return nil, err 212 } 213 return beaconState, nil 214 }, 215 error: "", 216 }, 217 } 218 219 var err error 220 var oldHTR []byte 221 for _, tt := range initTests { 222 t.Run(tt.name, func(t *testing.T) { 223 testState, err = tt.stateModify(testState) 224 assert.NoError(t, err) 225 root, err := testState.HashTreeRoot(context.Background()) 226 if err == nil && tt.error != "" { 227 t.Errorf("Expected error, expected %v, recevied %v", tt.error, err) 228 } 229 pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) 230 require.NoError(t, err) 231 genericHTR, err := pbState.HashTreeRoot() 232 if err == nil && tt.error != "" { 233 t.Errorf("Expected error, expected %v, recevied %v", tt.error, err) 234 } 235 assert.DeepNotEqual(t, []byte{}, root[:], "Received empty hash tree root") 236 assert.DeepEqual(t, genericHTR[:], root[:], "Expected hash tree root to match generic") 237 if len(oldHTR) != 0 && bytes.Equal(root[:], oldHTR) { 238 t.Errorf("Expected HTR to change, received %#x == old %#x", root, oldHTR) 239 } 240 oldHTR = root[:] 241 }) 242 } 243 } 244 245 func TestBeaconState_AppendValidator_DoesntMutateCopy(t *testing.T) { 246 st0, err := testutil.NewBeaconState() 247 require.NoError(t, err) 248 st1 := st0.Copy() 249 originalCount := st1.NumValidators() 250 251 val := ð.Validator{Slashed: true} 252 assert.NoError(t, st0.AppendValidator(val)) 253 assert.Equal(t, originalCount, st1.NumValidators(), "st1 NumValidators mutated") 254 _, ok := st1.ValidatorIndexByPubkey(bytesutil.ToBytes48(val.PublicKey)) 255 assert.Equal(t, false, ok, "Expected no validator index to be present in st1 for the newly inserted pubkey") 256 } 257 258 func TestBeaconState_ToProto(t *testing.T) { 259 source, err := testutil.NewBeaconState(testutil.FillRootsNaturalOpt, func(state *pbp2p.BeaconState) error { 260 state.GenesisTime = 1 261 state.GenesisValidatorsRoot = bytesutil.PadTo([]byte("genesisvalidatorroot"), 32) 262 state.Slot = 2 263 state.Fork = &pbp2p.Fork{ 264 PreviousVersion: bytesutil.PadTo([]byte("123"), 4), 265 CurrentVersion: bytesutil.PadTo([]byte("456"), 4), 266 Epoch: 3, 267 } 268 state.LatestBlockHeader = ð.BeaconBlockHeader{ 269 Slot: 4, 270 ProposerIndex: 5, 271 ParentRoot: bytesutil.PadTo([]byte("lbhparentroot"), 32), 272 StateRoot: bytesutil.PadTo([]byte("lbhstateroot"), 32), 273 BodyRoot: bytesutil.PadTo([]byte("lbhbodyroot"), 32), 274 } 275 state.BlockRoots = [][]byte{bytesutil.PadTo([]byte("blockroots"), 32)} 276 state.StateRoots = [][]byte{bytesutil.PadTo([]byte("stateroots"), 32)} 277 state.HistoricalRoots = [][]byte{bytesutil.PadTo([]byte("historicalroots"), 32)} 278 state.Eth1Data = ð.Eth1Data{ 279 DepositRoot: bytesutil.PadTo([]byte("e1ddepositroot"), 32), 280 DepositCount: 6, 281 BlockHash: bytesutil.PadTo([]byte("e1dblockhash"), 32), 282 } 283 state.Eth1DataVotes = []*eth.Eth1Data{{ 284 DepositRoot: bytesutil.PadTo([]byte("e1dvdepositroot"), 32), 285 DepositCount: 7, 286 BlockHash: bytesutil.PadTo([]byte("e1dvblockhash"), 32), 287 }} 288 state.Eth1DepositIndex = 8 289 state.Validators = []*eth.Validator{{ 290 PublicKey: bytesutil.PadTo([]byte("publickey"), 48), 291 WithdrawalCredentials: bytesutil.PadTo([]byte("withdrawalcredentials"), 32), 292 EffectiveBalance: 9, 293 Slashed: true, 294 ActivationEligibilityEpoch: 10, 295 ActivationEpoch: 11, 296 ExitEpoch: 12, 297 WithdrawableEpoch: 13, 298 }} 299 state.Balances = []uint64{14} 300 state.RandaoMixes = [][]byte{bytesutil.PadTo([]byte("randaomixes"), 32)} 301 state.Slashings = []uint64{15} 302 state.PreviousEpochAttestations = []*pbp2p.PendingAttestation{{ 303 AggregationBits: bitfield.Bitlist{16}, 304 Data: ð.AttestationData{ 305 Slot: 17, 306 CommitteeIndex: 18, 307 BeaconBlockRoot: bytesutil.PadTo([]byte("peabeaconblockroot"), 32), 308 Source: ð.Checkpoint{ 309 Epoch: 19, 310 Root: bytesutil.PadTo([]byte("peasroot"), 32), 311 }, 312 Target: ð.Checkpoint{ 313 Epoch: 20, 314 Root: bytesutil.PadTo([]byte("peatroot"), 32), 315 }, 316 }, 317 InclusionDelay: 21, 318 ProposerIndex: 22, 319 }} 320 state.CurrentEpochAttestations = []*pbp2p.PendingAttestation{{ 321 AggregationBits: bitfield.Bitlist{23}, 322 Data: ð.AttestationData{ 323 Slot: 24, 324 CommitteeIndex: 25, 325 BeaconBlockRoot: bytesutil.PadTo([]byte("ceabeaconblockroot"), 32), 326 Source: ð.Checkpoint{ 327 Epoch: 26, 328 Root: bytesutil.PadTo([]byte("ceasroot"), 32), 329 }, 330 Target: ð.Checkpoint{ 331 Epoch: 27, 332 Root: bytesutil.PadTo([]byte("ceatroot"), 32), 333 }, 334 }, 335 InclusionDelay: 28, 336 ProposerIndex: 29, 337 }} 338 state.JustificationBits = bitfield.Bitvector4{1} 339 state.PreviousJustifiedCheckpoint = ð.Checkpoint{ 340 Epoch: 30, 341 Root: bytesutil.PadTo([]byte("pjcroot"), 32), 342 } 343 state.CurrentJustifiedCheckpoint = ð.Checkpoint{ 344 Epoch: 31, 345 Root: bytesutil.PadTo([]byte("cjcroot"), 32), 346 } 347 state.FinalizedCheckpoint = ð.Checkpoint{ 348 Epoch: 32, 349 Root: bytesutil.PadTo([]byte("fcroot"), 32), 350 } 351 return nil 352 }) 353 require.NoError(t, err) 354 355 result, err := source.ToProto() 356 require.NoError(t, err) 357 require.NotNil(t, result) 358 assert.Equal(t, uint64(1), result.GenesisTime) 359 assert.DeepEqual(t, bytesutil.PadTo([]byte("genesisvalidatorroot"), 32), result.GenesisValidatorsRoot) 360 assert.Equal(t, types.Slot(2), result.Slot) 361 resultFork := result.Fork 362 require.NotNil(t, resultFork) 363 assert.DeepEqual(t, bytesutil.PadTo([]byte("123"), 4), resultFork.PreviousVersion) 364 assert.DeepEqual(t, bytesutil.PadTo([]byte("456"), 4), resultFork.CurrentVersion) 365 assert.Equal(t, types.Epoch(3), resultFork.Epoch) 366 resultLatestBlockHeader := result.LatestBlockHeader 367 require.NotNil(t, resultLatestBlockHeader) 368 assert.Equal(t, types.Slot(4), resultLatestBlockHeader.Slot) 369 assert.Equal(t, types.ValidatorIndex(5), resultLatestBlockHeader.ProposerIndex) 370 assert.DeepEqual(t, bytesutil.PadTo([]byte("lbhparentroot"), 32), resultLatestBlockHeader.ParentRoot) 371 assert.DeepEqual(t, bytesutil.PadTo([]byte("lbhstateroot"), 32), resultLatestBlockHeader.StateRoot) 372 assert.DeepEqual(t, bytesutil.PadTo([]byte("lbhbodyroot"), 32), resultLatestBlockHeader.BodyRoot) 373 assert.DeepEqual(t, [][]byte{bytesutil.PadTo([]byte("blockroots"), 32)}, result.BlockRoots) 374 assert.DeepEqual(t, [][]byte{bytesutil.PadTo([]byte("stateroots"), 32)}, result.StateRoots) 375 assert.DeepEqual(t, [][]byte{bytesutil.PadTo([]byte("historicalroots"), 32)}, result.HistoricalRoots) 376 resultEth1Data := result.Eth1Data 377 require.NotNil(t, resultEth1Data) 378 assert.DeepEqual(t, bytesutil.PadTo([]byte("e1ddepositroot"), 32), resultEth1Data.DepositRoot) 379 assert.Equal(t, uint64(6), resultEth1Data.DepositCount) 380 assert.DeepEqual(t, bytesutil.PadTo([]byte("e1dblockhash"), 32), resultEth1Data.BlockHash) 381 require.Equal(t, 1, len(result.Eth1DataVotes)) 382 resultEth1DataVote := result.Eth1DataVotes[0] 383 require.NotNil(t, resultEth1DataVote) 384 assert.DeepEqual(t, bytesutil.PadTo([]byte("e1dvdepositroot"), 32), resultEth1DataVote.DepositRoot) 385 assert.Equal(t, uint64(7), resultEth1DataVote.DepositCount) 386 assert.DeepEqual(t, bytesutil.PadTo([]byte("e1dvblockhash"), 32), resultEth1DataVote.BlockHash) 387 assert.Equal(t, uint64(8), result.Eth1DepositIndex) 388 require.Equal(t, 1, len(result.Validators)) 389 resultValidator := result.Validators[0] 390 require.NotNil(t, resultValidator) 391 assert.DeepEqual(t, bytesutil.PadTo([]byte("publickey"), 48), resultValidator.Pubkey) 392 assert.DeepEqual(t, bytesutil.PadTo([]byte("withdrawalcredentials"), 32), resultValidator.WithdrawalCredentials) 393 assert.Equal(t, uint64(9), resultValidator.EffectiveBalance) 394 assert.Equal(t, true, resultValidator.Slashed) 395 assert.Equal(t, types.Epoch(10), resultValidator.ActivationEligibilityEpoch) 396 assert.Equal(t, types.Epoch(11), resultValidator.ActivationEpoch) 397 assert.Equal(t, types.Epoch(12), resultValidator.ExitEpoch) 398 assert.Equal(t, types.Epoch(13), resultValidator.WithdrawableEpoch) 399 assert.DeepEqual(t, []uint64{14}, result.Balances) 400 assert.DeepEqual(t, [][]byte{bytesutil.PadTo([]byte("randaomixes"), 32)}, result.RandaoMixes) 401 assert.DeepEqual(t, []uint64{15}, result.Slashings) 402 require.Equal(t, 1, len(result.PreviousEpochAttestations)) 403 resultPrevEpochAtt := result.PreviousEpochAttestations[0] 404 require.NotNil(t, resultPrevEpochAtt) 405 assert.DeepEqual(t, bitfield.Bitlist{16}, resultPrevEpochAtt.AggregationBits) 406 resultPrevEpochAttData := resultPrevEpochAtt.Data 407 require.NotNil(t, resultPrevEpochAttData) 408 assert.Equal(t, types.Slot(17), resultPrevEpochAttData.Slot) 409 assert.Equal(t, types.CommitteeIndex(18), resultPrevEpochAttData.Index) 410 assert.DeepEqual(t, bytesutil.PadTo([]byte("peabeaconblockroot"), 32), resultPrevEpochAttData.BeaconBlockRoot) 411 resultPrevEpochAttSource := resultPrevEpochAttData.Source 412 require.NotNil(t, resultPrevEpochAttSource) 413 assert.Equal(t, types.Epoch(19), resultPrevEpochAttSource.Epoch) 414 assert.DeepEqual(t, bytesutil.PadTo([]byte("peasroot"), 32), resultPrevEpochAttSource.Root) 415 resultPrevEpochAttTarget := resultPrevEpochAttData.Target 416 require.NotNil(t, resultPrevEpochAttTarget) 417 assert.Equal(t, types.Epoch(20), resultPrevEpochAttTarget.Epoch) 418 assert.DeepEqual(t, bytesutil.PadTo([]byte("peatroot"), 32), resultPrevEpochAttTarget.Root) 419 assert.Equal(t, types.Slot(21), resultPrevEpochAtt.InclusionDelay) 420 assert.Equal(t, types.ValidatorIndex(22), resultPrevEpochAtt.ProposerIndex) 421 resultCurrEpochAtt := result.CurrentEpochAttestations[0] 422 require.NotNil(t, resultCurrEpochAtt) 423 assert.DeepEqual(t, bitfield.Bitlist{23}, resultCurrEpochAtt.AggregationBits) 424 resultCurrEpochAttData := resultCurrEpochAtt.Data 425 require.NotNil(t, resultCurrEpochAttData) 426 assert.Equal(t, types.Slot(24), resultCurrEpochAttData.Slot) 427 assert.Equal(t, types.CommitteeIndex(25), resultCurrEpochAttData.Index) 428 assert.DeepEqual(t, bytesutil.PadTo([]byte("ceabeaconblockroot"), 32), resultCurrEpochAttData.BeaconBlockRoot) 429 resultCurrEpochAttSource := resultCurrEpochAttData.Source 430 require.NotNil(t, resultCurrEpochAttSource) 431 assert.Equal(t, types.Epoch(26), resultCurrEpochAttSource.Epoch) 432 assert.DeepEqual(t, bytesutil.PadTo([]byte("ceasroot"), 32), resultCurrEpochAttSource.Root) 433 resultCurrEpochAttTarget := resultCurrEpochAttData.Target 434 require.NotNil(t, resultCurrEpochAttTarget) 435 assert.Equal(t, types.Epoch(27), resultCurrEpochAttTarget.Epoch) 436 assert.DeepEqual(t, bytesutil.PadTo([]byte("ceatroot"), 32), resultCurrEpochAttTarget.Root) 437 assert.Equal(t, types.Slot(28), resultCurrEpochAtt.InclusionDelay) 438 assert.Equal(t, types.ValidatorIndex(29), resultCurrEpochAtt.ProposerIndex) 439 assert.DeepEqual(t, bitfield.Bitvector4{1}, result.JustificationBits) 440 resultPrevJustifiedCheckpoint := result.PreviousJustifiedCheckpoint 441 require.NotNil(t, resultPrevJustifiedCheckpoint) 442 assert.Equal(t, types.Epoch(30), resultPrevJustifiedCheckpoint.Epoch) 443 assert.DeepEqual(t, bytesutil.PadTo([]byte("pjcroot"), 32), resultPrevJustifiedCheckpoint.Root) 444 resultCurrJustifiedCheckpoint := result.CurrentJustifiedCheckpoint 445 require.NotNil(t, resultCurrJustifiedCheckpoint) 446 assert.Equal(t, types.Epoch(31), resultCurrJustifiedCheckpoint.Epoch) 447 assert.DeepEqual(t, bytesutil.PadTo([]byte("cjcroot"), 32), resultCurrJustifiedCheckpoint.Root) 448 resultFinalizedCheckpoint := result.FinalizedCheckpoint 449 require.NotNil(t, resultFinalizedCheckpoint) 450 assert.Equal(t, types.Epoch(32), resultFinalizedCheckpoint.Epoch) 451 assert.DeepEqual(t, bytesutil.PadTo([]byte("fcroot"), 32), resultFinalizedCheckpoint.Root) 452 }