mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 03:30:35 +00:00
Add tool and script for interop testing (#3417)
* add tool and script for interop testing * identity * lint * merge upstream, fix conflict, update script, add comment * add comma separated support for --peer= * remove NUM_VALIDATORS, comma fix * WIP docker image * use CI builder * pr feedback * whatever antoine says * ignore git in docker * jobs=auto * disable remote cache * try to cache the golang part * try to cache the golang part * nvm * From Antoine with love * fix
This commit is contained in:
parent
af07c13730
commit
3708a8f476
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
bazel-*
|
||||||
|
.git
|
@ -26,6 +26,7 @@ go_library(
|
|||||||
"//shared/featureconfig:go_default_library",
|
"//shared/featureconfig:go_default_library",
|
||||||
"//shared/params:go_default_library",
|
"//shared/params:go_default_library",
|
||||||
"//shared/prometheus:go_default_library",
|
"//shared/prometheus:go_default_library",
|
||||||
|
"//shared/sliceutil:go_default_library",
|
||||||
"//shared/tracing:go_default_library",
|
"//shared/tracing:go_default_library",
|
||||||
"//shared/version:go_default_library",
|
"//shared/version:go_default_library",
|
||||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||||
|
@ -34,6 +34,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||||
"github.com/prysmaticlabs/prysm/shared/params"
|
"github.com/prysmaticlabs/prysm/shared/params"
|
||||||
"github.com/prysmaticlabs/prysm/shared/prometheus"
|
"github.com/prysmaticlabs/prysm/shared/prometheus"
|
||||||
|
"github.com/prysmaticlabs/prysm/shared/sliceutil"
|
||||||
"github.com/prysmaticlabs/prysm/shared/tracing"
|
"github.com/prysmaticlabs/prysm/shared/tracing"
|
||||||
"github.com/prysmaticlabs/prysm/shared/version"
|
"github.com/prysmaticlabs/prysm/shared/version"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -213,7 +214,7 @@ func (b *BeaconNode) registerP2P(ctx *cli.Context) error {
|
|||||||
|
|
||||||
svc, err := p2p.NewService(&p2p.Config{
|
svc, err := p2p.NewService(&p2p.Config{
|
||||||
NoDiscovery: ctx.GlobalBool(cmd.NoDiscovery.Name),
|
NoDiscovery: ctx.GlobalBool(cmd.NoDiscovery.Name),
|
||||||
StaticPeers: ctx.GlobalStringSlice(cmd.StaticPeers.Name),
|
StaticPeers: sliceutil.SplitCommaSeparated(ctx.GlobalStringSlice(cmd.StaticPeers.Name)),
|
||||||
BootstrapNodeAddr: bootnodeENR,
|
BootstrapNodeAddr: bootnodeENR,
|
||||||
RelayNodeAddr: ctx.GlobalString(cmd.RelayNode.Name),
|
RelayNodeAddr: ctx.GlobalString(cmd.RelayNode.Name),
|
||||||
HostAddress: ctx.GlobalString(cmd.P2PHost.Name),
|
HostAddress: ctx.GlobalString(cmd.P2PHost.Name),
|
||||||
|
24
interop.Dockerfile
Normal file
24
interop.Dockerfile
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
FROM gcr.io/prysmaticlabs/build-agent AS builder
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
|
||||||
|
COPY . /workspace/.
|
||||||
|
|
||||||
|
# Build binaries for minimal configuration.
|
||||||
|
RUN bazel build --define ssz=minimal --jobs=auto --remote_cache= \
|
||||||
|
//beacon-chain \
|
||||||
|
//validator \
|
||||||
|
//tools/interop/convert-keys
|
||||||
|
|
||||||
|
|
||||||
|
FROM gcr.io/whiteblock/base:ubuntu1804
|
||||||
|
|
||||||
|
COPY --from=builder /workspace/bazel-bin/beacon-chain/linux_amd64_stripped/beacon-chain .
|
||||||
|
COPY --from=builder /workspace/bazel-bin/validator/linux_amd64_pure_stripped/validator .
|
||||||
|
COPY --from=builder /workspace/bazel-bin/tools/interop/convert-keys/linux_amd64_stripped/convert-keys .
|
||||||
|
|
||||||
|
RUN mkdir /launch
|
||||||
|
|
||||||
|
COPY scripts/interop_start.sh /launch/start.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["start.sh"]
|
93
scripts/interop_start.sh
Executable file
93
scripts/interop_start.sh
Executable file
@ -0,0 +1,93 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
"""
|
||||||
|
2019/09/08 -- Interop start script.
|
||||||
|
This script is intended for dockerfile deployment for interop testing.
|
||||||
|
This script is fragile and subject to break as flags change.
|
||||||
|
Use at your own risk!
|
||||||
|
|
||||||
|
|
||||||
|
Use with interop.Dockerfile from the workspace root:
|
||||||
|
|
||||||
|
docker build -f interop.Dockerfile .
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Flags
|
||||||
|
IDENTITY="" # P2P private key
|
||||||
|
PEERS="" # Comma separated list of peers
|
||||||
|
GEN_STATE="" # filepath to ssz encoded state.
|
||||||
|
PORT="8000" # port to serve p2p traffic
|
||||||
|
YAML_KEY_FILE="" # Path to yaml keyfile as defined here: https://github.com/ethereum/eth2.0-pm/tree/master/interop/mocked_start
|
||||||
|
|
||||||
|
# Constants
|
||||||
|
BEACON_LOG_FILE="/tmp/beacon.log"
|
||||||
|
VALIDATOR_LOG_FILE="/tmp/validator.log"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "--identity=<identity>"
|
||||||
|
echo "--peer=<peer>"
|
||||||
|
echo "--num-validators=<number>"
|
||||||
|
echo "--gen-state=<file path>"
|
||||||
|
port "--port=<port number>"
|
||||||
|
}
|
||||||
|
|
||||||
|
while [ "$1" != "" ];
|
||||||
|
do
|
||||||
|
PARAM=`echo $1 | awk -F= '{print $1}'`
|
||||||
|
VALUE=`echo $1 | sed 's/^[^=]*=//g'`
|
||||||
|
|
||||||
|
case $PARAM in
|
||||||
|
--identity)
|
||||||
|
IDENTITY=$VALUE
|
||||||
|
;;
|
||||||
|
--peers)
|
||||||
|
PEERS+=",$VALUE"
|
||||||
|
;;
|
||||||
|
--validator-keys)
|
||||||
|
YAML_KEY_FILE=$VALUE
|
||||||
|
;;
|
||||||
|
--gen-state)
|
||||||
|
GEN_STATE=$VALUE
|
||||||
|
;;
|
||||||
|
--port)
|
||||||
|
PORT=$VALUE
|
||||||
|
;;
|
||||||
|
--help)
|
||||||
|
usage
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "ERROR: unknown parameter \"$PARAM\""
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
echo "Converting hex yaml keys to a format that Prysm understands"
|
||||||
|
|
||||||
|
# Expect YAML keys in hex encoded format. Convert this into the format the the validator already understands.
|
||||||
|
./convert-keys $YAML_KEY_FILE /tmp/keys.json
|
||||||
|
|
||||||
|
echo "Starting beacon chain and logging to $BEACON_LOG_FILE"
|
||||||
|
|
||||||
|
BEACON_FLAGS="--bootstrap-node= \
|
||||||
|
--deposit-contract=0xD775140349E6A5D12524C6ccc3d6A1d4519D4029 \
|
||||||
|
--p2p-port=$PORT \
|
||||||
|
--peer=$PEERS \
|
||||||
|
--interop-genesis-state=$GEN_STATE \
|
||||||
|
--p2p-priv-key=$IDENTITY \
|
||||||
|
--log-file=$BEACON_LOG_FILE"
|
||||||
|
|
||||||
|
./beacon-chain $BEACON_FLAGS &
|
||||||
|
|
||||||
|
echo "Starting validator client and logging to $VALIDATOR_LOG_FILE"
|
||||||
|
|
||||||
|
VALIDATOR_FLAGS="--monitoring-port=9091 \
|
||||||
|
--unencrypted-keys /tmp/keys.json \
|
||||||
|
--log-file=$VALIDATOR_LOG_FILE
|
||||||
|
|
||||||
|
./validator- $VALIDATOR_FLAGS &
|
||||||
|
|
@ -1,5 +1,9 @@
|
|||||||
package sliceutil
|
package sliceutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// SubsetUint64 returns true if the first array is
|
// SubsetUint64 returns true if the first array is
|
||||||
// completely contained in the second array with time
|
// completely contained in the second array with time
|
||||||
// complexity of approximately o(n).
|
// complexity of approximately o(n).
|
||||||
@ -259,3 +263,12 @@ func IntersectionByteSlices(s ...[][]byte) [][]byte {
|
|||||||
}
|
}
|
||||||
return inter
|
return inter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SplitCommaSeparated values from the list. Example: []string{"a,b", "c,d"} becomes []string{"a", "b", "c", "d"}.
|
||||||
|
func SplitCommaSeparated(arr []string) []string {
|
||||||
|
var result []string
|
||||||
|
for _, val := range arr {
|
||||||
|
result = append(result, strings.Split(val, ",")...)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
@ -352,3 +352,29 @@ func TestIntersectionByteSlices(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSplitCommaSeparated(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
input []string
|
||||||
|
output []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: []string{"a,b", "c,d"},
|
||||||
|
output: []string{"a", "b", "c", "d"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []string{"a", "b,c,d"},
|
||||||
|
output: []string{"a", "b", "c", "d"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []string{"a", "b", "c"},
|
||||||
|
output: []string{"a", "b", "c"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
if result := SplitCommaSeparated(tt.input); !reflect.DeepEqual(result, tt.output) {
|
||||||
|
t.Errorf("SplitCommaSeparated(%v) = %v; wanted %v", tt.input, result, tt.output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
18
tools/interop/convert-keys/BUILD.bazel
Normal file
18
tools/interop/convert-keys/BUILD.bazel
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["main.go"],
|
||||||
|
importpath = "github.com/prysmaticlabs/prysm/tools/interop/convert-keys",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
"//tools/unencrypted-keys-gen:go_default_library",
|
||||||
|
"@in_gopkg_yaml_v2//:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_binary(
|
||||||
|
name = "convert-keys",
|
||||||
|
embed = [":go_default_library"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
65
tools/interop/convert-keys/main.go
Normal file
65
tools/interop/convert-keys/main.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Used for converting keys.yaml files from eth2.0-pm for interop testing.
|
||||||
|
// See: https://github.com/ethereum/eth2.0-pm/tree/master/interop/mocked_start
|
||||||
|
//
|
||||||
|
// This code can be discarded after interop testing.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
keygen "github.com/prysmaticlabs/prysm/tools/unencrypted-keys-gen"
|
||||||
|
)
|
||||||
|
|
||||||
|
// KeyPair with hex encoded data.
|
||||||
|
type KeyPair struct {
|
||||||
|
Priv string `yaml:"privkey"`
|
||||||
|
Pub string `yaml:"pubkey"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyPairs represent the data format in the upstream yaml.
|
||||||
|
type KeyPairs []KeyPair
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) < 3 {
|
||||||
|
fmt.Println("Usage: convert-keys path/to/keys.yaml path/to/output.json")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
inFile := os.Args[1]
|
||||||
|
|
||||||
|
in, err := ioutil.ReadFile(inFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to read file %s: %v", inFile, err)
|
||||||
|
}
|
||||||
|
data := make(KeyPairs, 0)
|
||||||
|
if err := yaml.Unmarshal(in, &data); err != nil {
|
||||||
|
log.Fatalf("Failed to unmarshal yaml: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
out := &keygen.UnencryptedKeysContainer{}
|
||||||
|
for _, key := range data {
|
||||||
|
pk, err := hex.DecodeString(key.Priv[2:])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to decode hex string %s: %v", key.Priv, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
out.Keys = append(out.Keys, &keygen.UnencryptedKeys{
|
||||||
|
ValidatorKey: pk,
|
||||||
|
WithdrawalKey: pk,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile, err := os.Create(os.Args[2])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to create file at %s: %v", os.Args[2], err)
|
||||||
|
}
|
||||||
|
defer outFile.Close()
|
||||||
|
if err := keygen.SaveUnencryptedKeysToFile(outFile, out); err != nil {
|
||||||
|
log.Fatalf("Failed to save %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("Wrote %s\n", os.Args[2])
|
||||||
|
}
|
@ -4,7 +4,9 @@ go_library(
|
|||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = ["main.go"],
|
srcs = ["main.go"],
|
||||||
importpath = "github.com/prysmaticlabs/prysm/tools/unencrypted-keys-gen",
|
importpath = "github.com/prysmaticlabs/prysm/tools/unencrypted-keys-gen",
|
||||||
visibility = ["//visibility:private"],
|
visibility = [
|
||||||
|
"//tools/interop/convert-keys:__pkg__",
|
||||||
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"//shared/bls:go_default_library",
|
"//shared/bls:go_default_library",
|
||||||
],
|
],
|
||||||
|
@ -18,11 +18,13 @@ var (
|
|||||||
overwrite = flag.Bool("overwrite", false, "If the key file exists, it will be overwritten")
|
overwrite = flag.Bool("overwrite", false, "If the key file exists, it will be overwritten")
|
||||||
)
|
)
|
||||||
|
|
||||||
type unencryptedKeysContainer struct {
|
// UnencryptedKeysContainer defines the structure of the unecrypted key JSON file.
|
||||||
Keys []*unencryptedKeys `json:"keys"`
|
type UnencryptedKeysContainer struct {
|
||||||
|
Keys []*UnencryptedKeys `json:"keys"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type unencryptedKeys struct {
|
// UnencryptedKeys is the inner struct of the JSON file.
|
||||||
|
type UnencryptedKeys struct {
|
||||||
ValidatorKey []byte `json:"validator_key"`
|
ValidatorKey []byte `json:"validator_key"`
|
||||||
WithdrawalKey []byte `json:"withdrawal_key"`
|
WithdrawalKey []byte `json:"withdrawal_key"`
|
||||||
}
|
}
|
||||||
@ -53,14 +55,14 @@ func main() {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
ctnr := generateUnencryptedKeys(rand.Reader)
|
ctnr := generateUnencryptedKeys(rand.Reader)
|
||||||
if err := saveUnencryptedKeysToFile(file, ctnr); err != nil {
|
if err := SaveUnencryptedKeysToFile(file, ctnr); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateUnencryptedKeys(r io.Reader) *unencryptedKeysContainer {
|
func generateUnencryptedKeys(r io.Reader) *UnencryptedKeysContainer {
|
||||||
ctnr := &unencryptedKeysContainer{
|
ctnr := &UnencryptedKeysContainer{
|
||||||
Keys: make([]*unencryptedKeys, *numKeys),
|
Keys: make([]*UnencryptedKeys, *numKeys),
|
||||||
}
|
}
|
||||||
for i := 0; i < *numKeys; i++ {
|
for i := 0; i < *numKeys; i++ {
|
||||||
signingKey, err := bls.RandKey(r)
|
signingKey, err := bls.RandKey(r)
|
||||||
@ -71,7 +73,7 @@ func generateUnencryptedKeys(r io.Reader) *unencryptedKeysContainer {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
ctnr.Keys[i] = &unencryptedKeys{
|
ctnr.Keys[i] = &UnencryptedKeys{
|
||||||
ValidatorKey: signingKey.Marshal(),
|
ValidatorKey: signingKey.Marshal(),
|
||||||
WithdrawalKey: withdrawalKey.Marshal(),
|
WithdrawalKey: withdrawalKey.Marshal(),
|
||||||
}
|
}
|
||||||
@ -79,7 +81,8 @@ func generateUnencryptedKeys(r io.Reader) *unencryptedKeysContainer {
|
|||||||
return ctnr
|
return ctnr
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveUnencryptedKeysToFile(w io.Writer, ctnr *unencryptedKeysContainer) error {
|
// SaveUnencryptedKeysToFile JSON encodes the container and writes to the writer.
|
||||||
|
func SaveUnencryptedKeysToFile(w io.Writer, ctnr *UnencryptedKeysContainer) error {
|
||||||
enc, err := json.Marshal(ctnr)
|
enc, err := json.Marshal(ctnr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -11,11 +11,11 @@ import (
|
|||||||
func TestSavesUnencryptedKeys(t *testing.T) {
|
func TestSavesUnencryptedKeys(t *testing.T) {
|
||||||
ctnr := generateUnencryptedKeys(rand.Reader)
|
ctnr := generateUnencryptedKeys(rand.Reader)
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
if err := saveUnencryptedKeysToFile(buf, ctnr); err != nil {
|
if err := SaveUnencryptedKeysToFile(buf, ctnr); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
enc := buf.Bytes()
|
enc := buf.Bytes()
|
||||||
dec := &unencryptedKeysContainer{}
|
dec := &UnencryptedKeysContainer{}
|
||||||
if err := json.Unmarshal(enc, dec); err != nil {
|
if err := json.Unmarshal(enc, dec); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user