2020-07-06 22:27:42 +00:00
|
|
|
package blocks_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
|
|
|
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
|
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
|
|
"github.com/prysmaticlabs/prysm/shared/bls"
|
|
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
|
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
|
|
"github.com/prysmaticlabs/prysm/shared/testutil"
|
2020-08-08 19:06:04 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
|
|
|
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
2020-07-06 22:27:42 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/shared/trieutil"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestProcessDeposits_SameValidatorMultipleDepositsSameBlock(t *testing.T) {
|
|
|
|
// Same validator created 3 valid deposits within the same block
|
|
|
|
testutil.ResetCache()
|
|
|
|
dep, _, err := testutil.DeterministicDepositsAndKeysSameValidator(3)
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-09-01 01:29:27 +00:00
|
|
|
b := testutil.NewBeaconBlock()
|
|
|
|
b.Block = ðpb.BeaconBlock{
|
2020-07-06 22:27:42 +00:00
|
|
|
Body: ðpb.BeaconBlockBody{
|
|
|
|
// 3 deposits from the same validator
|
|
|
|
Deposits: []*ethpb.Deposit{dep[0], dep[1], dep[2]},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
registry := []*ethpb.Validator{
|
|
|
|
{
|
|
|
|
PublicKey: []byte{1},
|
|
|
|
WithdrawalCredentials: []byte{1, 2, 3},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
balances := []uint64{0}
|
|
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
|
|
Validators: registry,
|
|
|
|
Balances: balances,
|
|
|
|
Eth1Data: eth1Data,
|
|
|
|
Fork: &pb.Fork{
|
|
|
|
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
|
|
|
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
|
|
|
},
|
|
|
|
})
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-09-01 01:29:27 +00:00
|
|
|
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b)
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err, "Expected block deposits to process correctly")
|
2020-07-06 22:27:42 +00:00
|
|
|
|
2020-08-08 19:06:04 +00:00
|
|
|
assert.Equal(t, 2, len(newState.Validators()), "Incorrect validator count")
|
2020-07-06 22:27:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
|
|
|
|
deposit := ðpb.Deposit{
|
|
|
|
Data: ðpb.Deposit_Data{
|
2020-08-27 18:13:32 +00:00
|
|
|
PublicKey: bytesutil.PadTo([]byte{1, 2, 3}, 48),
|
|
|
|
WithdrawalCredentials: make([]byte, 32),
|
|
|
|
Signature: make([]byte, 96),
|
2020-07-06 22:27:42 +00:00
|
|
|
},
|
|
|
|
}
|
2020-08-27 18:13:32 +00:00
|
|
|
leaf, err := deposit.Data.HashTreeRoot()
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
|
|
|
|
// We then create a merkle branch for the test.
|
|
|
|
depositTrie, err := trieutil.GenerateTrieFromItems([][]byte{leaf[:]}, int(params.BeaconConfig().DepositContractTreeDepth))
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err, "Could not generate trie")
|
2020-07-06 22:27:42 +00:00
|
|
|
proof, err := depositTrie.MerkleProof(0)
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err, "Could not generate proof")
|
2020-07-06 22:27:42 +00:00
|
|
|
|
|
|
|
deposit.Proof = proof
|
2020-09-01 01:29:27 +00:00
|
|
|
b := testutil.NewBeaconBlock()
|
|
|
|
b.Block = ðpb.BeaconBlock{
|
2020-07-06 22:27:42 +00:00
|
|
|
Body: ðpb.BeaconBlockBody{
|
|
|
|
Deposits: []*ethpb.Deposit{deposit},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
|
|
Eth1Data: ðpb.Eth1Data{
|
|
|
|
DepositRoot: []byte{0},
|
|
|
|
BlockHash: []byte{1},
|
|
|
|
},
|
|
|
|
})
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
want := "deposit root did not verify"
|
2020-09-01 01:29:27 +00:00
|
|
|
_, err = blocks.ProcessDeposits(context.Background(), beaconState, b)
|
2020-08-08 19:06:04 +00:00
|
|
|
assert.ErrorContains(t, want, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestProcessDeposits_AddsNewValidatorDeposit(t *testing.T) {
|
|
|
|
dep, _, err := testutil.DeterministicDepositsAndKeys(1)
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
|
2020-09-01 01:29:27 +00:00
|
|
|
b := testutil.NewBeaconBlock()
|
|
|
|
b.Block = ðpb.BeaconBlock{
|
2020-07-06 22:27:42 +00:00
|
|
|
Body: ðpb.BeaconBlockBody{
|
|
|
|
Deposits: []*ethpb.Deposit{dep[0]},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
registry := []*ethpb.Validator{
|
|
|
|
{
|
|
|
|
PublicKey: []byte{1},
|
|
|
|
WithdrawalCredentials: []byte{1, 2, 3},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
balances := []uint64{0}
|
|
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
|
|
Validators: registry,
|
|
|
|
Balances: balances,
|
|
|
|
Eth1Data: eth1Data,
|
|
|
|
Fork: &pb.Fork{
|
|
|
|
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
|
|
|
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
|
|
|
},
|
|
|
|
})
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-09-01 01:29:27 +00:00
|
|
|
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b)
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err, "Expected block deposits to process correctly")
|
2020-07-06 22:27:42 +00:00
|
|
|
if newState.Balances()[1] != dep[0].Data.Amount {
|
|
|
|
t.Errorf(
|
|
|
|
"Expected state validator balances index 0 to equal %d, received %d",
|
|
|
|
dep[0].Data.Amount,
|
|
|
|
newState.Balances()[1],
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T) {
|
|
|
|
sk := bls.RandKey()
|
|
|
|
deposit := ðpb.Deposit{
|
|
|
|
Data: ðpb.Deposit_Data{
|
2020-08-27 18:13:32 +00:00
|
|
|
PublicKey: sk.PublicKey().Marshal(),
|
|
|
|
Amount: 1000,
|
|
|
|
WithdrawalCredentials: make([]byte, 32),
|
|
|
|
Signature: make([]byte, 96),
|
2020-07-06 22:27:42 +00:00
|
|
|
},
|
|
|
|
}
|
2020-08-27 18:13:32 +00:00
|
|
|
sr, err := helpers.ComputeSigningRoot(deposit.Data, bytesutil.ToBytes(3, 32))
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
sig := sk.Sign(sr[:])
|
|
|
|
deposit.Data.Signature = sig.Marshal()
|
2020-08-27 18:13:32 +00:00
|
|
|
leaf, err := deposit.Data.HashTreeRoot()
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
|
|
|
|
// We then create a merkle branch for the test.
|
|
|
|
depositTrie, err := trieutil.GenerateTrieFromItems([][]byte{leaf[:]}, int(params.BeaconConfig().DepositContractTreeDepth))
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err, "Could not generate trie")
|
2020-07-06 22:27:42 +00:00
|
|
|
proof, err := depositTrie.MerkleProof(0)
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err, "Could not generate proof")
|
2020-07-06 22:27:42 +00:00
|
|
|
|
|
|
|
deposit.Proof = proof
|
2020-09-01 01:29:27 +00:00
|
|
|
b := testutil.NewBeaconBlock()
|
|
|
|
b.Block = ðpb.BeaconBlock{
|
2020-07-06 22:27:42 +00:00
|
|
|
Body: ðpb.BeaconBlockBody{
|
|
|
|
Deposits: []*ethpb.Deposit{deposit},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
registry := []*ethpb.Validator{
|
|
|
|
{
|
|
|
|
PublicKey: []byte{1, 2, 3},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
PublicKey: sk.PublicKey().Marshal(),
|
|
|
|
WithdrawalCredentials: []byte{1},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
balances := []uint64{0, 50}
|
|
|
|
root := depositTrie.Root()
|
|
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
|
|
Validators: registry,
|
|
|
|
Balances: balances,
|
|
|
|
Eth1Data: ðpb.Eth1Data{
|
|
|
|
DepositRoot: root[:],
|
|
|
|
BlockHash: root[:],
|
|
|
|
},
|
|
|
|
})
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-09-01 01:29:27 +00:00
|
|
|
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b)
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err, "Process deposit failed")
|
|
|
|
assert.Equal(t, uint64(1000+50), newState.Balances()[1], "Expected balance at index 1 to be 1050")
|
2020-07-06 22:27:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestProcessDeposit_AddsNewValidatorDeposit(t *testing.T) {
|
|
|
|
//Similar to TestProcessDeposits_AddsNewValidatorDeposit except that this test directly calls ProcessDeposit
|
|
|
|
dep, _, err := testutil.DeterministicDepositsAndKeys(1)
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
|
|
|
|
registry := []*ethpb.Validator{
|
|
|
|
{
|
|
|
|
PublicKey: []byte{1},
|
|
|
|
WithdrawalCredentials: []byte{1, 2, 3},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
balances := []uint64{0}
|
|
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
|
|
Validators: registry,
|
|
|
|
Balances: balances,
|
|
|
|
Eth1Data: eth1Data,
|
|
|
|
Fork: &pb.Fork{
|
|
|
|
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
|
|
|
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
|
|
|
},
|
|
|
|
})
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
newState, err := blocks.ProcessDeposit(beaconState, dep[0], true)
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err, "Process deposit failed")
|
|
|
|
assert.Equal(t, 2, len(newState.Validators()), "Expected validator list to have length 2")
|
|
|
|
assert.Equal(t, 2, len(newState.Balances()), "Expected validator balances list to have length 2")
|
2020-07-06 22:27:42 +00:00
|
|
|
if newState.Balances()[1] != dep[0].Data.Amount {
|
|
|
|
t.Errorf(
|
|
|
|
"Expected state validator balances index 1 to equal %d, received %d",
|
|
|
|
dep[0].Data.Amount,
|
|
|
|
newState.Balances()[1],
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestProcessDeposit_SkipsInvalidDeposit(t *testing.T) {
|
|
|
|
// Same test settings as in TestProcessDeposit_AddsNewValidatorDeposit, except that we use an invalid signature
|
|
|
|
dep, _, err := testutil.DeterministicDepositsAndKeys(1)
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
dep[0].Data.Signature = make([]byte, 96)
|
|
|
|
trie, _, err := testutil.DepositTrieFromDeposits(dep)
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
root := trie.Root()
|
|
|
|
eth1Data := ðpb.Eth1Data{
|
|
|
|
DepositRoot: root[:],
|
|
|
|
DepositCount: 1,
|
|
|
|
}
|
|
|
|
registry := []*ethpb.Validator{
|
|
|
|
{
|
|
|
|
PublicKey: []byte{1},
|
|
|
|
WithdrawalCredentials: []byte{1, 2, 3},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
balances := []uint64{0}
|
|
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
|
|
Validators: registry,
|
|
|
|
Balances: balances,
|
|
|
|
Eth1Data: eth1Data,
|
|
|
|
Fork: &pb.Fork{
|
|
|
|
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
|
|
|
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
|
|
|
},
|
|
|
|
})
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err)
|
2020-07-06 22:27:42 +00:00
|
|
|
newState, err := blocks.ProcessDeposit(beaconState, dep[0], true)
|
2020-08-08 19:06:04 +00:00
|
|
|
require.NoError(t, err, "Expected invalid block deposit to be ignored without error")
|
2020-07-06 22:27:42 +00:00
|
|
|
|
|
|
|
if newState.Eth1DepositIndex() != 1 {
|
|
|
|
t.Errorf(
|
|
|
|
"Expected Eth1DepositIndex to be increased by 1 after processing an invalid deposit, received change: %v",
|
|
|
|
newState.Eth1DepositIndex(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
if len(newState.Validators()) != 1 {
|
|
|
|
t.Errorf("Expected validator list to have length 1, received: %v", len(newState.Validators()))
|
|
|
|
}
|
|
|
|
if len(newState.Balances()) != 1 {
|
|
|
|
t.Errorf("Expected validator balances list to have length 1, received: %v", len(newState.Balances()))
|
|
|
|
}
|
|
|
|
if newState.Balances()[0] != 0 {
|
|
|
|
t.Errorf("Expected validator balance at index 0 to stay 0, received: %v", newState.Balances()[0])
|
|
|
|
}
|
|
|
|
}
|