bridge: devnet guardian key generation

This commit is contained in:
Leo 2020-08-17 18:20:15 +02:00
parent e040449197
commit 955bcc93fe
7 changed files with 104 additions and 22 deletions

View File

@ -5,7 +5,7 @@ WORKDIR /app
ADD . .
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg \
go build -o /guardiand github.com/certusone/wormhole/bridge/cmd/guardiand
RUN --mount=type=cache,target=/root/.cache --mount=type=cache,target=/go \
go build -mod=readonly -o /guardiand github.com/certusone/wormhole/bridge/cmd/guardiand
ENTRYPOINT /guardiand

View File

@ -0,0 +1,49 @@
package main
import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"encoding/binary"
"fmt"
"os"
"strconv"
"strings"
)
// getDevnetIndex returns the current host's devnet index (i.e. 0 for guardian-0).
func getDevnetIndex() (int, error) {
hostname, err := os.Hostname()
if err != nil {
panic(err)
}
h := strings.Split(hostname, "-")
if h[0] != "guardian" {
return 0, fmt.Errorf("hostname %s does not appear to be a devnet host", hostname)
}
i, err := strconv.Atoi(h[1])
if err != nil {
return 0, fmt.Errorf("invalid devnet index %s in hostname %s", h[1], hostname)
}
return i, nil
}
// deterministicKeyByIndex generates a deterministic address from a given index.
func deterministicKeyByIndex(c elliptic.Curve, idx uint64) (*ecdsa.PrivateKey) {
buf := make([]byte, 200)
binary.LittleEndian.PutUint64(buf, idx)
worstRNG := bytes.NewBuffer(buf)
key, err := ecdsa.GenerateKey(c, bytes.NewReader(worstRNG.Bytes()))
if err != nil {
panic(err)
}
return key
}

View File

