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

Create Pcli #5644

Merged
merged 14 commits into from
Apr 27, 2020
3 changes: 2 additions & 1 deletion beacon-chain/core/state/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ go_library(
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/state",
visibility = [
"//beacon-chain:__subpackages__",
"//endtoend:__pkg__",
"//shared/interop:__pkg__",
"//shared/testutil:__pkg__",
"//tools/benchmark-files-gen:__pkg__",
"//tools/genesis-state-gen:__pkg__",
"//endtoend:__pkg__",
rauljordan marked this conversation as resolved.
Show resolved Hide resolved
"//tools/pcli:__pkg__",
],
deps = [
"//beacon-chain/cache:go_default_library",
Expand Down
1 change: 1 addition & 0 deletions beacon-chain/state/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ go_library(
"//shared/benchutil:__pkg__",
"//shared/testutil:__pkg__",
"//tools/benchmark-files-gen:__pkg__",
"//tools/pcli:__pkg__",
],
deps = [
"//beacon-chain/core/state/stateutils:go_default_library",
Expand Down
1 change: 1 addition & 0 deletions beacon-chain/state/stateutil/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ go_library(
"//beacon-chain:__subpackages__",
"//proto/testing:__subpackages__",
"//shared/testutil:__subpackages__",
"//tools/pcli:__pkg__",
],
deps = [
"//proto/beacon/p2p/v1:go_default_library",
Expand Down
71 changes: 71 additions & 0 deletions tools/pcli/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
load("@io_bazel_rules_docker//go:image.bzl", "go_image")
load("@io_bazel_rules_docker//container:container.bzl", "container_bundle")
load("@io_bazel_rules_docker//contrib:push-all.bzl", "docker_push")

go_library(
name = "go_default_library",
srcs = ["main.go"],
importpath = "github.com/prysmaticlabs/prysm/tools/pcli",
visibility = ["//visibility:private"],
deps = [
"//beacon-chain/core/state:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/version:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_x_cray_logrus_prefixed_formatter//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@in_gopkg_urfave_cli_v2//:go_default_library",
],
)

go_image(
name = "image",
srcs = ["main.go"],
base = "//tools:go_image",
goarch = "amd64",
goos = "linux",
importpath = "github.com/prysmaticlabs/prysm/tools/pcli",
pure = "on",
race = "off",
tags = ["manual"],
visibility = ["//visibility:private"],
deps = [
"//beacon-chain/core/state:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/version:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_x_cray_logrus_prefixed_formatter//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@in_gopkg_urfave_cli_v2//:go_default_library",
],
)

go_binary(
name = "pcli",
embed = [":go_default_library"],
visibility = ["//visibility:public"],
)

container_bundle(
name = "image_bundle",
images = {
"gcr.io/prysmaticlabs/prysm/pcli:latest": ":image",
"gcr.io/prysmaticlabs/prysm/pcli:{DOCKER_TAG}": ":image",
},
tags = ["manual"],
)

docker_push(
name = "push_images",
bundle = ":image_bundle",
tags = ["manual"],
)
142 changes: 142 additions & 0 deletions tools/pcli/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package main

import (
"bufio"
"context"
"io/ioutil"
"os"
"strings"

ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/version"
log "github.com/sirupsen/logrus"
prefixed "github.com/x-cray/logrus-prefixed-formatter"
"gopkg.in/d4l3k/messagediff.v1"
"gopkg.in/urfave/cli.v2"
)

func main() {
var blockPath string
var preStatePath string
var expectedPostStatePath string

customFormatter := new(prefixed.TextFormatter)
customFormatter.TimestampFormat = "2006-01-02 15:04:05"
customFormatter.FullTimestamp = true
log.SetFormatter(customFormatter)

app := cli.App{}
app.Name = "pcli"
app.Usage = "A command line utility to run eth2 specific actions"
app.Version = version.GetVersion()
app.Commands = []*cli.Command{{
Name: "state-transition",
Category: "state-transition",
Usage: "Subcommand to run manual state transitions",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "blockPath",
rauljordan marked this conversation as resolved.
Show resolved Hide resolved
Usage: "Path to block file(ssz)",
Destination: &blockPath,
},
&cli.StringFlag{
Name: "preStatePath",
Copy link
Contributor

Choose a reason for hiding this comment

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

our cli flags are using dashes usually

Suggested change
Name: "preStatePath",
Name: "pre-state-path",

Usage: "Path to pre state file(ssz)",
Destination: &preStatePath,
},
&cli.StringFlag{
Name: "expectedPostStatePath",
rauljordan marked this conversation as resolved.
Show resolved Hide resolved
Usage: "Path to expected post state file(ssz)",
Destination: &expectedPostStatePath,
},
},
Action: func(c *cli.Context) error {
if blockPath == "" {
log.Info("Block path not provided for state transition. " +
"Please provide path")
reader := bufio.NewReader(os.Stdin)
text, err := reader.ReadString('\n')
if err != nil {
log.Fatal(err)
}
if text = strings.Replace(text, "\n", "", -1); text == "" {
log.Fatal("Empty block path given")
}
blockPath = text
}
block := &ethpb.SignedBeaconBlock{}
if err := dataFetcher(blockPath, block); err != nil {
log.Fatal(err)
}
blkRoot, err := stateutil.BlockRoot(block.Block)
if err != nil {
log.Fatal(err)
}
if preStatePath == "" {
log.Info("Pre State path not provided for state transition. " +
"Please provide path")
reader := bufio.NewReader(os.Stdin)
text, err := reader.ReadString('\n')
if err != nil {
log.Fatal(err)
}
if text = strings.Replace(text, "\n", "", -1); text == "" {
log.Fatal("Empty state path given")
}
preStatePath = text
}
preState := &pb.BeaconState{}
if err := dataFetcher(preStatePath, preState); err != nil {
log.Fatal(err)
}
stateObj, err := stateTrie.InitializeFromProto(preState)
if err != nil {
log.Fatal(err)
}
preStateRoot, err := stateObj.HashTreeRoot(context.Background())
if err != nil {
log.Fatal(err)
}
log.Infof("Performing State Transition with a block root of %#x and pre state root of %#x",
rauljordan marked this conversation as resolved.
Show resolved Hide resolved
blkRoot, preStateRoot)
postState, err := state.ExecuteStateTransition(context.Background(), stateObj, block)
if err != nil {
log.Fatal(err)
}
postRoot, err := postState.HashTreeRoot(context.Background())
log.Infof("Finished Performing State Transition with Post state root of %#x", postRoot)
rauljordan marked this conversation as resolved.
Show resolved Hide resolved

// diff the state if a post state is provided
nisdas marked this conversation as resolved.
Show resolved Hide resolved
if expectedPostStatePath != "" {
expectedState := &pb.BeaconState{}
if err := dataFetcher(expectedPostStatePath, expectedState); err != nil {
log.Fatal(err)
}
if !ssz.DeepEqual(expectedState, postState.InnerStateUnsafe()) {
diff, _ := messagediff.PrettyDiff(expectedState, postState.InnerStateUnsafe())
log.Errorf("Derived state differs from provided post state: %s", diff)
}
}
return nil
},
},
}
if err := app.Run(os.Args); err != nil {
log.Error(err.Error())
os.Exit(1)
}
}

// fetch data and unmarshal to provided data structure from file
nisdas marked this conversation as resolved.
Show resolved Hide resolved
func dataFetcher(fPath string, data interface{}) error {
rawFile, err := ioutil.ReadFile(fPath)
if err != nil {
return err
}
return ssz.Unmarshal(rawFile, data)
}