prysm-pulse/beacon-chain/casper/state_transition_test.go

263 lines
7.2 KiB
Go

package casper
import (
"bytes"
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/params"
"github.com/prysmaticlabs/prysm/beacon-chain/utils"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
b "github.com/prysmaticlabs/prysm/shared/bytes"
)
func TestTallyVoteBalances(t *testing.T) {
var validators []*pb.ValidatorRecord
var blockHash [32]byte
blockVoteCache := utils.NewBlockVoteCache()
initialBalance := uint64(1e9)
for i := 0; i < 1000; i++ {
validator := &pb.ValidatorRecord{
WithdrawalShard: 0,
Balance: initialBalance}
validators = append(validators, validator)
}
validators[20].Status = uint64(params.Active)
validators[10].Status = uint64(params.Active)
blockVote := &utils.BlockVote{
VoterIndices: []uint32{20, 10},
VoteTotalDeposit: 300,
}
copy(blockHash[:], []byte{'t', 'e', 's', 't', 'i', 'n', 'g'})
blockVoteCache[blockHash] = blockVote
zeroBalance, _ := TallyVoteBalances([32]byte{}, 10, blockVoteCache, validators, 2)
if zeroBalance != 0 {
t.Fatalf("votes have been calculated despite blockhash not existing in cache")
}
voteBalance, newValidators := TallyVoteBalances(blockHash, 10, blockVoteCache, validators, 2)
if voteBalance != 300 {
t.Fatalf("vote balances is not the amount expected %d", voteBalance)
}
if newValidators[1].Balance != initialBalance {
t.Fatalf("validator balance changed %d ", newValidators[1].Balance)
}
if newValidators[20].Balance == initialBalance {
t.Fatalf("validator balance not changed %d ", newValidators[20].Balance)
}
if newValidators[10].Balance == initialBalance {
t.Errorf("validator balance not changed %d ", newValidators[10].Balance)
}
}
func TestFinalizeAndJustifySlots(t *testing.T) {
slot := uint64(10)
justifiedSlot := uint64(8)
finalizedSlot := uint64(6)
justifiedStreak := uint64(2)
blockVoteBalance := uint64(2e9)
totalDeposit := uint64(4e9)
justifiedSlot, finalizedSlot, justifiedStreak = FinalizeAndJustifySlots(slot, justifiedSlot, finalizedSlot,
justifiedStreak, blockVoteBalance, totalDeposit)
if justifiedSlot != 8 {
t.Fatalf("justified slot has been updated %d", justifiedSlot)
}
if justifiedStreak != 0 {
t.Fatalf("justified streak not updated %d", justifiedStreak)
}
if finalizedSlot != 6 {
t.Fatalf("finalized slot changed when it was not supposed to %d", finalizedSlot)
}
blockVoteBalance = uint64(3e9)
justifiedSlot, finalizedSlot, justifiedStreak = FinalizeAndJustifySlots(slot, justifiedSlot, finalizedSlot,
justifiedStreak, blockVoteBalance, totalDeposit)
if justifiedSlot != 10 {
t.Fatalf("justified slot has not been updated %d", justifiedSlot)
}
if justifiedStreak != 1 {
t.Fatalf("justified streak not updated %d", justifiedStreak)
}
if finalizedSlot != 6 {
t.Fatalf("finalized slot changed when it was not supposed to %d", finalizedSlot)
}
slot = 100
justifiedStreak = 70
justifiedSlot, finalizedSlot, justifiedStreak = FinalizeAndJustifySlots(slot, justifiedSlot, finalizedSlot,
justifiedStreak, blockVoteBalance, totalDeposit)
if justifiedSlot != 100 {
t.Fatalf("justified slot has not been updated %d", justifiedSlot)
}
if justifiedStreak != 71 {
t.Fatalf("justified streak not updated %d", justifiedStreak)
}
if finalizedSlot == 6 {
t.Fatalf("finalized slot not updated when it was supposed to %d", finalizedSlot)
}
}
func TestApplyCrosslinkRewardsAndPenalties(t *testing.T) {
var validators []*pb.ValidatorRecord
initialBalance := uint64(1e9)
totalBalance := uint64(5e9)
voteBalance := uint64(4e9)
indices := []uint32{20, 10}
for i := 0; i < 1000; i++ {
validator := &pb.ValidatorRecord{
WithdrawalShard: 0,
Balance: initialBalance}
validators = append(validators, validator)
}
validators[20].Status = uint64(params.Active)
validators[10].Status = uint64(params.Active)
crossLinks := []*pb.CrosslinkRecord{
{
RecentlyChanged: false,
ShardBlockHash: []byte{'A'},
Slot: 10,
},
{
RecentlyChanged: false,
ShardBlockHash: []byte{'B'},
Slot: 10,
},
{
RecentlyChanged: false,
ShardBlockHash: []byte{'C'},
Slot: 10,
},
{
RecentlyChanged: false,
ShardBlockHash: []byte{'D'},
Slot: 10,
},
}
attestation := &pb.AggregatedAttestation{
Slot: 10,
Shard: 1,
AttesterBitfield: []byte{100, 128, 8},
}
ApplyCrosslinkRewardsAndPenalties(crossLinks, 12, indices, attestation, validators, totalBalance, voteBalance)
if validators[20].Balance <= initialBalance {
t.Fatalf("validator balance has not been updated %d", validators[20].Balance)
}
if validators[10].Balance >= initialBalance {
t.Fatalf("validator balance has not been updated %d", validators[10].Balance)
}
if validators[1].Balance != initialBalance {
t.Fatalf("validator balance updated when it was not supposed to %d", validators[1].Balance)
}
}
func TestCrosslinks(t *testing.T) {
totalBalance := uint64(5e9)
voteBalance := uint64(4e9)
crossLinks := []*pb.CrosslinkRecord{
{
RecentlyChanged: false,
ShardBlockHash: []byte{'A'},
Slot: 10,
},
{
RecentlyChanged: true,
ShardBlockHash: []byte{'A'},
Slot: 10,
},
}
attestation := &pb.AggregatedAttestation{
Slot: 10,
Shard: 1,
ShardBlockHash: []byte{'B'},
AttesterBitfield: []byte{100, 128, 8},
}
crossLinks = ProcessCrosslink(10, voteBalance, totalBalance, attestation, crossLinks)
if bytes.Equal(crossLinks[1].GetShardBlockHash(), []byte{'B'}) {
t.Fatal("crosslink updated when it was not supposed to")
}
crossLinks[1].RecentlyChanged = false
crossLinks = ProcessCrosslink(10, voteBalance, totalBalance, attestation, crossLinks)
if !bytes.Equal(crossLinks[1].GetShardBlockHash(), []byte{'B'}) {
t.Errorf("shard blockhash not saved in crosslink record %v", crossLinks[1].GetShardBlockHash())
}
}
func TestProcessSpecialRecords(t *testing.T) {
specialRecords := []*pb.SpecialRecord{
{Kind: uint32(params.Logout), Data: [][]byte{b.Bytes8(4)}}, // Validator 4
{Kind: uint32(params.Logout), Data: [][]byte{b.Bytes8(5)}}, // Validator 5
{Kind: uint32(params.RandaoChange), Data: [][]byte{b.Bytes8(6), {byte('A')}}}, // Validator 6
{Kind: uint32(params.RandaoChange), Data: [][]byte{b.Bytes8(7), {byte('B')}}}, // Validator 7
}
validators := make([]*pb.ValidatorRecord, 10)
for i := 0; i < len(validators); i++ {
validators[i] = &pb.ValidatorRecord{Status: uint64(params.Active)}
}
newValidators, err := ProcessSpecialRecords(99, validators, specialRecords)
if err != nil {
t.Fatalf("Failed to call process special records %v", err)
}
if newValidators[4].Status != uint64(params.PendingExit) {
t.Error("Validator 4 status is not PendingExit")
}
if newValidators[4].ExitSlot != 99 {
t.Error("Validator 4 exit slot is not 99")
}
if newValidators[5].Status != uint64(params.PendingExit) {
t.Error("Validator 5 status is not PendingExit")
}
if newValidators[5].ExitSlot != 99 {
t.Error("Validator 5 exit slot is not 99")
}
if !(bytes.Equal(newValidators[6].RandaoCommitment, []byte{'A'})) {
t.Error("Failed to set validator 7's randao reveal")
}
if !(bytes.Equal(newValidators[7].RandaoCommitment, []byte{'B'})) {
t.Error("Failed to set validator 8's randao reveal")
}
}