Skip to content

Commit

Permalink
add all this in
Browse files Browse the repository at this point in the history
  • Loading branch information
nisdas committed Jan 18, 2024
1 parent c3dbfa6 commit 946d466
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 21 deletions.
21 changes: 19 additions & 2 deletions encoding/ssz/detect/configfork.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,23 @@ func FromState(marshaled []byte) (*VersionedUnmarshaler, error) {
return FromForkVersion(cv)
}

// FromBlock uses the known size of an offset and signature to determine the slot of a block without unmarshalling it.
// The slot is used to determine the version along with the respective config.
func FromBlock(marshaled []byte) (*VersionedUnmarshaler, error) {
slot, err := slotFromBlock(marshaled)
if err != nil {
return nil, err
}
copiedCfg := params.BeaconConfig().Copy()
epoch := slots.ToEpoch(slot)
fs := forks.NewOrderedSchedule(copiedCfg)
ver, err := fs.VersionForEpoch(epoch)
if err != nil {
return nil, err
}
return FromForkVersion(ver)
}

var ErrForkNotFound = errors.New("version found in fork schedule but can't be matched to a named fork")

// FromForkVersion uses a lookup table to resolve a Version (from a beacon node api for instance, or obtained by peeking at
Expand Down Expand Up @@ -162,7 +179,7 @@ var errBlockForkMismatch = errors.New("fork or config detected in unmarshaler is

// UnmarshalBeaconBlock uses internal knowledge in the VersionedUnmarshaler to pick the right concrete ReadOnlySignedBeaconBlock type,
// then Unmarshal()s the type and returns an instance of block.ReadOnlySignedBeaconBlock if successful.
func (cf *VersionedUnmarshaler) UnmarshalBeaconBlock(marshaled []byte) (interfaces.ReadOnlySignedBeaconBlock, error) {
func (cf *VersionedUnmarshaler) UnmarshalBeaconBlock(marshaled []byte) (interfaces.SignedBeaconBlock, error) {
slot, err := slotFromBlock(marshaled)
if err != nil {
return nil, err
Expand Down Expand Up @@ -197,7 +214,7 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconBlock(marshaled []byte) (interfac
// UnmarshalBlindedBeaconBlock uses internal knowledge in the VersionedUnmarshaler to pick the right concrete blinded ReadOnlySignedBeaconBlock type,
// then Unmarshal()s the type and returns an instance of block.ReadOnlySignedBeaconBlock if successful.
// For Phase0 and Altair it works exactly line UnmarshalBeaconBlock.
func (cf *VersionedUnmarshaler) UnmarshalBlindedBeaconBlock(marshaled []byte) (interfaces.ReadOnlySignedBeaconBlock, error) {
func (cf *VersionedUnmarshaler) UnmarshalBlindedBeaconBlock(marshaled []byte) (interfaces.SignedBeaconBlock, error) {
slot, err := slotFromBlock(marshaled)
if err != nil {
return nil, err
Expand Down
91 changes: 91 additions & 0 deletions encoding/ssz/detect/configfork_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,97 @@ func TestUnmarshalState(t *testing.T) {
}
}

func TestDetectAndUnmarshalBlock(t *testing.T) {
undo := util.HackDenebMaxuint(t)
defer undo()
altairS, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch)
require.NoError(t, err)
bellaS, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch)
require.NoError(t, err)
capellaS, err := slots.EpochStart(params.BeaconConfig().CapellaForkEpoch)
require.NoError(t, err)
denebS, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
require.NoError(t, err)
cases := []struct {
b func(*testing.T, primitives.Slot) interfaces.ReadOnlySignedBeaconBlock
name string
slot primitives.Slot
errExists bool
}{
{
name: "genesis - slot 0",
b: signedTestBlockGenesis,
},
{
name: "last slot of phase 0",
b: signedTestBlockGenesis,
slot: altairS - 1,
},
{
name: "first slot of altair",
b: signedTestBlockAltair,
slot: altairS,
},
{
name: "last slot of altair",
b: signedTestBlockAltair,
slot: bellaS - 1,
},
{
name: "first slot of bellatrix",
b: signedTestBlockBellatrix,
slot: bellaS,
},
{
name: "first slot of capella",
b: signedTestBlockCapella,
slot: capellaS,
},
{
name: "last slot of capella",
b: signedTestBlockCapella,
slot: denebS - 1,
},
{
name: "first slot of deneb",
b: signedTestBlockDeneb,
slot: denebS,
},
{
name: "bellatrix block in altair slot",
b: signedTestBlockBellatrix,
slot: bellaS - 1,
errExists: true,
},
{
name: "genesis block in altair slot",
b: signedTestBlockGenesis,
slot: bellaS - 1,
errExists: true,
},
}
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 := FromBlock(marshaled)
require.NoError(t, err)
bcf, err := cf.UnmarshalBeaconBlock(marshaled)
if c.errExists {
require.NotNil(t, 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 TestUnmarshalBlock(t *testing.T) {
undo := util.HackDenebMaxuint(t)
defer undo()
Expand Down
4 changes: 4 additions & 0 deletions tools/pcli/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ go_library(
visibility = ["//visibility:private"],
deps = [
"//beacon-chain/core/transition:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//encoding/ssz/detect:go_default_library",
"//encoding/ssz/equality:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/logging/logrus-prefixed-formatter:go_default_library",
"//runtime/version:go_default_library",
"@com_github_kr_pretty//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_fastssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library",
Expand Down
61 changes: 42 additions & 19 deletions tools/pcli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ import (
"time"

"github.com/kr/pretty"
"github.com/pkg/errors"
fssz "github.com/prysmaticlabs/fastssz"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
state_native "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v4/encoding/ssz/detect"
"github.com/prysmaticlabs/prysm/v4/encoding/ssz/equality"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
prefixed "github.com/prysmaticlabs/prysm/v4/runtime/logging/logrus-prefixed-formatter"
Expand Down Expand Up @@ -172,11 +175,11 @@ func main() {
}
blockPath = text
}
block := &ethpb.SignedBeaconBlock{}
if err := dataFetcher(blockPath, block); err != nil {
block, err := detectBlock(blockPath)
if err != nil {
log.Fatal(err)
}
blkRoot, err := block.Block.HashTreeRoot()
blkRoot, err := block.Block().HashTreeRoot()
if err != nil {
log.Fatal(err)
}
Expand All @@ -193,11 +196,7 @@ func main() {
}
preStatePath = text
}
preState := &ethpb.BeaconState{}
if err := dataFetcher(preStatePath, preState); err != nil {
log.Fatal(err)
}
stateObj, err := state_native.InitializeFromProtoPhase0(preState)
stateObj, err := detectState(preStatePath)
if err != nil {
log.Fatal(err)
}
Expand All @@ -206,18 +205,14 @@ func main() {
log.Fatal(err)
}
log.WithFields(log.Fields{
"blockSlot": fmt.Sprintf("%d", block.Block.Slot),
"blockSlot": fmt.Sprintf("%d", block.Block().Slot()),
"preStateSlot": fmt.Sprintf("%d", stateObj.Slot()),
}).Infof(
"Performing state transition with a block root of %#x and pre state root of %#x",
blkRoot,
preStateRoot,
)
wsb, err := blocks.NewSignedBeaconBlock(block)
if err != nil {
log.Fatal(err)
}
postState, err := transition.ExecuteStateTransition(context.Background(), stateObj, wsb)
postState, err := transition.ExecuteStateTransition(context.Background(), stateObj, block)
if err != nil {
log.Fatal(err)
}
Expand All @@ -229,12 +224,12 @@ func main() {

// Diff the state if a post state is provided.
if expectedPostStatePath != "" {
expectedState := &ethpb.BeaconState{}
if err := dataFetcher(expectedPostStatePath, expectedState); err != nil {
expectedState, err := detectState(expectedPostStatePath)
if err != nil {
log.Fatal(err)
}
if !equality.DeepEqual(expectedState, postState.ToProtoUnsafe()) {
diff, _ := messagediff.PrettyDiff(expectedState, postState.ToProtoUnsafe())
if !equality.DeepEqual(expectedState.ToProtoUnsafe(), postState.ToProtoUnsafe()) {
diff, _ := messagediff.PrettyDiff(expectedState.ToProtoUnsafe(), postState.ToProtoUnsafe())
log.Errorf("Derived state differs from provided post state: %s", diff)
}
}
Expand All @@ -257,6 +252,34 @@ func dataFetcher(fPath string, data fssz.Unmarshaler) error {
return data.UnmarshalSSZ(rawFile)
}

func detectState(fPath string) (state.BeaconState, error) {
rawFile, err := os.ReadFile(fPath) // #nosec G304
if err != nil {
return nil, err
}
vu, err := detect.FromState(rawFile)
if err != nil {
return nil, errors.Wrap(err, "error detecting state from file")
}
s, err := vu.UnmarshalBeaconState(rawFile)
if err != nil {
return nil, errors.Wrap(err, "error unmarshalling state")
}
return s, nil
}

func detectBlock(fPath string) (interfaces.SignedBeaconBlock, error) {
rawFile, err := os.ReadFile(fPath) // #nosec G304
if err != nil {
return nil, err
}
vu, err := detect.FromBlock(rawFile)
if err != nil {
return nil, err
}
return vu.UnmarshalBeaconBlock(rawFile)
}

func prettyPrint(sszPath string, data fssz.Unmarshaler) {
if err := dataFetcher(sszPath, data); err != nil {
log.Fatal(err)
Expand Down

0 comments on commit 946d466

Please sign in to comment.