Update ProcessBlock to use a pipeline (#7148)

This commit is contained in:
terence tsao
2020-08-31 18:29:27 -07:00
committed by GitHub
parent ecbab20bad
commit fbe088625a
26 changed files with 315 additions and 276 deletions

View File

@@ -22,10 +22,14 @@ import (
func ProcessAttestations(
ctx context.Context,
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
var err error
for idx, attestation := range body.Attestations {
for idx, attestation := range b.Block.Body.Attestations {
beaconState, err = ProcessAttestation(ctx, beaconState, attestation)
if err != nil {
return nil, errors.Wrapf(err, "could not verify attestation at index %d in block", idx)
@@ -80,8 +84,12 @@ func ProcessAttestation(
func ProcessAttestationsNoVerifySignature(
ctx context.Context,
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
body := b.Block.Body
var err error
for idx, attestation := range body.Attestations {
beaconState, err = ProcessAttestationNoVerifySignature(ctx, beaconState, attestation)
@@ -205,9 +213,10 @@ func ProcessAttestationNoVerifySignature(
// of the provided attestations must have valid signatures or this method will return an error.
// This method does not determine which attestation signature is invalid, only that one or more
// attestation signatures were not valid.
func VerifyAttestationsSignatures(ctx context.Context, beaconState *stateTrie.BeaconState, atts []*ethpb.Attestation) error {
func VerifyAttestationsSignatures(ctx context.Context, beaconState *stateTrie.BeaconState, b *ethpb.SignedBeaconBlock) error {
ctx, span := trace.StartSpan(ctx, "core.VerifyAttestationsSignatures")
defer span.End()
atts := b.Block.Body.Attestations
span.AddAttributes(trace.Int64Attribute("attestations", int64(len(atts))))
if len(atts) == 0 {

View File

@@ -31,7 +31,8 @@ func TestProcessAttestations_InclusionDelayFailure(t *testing.T) {
},
},
}
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: attestations,
},
@@ -44,7 +45,7 @@ func TestProcessAttestations_InclusionDelayFailure(t *testing.T) {
params.BeaconConfig().MinAttestationInclusionDelay,
beaconState.Slot(),
)
_, err := blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err := blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -54,7 +55,8 @@ func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0}}}
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: []*ethpb.Attestation{att},
},
@@ -73,7 +75,7 @@ func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
helpers.PrevEpoch(beaconState),
helpers.CurrentEpoch(beaconState),
)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -88,7 +90,8 @@ func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
AggregationBits: aggBits,
},
}
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: attestations,
},
@@ -105,18 +108,18 @@ func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
helpers.CurrentEpoch(beaconState),
attestations[0].Data.Source.Epoch,
)
_, err := blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err := blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
block.Body.Attestations[0].Data.Source.Epoch = helpers.CurrentEpoch(beaconState)
block.Body.Attestations[0].Data.Source.Root = []byte{}
b.Block.Body.Attestations[0].Data.Source.Epoch = helpers.CurrentEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Source.Root = []byte{}
want = fmt.Sprintf(
"expected source root %#x, received %#x",
beaconState.CurrentJustifiedCheckpoint().Root,
attestations[0].Data.Source.Root,
)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -135,7 +138,8 @@ func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
AggregationBits: aggBits,
},
}
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: attestations,
},
@@ -153,19 +157,19 @@ func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
helpers.PrevEpoch(beaconState),
attestations[0].Data.Source.Epoch,
)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
block.Body.Attestations[0].Data.Source.Epoch = helpers.PrevEpoch(beaconState)
block.Body.Attestations[0].Data.Target.Epoch = helpers.CurrentEpoch(beaconState)
block.Body.Attestations[0].Data.Source.Root = []byte{}
b.Block.Body.Attestations[0].Data.Source.Epoch = helpers.PrevEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Target.Epoch = helpers.CurrentEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Source.Root = []byte{}
want = fmt.Sprintf(
"expected source root %#x, received %#x",
beaconState.CurrentJustifiedCheckpoint().Root,
attestations[0].Data.Source.Root,
)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -180,7 +184,8 @@ func TestProcessAttestations_InvalidAggregationBitsLength(t *testing.T) {
AggregationBits: aggBits,
}
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: []*ethpb.Attestation{att},
},
@@ -195,7 +200,7 @@ func TestProcessAttestations_InvalidAggregationBitsLength(t *testing.T) {
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
expected := "failed to verify aggregation bitfield: wanted participants bitfield length 3, got: 4"
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, expected, err)
}
@@ -240,7 +245,7 @@ func TestProcessAttestations_OK(t *testing.T) {
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
require.NoError(t, err)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block)
assert.NoError(t, err)
}
@@ -375,7 +380,7 @@ func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
require.NoError(t, err)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block)
assert.NoError(t, err)
}
@@ -735,7 +740,9 @@ func TestVerifyAttestations_VerifiesMultipleAttestations(t *testing.T) {
}
att2.Signature = bls.AggregateSignatures(sigs).Marshal()
require.NoError(t, blocks.VerifyAttestationsSignatures(ctx, st, []*ethpb.Attestation{att1, att2}))
b := testutil.NewBeaconBlock()
b.Block.Body.Attestations = []*ethpb.Attestation{att1, att2}
require.NoError(t, blocks.VerifyAttestationsSignatures(ctx, st, b))
}
func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
@@ -809,7 +816,9 @@ func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
}
att2.Signature = bls.AggregateSignatures(sigs).Marshal()
require.NoError(t, blocks.VerifyAttestationsSignatures(ctx, st, []*ethpb.Attestation{att1, att2}))
b := testutil.NewBeaconBlock()
b.Block.Body.Attestations = []*ethpb.Attestation{att1, att2}
require.NoError(t, blocks.VerifyAttestationsSignatures(ctx, st, b))
}
func TestRetrieveAttestationSignatureSet_VerifiesMultipleAttestations(t *testing.T) {

View File

@@ -35,8 +35,13 @@ import (
func ProcessAttesterSlashings(
ctx context.Context,
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
body := b.Block.Body
for idx, slashing := range body.AttesterSlashings {
if err := VerifyAttesterSlashing(ctx, beaconState, slashing); err != nil {
return nil, errors.Wrapf(err, "could not verify attester slashing %d", idx)

View File

@@ -65,13 +65,14 @@ func TestProcessAttesterSlashings_DataNotSlashable(t *testing.T) {
Slot: currentSlot,
})
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
AttesterSlashings: slashings,
},
}
want := fmt.Sprint("attestations are not slashable")
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -108,14 +109,15 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
},
}
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
AttesterSlashings: slashings,
},
}
want := fmt.Sprint("validator indices count exceeds MAX_VALIDATORS_PER_COMMITTEE")
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -167,13 +169,14 @@ func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
currentSlot := 2 * params.BeaconConfig().SlotsPerEpoch
require.NoError(t, beaconState.SetSlot(currentSlot))
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
AttesterSlashings: slashings,
},
}
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, block.Body)
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, b)
require.NoError(t, err)
newRegistry := newState.Validators()

