Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drop blinded block rejection #305

Merged
merged 8 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion ssv/spectest/generate/tests.json

Large diffs are not rendered by default.

54 changes: 53 additions & 1 deletion ssv/spectest/tests/runner/full_happy_flow.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,32 @@ func FullHappyFlow() tests.SpecTest {
}
}

// proposerReceivingBlindedBlockV creates a test specification for versioned proposer receiving blinded block as proposal.
proposerReceivingBlindedBlockV := func(version spec.DataVersion) *tests.MsgProcessingSpecTest {
return &tests.MsgProcessingSpecTest{
Name: fmt.Sprintf("proposer receiving blinded block (%s)", version.String()),
Runner: testingutils.ProposerRunner(ks),
Duty: testingutils.TestingProposerDutyV(version),
Messages: append(
testingutils.SSVDecidingMsgsV(testingutils.TestProposerBlindedBlockConsensusDataV(version), ks, types.BNRoleProposer), // consensus
[]*types.SSVMessage{ // post consensus
testingutils.SSVMsgProposer(nil, testingutils.PostConsensusProposerMsgV(ks.Shares[1], 1, version)),
testingutils.SSVMsgProposer(nil, testingutils.PostConsensusProposerMsgV(ks.Shares[2], 2, version)),
testingutils.SSVMsgProposer(nil, testingutils.PostConsensusProposerMsgV(ks.Shares[3], 3, version)),
}...,
),
PostDutyRunnerStateRoot: fullHappyFlowProposerReceivingBlindedBlockSC(version).Root(),
PostDutyRunnerState: fullHappyFlowProposerReceivingBlindedBlockSC(version).ExpectedState,
OutputMessages: []*types.SignedPartialSignatureMessage{
testingutils.PreConsensusRandaoMsgV(ks.Shares[1], 1, version),
testingutils.PostConsensusProposerMsgV(ks.Shares[1], 1, version),
},
BeaconBroadcastedRoots: []string{
testingutils.GetSSZRootNoError(testingutils.TestingSignedBeaconBlockV(ks, version)),
},
}
}

// proposerBlindedV creates a test specification for versioned proposer with blinded block.
proposerBlindedV := func(version spec.DataVersion) *tests.MsgProcessingSpecTest {
return &tests.MsgProcessingSpecTest{
Expand All @@ -205,8 +231,34 @@ func FullHappyFlow() tests.SpecTest {
}
}

// proposerBlindedReceivingNormalBlockV creates a test specification for versioned blinded proposer receiving a normal block.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would separate it into a separate test, testing specific cases in which some of the cluster members propose blinded blocks and others don't

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took it out of the happy flow test and put it in a file of its own in runner/proposer. What do you think?

proposerBlindedReceivingNormalBlockV := func(version spec.DataVersion) *tests.MsgProcessingSpecTest {
return &tests.MsgProcessingSpecTest{
Name: fmt.Sprintf("blinded proposer receiving normal block (%s)", version.String()),
Runner: testingutils.ProposerBlindedBlockRunner(ks),
Duty: testingutils.TestingProposerDutyV(version),
Messages: append(
testingutils.SSVDecidingMsgsV(testingutils.TestProposerConsensusDataV(version), ks, types.BNRoleProposer), // consensus
[]*types.SSVMessage{ // post consensus
testingutils.SSVMsgProposer(nil, testingutils.PostConsensusProposerMsgV(ks.Shares[1], 1, version)),
testingutils.SSVMsgProposer(nil, testingutils.PostConsensusProposerMsgV(ks.Shares[2], 2, version)),
testingutils.SSVMsgProposer(nil, testingutils.PostConsensusProposerMsgV(ks.Shares[3], 3, version)),
}...,
),
PostDutyRunnerStateRoot: fullHappyFlowBlindedProposerReceivingNormalBlockSC(version).Root(),
PostDutyRunnerState: fullHappyFlowBlindedProposerReceivingNormalBlockSC(version).ExpectedState,
OutputMessages: []*types.SignedPartialSignatureMessage{
testingutils.PreConsensusRandaoMsgV(ks.Shares[1], 1, version),
testingutils.PostConsensusProposerMsgV(ks.Shares[1], 1, version),
},
BeaconBroadcastedRoots: []string{
testingutils.GetSSZRootNoError(testingutils.TestingSignedBeaconBlockV(ks, version)),
},
}
}

for _, v := range testingutils.SupportedBlockVersions {
multiSpecTest.Tests = append(multiSpecTest.Tests, []*tests.MsgProcessingSpecTest{proposerV(v), proposerBlindedV(v)}...)
multiSpecTest.Tests = append(multiSpecTest.Tests, []*tests.MsgProcessingSpecTest{proposerV(v), proposerReceivingBlindedBlockV(v), proposerBlindedV(v), proposerBlindedReceivingNormalBlockV(v)}...)
}

return multiSpecTest
Expand Down
112 changes: 112 additions & 0 deletions ssv/spectest/tests/runner/full_happy_flow_sc.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,118 @@ func fullHappyFlowBlindedProposerSC(version spec.DataVersion) *comparable.StateC
}
}