@ -2,12 +2,14 @@ package main
import (
"context"
"crypto/ecdsa"
"encoding/hex"
"flag"
"fmt"
"os"
eth_common "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"go.uber.org/zap"
"github.com/certusone/wormhole/bridge/pkg/common"
@ -29,6 +31,8 @@ var (
ethConfirmations = flag.Uint64("ethConfirmations", 15, "Ethereum confirmation count requirement")
logLevel = flag.String("loglevel", "info", "Logging level (debug, info, warn, error, dpanic, panic, fatal)")
unsafeDevMode = flag.Bool("unsafeDevMode", false, "Launch node in unsafe, deterministic devnet mode")
)
var (
@ -54,8 +58,8 @@ func main() {
panic(err)
}
// Our root logger.
logger := ipfslog.Logger(fmt.Sprintf("%s-%s", "wormhole", hostname))
// Our root logger. Convert directly to a regular Zap logger.
logger := ipfslog.Logger(fmt.Sprintf("%s-%s", "wormhole", hostname)).Desugar()
// Override the default go-log config, which uses a magic environment variable.
ipfslog.SetAllLoggers(lvl)
@ -73,6 +77,25 @@ func main() {
ethContractAddr := eth_common.HexToAddress(*ethContract)
// Guardian key initialization
var gk *ecdsa.PrivateKey
if *unsafeDevMode {
// Figure out our devnet index
idx, err := getDevnetIndex()
if err != nil {
logger.Fatal("Failed to parse hostname - are we running in devnet?")
}
// Generate guardian key
gk = deterministicKeyByIndex(crypto.S256(), uint64(idx))
} else {
panic("not implemented") // TODO
}
logger.Info("Loaded guardian key", zap.String(
"address", crypto.PubkeyToAddress(gk.PublicKey).String()))
// Node's main lifecycle context.
rootCtx, rootCtxCancel = context.WithCancel(context.Background())
defer rootCtxCancel()
@ -81,7 +104,7 @@ func main() {
ec := make(chan *common.ChainLock)
// Run supervisor.
supervisor.New(rootCtx, logger.Desugar(), func(ctx context.Context) error {
supervisor.New(rootCtx, logger, func(ctx context.Context) error {
if err := supervisor.Run(ctx, "p2p", p2p); err != nil {
return err
}

View File

@ -48,16 +48,14 @@ func getOrCreateNodeKey(logger *zap.Logger, path string) (crypto.PrivKey, error)
return priv, nil
}
// FIXME: this hardcodes the private key if we're guardian-0.
// Proper fix is to add a debug mode and fetch the remote peer ID,
// or add a special bootstrap pod.
func bootstrapNodePrivateKeyHack() crypto.PrivKey {
hostname, err := os.Hostname()
// deterministicNodeKey returns a non-nil value if we have a deterministic key on file for the current host.
func deterministicNodeKey() crypto.PrivKey {
idx, err := getDevnetIndex()
if err != nil {
panic(err)
}
if hostname == "guardian-0" {
if idx == 0 {
// node ID: 12D3KooWQ1sV2kowPY1iJX1hJcVTysZjKv3sfULTGwhdpUGGZ1VF
b, err := base64.StdEncoding.DecodeString("CAESQGlv6OJOMXrZZVTCC0cgCv7goXr6QaSVMZIndOIXKNh80vYnG+EutVlZK20Nx9cLkUG5ymKB\n88LXi/vPBwP8zfY=")
if err != nil {

View File

@ -18,6 +18,7 @@ import (
libp2pquic "github.com/libp2p/go-libp2p-quic-transport"
swarm "github.com/libp2p/go-libp2p-swarm"
libp2ptls "github.com/libp2p/go-libp2p-tls"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/multiformats/go-multiaddr"
"go.uber.org/zap"
"google.golang.org/protobuf/proto"
@ -29,16 +30,26 @@ import (
func p2p(ctx context.Context) (re error) {
logger := supervisor.Logger(ctx)
priv := bootstrapNodePrivateKeyHack()
var priv crypto.PrivKey
var err error
if priv == nil {
priv, err = getOrCreateNodeKey(logger, *nodeKeyPath)
if err != nil {
panic(err)
if *unsafeDevMode {
priv = deterministicNodeKey()
var err error
if priv == nil {
priv, err = getOrCreateNodeKey(logger, *nodeKeyPath)
if err != nil {
return fmt.Errorf("failed to load node key: %w", err)
}
} else {
logger.Info("devnet: loaded hardcoded node key")
}
} else {
logger.Info("HACK: loaded hardcoded guardian-0 node key")
priv, err = getOrCreateNodeKey(logger, *nodeKeyPath)
if err != nil {
return fmt.Errorf("failed to load node key: %w", err)
}
}
var idht *dht.IpfsDHT

View File

@ -300,8 +300,6 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leoluk/go-libp2p-connmgr v0.0.0-20200817112351-3d0c029185f1 h1:ApGN0fTah3pRuSgHeFSeLJZGknMYlI3oKDqwmgXbEY8=
github.com/leoluk/go-libp2p-connmgr v0.0.0-20200817112351-3d0c029185f1/go.mod h1:YV0b/RIm8NGPnnNWM7hG9Q38OeQiQfKhHCCs1++ufn0=
github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ=
github.com/libp2p/go-addr-util v0.0.2 h1:7cWK5cdA5x72jX0g8iLrQWm5TRJZ6CzGdPEhWj7plWU=
github.com/libp2p/go-addr-util v0.0.2/go.mod h1:Ecd6Fb3yIuLzq4bD7VcywcVSBtefcAwnUISBM3WG15E=
@ -343,6 +341,8 @@ github.com/libp2p/go-libp2p-circuit v0.2.2/go.mod h1:nkG3iE01tR3FoQ2nMm06IUrCpCy
github.com/libp2p/go-libp2p-circuit v0.2.3/go.mod h1:nkG3iE01tR3FoQ2nMm06IUrCpCyJp1Eo4A1xYdpjfs4=
github.com/libp2p/go-libp2p-circuit v0.3.1 h1:69ENDoGnNN45BNDnBd+8SXSetDuw0eJFcGmOvvtOgBw=
github.com/libp2p/go-libp2p-circuit v0.3.1/go.mod h1:8RMIlivu1+RxhebipJwFDA45DasLx+kkrp4IlJj53F4=
github.com/libp2p/go-libp2p-connmgr v0.2.4 h1:TMS0vc0TCBomtQJyWr7fYxcVYYhx+q/2gF++G5Jkl/w=
github.com/libp2p/go-libp2p-connmgr v0.2.4/go.mod h1:YV0b/RIm8NGPnnNWM7hG9Q38OeQiQfKhHCCs1++ufn0=
github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco=
github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I=
github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI=

View File

@ -33,7 +33,7 @@ spec:
labels:
app: guardian
spec:
terminationGracePeriodSeconds: 1
terminationGracePeriodSeconds: 0
containers:
- name: guardiand
image: guardiand-image
@ -48,7 +48,8 @@ spec:
- -ethContract
- 0xCfEB869F69431e42cdB54A4F4f105C19C080A601
- -ethConfirmations
- '1'
- '2'
- -unsafeDevMode
ports:
- containerPort: 8999
name: p2p