View File

@@ -40,7 +40,7 @@ func TestFuzzProcessBlockHeader_10000(t *testing.T) {
fuzzer.Fuzz(block)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
_, err = ProcessBlockHeader(s, block)
_, err = ProcessBlockHeader(context.Background(), s, block)
_ = err
}
}
@@ -70,14 +70,14 @@ func TestFuzzverifyDepositDataSigningRoot_10000(t *testing.T) {
func TestFuzzProcessEth1DataInBlock_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
block := &eth.BeaconBlock{}
b := &eth.SignedBeaconBlock{}
state := &stateTrie.BeaconState{}
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(block)
s, err := ProcessEth1DataInBlock(state, block)
fuzzer.Fuzz(b)
s, err := ProcessEth1DataInBlock(context.Background(), state, b)
if err != nil && s != nil {
t.Fatalf("state should be nil on err. found: %v on error: %v for state: %v and block: %v", s, err, state, block)
t.Fatalf("state should be nil on err. found: %v on error: %v for state: %v and block: %v", s, err, state, b)
}
}
}
@@ -128,15 +128,15 @@ func TestFuzzProcessBlockHeaderNoVerify_10000(t *testing.T) {
func TestFuzzProcessRandao_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessRandao(s, blockBody)
r, err := ProcessRandao(context.Background(), s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -160,15 +160,15 @@ func TestFuzzProcessRandaoNoVerify_10000(t *testing.T) {
func TestFuzzProcessProposerSlashings_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessProposerSlashings(ctx, s, blockBody)
r, err := ProcessProposerSlashings(ctx, s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -189,15 +189,15 @@ func TestFuzzVerifyProposerSlashing_10000(t *testing.T) {
func TestFuzzProcessAttesterSlashings_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessAttesterSlashings(ctx, s, blockBody)
r, err := ProcessAttesterSlashings(ctx, s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -241,15 +241,15 @@ func TestFuzzslashableAttesterIndices_10000(t *testing.T) {
func TestFuzzProcessAttestations_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessAttestations(ctx, s, blockBody)
r, err := ProcessAttestations(ctx, s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -257,15 +257,15 @@ func TestFuzzProcessAttestations_10000(t *testing.T) {
func TestFuzzProcessAttestationsNoVerify_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessAttestationsNoVerifySignature(ctx, s, blockBody)
r, err := ProcessAttestationsNoVerifySignature(ctx, s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -317,15 +317,15 @@ func TestFuzzVerifyAttestation_10000(t *testing.T) {
func TestFuzzProcessDeposits_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessDeposits(ctx, s, blockBody.Deposits)
r, err := ProcessDeposits(ctx, s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -379,15 +379,15 @@ func TestFuzzverifyDeposit_10000(t *testing.T) {
func TestFuzzProcessVoluntaryExits_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessVoluntaryExits(ctx, s, blockBody)
r, err := ProcessVoluntaryExits(ctx, s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -395,14 +395,14 @@ func TestFuzzProcessVoluntaryExits_10000(t *testing.T) {
func TestFuzzProcessVoluntaryExitsNoVerify_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessVoluntaryExits(context.Background(), s, blockBody)
r, err := ProcessVoluntaryExits(context.Background(), s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}

View File

@@ -88,13 +88,14 @@ func TestProcessAttesterSlashings_RegressionSlashableIndices(t *testing.T) {
currentSlot := 2 * params.BeaconConfig().SlotsPerEpoch
require.NoError(t, beaconState.SetSlot(currentSlot))
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
AttesterSlashings: slashings,
},
}
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, block.Body)
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, b)
require.NoError(t, err)
newRegistry := newState.Validators()
if !newRegistry[expectedSlashedVal].Slashed {

View File

@@ -25,7 +25,8 @@ func ProcessPreGenesisDeposits(
deposits []*ethpb.Deposit,
) (*stateTrie.BeaconState, error) {
var err error
beaconState, err = ProcessDeposits(ctx, beaconState, deposits)
beaconState, err = ProcessDeposits(ctx, beaconState, &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{Body: &ethpb.BeaconBlockBody{Deposits: deposits}}})
if err != nil {
return nil, errors.Wrap(err, "could not process deposit")
}
@@ -66,10 +67,14 @@ func ProcessPreGenesisDeposits(
func ProcessDeposits(
ctx context.Context,
beaconState *stateTrie.BeaconState,
deposits []*ethpb.Deposit,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
var err error
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
deposits := b.Block.Body.Deposits
var err error
domain, err := helpers.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil)
if err != nil {
return nil, err

View File

@@ -25,7 +25,8 @@ func TestProcessDeposits_SameValidatorMultipleDepositsSameBlock(t *testing.T) {
require.NoError(t, err)
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
// 3 deposits from the same validator
Deposits: []*ethpb.Deposit{dep[0], dep[1], dep[2]},
@@ -48,7 +49,7 @@ func TestProcessDeposits_SameValidatorMultipleDepositsSameBlock(t *testing.T) {
},
})
require.NoError(t, err)
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, block.Body.Deposits)
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b)
require.NoError(t, err, "Expected block deposits to process correctly")
assert.Equal(t, 2, len(newState.Validators()), "Incorrect validator count")
@@ -72,7 +73,8 @@ func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
require.NoError(t, err, "Could not generate proof")
deposit.Proof = proof
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Deposits: []*ethpb.Deposit{deposit},
},
@@ -85,7 +87,7 @@ func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
})
require.NoError(t, err)
want := "deposit root did not verify"
_, err = blocks.ProcessDeposits(context.Background(), beaconState, block.Body.Deposits)
_, err = blocks.ProcessDeposits(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -95,7 +97,8 @@ func TestProcessDeposits_AddsNewValidatorDeposit(t *testing.T) {
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Deposits: []*ethpb.Deposit{dep[0]},
},
@@ -117,7 +120,7 @@ func TestProcessDeposits_AddsNewValidatorDeposit(t *testing.T) {
},
})
require.NoError(t, err)
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, block.Body.Deposits)
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b)
require.NoError(t, err, "Expected block deposits to process correctly")
if newState.Balances()[1] != dep[0].Data.Amount {
t.Errorf(
@@ -152,7 +155,8 @@ func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
require.NoError(t, err, "Could not generate proof")
deposit.Proof = proof
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Deposits: []*ethpb.Deposit{deposit},
},
@@ -177,7 +181,7 @@ func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
},
})
require.NoError(t, err)
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, block.Body.Deposits)
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b)
require.NoError(t, err, "Process deposit failed")
assert.Equal(t, uint64(1000+50), newState.Balances()[1], "Expected balance at index 1 to be 1050")
}

View File

@@ -2,6 +2,7 @@ package blocks
import (
"bytes"
"context"
"errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
@@ -18,7 +19,8 @@ import (
// state.eth1_data_votes.append(body.eth1_data)
// if state.eth1_data_votes.count(body.eth1_data) * 2 > EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH:
// state.latest_eth1_data = body.eth1_data
func ProcessEth1DataInBlock(beaconState *stateTrie.BeaconState, block *ethpb.BeaconBlock) (*stateTrie.BeaconState, error) {
func ProcessEth1DataInBlock(ctx context.Context, beaconState *stateTrie.BeaconState, b *ethpb.SignedBeaconBlock) (*stateTrie.BeaconState, error) {
block := b.Block
if beaconState == nil {
return nil, errors.New("nil state")
}

View File

@@ -1,6 +1,7 @@
package blocks_test
import (
"context"
"fmt"
"testing"
@@ -11,6 +12,7 @@ import (
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
@@ -162,7 +164,8 @@ func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
})
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Eth1Data: &ethpb.Eth1Data{
DepositRoot: []byte{2},
@@ -173,7 +176,7 @@ func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
period := params.BeaconConfig().EpochsPerEth1VotingPeriod * params.BeaconConfig().SlotsPerEpoch
for i := uint64(0); i < period; i++ {
beaconState, err = blocks.ProcessEth1DataInBlock(beaconState, block)
beaconState, err = blocks.ProcessEth1DataInBlock(context.Background(), beaconState, b)
require.NoError(t, err)
}
@@ -181,10 +184,10 @@ func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
if len(newETH1DataVotes) <= 1 {
t.Error("Expected new ETH1 data votes to have length > 1")
}
if !proto.Equal(beaconState.Eth1Data(), beaconstate.CopyETH1Data(block.Body.Eth1Data)) {
if !proto.Equal(beaconState.Eth1Data(), beaconstate.CopyETH1Data(b.Block.Body.Eth1Data)) {
t.Errorf(
"Expected latest eth1 data to have been set to %v, received %v",
block.Body.Eth1Data,
b.Block.Body.Eth1Data,
beaconState.Eth1Data(),
)
}

View File

@@ -39,8 +39,13 @@ import (
func ProcessVoluntaryExits(
ctx context.Context,
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
body := b.Block.Body
exits := body.VoluntaryExits
for idx, exit := range exits {
if exit == nil || exit.Exit == nil {

View File

@@ -11,6 +11,7 @@ import (
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
@@ -32,18 +33,19 @@ func TestProcessVoluntaryExits_ValidatorNotActive(t *testing.T) {
Validators: registry,
})
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
VoluntaryExits: exits,
},
}
want := "non-active validator cannot exit"
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, block.Body)
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
assert.ErrorContains(t, want, err)
// Check conformance of no verify method.
_, err = blocks.ProcessVoluntaryExitsNoVerifySignature(state, block.Body)
_, err = blocks.ProcessVoluntaryExitsNoVerifySignature(state, b.Block.Body)
assert.ErrorContains(t, want, err)
}
@@ -65,18 +67,19 @@ func TestProcessVoluntaryExits_InvalidExitEpoch(t *testing.T) {
Slot: 0,
})
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
VoluntaryExits: exits,
},
}
want := "expected current epoch >= exit epoch"
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, block.Body)
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
assert.ErrorContains(t, want, err)
// Check conformance of no verify method.
_, err = blocks.ProcessVoluntaryExitsNoVerifySignature(state, block.Body)
_, err = blocks.ProcessVoluntaryExitsNoVerifySignature(state, b.Block.Body)
assert.ErrorContains(t, want, err)
}
@@ -99,14 +102,15 @@ func TestProcessVoluntaryExits_NotActiveLongEnoughToExit(t *testing.T) {
Slot: 10,
})
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
VoluntaryExits: exits,
},
}
want := "validator has not been active long enough to exit"
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, block.Body)
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
assert.ErrorContains(t, want, err)
}
@@ -145,14 +149,15 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
exits[0].Signature, err = helpers.ComputeDomainAndSign(state, helpers.CurrentEpoch(state), exits[0].Exit, params.BeaconConfig().DomainVoluntaryExit, priv)
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
VoluntaryExits: exits,
},
}
stateCopy := state.Copy()
newState, err := blocks.ProcessVoluntaryExits(context.Background(), state, block.Body)
newState, err := blocks.ProcessVoluntaryExits(context.Background(), state, b)
require.NoError(t, err, "Could not process exits")
newRegistry := newState.Validators()
if newRegistry[0].ExitEpoch != helpers.ActivationExitEpoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch) {
@@ -161,7 +166,7 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
}
// Check conformance with NoVerify Exit Method.
newState, err = blocks.ProcessVoluntaryExitsNoVerifySignature(stateCopy, block.Body)
newState, err = blocks.ProcessVoluntaryExitsNoVerifySignature(stateCopy, b.Block.Body)
require.NoError(t, err, "Could not process exits")
newRegistry = newState.Validators()
if newRegistry[0].ExitEpoch != helpers.ActivationExitEpoch(stateCopy.Slot()/params.BeaconConfig().SlotsPerEpoch) {

View File

@@ -2,6 +2,7 @@ package blocks
import (
"bytes"
"context"
"fmt"
"github.com/pkg/errors"
@@ -36,6 +37,7 @@ import (
// # Verify proposer signature
// assert bls_verify(proposer.pubkey, signing_root(block), block.signature, get_domain(state, DOMAIN_BEACON_PROPOSER))
func ProcessBlockHeader(
ctx context.Context,
beaconState *stateTrie.BeaconState,
block *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {

View File

@@ -1,6 +1,7 @@
package blocks_test
import (
"context"
"io/ioutil"
"testing"
@@ -65,7 +66,7 @@ func TestProcessBlockHeader_ImproperBlockSlot(t *testing.T) {
err = state.UpdateValidatorAtIndex(proposerIdx, validators[proposerIdx])
require.NoError(t, err)
_, err = blocks.ProcessBlockHeader(state, block)
_, err = blocks.ProcessBlockHeader(context.Background(), state, block)
assert.ErrorContains(t, "block.Slot 10 must be greater than state.LatestBlockHeader.Slot 10", err)
}
@@ -94,7 +95,7 @@ func TestProcessBlockHeader_WrongProposerSig(t *testing.T) {
block.Signature, err = helpers.ComputeDomainAndSign(beaconState, 0, block.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx+1])
require.NoError(t, err)
_, err = blocks.ProcessBlockHeader(beaconState, block)
_, err = blocks.ProcessBlockHeader(context.Background(), beaconState, block)
want := "signature did not verify"
assert.ErrorContains(t, want, err)
}
@@ -140,7 +141,7 @@ func TestProcessBlockHeader_DifferentSlots(t *testing.T) {
Signature: blockSig,
}
_, err = blocks.ProcessBlockHeader(state, block)
_, err = blocks.ProcessBlockHeader(context.Background(), state, block)
want := "is different than block slot"
assert.ErrorContains(t, want, err)
}
@@ -176,7 +177,7 @@ func TestProcessBlockHeader_PreviousBlockRootNotSignedRoot(t *testing.T) {
block.Block.ParentRoot = bytesutil.PadTo([]byte{'A'}, 32)
block.Signature = blockSig
_, err = blocks.ProcessBlockHeader(state, block)
_, err = blocks.ProcessBlockHeader(context.Background(), state, block)
want := "does not match"
assert.ErrorContains(t, want, err)
}
@@ -215,7 +216,7 @@ func TestProcessBlockHeader_SlashedProposer(t *testing.T) {
block.Block.ParentRoot = parentRoot[:]
block.Signature = blockSig
_, err = blocks.ProcessBlockHeader(state, block)
_, err = blocks.ProcessBlockHeader(context.Background(), state, block)
want := "was previously slashed"
assert.ErrorContains(t, want, err)
}
@@ -266,7 +267,7 @@ func TestProcessBlockHeader_OK(t *testing.T) {
err = state.UpdateValidatorAtIndex(proposerIdx, validators[proposerIdx])
require.NoError(t, err)
newState, err := blocks.ProcessBlockHeader(state, block)
newState, err := blocks.ProcessBlockHeader(context.Background(), state, block)
require.NoError(t, err, "Failed to process block header got")
var zeroHash [32]byte
nsh := newState.LatestBlockHeader()

View File

@@ -38,8 +38,13 @@ import (
func ProcessProposerSlashings(
ctx context.Context,
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
body := b.Block.Body
var err error
for idx, slashing := range body.ProposerSlashings {
if slashing == nil {

View File

@@ -39,13 +39,14 @@ func TestProcessProposerSlashings_UnmatchedHeaderSlots(t *testing.T) {
}
require.NoError(t, beaconState.SetSlot(currentSlot))
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
ProposerSlashings: slashings,
},
}
want := "mismatched header slots"
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Body)
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -71,13 +72,14 @@ func TestProcessProposerSlashings_SameHeaders(t *testing.T) {
}
require.NoError(t, beaconState.SetSlot(currentSlot))
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
ProposerSlashings: slashings,
},
}
want := "expected slashing headers to differ"
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Body)
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -115,7 +117,8 @@ func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
Slot: currentSlot,
})
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
ProposerSlashings: slashings,
},
@@ -124,7 +127,7 @@ func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
"validator with key %#x is not slashable",
bytesutil.ToBytes48(beaconState.Validators()[0].PublicKey),
)
_, err = blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessProposerSlashings(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -169,7 +172,7 @@ func TestProcessProposerSlashings_AppliesCorrectStatus(t *testing.T) {
block := testutil.NewBeaconBlock()
block.Block.Body.ProposerSlashings = slashings
newState, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Block.Body)
newState, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block)
require.NoError(t, err)
newStateVals := newState.Validators()