// fullHappyFlowProposerReceivingBlindedBlockSC returns state comparison object for the FullHappyFlow for a normal Proposer receiving a Blinded Block versioned spec test
func fullHappyFlowProposerReceivingBlindedBlockSC(version spec.DataVersion) *comparable.StateComparison {
ks := testingutils.Testing4SharesSet()
// consensus data used for message creation
cd := testingutils.TestProposerBlindedBlockConsensusDataV(version)
// encoded consensus data relative to messages
cdBytes := testingutils.TestProposerBlindedBlockConsensusDataBytsV(version)
// encoded consensus data that the runner set as StartValue
startedCdBytes := testingutils.TestProposerConsensusDataBytsV(version)

return &comparable.StateComparison{
ExpectedState: func() ssv.Runner {
ret := testingutils.ProposerRunner(ks)
ret.GetBaseRunner().State = &ssv.State{
PreConsensusContainer: ssvcomparable.SetMessagesInContainer(
ssv.NewPartialSigContainer(3),
testingutils.ExpectedSSVDecidingMsgsV(cd, ks, types.BNRoleProposer)[:3],
),
PostConsensusContainer: ssvcomparable.SetMessagesInContainer(
ssv.NewPartialSigContainer(3),
[]*types.SSVMessage{
testingutils.SSVMsgProposer(nil, testingutils.PostConsensusProposerMsgV(ks.Shares[1], 1, version)),
testingutils.SSVMsgProposer(nil, testingutils.PostConsensusProposerMsgV(ks.Shares[2], 2, version)),
testingutils.SSVMsgProposer(nil, testingutils.PostConsensusProposerMsgV(ks.Shares[3], 3, version)),
},
),
DecidedValue: comparable.FixIssue178(cd, version),
StartingDuty: &testingutils.TestProposerConsensusDataV(version).Duty,
Finished: true,
}
ret.GetBaseRunner().State.RunningInstance = &qbft.Instance{
State: &qbft.State{
Share: testingutils.TestingShare(ks),
ID: ret.GetBaseRunner().QBFTController.Identifier,
Round: qbft.FirstRound,
Height: qbft.Height(testingutils.TestingDutySlotV(version)),
LastPreparedRound: qbft.FirstRound,
LastPreparedValue: cdBytes,
ProposalAcceptedForCurrentRound: testingutils.TestingProposalMessageWithIdentifierAndFullData(
ks.Shares[1], types.OperatorID(1), ret.GetBaseRunner().QBFTController.Identifier, cdBytes, qbft.Height(testingutils.TestingDutySlotV(version))),
Decided: true,
DecidedValue: cdBytes,
},
StartValue: startedCdBytes,
}
ret.GetBaseRunner().QBFTController.Height = qbft.Height(testingutils.TestingDutySlotV(version))
comparable.SetMessages(
ret.GetBaseRunner().State.RunningInstance,
testingutils.ExpectedSSVDecidingMsgsV(cd, ks, types.BNRoleProposer)[3:10],
)
ret.GetBaseRunner().QBFTController.StoredInstances = append(ret.GetBaseRunner().QBFTController.StoredInstances, ret.GetBaseRunner().State.RunningInstance)
return ret
}(),
}
}

