mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-21 19:20:38 +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/params:go_default_library",
|
||||
"//shared/prometheus:go_default_library",
|
||||
"//shared/sliceutil:go_default_library",
|
||||
"//shared/tracing:go_default_library",
|
||||
"//shared/version: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/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/prometheus"
|
||||
"github.com/prysmaticlabs/prysm/shared/sliceutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/tracing"
|
||||
"github.com/prysmaticlabs/prysm/shared/version"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -213,7 +214,7 @@ func (b *BeaconNode) registerP2P(ctx *cli.Context) error {
|
||||
|
||||
svc, err := p2p.NewService(&p2p.Config{
|
||||
NoDiscovery: ctx.GlobalBool(cmd.NoDiscovery.Name),
|
||||
StaticPeers: ctx.GlobalStringSlice(cmd.StaticPeers.Name),
|
||||
StaticPeers: sliceutil.SplitCommaSeparated(ctx.GlobalStringSlice(cmd.StaticPeers.Name)),
|
||||
BootstrapNodeAddr: bootnodeENR,
|
||||
RelayNodeAddr: ctx.GlobalString(cmd.RelayNode.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
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SubsetUint64 returns true if the first array is
|
||||
// completely contained in the second array with time
|
||||
// complexity of approximately o(n).
|
||||
@ -259,3 +263,12 @@ func IntersectionByteSlices(s ...[][]byte) [][]byte {
|
||||
}
|
||||
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",
|
||||
srcs = ["main.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/tools/unencrypted-keys-gen",
|
||||
visibility = ["//visibility:private"],
|
||||
visibility = [
|
||||
"//tools/interop/convert-keys:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//shared/bls:go_default_library",
|
||||
],
|
||||
|
@ -18,11 +18,13 @@ var (
|
||||
overwrite = flag.Bool("overwrite", false, "If the key file exists, it will be overwritten")
|
||||
)
|
||||
|
||||
type unencryptedKeysContainer struct {
|
||||
Keys []*unencryptedKeys `json:"keys"`
|
||||
// UnencryptedKeysContainer defines the structure of the unecrypted key JSON file.
|
||||
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"`
|
||||
WithdrawalKey []byte `json:"withdrawal_key"`
|
||||
}
|
||||
@ -53,14 +55,14 @@ func main() {
|
||||
}()
|
||||
|
||||
ctnr := generateUnencryptedKeys(rand.Reader)
|
||||
if err := saveUnencryptedKeysToFile(file, ctnr); err != nil {
|
||||
if err := SaveUnencryptedKeysToFile(file, ctnr); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func generateUnencryptedKeys(r io.Reader) *unencryptedKeysContainer {
|
||||
ctnr := &unencryptedKeysContainer{
|
||||
Keys: make([]*unencryptedKeys, *numKeys),
|
||||
func generateUnencryptedKeys(r io.Reader) *UnencryptedKeysContainer {
|
||||
ctnr := &UnencryptedKeysContainer{
|
||||
Keys: make([]*UnencryptedKeys, *numKeys),
|
||||
}
|
||||
for i := 0; i < *numKeys; i++ {
|
||||
signingKey, err := bls.RandKey(r)
|
||||
@ -71,7 +73,7 @@ func generateUnencryptedKeys(r io.Reader) *unencryptedKeysContainer {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
ctnr.Keys[i] = &unencryptedKeys{
|
||||
ctnr.Keys[i] = &UnencryptedKeys{
|
||||
ValidatorKey: signingKey.Marshal(),
|
||||
WithdrawalKey: withdrawalKey.Marshal(),
|
||||
}
|
||||
@ -79,7 +81,8 @@ func generateUnencryptedKeys(r io.Reader) *unencryptedKeysContainer {
|
||||
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)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -11,11 +11,11 @@ import (
|
||||
func TestSavesUnencryptedKeys(t *testing.T) {
|
||||
ctnr := generateUnencryptedKeys(rand.Reader)
|
||||
buf := new(bytes.Buffer)
|
||||
if err := saveUnencryptedKeysToFile(buf, ctnr); err != nil {
|
||||
if err := SaveUnencryptedKeysToFile(buf, ctnr); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
enc := buf.Bytes()
|
||||
dec := &unencryptedKeysContainer{}
|
||||
dec := &UnencryptedKeysContainer{}
|
||||
if err := json.Unmarshal(enc, dec); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user