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 all 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
2 changes: 2 additions & 0 deletions ssv/spectest/all_tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ var AllTests = []tests.TestF{

proposer.ProposeBlindedBlockDecidedRegular,
proposer.ProposeRegularBlockDecidedBlinded,
proposer.BlindedRunnerAcceptsNormalBlock,
proposer.NormalProposerAcceptsBlindedBlock,

// pre_consensus_justifications.PastSlot,
// pre_consensus_justifications.InvalidData,
Expand Down

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.

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package proposer

import (
"fmt"

"github.com/attestantio/go-eth2-client/spec"

"github.com/bloxapp/ssv-spec/ssv/spectest/tests"
"github.com/bloxapp/ssv-spec/types"
"github.com/bloxapp/ssv-spec/types/testingutils"
)

// BlindedRunnerAcceptsNormalBlock tests a full happy flow for a proposer runner that produces blinded blocks but receives as proposal a normal block
func BlindedRunnerAcceptsNormalBlock() tests.SpecTest {
ks := testingutils.Testing4SharesSet()

multiSpecTest := &tests.MultiMsgProcessingSpecTest{
Name: "blinded proposer accepts normal block proposal",
Tests: []*tests.MsgProcessingSpecTest{},
}

// proposerBlindedReceivingNormalBlockV creates a test specification for versioned blinded proposer receiving a normal block.
proposerBlindedReceivingNormalBlockV := func(version spec.DataVersion) *tests.MsgProcessingSpecTest {
return &tests.MsgProcessingSpecTest{
Name: fmt.Sprintf("blinded proposer accepts normal block proposal (%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{proposerBlindedReceivingNormalBlockV(v)}...)
}
return multiSpecTest
}
124 changes: 124 additions & 0 deletions ssv/spectest/tests/runner/duties/proposer/blinded_sc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package proposer

import (
"github.com/attestantio/go-eth2-client/spec"

"github.com/bloxapp/ssv-spec/qbft"
"github.com/bloxapp/ssv-spec/ssv"
ssvcomparable "github.com/bloxapp/ssv-spec/ssv/spectest/comparable"
"github.com/bloxapp/ssv-spec/types"
"github.com/bloxapp/ssv-spec/types/testingutils"
"github.com/bloxapp/ssv-spec/types/testingutils/comparable"
)

// 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
}(),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package proposer

import (
"fmt"

"github.com/attestantio/go-eth2-client/spec"

"github.com/bloxapp/ssv-spec/ssv/spectest/tests"
"github.com/bloxapp/ssv-spec/types"
"github.com/bloxapp/ssv-spec/types/testingutils"
)

// NormalProposerAcceptsBlindedBlock tests a full happy flow for a proposer runner that produces normal blocks but receives as proposal a blinded block
func NormalProposerAcceptsBlindedBlock() tests.SpecTest {
ks := testingutils.Testing4SharesSet()

multiSpecTest := &tests.MultiMsgProcessingSpecTest{
Name: "normal proposer accepts blinded block proposal",
Tests: []*tests.MsgProcessingSpecTest{},
}

// proposerReceivingBlindedBlockV creates a test specification for versioned normal proposer receiving blinded block as proposal.
proposerReceivingBlindedBlockV := func(version spec.DataVersion) *tests.MsgProcessingSpecTest {
return &tests.MsgProcessingSpecTest{
Name: fmt.Sprintf("normal proposer accepts blinded block proposal (%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)),
},
}
}

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

return multiSpecTest
}
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