diff --git a/beacon-chain/core/blocks/withdrawals.go b/beacon-chain/core/blocks/withdrawals.go index 79ec767ca..05114667f 100644 --- a/beacon-chain/core/blocks/withdrawals.go +++ b/beacon-chain/core/blocks/withdrawals.go @@ -176,7 +176,17 @@ func BLSChangesSignatureBatch( Descriptions: make([]string, len(changes)), } epoch := slots.ToEpoch(st.Slot()) - domain, err := signing.Domain(st.Fork(), epoch, params.BeaconConfig().DomainBLSToExecutionChange, st.GenesisValidatorsRoot()) + var fork *ethpb.Fork + if st.Version() < version.Capella { + fork = ðpb.Fork{ + PreviousVersion: params.BeaconConfig().BellatrixForkVersion, + CurrentVersion: params.BeaconConfig().CapellaForkVersion, + Epoch: params.BeaconConfig().CapellaForkEpoch, + } + } else { + fork = st.Fork() + } + domain, err := signing.Domain(fork, epoch, params.BeaconConfig().DomainBLSToExecutionChange, st.GenesisValidatorsRoot()) if err != nil { return nil, err } diff --git a/beacon-chain/core/blocks/withdrawals_test.go b/beacon-chain/core/blocks/withdrawals_test.go index c6d18248c..b022533c6 100644 --- a/beacon-chain/core/blocks/withdrawals_test.go +++ b/beacon-chain/core/blocks/withdrawals_test.go @@ -785,3 +785,73 @@ func TestBLSChangesSignatureBatch(t *testing.T) { require.NoError(t, err) require.Equal(t, true, verify) } + +func TestBLSChangesSignatureBatchFromBellatrix(t *testing.T) { + spb := ðpb.BeaconStateBellatrix{ + Fork: ðpb.Fork{ + CurrentVersion: params.BeaconConfig().AltairForkVersion, + PreviousVersion: params.BeaconConfig().BellatrixForkVersion, + }, + } + numValidators := 10 + validators := make([]*ethpb.Validator, numValidators) + blsChanges := make([]*ethpb.BLSToExecutionChange, numValidators) + spb.Balances = make([]uint64, numValidators) + privKeys := make([]common.SecretKey, numValidators) + maxEffectiveBalance := params.BeaconConfig().MaxEffectiveBalance + executionAddress := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13} + + for i := range validators { + v := ðpb.Validator{} + v.EffectiveBalance = maxEffectiveBalance + v.WithdrawableEpoch = params.BeaconConfig().FarFutureEpoch + v.WithdrawalCredentials = make([]byte, 32) + priv, err := bls.RandKey() + require.NoError(t, err) + privKeys[i] = priv + pubkey := priv.PublicKey().Marshal() + + message := ðpb.BLSToExecutionChange{ + ToExecutionAddress: executionAddress, + ValidatorIndex: types.ValidatorIndex(i), + FromBlsPubkey: pubkey, + } + + hashFn := ssz.NewHasherFunc(hash.CustomSHA256Hasher()) + digest := hashFn.Hash(pubkey) + digest[0] = params.BeaconConfig().BLSWithdrawalPrefixByte + copy(v.WithdrawalCredentials, digest[:]) + validators[i] = v + blsChanges[i] = message + } + spb.Validators = validators + st, err := state_native.InitializeFromProtoBellatrix(spb) + require.NoError(t, err) + + signedChanges := make([]*ethpb.SignedBLSToExecutionChange, numValidators) + spc := ðpb.BeaconStateCapella{ + Fork: ðpb.Fork{ + CurrentVersion: params.BeaconConfig().CapellaForkVersion, + PreviousVersion: params.BeaconConfig().BellatrixForkVersion, + Epoch: params.BeaconConfig().CapellaForkEpoch, + }, + } + stc, err := state_native.InitializeFromProtoCapella(spc) + require.NoError(t, err) + + for i, message := range blsChanges { + signature, err := signing.ComputeDomainAndSign(stc, time.CurrentEpoch(stc), message, params.BeaconConfig().DomainBLSToExecutionChange, privKeys[i]) + require.NoError(t, err) + + signed := ðpb.SignedBLSToExecutionChange{ + Message: message, + Signature: signature, + } + signedChanges[i] = signed + } + batch, err := blocks.BLSChangesSignatureBatch(st, signedChanges) + require.NoError(t, err) + verify, err := batch.Verify() + require.NoError(t, err) + require.Equal(t, true, verify) +}