Allow SSZ-serialized blocks in publishBlindedBlock (#10679)

* SubmitBlockSSZ grpc

* SubmitBlockSSZ middleware

* test fixes

* use VersionedUnmarshaller

* use VersionedUnmarshaller

(cherry picked from commit 7388eeb963)

* tests

* fuzz: Add fuzz tests for sparse merkle trie (#10662)

* Add fuzz tests for sparse merkle trie and change HTR signature to return an error

* fix capitalization of error message

* Add engine timeout values (#10645)

* Add timeout values

* Update engine_client.go

* Update engine_client.go

* Update beacon-chain/powchain/engine_client.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Update beacon-chain/powchain/engine_client.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Update beacon-chain/powchain/engine_client.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Update engine_client.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Cleanup of `stategen` package (#10607)

* powchain and stategen

* revert powchain changes

* rename field to blockRootsOfSavedStates

* rename params to blockRoot

* review feedback

* fix loop

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>

* Process atts and update head before proposing (#10653)

* Process atts and updeate head

* Fix ctx

* New test and old tests

* Update validator_test.go

* Update validator_test.go

* Update service.go

* Rename to UpdateHead

* Update receive_attestation.go

* Update receive_attestation.go

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>

* Add link to e2e docs in `README` (#10672)

* Improve `ReceiveBlock`'s comment (#10671)

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>

* Call fcu on invalid payload (#10565)

* Starting

* remove finalized root

* Just call fcu

* Review feedbacks

* fix one test

* Fix conflicts

* Update execution_engine_test.go

* Add a test for invalid recursive call

* Add comprehensive recursive test

* dissallow override empty hash

Co-authored-by: Potuz <potuz@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>

* Cache and use justified and finalized payload block hash (#10657)

* Cache and use justified and finalized payload block hash

* Fix tests

* Use real byte

* Fix conflicts

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>

* do not export slotFromBlock

* simplify tests

* grpc

* middleware

* extract package-level consts

* Simplify SSZ handling

* fix tests

* test fixes

* test hack

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: terencechain <terence@prysmaticlabs.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Potuz <potuz@prysmaticlabs.com>
This commit is contained in:
Radosław Kapka
2022-05-16 19:59:43 +02:00
committed by GitHub
parent 16e66ee1b8
commit f09b06d6f6
10 changed files with 711 additions and 337 deletions

View File

@@ -42,7 +42,6 @@ go_test(
"//consensus-types/primitives:go_default_library",
"//consensus-types/wrapper:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"//testing/require:go_default_library",

View File

@@ -145,19 +145,9 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconBlock(marshaled []byte) (interfac
if err != nil {
return nil, err
}
// heuristic to make sure block is from the same version as the VersionedUnmarshaler.
// Look up the version for the epoch that the block is from, then ensure that it matches the Version in the
// VersionedUnmarshaler.
epoch := slots.ToEpoch(slot)
fs := forks.NewOrderedSchedule(cf.Config)
ver, err := fs.VersionForEpoch(epoch)
if err != nil {
if err := cf.validateVersion(slot); err != nil {
return nil, err
}
if ver != cf.Version {
return nil, errors.Wrapf(errBlockForkMismatch, "slot=%d, epoch=%d, version=%#x", slot, epoch, ver)
}
var blk ssz.Unmarshaler
switch cf.Fork {
@@ -177,3 +167,50 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconBlock(marshaled []byte) (interfac
}
return wrapper.WrappedSignedBeaconBlock(blk)
}
// UnmarshalBlindedBeaconBlock uses internal knowledge in the VersionedUnmarshaler to pick the right concrete blinded SignedBeaconBlock type,
// then Unmarshal()s the type and returns an instance of block.SignedBeaconBlock if successful.
// For Phase0 and Altair it works exactly line UnmarshalBeaconBlock.
func (cf *VersionedUnmarshaler) UnmarshalBlindedBeaconBlock(marshaled []byte) (interfaces.SignedBeaconBlock, error) {
slot, err := slotFromBlock(marshaled)
if err != nil {
return nil, err
}
if err := cf.validateVersion(slot); err != nil {
return nil, err
}
var blk ssz.Unmarshaler
switch cf.Fork {
case version.Phase0:
blk = &ethpb.SignedBeaconBlock{}
case version.Altair:
blk = &ethpb.SignedBeaconBlockAltair{}
case version.Bellatrix:
blk = &ethpb.SignedBlindedBeaconBlockBellatrix{}
default:
forkName := version.String(cf.Fork)
return nil, fmt.Errorf("unable to initialize BeaconBlock for fork version=%s at slot=%d", forkName, slot)
}
err = blk.UnmarshalSSZ(marshaled)
if err != nil {
return nil, errors.Wrap(err, "failed to unmarshal SignedBeaconBlock in UnmarshalSSZ")
}
return wrapper.WrappedSignedBeaconBlock(blk)
}
// Heuristic to make sure block is from the same version as the VersionedUnmarshaler.
// Look up the version for the epoch that the block is from, then ensure that it matches the Version in the
// VersionedUnmarshaler.
func (cf *VersionedUnmarshaler) validateVersion(slot types.Slot) error {
epoch := slots.ToEpoch(slot)
fs := forks.NewOrderedSchedule(cf.Config)
ver, err := fs.VersionForEpoch(epoch)
if err != nil {
return err
}
if ver != cf.Version {
return errors.Wrapf(errBlockForkMismatch, "slot=%d, epoch=%d, version=%#x", slot, epoch, ver)
}
return nil
}

View File

@@ -16,13 +16,12 @@ import (
"github.com/prysmaticlabs/prysm/time/slots"
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
v1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/testing/require"
)
func TestSlotFromBlock(t *testing.T) {
b := testBlockGenesis()
b := util.NewBeaconBlock()
var slot types.Slot = 3
b.Block.Slot = slot
bb, err := b.MarshalSSZ()
@@ -31,7 +30,7 @@ func TestSlotFromBlock(t *testing.T) {
require.NoError(t, err)
require.Equal(t, slot, sfb)
ba := testBlockAltair()
ba := util.NewBeaconBlockAltair()
ba.Block.Slot = slot
bab, err := ba.MarshalSSZ()
require.NoError(t, err)
@@ -39,7 +38,7 @@ func TestSlotFromBlock(t *testing.T) {
require.NoError(t, err)
require.Equal(t, slot, sfba)
bm := testBlockBellatrix()
bm := util.NewBeaconBlockBellatrix()
bm.Block.Slot = slot
bmb, err := ba.MarshalSSZ()
require.NoError(t, err)
@@ -277,125 +276,123 @@ func TestUnmarshalBlock(t *testing.T) {
}
}
func TestUnmarshalBlindedBlock(t *testing.T) {
bc, cleanup := hackBellatrixMaxuint()
defer cleanup()
require.Equal(t, types.Epoch(math.MaxUint32), params.KnownConfigs[params.MainnetName]().BellatrixForkEpoch)
genv := bytesutil.ToBytes4(bc.GenesisForkVersion)
altairv := bytesutil.ToBytes4(bc.AltairForkVersion)
bellav := bytesutil.ToBytes4(bc.BellatrixForkVersion)
altairS, err := slots.EpochStart(bc.AltairForkEpoch)
bellaS, err := slots.EpochStart(bc.BellatrixForkEpoch)
require.NoError(t, err)
cases := []struct {
b func(*testing.T, types.Slot) interfaces.SignedBeaconBlock
name string
version [4]byte
slot types.Slot
err error
}{
{
name: "genesis - slot 0",
b: signedTestBlockGenesis,
version: genv,
},
{
name: "last slot of phase 0",
b: signedTestBlockGenesis,
version: genv,
slot: altairS - 1,
},
{
name: "first slot of altair",
b: signedTestBlockAltair,
version: altairv,
slot: altairS,
},
{
name: "last slot of altair",
b: signedTestBlockAltair,
version: altairv,
slot: bellaS - 1,
},
{
name: "first slot of bellatrix",
b: signedTestBlindedBlockBellatrix,
version: bellav,
slot: bellaS,
},
{
name: "bellatrix block in altair slot",
b: signedTestBlindedBlockBellatrix,
version: bellav,
slot: bellaS - 1,
err: errBlockForkMismatch,
},
{
name: "genesis block in altair slot",
b: signedTestBlockGenesis,
version: genv,
slot: bellaS - 1,
err: errBlockForkMismatch,
},
{
name: "altair block in genesis slot",
b: signedTestBlockAltair,
version: altairv,
err: errBlockForkMismatch,
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
b := c.b(t, c.slot)
marshaled, err := b.MarshalSSZ()
require.NoError(t, err)
cf, err := FromForkVersion(c.version)
require.NoError(t, err)
bcf, err := cf.UnmarshalBlindedBeaconBlock(marshaled)
if c.err != nil {
require.ErrorIs(t, err, c.err)
return
}
require.NoError(t, err)
expected, err := b.Block().HashTreeRoot()
require.NoError(t, err)
actual, err := bcf.Block().HashTreeRoot()
require.NoError(t, err)
require.Equal(t, expected, actual)
})
}
}
func signedTestBlockGenesis(t *testing.T, slot types.Slot) interfaces.SignedBeaconBlock {
b := testBlockGenesis()
b := util.NewBeaconBlock()
b.Block.Slot = slot
s, err := wrapper.WrappedSignedBeaconBlock(b)
require.NoError(t, err)
return s
}
func testBlockGenesis() *ethpb.SignedBeaconBlock {
return &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
ProposerIndex: types.ValidatorIndex(0),
ParentRoot: make([]byte, 32),
StateRoot: make([]byte, 32),
Body: &ethpb.BeaconBlockBody{
RandaoReveal: make([]byte, 96),
Graffiti: make([]byte, 32),
ProposerSlashings: []*ethpb.ProposerSlashing{},
AttesterSlashings: []*ethpb.AttesterSlashing{},
Attestations: []*ethpb.Attestation{},
Deposits: []*ethpb.Deposit{},
VoluntaryExits: []*ethpb.SignedVoluntaryExit{},
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, 32),
DepositCount: 0,
BlockHash: make([]byte, 32),
},
},
},
Signature: make([]byte, 96),
}
}
func signedTestBlockAltair(t *testing.T, slot types.Slot) interfaces.SignedBeaconBlock {
b := testBlockAltair()
b := util.NewBeaconBlockAltair()
b.Block.Slot = slot
s, err := wrapper.WrappedSignedBeaconBlock(b)
require.NoError(t, err)
return s
}
func testBlockAltair() *ethpb.SignedBeaconBlockAltair {
return &ethpb.SignedBeaconBlockAltair{
Block: &ethpb.BeaconBlockAltair{
ProposerIndex: types.ValidatorIndex(0),
ParentRoot: make([]byte, 32),
StateRoot: make([]byte, 32),
Body: &ethpb.BeaconBlockBodyAltair{
RandaoReveal: make([]byte, 96),
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, 32),
DepositCount: 0,
BlockHash: make([]byte, 32),
},
Graffiti: make([]byte, 32),
ProposerSlashings: []*ethpb.ProposerSlashing{},
AttesterSlashings: []*ethpb.AttesterSlashing{},
Attestations: []*ethpb.Attestation{},
Deposits: []*ethpb.Deposit{},
VoluntaryExits: []*ethpb.SignedVoluntaryExit{},
SyncAggregate: &ethpb.SyncAggregate{
SyncCommitteeBits: make([]byte, 64),
SyncCommitteeSignature: make([]byte, 96),
},
},
},
Signature: make([]byte, 96),
}
}
func signedTestBlockBellatrix(t *testing.T, slot types.Slot) interfaces.SignedBeaconBlock {
b := testBlockBellatrix()
b := util.NewBeaconBlockBellatrix()
b.Block.Slot = slot
s, err := wrapper.WrappedSignedBeaconBlock(b)
require.NoError(t, err)
return s
}
func testBlockBellatrix() *ethpb.SignedBeaconBlockBellatrix {
return &ethpb.SignedBeaconBlockBellatrix{
Block: &ethpb.BeaconBlockBellatrix{
ProposerIndex: types.ValidatorIndex(0),
ParentRoot: make([]byte, 32),
StateRoot: make([]byte, 32),
Body: &ethpb.BeaconBlockBodyBellatrix{
RandaoReveal: make([]byte, 96),
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, 32),
DepositCount: 0,
BlockHash: make([]byte, 32),
},
Graffiti: make([]byte, 32),
ProposerSlashings: []*ethpb.ProposerSlashing{},
AttesterSlashings: []*ethpb.AttesterSlashing{},
Attestations: []*ethpb.Attestation{},
Deposits: []*ethpb.Deposit{},
VoluntaryExits: []*ethpb.SignedVoluntaryExit{},
SyncAggregate: &ethpb.SyncAggregate{
SyncCommitteeBits: make([]byte, 64),
SyncCommitteeSignature: make([]byte, 96),
},
ExecutionPayload: &v1.ExecutionPayload{
ParentHash: make([]byte, 32),
FeeRecipient: make([]byte, 20),
StateRoot: make([]byte, 32),
ReceiptsRoot: make([]byte, 32),
LogsBloom: make([]byte, 256),
BlockNumber: 0,
GasLimit: 0,
GasUsed: 0,
Timestamp: 0,
ExtraData: make([]byte, 32),
BaseFeePerGas: make([]byte, 32),
BlockHash: make([]byte, 32),
Transactions: make([][]byte, 0),
PrevRandao: make([]byte, 32),
},
},
},
Signature: make([]byte, 96),
}
func signedTestBlindedBlockBellatrix(t *testing.T, slot types.Slot) interfaces.SignedBeaconBlock {
b := util.NewBlindedBeaconBlockBellatrix()
b.Block.Slot = slot
s, err := wrapper.WrappedSignedBeaconBlock(b)
require.NoError(t, err)
return s
}