// fullHappyFlowBlindedProposerReceivingNormalBlockSC returns state comparison object for the FullHappyFlow for a Blinded Proposer receiving a Normal Block versioned spec test
func fullHappyFlowBlindedProposerReceivingNormalBlockSC(version spec.DataVersion) *comparable.StateComparison {
ks := testingutils.Testing4SharesSet()
// consensus data used for message creation
cd := testingutils.TestProposerConsensusDataV(version)
// encoded consensus data relative to messages
cdBytes := testingutils.TestProposerConsensusDataBytsV(version)
// encoded consensus data that the runner set as StartValue
startedCdBytes := testingutils.TestProposerBlindedBlockConsensusDataBytsV(version)

return &comparable.StateComparison{
ExpectedState: func() ssv.Runner {
ret := testingutils.ProposerBlindedBlockRunner(ks)
ret.GetBaseRunner().State = &ssv.State{
PreConsensusContainer: ssvcomparable.SetMessagesInContainer(
ssv.NewPartialSigContainer(3),
testingutils.ExpectedSSVDecidingMsgsV(cd, ks, types.BNRoleProposer)[:3],
),
PostConsensusContainer: ssvcomparable.SetMessagesInContainer(
ssv.NewPartialSigContainer(3),
[]*types.SSVMessage{
testingutils.SSVMsgProposer(nil, testingutils.PostConsensusProposerMsgV(ks.Shares[1], 1, version)),
testingutils.SSVMsgProposer(nil, testingutils.PostConsensusProposerMsgV(ks.Shares[2], 2, version)),
testingutils.SSVMsgProposer(nil, testingutils.PostConsensusProposerMsgV(ks.Shares[3], 3, version)),
},
),
DecidedValue: comparable.FixIssue178(cd, version),
StartingDuty: &testingutils.TestProposerConsensusDataV(version).Duty,
Finished: true,
}
ret.GetBaseRunner().State.RunningInstance = &qbft.Instance{
State: &qbft.State{
Share: testingutils.TestingShare(ks),
ID: ret.GetBaseRunner().QBFTController.Identifier,
Round: qbft.FirstRound,
Height: qbft.Height(testingutils.TestingDutySlotV(version)),
LastPreparedRound: qbft.FirstRound,
LastPreparedValue: cdBytes,
ProposalAcceptedForCurrentRound: testingutils.TestingProposalMessageWithIdentifierAndFullData(
ks.Shares[1], types.OperatorID(1), ret.GetBaseRunner().QBFTController.Identifier, cdBytes, qbft.Height(testingutils.TestingDutySlotV(version))),
Decided: true,
DecidedValue: cdBytes,
},
StartValue: startedCdBytes,
}
ret.GetBaseRunner().QBFTController.Height = qbft.Height(testingutils.TestingDutySlotV(version))
comparable.SetMessages(
ret.GetBaseRunner().State.RunningInstance,
testingutils.ExpectedSSVDecidingMsgsV(cd, ks, types.BNRoleProposer)[3:10],
)
ret.GetBaseRunner().QBFTController.StoredInstances = append(ret.GetBaseRunner().QBFTController.StoredInstances, ret.GetBaseRunner().State.RunningInstance)
return ret
}(),
}
}