View File

@@ -1,6 +1,8 @@
package blocks
import (
"context"
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
@@ -24,9 +26,15 @@ import (
// mix = xor(get_randao_mix(state, epoch), hash(body.randao_reveal))
// state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR] = mix
func ProcessRandao(
ctx context.Context,
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
body := b.Block.Body
buf, proposerPub, domain, err := randaoSigningData(beaconState)
if err != nil {
return nil, err

View File

@@ -2,6 +2,7 @@ package blocks_test
import (
"bytes"
"context"
"encoding/binary"
"testing"
@@ -29,14 +30,15 @@ func TestProcessRandao_IncorrectProposerFailsVerification(t *testing.T) {
require.NoError(t, err)
// We make the previous validator's index sign the message instead of the proposer.
epochSignature := privKeys[proposerIdx-1].Sign(root[:])
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
RandaoReveal: epochSignature.Marshal(),
},
}
want := "block randao: signature did not verify"
_, err = blocks.ProcessRandao(beaconState, block.Body)
_, err = blocks.ProcessRandao(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -47,15 +49,17 @@ func TestProcessRandao_SignatureVerifiesAndUpdatesLatestStateMixes(t *testing.T)
epochSignature, err := testutil.RandaoReveal(beaconState, epoch, privKeys)
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
RandaoReveal: epochSignature,
},
}
newState, err := blocks.ProcessRandao(
context.Background(),
beaconState,
block.Body,
b,
)
require.NoError(t, err, "Unexpected error processing block randao")
currentEpoch := helpers.CurrentEpoch(beaconState)

View File

@@ -26,8 +26,8 @@ func runDepositTest(t *testing.T, config string) {
require.NoError(t, deposit.UnmarshalSSZ(depositFile), "Failed to unmarshal")
body := &ethpb.BeaconBlockBody{Deposits: []*ethpb.Deposit{deposit}}
testutil.RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, state *state.BeaconState, body *ethpb.BeaconBlockBody) (*state.BeaconState, error) {
return blocks.ProcessDeposits(ctx, state, body.Deposits)
testutil.RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, state *state.BeaconState, b *ethpb.SignedBeaconBlock) (*state.BeaconState, error) {
return blocks.ProcessDeposits(ctx, state, b)
})
})
}

