mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 05:47:59 -05:00
Fix same deposits from same validator in same block (#4319)
* Update dict * Test helper * Regression test * Comment * Reset test cache
This commit is contained in:
committed by
Raul Jordan
parent
ff1fd77425
commit
908d220eb2
@@ -934,6 +934,7 @@ func ProcessDeposit(beaconState *pb.BeaconState, deposit *ethpb.Deposit, valInde
|
||||
EffectiveBalance: effectiveBalance,
|
||||
})
|
||||
beaconState.Balances = append(beaconState.Balances, amount)
|
||||
valIndexMap[bytesutil.ToBytes48(pubKey)] = len(beaconState.Validators) - 1
|
||||
} else {
|
||||
beaconState = helpers.IncreaseBalance(beaconState, uint64(index), amount)
|
||||
}
|
||||
|
||||
@@ -1343,6 +1343,47 @@ func TestValidateIndexedAttestation_AboveMaxLength(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessDeposits_SameValidatorMultipleDepositsSameBlock(t *testing.T) {
|
||||
// Same validator created 3 valid deposits within the same block
|
||||
testutil.ResetCache()
|
||||
dep, _, _ := testutil.DeterministicDepositsAndKeysSameValidator(3)
|
||||
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(dep)
|
||||
block := ðpb.BeaconBlock{
|
||||
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 := &pb.BeaconState{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
Eth1Data: eth1Data,
|
||||
Fork: &pb.Fork{
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
},
|
||||
}
|
||||
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, block.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected block deposits to process correctly, received: %v", err)
|
||||
}
|
||||
|
||||
if len(newState.Validators) != 2 {
|
||||
t.Errorf("Incorrect validator count. Wanted %d, got %d", 2, len(newState.Validators))
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
|
||||
deposit := ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
|
||||
@@ -212,7 +212,7 @@ func CommitteeAssignments(state *pb.BeaconState, epoch uint64) (map[uint64]*Comm
|
||||
if epoch > NextEpoch(state) {
|
||||
return nil, nil, fmt.Errorf(
|
||||
"epoch %d can't be greater than next epoch %d",
|
||||
epoch,
|
||||
epoch,
|
||||
NextEpoch(state),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
|
||||
|
||||
state := &pb.BeaconState{
|
||||
Validators: validators,
|
||||
Slot: 2*params.BeaconConfig().SlotsPerEpoch, // epoch 2
|
||||
Slot: 2 * params.BeaconConfig().SlotsPerEpoch, // epoch 2
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
}
|
||||
|
||||
|
||||
@@ -306,7 +306,7 @@ func BenchmarkCommitteeAssignment(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
|
||||
genesis := blk.NewGenesisBlock([]byte{})
|
||||
depChainStart := uint64(8192*2)
|
||||
depChainStart := uint64(8192 * 2)
|
||||
deposits, _, _ := testutil.DeterministicDepositsAndKeys(depChainStart)
|
||||
eth1Data, err := testutil.DeterministicEth1Data(len(deposits))
|
||||
if err != nil {
|
||||
|
||||
@@ -189,3 +189,79 @@ func ResetCache() {
|
||||
privKeys = []*bls.SecretKey{}
|
||||
cachedDeposits = []*ethpb.Deposit{}
|
||||
}
|
||||
|
||||
// DeterministicDepositsAndKeysSameValidator returns the entered amount of deposits and secret keys.
|
||||
// of the same validator. This is for negative test cases such as same deposits from same validators in a block don't
|
||||
// result in duplicated validator indices.
|
||||
func DeterministicDepositsAndKeysSameValidator(numDeposits uint64) ([]*ethpb.Deposit, []*bls.SecretKey, error) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
var err error
|
||||
|
||||
// Populate trie cache, if not initialized yet.
|
||||
if trie == nil {
|
||||
trie, err = trieutil.NewTrie(int(params.BeaconConfig().DepositContractTreeDepth))
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "failed to create new trie")
|
||||
}
|
||||
}
|
||||
|
||||
// If more deposits requested than cached, generate more.
|
||||
if numDeposits > uint64(len(cachedDeposits)) {
|
||||
numExisting := uint64(len(cachedDeposits))
|
||||
numRequired := numDeposits - uint64(len(cachedDeposits))
|
||||
// Fetch the required number of keys.
|
||||
secretKeys, publicKeys, err := interop.DeterministicallyGenerateKeys(numExisting, numRequired+1)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not create deterministic keys: ")
|
||||
}
|
||||
privKeys = append(privKeys, secretKeys[:len(secretKeys)-1]...)
|
||||
|
||||
// Create the new deposits and add them to the trie. Always use the first validator to create deposit
|
||||
for i := uint64(0); i < numRequired; i++ {
|
||||
withdrawalCreds := hashutil.Hash(publicKeys[1].Marshal())
|
||||
withdrawalCreds[0] = params.BeaconConfig().BLSWithdrawalPrefixByte
|
||||
|
||||
depositData := ðpb.Deposit_Data{
|
||||
PublicKey: publicKeys[1].Marshal(),
|
||||
Amount: params.BeaconConfig().MaxEffectiveBalance,
|
||||
WithdrawalCredentials: withdrawalCreds[:],
|
||||
}
|
||||
|
||||
domain := bls.ComputeDomain(params.BeaconConfig().DomainDeposit)
|
||||
root, err := ssz.SigningRoot(depositData)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not get signing root of deposit data")
|
||||
}
|
||||
// Always use the same validator to sign
|
||||
depositData.Signature = secretKeys[1].Sign(root[:], domain).Marshal()
|
||||
|
||||
deposit := ðpb.Deposit{
|
||||
Data: depositData,
|
||||
}
|
||||
cachedDeposits = append(cachedDeposits, deposit)
|
||||
|
||||
hashedDeposit, err := ssz.HashTreeRoot(deposit.Data)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not tree hash deposit data")
|
||||
}
|
||||
|
||||
trie.Insert(hashedDeposit[:], int(numExisting+i))
|
||||
}
|
||||
}
|
||||
|
||||
depositTrie, _, err := DeterministicDepositTrie(int(numDeposits))
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "failed to create deposit trie")
|
||||
}
|
||||
requestedDeposits := cachedDeposits[:numDeposits]
|
||||
for i := range requestedDeposits {
|
||||
proof, err := depositTrie.MerkleProof(int(i))
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not create merkle proof")
|
||||
}
|
||||
requestedDeposits[i].Proof = proof
|
||||
}
|
||||
|
||||
return requestedDeposits, privKeys[0:numDeposits], nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user