// fullHappyFlowAttesterSC returns state comparison object for the FullHappyFlow Attester spec test
func fullHappyFlowAttesterSC() *comparable.StateComparison {
ks := testingutils.Testing4SharesSet()
Expand Down
3 changes: 1 addition & 2 deletions ssv/spectest/tests/valcheck/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ type SpecTest struct {
BeaconRole types.BeaconRole
Input []byte
SlashableDataRoots [][]byte
SupportsBlinded bool
ExpectedError string
AnyError bool
}
Expand Down Expand Up @@ -50,7 +49,7 @@ func (test *SpecTest) valCheckF(signer types.BeaconSigner) qbft.ProposedValueChe
case types.BNRoleAttester:
return ssv.AttesterValueCheckF(signer, test.Network, testingutils.TestingValidatorPubKey[:], testingutils.TestingValidatorIndex, nil)
case types.BNRoleProposer:
return ssv.ProposerValueCheckF(signer, test.Network, testingutils.TestingValidatorPubKey[:], testingutils.TestingValidatorIndex, nil, test.SupportsBlinded)
return ssv.ProposerValueCheckF(signer, test.Network, testingutils.TestingValidatorPubKey[:], testingutils.TestingValidatorIndex, nil)
case types.BNRoleAggregator:
return ssv.AggregatorValueCheckF(signer, test.Network, testingutils.TestingValidatorPubKey[:], testingutils.TestingValidatorIndex)
case types.BNRoleSyncCommittee:
Expand Down
19 changes: 5 additions & 14 deletions ssv/spectest/tests/valcheck/valcheckproposer/blinded_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,11 @@ func BlindedBlock() tests.SpecTest {
Name: "blinded blocks",
Tests: []*valcheck.SpecTest{
{
Name: "blinded blocks not allowed",
Network: types.BeaconTestNetwork,
BeaconRole: types.BNRoleProposer,
Input: testingutils.TestProposerBlindedBlockConsensusDataBytsV(spec.DataVersionBellatrix),
SupportsBlinded: false,
ExpectedError: "blinded blocks are not supported",
},
{
Name: "blinded blocks allowed",
Network: types.BeaconTestNetwork,
BeaconRole: types.BNRoleProposer,
Input: testingutils.TestProposerBlindedBlockConsensusDataBytsV(spec.DataVersionBellatrix),
SupportsBlinded: true,
AnyError: false,
Name: "blinded blocks accepted",
Network: types.BeaconTestNetwork,
BeaconRole: types.BNRoleProposer,
Input: testingutils.TestProposerBlindedBlockConsensusDataBytsV(spec.DataVersionBellatrix),
AnyError: false,
},
},
}
Expand Down
5 changes: 0 additions & 5 deletions ssv/value_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package ssv

import (
"bytes"
"fmt"

"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/pkg/errors"
Expand Down Expand Up @@ -85,7 +84,6 @@ func ProposerValueCheckF(
validatorPK types.ValidatorPK,
validatorIndex phase0.ValidatorIndex,
sharePublicKey []byte,
supportsBlinded bool,
) qbft.ProposedValueCheckF {
return func(data []byte) error {
cd := &types.ConsensusData{}
Expand All @@ -101,9 +99,6 @@ func ProposerValueCheckF(
}

if blockData, _, err := cd.GetBlindedBlockData(); err == nil {
if !supportsBlinded {
return fmt.Errorf("blinded blocks are not supported")
}
slot, err := blockData.Slot()
if err != nil {
return errors.Wrap(err, "failed to get slot from blinded block data")
Expand Down
2 changes: 1 addition & 1 deletion types/spectest/generate/tests.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions types/testingutils/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ var AttesterRunner7Operators = func(keySet *TestKeySet) ssv.Runner {
}

var ProposerRunner = func(keySet *TestKeySet) ssv.Runner {
return baseRunner(types.BNRoleProposer, ssv.ProposerValueCheckF(NewTestingKeyManager(), types.BeaconTestNetwork, TestingValidatorPubKey[:], TestingValidatorIndex, nil, true), keySet)
return baseRunner(types.BNRoleProposer, ssv.ProposerValueCheckF(NewTestingKeyManager(), types.BeaconTestNetwork, TestingValidatorPubKey[:], TestingValidatorIndex, nil), keySet)
}

var ProposerBlindedBlockRunner = func(keySet *TestKeySet) ssv.Runner {
ret := baseRunner(
types.BNRoleProposer,
ssv.ProposerValueCheckF(NewTestingKeyManager(), types.BeaconTestNetwork, TestingValidatorPubKey[:], TestingValidatorIndex, nil, true),
ssv.ProposerValueCheckF(NewTestingKeyManager(), types.BeaconTestNetwork, TestingValidatorPubKey[:], TestingValidatorIndex, nil),
keySet,
)
ret.(*ssv.ProposerRunner).ProducesBlindedBlocks = true
Expand Down