View File

@@ -25,6 +25,23 @@ import (
"go.opencensus.io/trace"
)
// processFunc is a function that processes a block with a given state. State is mutated.
type processFunc func(context.Context, *stateTrie.BeaconState, *ethpb.SignedBeaconBlock) (*stateTrie.BeaconState, error)
// This defines the processing block routine as outlined in eth2 spec:
// https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md#block-processing
var processingPipeline = []processFunc{
b.ProcessBlockHeader,
b.ProcessRandao,
b.ProcessEth1DataInBlock,
VerifyOperationLengths,
b.ProcessProposerSlashings,
b.ProcessAttesterSlashings,
b.ProcessAttestations,
b.ProcessDeposits,
b.ProcessVoluntaryExits,
}
// ExecuteStateTransition defines the procedure for a state transition function.
//
// Spec pseudocode definition:
@@ -400,28 +417,12 @@ func ProcessBlock(
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessBlock")
defer span.End()
state, err := b.ProcessBlockHeader(state, signed)
if err != nil {
traceutil.AnnotateError(span, err)
return nil, errors.Wrap(err, "could not process block header")
}
state, err = b.ProcessRandao(state, signed.Block.Body)
if err != nil {
traceutil.AnnotateError(span, err)
return nil, errors.Wrap(err, "could not verify and process randao")
}
state, err = b.ProcessEth1DataInBlock(state, signed.Block)
if err != nil {
traceutil.AnnotateError(span, err)
return nil, errors.Wrap(err, "could not process eth1 data")
}
state, err = ProcessOperations(ctx, state, signed.Block.Body)
if err != nil {
traceutil.AnnotateError(span, err)
return nil, errors.Wrap(err, "could not process block operation")
var err error
for _, p := range processingPipeline {
state, err = p(ctx, state, signed)
if err != nil {
return nil, errors.Wrap(err, "Could not process block")
}
}
return state, nil
@@ -446,25 +447,25 @@ func ProcessBlockNoVerifyAttSigs(
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessBlock")
defer span.End()
state, err := b.ProcessBlockHeader(state, signed)
state, err := b.ProcessBlockHeader(ctx, state, signed)
if err != nil {
traceutil.AnnotateError(span, err)
return nil, errors.Wrap(err, "could not process block header")
}
state, err = b.ProcessRandao(state, signed.Block.Body)
state, err = b.ProcessRandao(ctx, state, signed)
if err != nil {
traceutil.AnnotateError(span, err)
return nil, errors.Wrap(err, "could not verify and process randao")
}
state, err = b.ProcessEth1DataInBlock(state, signed.Block)
state, err = b.ProcessEth1DataInBlock(ctx, state, signed)
if err != nil {
traceutil.AnnotateError(span, err)
return nil, errors.Wrap(err, "could not process eth1 data")
}
state, err = ProcessOperationsNoVerifyAttsSigs(ctx, state, signed.Block.Body)
state, err = ProcessOperationsNoVerifyAttsSigs(ctx, state, signed)
if err != nil {
traceutil.AnnotateError(span, err)
return nil, errors.Wrap(err, "could not process block operation")
@@ -514,13 +515,13 @@ func ProcessBlockNoVerifyAnySig(
return nil, nil, errors.Wrap(err, "could not verify and process randao")
}
state, err = b.ProcessEth1DataInBlock(state, signed.Block)
state, err = b.ProcessEth1DataInBlock(ctx, state, signed)
if err != nil {
traceutil.AnnotateError(span, err)
return nil, nil, errors.Wrap(err, "could not process eth1 data")
}
state, err = ProcessOperationsNoVerifyAttsSigs(ctx, state, signed.Block.Body)
state, err = ProcessOperationsNoVerifyAttsSigs(ctx, state, signed)
if err != nil {
traceutil.AnnotateError(span, err)
return nil, nil, errors.Wrap(err, "could not process block operation")
@@ -537,66 +538,6 @@ func ProcessBlockNoVerifyAnySig(
return set, state, nil
}
// ProcessOperations processes the operations in the beacon block and updates beacon state
// with the operations in block.
//
// Spec pseudocode definition:
//
// def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
// # Verify that outstanding deposits are processed up to the maximum number of deposits
// assert len(body.deposits) == min(MAX_DEPOSITS, state.eth1_data.deposit_count - state.eth1_deposit_index)
// # Verify that there are no duplicate transfers
// assert len(body.transfers) == len(set(body.transfers))
//
// all_operations = (
// (body.proposer_slashings, process_proposer_slashing),
// (body.attester_slashings, process_attester_slashing),
// (body.attestations, process_attestation),
// (body.deposits, process_deposit),
// (body.voluntary_exits, process_voluntary_exit),
// (body.transfers, process_transfer),
// ) # type: Sequence[Tuple[List, Callable]]
// for operations, function in all_operations:
// for operation in operations:
// function(state, operation)
func ProcessOperations(
ctx context.Context,
state *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody) (*stateTrie.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessOperations")
defer span.End()
if err := verifyOperationLengths(state, body); err != nil {
return nil, errors.Wrap(err, "could not verify operation lengths")
}
state, err := b.ProcessProposerSlashings(ctx, state, body)
if err != nil {
return nil, errors.Wrap(err, "could not process block proposer slashings")
}
state, err = b.ProcessAttesterSlashings(ctx, state, body)
if err != nil {
return nil, errors.Wrap(err, "could not process block attester slashings")
}
state, err = b.ProcessAttestationsNoVerifySignature(ctx, state, body)
if err != nil {
return nil, errors.Wrap(err, "could not process block attestations")
}
if err := b.VerifyAttestationsSignatures(ctx, state, body.Attestations); err != nil {
return nil, errors.Wrap(err, "could not verify attestations")
}
state, err = b.ProcessDeposits(ctx, state, body.Deposits)
if err != nil {
return nil, errors.Wrap(err, "could not process block validator deposits")
}
state, err = b.ProcessVoluntaryExits(ctx, state, body)
if err != nil {
return nil, errors.Wrap(err, "could not process validator exits")
}
return state, nil
}
// ProcessOperationsNoVerifyAttsSigs processes the operations in the beacon block and updates beacon state
// with the operations in block. It does not verify attestation signatures.
//
@@ -625,31 +566,31 @@ func ProcessOperations(
func ProcessOperationsNoVerifyAttsSigs(
ctx context.Context,
state *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody) (*stateTrie.BeaconState, error) {
signedBeaconBlock *ethpb.SignedBeaconBlock) (*stateTrie.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessOperations")
defer span.End()
if err := verifyOperationLengths(state, body); err != nil {
if _, err := VerifyOperationLengths(ctx, state, signedBeaconBlock); err != nil {
return nil, errors.Wrap(err, "could not verify operation lengths")
}
state, err := b.ProcessProposerSlashings(ctx, state, body)
state, err := b.ProcessProposerSlashings(ctx, state, signedBeaconBlock)
if err != nil {
return nil, errors.Wrap(err, "could not process block proposer slashings")
}
state, err = b.ProcessAttesterSlashings(ctx, state, body)
state, err = b.ProcessAttesterSlashings(ctx, state, signedBeaconBlock)
if err != nil {
return nil, errors.Wrap(err, "could not process block attester slashings")
}
state, err = b.ProcessAttestationsNoVerifySignature(ctx, state, body)
state, err = b.ProcessAttestationsNoVerifySignature(ctx, state, signedBeaconBlock)
if err != nil {
return nil, errors.Wrap(err, "could not process block attestations")
}
state, err = b.ProcessDeposits(ctx, state, body.Deposits)
state, err = b.ProcessDeposits(ctx, state, signedBeaconBlock)
if err != nil {
return nil, errors.Wrap(err, "could not process block validator deposits")
}
state, err = b.ProcessVoluntaryExits(ctx, state, body)
state, err = b.ProcessVoluntaryExits(ctx, state, signedBeaconBlock)
if err != nil {
return nil, errors.Wrap(err, "could not process validator exits")
}
@@ -657,9 +598,15 @@ func ProcessOperationsNoVerifyAttsSigs(
return state, nil
}
func verifyOperationLengths(state *stateTrie.BeaconState, body *ethpb.BeaconBlockBody) error {
// VerifyOperationLengths verifies that block operation lengths are valid.
func VerifyOperationLengths(ctx context.Context, state *stateTrie.BeaconState, b *ethpb.SignedBeaconBlock) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
body := b.Block.Body
if uint64(len(body.ProposerSlashings)) > params.BeaconConfig().MaxProposerSlashings {
return fmt.Errorf(
return nil, fmt.Errorf(
"number of proposer slashings (%d) in block body exceeds allowed threshold of %d",
len(body.ProposerSlashings),
params.BeaconConfig().MaxProposerSlashings,
@@ -667,7 +614,7 @@ func verifyOperationLengths(state *stateTrie.BeaconState, body *ethpb.BeaconBloc
}
if uint64(len(body.AttesterSlashings)) > params.BeaconConfig().MaxAttesterSlashings {
return fmt.Errorf(
return nil, fmt.Errorf(
"number of attester slashings (%d) in block body exceeds allowed threshold of %d",
len(body.AttesterSlashings),
params.BeaconConfig().MaxAttesterSlashings,
@@ -675,7 +622,7 @@ func verifyOperationLengths(state *stateTrie.BeaconState, body *ethpb.BeaconBloc
}
if uint64(len(body.Attestations)) > params.BeaconConfig().MaxAttestations {
return fmt.Errorf(
return nil, fmt.Errorf(
"number of attestations (%d) in block body exceeds allowed threshold of %d",
len(body.Attestations),
params.BeaconConfig().MaxAttestations,
@@ -683,7 +630,7 @@ func verifyOperationLengths(state *stateTrie.BeaconState, body *ethpb.BeaconBloc
}
if uint64(len(body.VoluntaryExits)) > params.BeaconConfig().MaxVoluntaryExits {
return fmt.Errorf(
return nil, fmt.Errorf(
"number of voluntary exits (%d) in block body exceeds allowed threshold of %d",
len(body.VoluntaryExits),
params.BeaconConfig().MaxVoluntaryExits,
@@ -691,19 +638,19 @@ func verifyOperationLengths(state *stateTrie.BeaconState, body *ethpb.BeaconBloc
}
eth1Data := state.Eth1Data()
if eth1Data == nil {
return errors.New("nil eth1data in state")
return nil, errors.New("nil eth1data in state")
}
if state.Eth1DepositIndex() > eth1Data.DepositCount {
return fmt.Errorf("expected state.deposit_index %d <= eth1data.deposit_count %d", state.Eth1DepositIndex(), eth1Data.DepositCount)
return nil, fmt.Errorf("expected state.deposit_index %d <= eth1data.deposit_count %d", state.Eth1DepositIndex(), eth1Data.DepositCount)
}
maxDeposits := mathutil.Min(params.BeaconConfig().MaxDeposits, eth1Data.DepositCount-state.Eth1DepositIndex())
// Verify outstanding deposits are processed up to max number of deposits
if uint64(len(body.Deposits)) != maxDeposits {
return fmt.Errorf("incorrect outstanding deposits in block body, wanted: %d, got: %d",
return nil, fmt.Errorf("incorrect outstanding deposits in block body, wanted: %d, got: %d",
maxDeposits, len(body.Deposits))
}
return nil
return state, nil
}
// CanProcessEpoch checks the eligibility to process epoch.
@@ -783,13 +730,13 @@ func ProcessBlockForStateRoot(
return nil, errors.Wrap(err, "could not verify and process randao")
}
state, err = b.ProcessEth1DataInBlock(state, signed.Block)
state, err = b.ProcessEth1DataInBlock(ctx, state, signed)
if err != nil {
traceutil.AnnotateError(span, err)
return nil, errors.Wrap(err, "could not process eth1 data")
}
state, err = ProcessOperationsNoVerifyAttsSigs(ctx, state, signed.Block.Body)
state, err = ProcessOperationsNoVerifyAttsSigs(ctx, state, signed)
if err != nil {
traceutil.AnnotateError(span, err)
return nil, errors.Wrap(err, "could not process block operation")

View File

@@ -138,13 +138,13 @@ func TestFuzzProcessOperations_1000(t *testing.T) {
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
bb := &ethpb.BeaconBlockBody{}
bb := &ethpb.SignedBeaconBlock{}
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
for i := 0; i < 1000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(bb)
s, err := ProcessOperations(ctx, state, bb)
s, err := ProcessBlock(ctx, state, bb)
if err != nil && s != nil {
t.Fatalf("state should be nil on err. found: %v on error: %v for block body: %v", s, err, bb)
}
@@ -156,7 +156,7 @@ func TestFuzzprocessOperationsNoVerify_1000(t *testing.T) {
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
bb := &ethpb.BeaconBlockBody{}
bb := &ethpb.SignedBeaconBlock{}
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
for i := 0; i < 1000; i++ {
@@ -173,13 +173,13 @@ func TestFuzzverifyOperationLengths_10000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
state := &stateTrie.BeaconState{}
bb := &ethpb.BeaconBlockBody{}
bb := &ethpb.SignedBeaconBlock{}
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(bb)
err := verifyOperationLengths(state, bb)
_, err := VerifyOperationLengths(context.Background(), state, bb)
_ = err
}
}

View File

@@ -194,7 +194,7 @@ func TestProcessBlock_IncorrectProposerSlashing(t *testing.T) {
beaconState, err = state.ProcessSlots(context.Background(), beaconState, 1)
require.NoError(t, err)
want := "could not process block proposer slashing"
want := "could not verify proposer slashing"
_, err = state.ProcessBlock(context.Background(), beaconState, block)
assert.ErrorContains(t, want, err)
}
@@ -225,7 +225,7 @@ func TestProcessBlock_IncorrectProcessBlockAttestations(t *testing.T) {
beaconState, err = state.ProcessSlots(context.Background(), beaconState, 1)
require.NoError(t, err)
want := "could not verify attestations"
want := "could not verify attestation"
_, err = state.ProcessBlock(context.Background(), beaconState, block)
assert.ErrorContains(t, want, err)
}
@@ -323,8 +323,9 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
cp.Root = []byte("hello-world")
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cp))
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
_, err = state.ProcessBlock(context.Background(), beaconState, block)
assert.ErrorContains(t, "could not process block header", err)
_, err = state.VerifyOperationLengths(context.Background(), beaconState, block)
wanted := "number of voluntary exits (17) in block body exceeds allowed threshold of 16"
assert.ErrorContains(t, wanted, err)
}
func createFullBlockWithOperations(t *testing.T) (*beaconstate.BeaconState,
@@ -856,77 +857,82 @@ func TestCanProcessEpoch_TrueOnEpochs(t *testing.T) {
}
}
func TestProcessOperations_OverMaxProposerSlashings(t *testing.T) {
func TestProcessBlock_OverMaxProposerSlashings(t *testing.T) {
maxSlashings := params.BeaconConfig().MaxProposerSlashings
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
ProposerSlashings: make([]*ethpb.ProposerSlashing, maxSlashings+1),
b := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
ProposerSlashings: make([]*ethpb.ProposerSlashing, maxSlashings+1),
},
},
}
want := fmt.Sprintf("number of proposer slashings (%d) in block body exceeds allowed threshold of %d",
len(block.Body.ProposerSlashings), params.BeaconConfig().MaxProposerSlashings)
_, err := state.ProcessOperations(context.Background(), &beaconstate.BeaconState{}, block.Body)
len(b.Block.Body.ProposerSlashings), params.BeaconConfig().MaxProposerSlashings)
_, err := state.VerifyOperationLengths(context.Background(), &beaconstate.BeaconState{}, b)
assert.ErrorContains(t, want, err)
}
func TestProcessOperations_OverMaxAttesterSlashings(t *testing.T) {
func TestProcessBlock_OverMaxAttesterSlashings(t *testing.T) {
maxSlashings := params.BeaconConfig().MaxAttesterSlashings
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
AttesterSlashings: make([]*ethpb.AttesterSlashing, maxSlashings+1),
b := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
AttesterSlashings: make([]*ethpb.AttesterSlashing, maxSlashings+1),
},
},
}
want := fmt.Sprintf("number of attester slashings (%d) in block body exceeds allowed threshold of %d",
len(block.Body.AttesterSlashings), params.BeaconConfig().MaxAttesterSlashings)
_, err := state.ProcessOperations(context.Background(), &beaconstate.BeaconState{}, block.Body)
len(b.Block.Body.AttesterSlashings), params.BeaconConfig().MaxAttesterSlashings)
_, err := state.VerifyOperationLengths(context.Background(), &beaconstate.BeaconState{}, b)
assert.ErrorContains(t, want, err)
}
func TestProcessOperations_OverMaxAttestations(t *testing.T) {
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: make([]*ethpb.Attestation, params.BeaconConfig().MaxAttestations+1),
func TestProcessBlock_OverMaxAttestations(t *testing.T) {
b := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: make([]*ethpb.Attestation, params.BeaconConfig().MaxAttestations+1),
},
},
}
want := fmt.Sprintf("number of attestations (%d) in block body exceeds allowed threshold of %d",
len(block.Body.Attestations), params.BeaconConfig().MaxAttestations)
_, err := state.ProcessOperations(context.Background(), &beaconstate.BeaconState{}, block.Body)
len(b.Block.Body.Attestations), params.BeaconConfig().MaxAttestations)
_, err := state.VerifyOperationLengths(context.Background(), &beaconstate.BeaconState{}, b)
assert.ErrorContains(t, want, err)
}
func TestProcessOperation_OverMaxVoluntaryExits(t *testing.T) {
func TestProcessBlock_OverMaxVoluntaryExits(t *testing.T) {
maxExits := params.BeaconConfig().MaxVoluntaryExits
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
VoluntaryExits: make([]*ethpb.SignedVoluntaryExit, maxExits+1),
b := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
VoluntaryExits: make([]*ethpb.SignedVoluntaryExit, maxExits+1),
},
},
}
want := fmt.Sprintf("number of voluntary exits (%d) in block body exceeds allowed threshold of %d",
len(block.Body.VoluntaryExits), maxExits)
_, err := state.ProcessOperations(context.Background(), &beaconstate.BeaconState{}, block.Body)
len(b.Block.Body.VoluntaryExits), maxExits)
_, err := state.VerifyOperationLengths(context.Background(), &beaconstate.BeaconState{}, b)
assert.ErrorContains(t, want, err)
}
func TestProcessOperations_IncorrectDeposits(t *testing.T) {
func TestProcessBlock_IncorrectDeposits(t *testing.T) {
base := &pb.BeaconState{
Eth1Data: &ethpb.Eth1Data{DepositCount: 100},
Eth1DepositIndex: 98,
}
s, err := beaconstate.InitializeFromProto(base)
require.NoError(t, err)
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Deposits: []*ethpb.Deposit{{}},
b := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Deposits: []*ethpb.Deposit{{}},
},
},
}
want := fmt.Sprintf("incorrect outstanding deposits in block body, wanted: %d, got: %d",
s.Eth1Data().DepositCount-s.Eth1DepositIndex(), len(block.Body.Deposits))
_, err = state.ProcessOperations(context.Background(), s, block.Body)
s.Eth1Data().DepositCount-s.Eth1DepositIndex(), len(b.Block.Body.Deposits))
_, err = state.VerifyOperationLengths(context.Background(), s, b)
assert.ErrorContains(t, want, err)
}

View File

@@ -347,7 +347,7 @@ func TestPendingDeposits_Eth1DataVoteOK(t *testing.T) {
assert.Equal(t, 0, eth1Height.Cmp(height))
newState, err := b.ProcessEth1DataInBlock(beaconState, blk.Block)
newState, err := b.ProcessEth1DataInBlock(ctx, beaconState, blk)
require.NoError(t, err)
if proto.Equal(newState.Eth1Data(), vote) {
@@ -361,7 +361,7 @@ func TestPendingDeposits_Eth1DataVoteOK(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, 0, eth1Height.Cmp(newHeight))
newState, err = b.ProcessEth1DataInBlock(beaconState, blk.Block)
newState, err = b.ProcessEth1DataInBlock(ctx, beaconState, blk)
require.NoError(t, err)
if !proto.Equal(newState.Eth1Data(), vote) {

View File

@@ -25,7 +25,12 @@ func BeaconFuzzAttesterSlashing(b []byte) ([]byte, bool) {
if err != nil {
return fail(err)
}
post, err := blocks.ProcessAttesterSlashings(context.Background(), st, &ethpb.BeaconBlockBody{AttesterSlashings: []*ethpb.AttesterSlashing{input.AttesterSlashing}})
block := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{AttesterSlashings: []*ethpb.AttesterSlashing{input.AttesterSlashing}},
},
}
post, err := blocks.ProcessAttesterSlashings(context.Background(), st, block)
if err != nil {
return fail(err)
}

View File

@@ -27,7 +27,12 @@ func BeaconFuzzProposerSlashing(b []byte) ([]byte, bool) {
if err != nil {
return fail(err)
}
post, err := blocks.ProcessProposerSlashings(context.Background(), st, &ethpb.BeaconBlockBody{ProposerSlashings: []*ethpb.ProposerSlashing{input.ProposerSlashing}})
block := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{ProposerSlashings: []*ethpb.ProposerSlashing{input.ProposerSlashing}},
},
}
post, err := blocks.ProcessProposerSlashings(context.Background(), st, block)
if err != nil {
return fail(err)
}

View File

@@ -20,7 +20,7 @@ import (
"gopkg.in/d4l3k/messagediff.v1"
)
type blockOperation func(context.Context, *beaconstate.BeaconState, *ethpb.BeaconBlockBody) (*beaconstate.BeaconState, error)
type blockOperation func(context.Context, *beaconstate.BeaconState, *ethpb.SignedBeaconBlock) (*beaconstate.BeaconState, error)
type epochOperation func(*testing.T, *beaconstate.BeaconState) (*beaconstate.BeaconState, error)
var json = jsoniter.Config{
@@ -105,7 +105,9 @@ func RunBlockOperationTest(
}
helpers.ClearCache()
beaconState, err := operationFn(context.Background(), preState, body)
b := NewBeaconBlock()
b.Block.Body = body
beaconState, err := operationFn(context.Background(), preState, b)
if postSSZExists {
require.NoError(t, err)