Skip to content

Commit

Permalink
user cli with env (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
shaspitz authored Mar 2, 2024
1 parent 42c6f6a commit 6fb57aa
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 87 deletions.
4 changes: 1 addition & 3 deletions standard/bridge-v1/Dockerfile.user
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,5 @@ RUN CGO_ENABLED=0 make user-cli
FROM alpine:latest

COPY --from=builder /app/bin/user_cli /usr/local/bin/user_cli
COPY --from=builder /app/example_config/user_config.yml /example_config/user_config.yml
COPY --from=builder /app/example_config/user_key /example_config/user_key

ENTRYPOINT ["user_cli", "bridge-to-settlement", "--amount", "2", "--dest-addr", "0xeE5d6F3eeF0ecB6EcbaCd51B7E3350B84882bc85", "--config", "/example_config/user_config.yml", "--cancel-pending"]
ENTRYPOINT ["user_cli", "bridge-to-settlement", "--amount", "2", "--dest-addr", "0xeE5d6F3eeF0ecB6EcbaCd51B7E3350B84882bc85", "--cancel-pending"]
38 changes: 24 additions & 14 deletions standard/bridge-v1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,39 @@ This document outlines multiple iteration plans for a simple lock and mint bridg

## User Quickstart

To bridge from L1 to the mev-commit chain, first configure a yaml file with the format found at `example_config/user_config.yml`, example below:

```yaml
priv_key_file: "example_config/user_key" # Relative path from working dir
log_level: "debug"
l1_rpc_url: "http://localhost:9545"
settlement_rpc_url: "http://localhost:8545"
l1_chain_id: 39999
settlement_chain_id: 17864
l1_contract_addr: "0x1a18dfEc4f2B66207b1Ad30aB5c7A0d62Ef4A40b"
settlement_contract_addr: "0xc1f93bE11D7472c9B9a4d87B41dD0a491F1fbc75"
First build the user cli for your machine from this directory:

```bash
make user_cli
```

Set proper environment variables for a cross-chain transfer, example below:

```bash
export PRIVATE_KEY="0xe82a054e06f89598485134b4f2ce8a612ce7f7f7e14e650f9f20b30efddd0e57"
export LOG_LEVEL="debug"
export L1_RPC_URL="https://ethereum-holesky.publicnode.com"
export SETTLEMENT_RPC_URL="https://chainrpc.testnet.mev-commit.xyz"
export L1_CHAIN_ID="17000"
export SETTLEMENT_CHAIN_ID="17864"
export L1_CONTRACT_ADDR="0xceff0a364f63f621ff6a8b5ce56569ec6f3c6220"
export SETTLEMENT_CONTRACT_ADDR="0xf60f8e762a3fe90fd4d8c005872b6f6e12eda8ca"
```

To build the user cli, and make a cross chain transfer:
To bridge ether from Holesky to the mev-commit chain, use:

```bash
make user_cli
./bin/user_cli bridge-to-settlement --amount $AMOUNT_IN_WEI --dest-addr $DEST_ADDR
```

Where `PRIVATE_KEY` corresponds to an account that's funded on Holesky.

To bridge ether back to Holesky from the mev-commit chain, use:

```bash
./bin/user_cli bridge-to-l1 --amount $AMOUNT --dest-addr $DEST_ADDR --config "example_config/user_config.yml"
./bin/user_cli bridge-to-l1 --amount $AMOUNT_IN_WEI --dest-addr $DEST_ADDR
```
Where `PRIVATE_KEY` corresponds to an account that's funded on the mev-commit chain.

## Relayer

Expand Down
112 changes: 52 additions & 60 deletions standard/bridge-v1/cmd/user_cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (
"fmt"
"math/big"
"os"
"path/filepath"
"standard-bridge/pkg/shared"
transfer "standard-bridge/pkg/transfer"
"strconv"
"strings"

"github.com/ethereum/go-ethereum/common"
Expand All @@ -17,16 +17,6 @@ import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/urfave/cli/v2"
"gopkg.in/yaml.v2"
)

var (
optionConfig = &cli.StringFlag{
Name: "config",
Usage: "path to CLI config file",
Required: true,
EnvVars: []string{"STANDARD_BRIDGE_CLI_CONFIG"},
}
)

func main() {
Expand All @@ -52,7 +42,6 @@ func main() {
Name: "cancel-pending",
Usage: "Automatically cancel existing pending transactions",
},
optionConfig,
},
Action: func(c *cli.Context) error {
return bridgeToSettlement(c)
Expand All @@ -76,7 +65,6 @@ func main() {
Name: "cancel-pending",
Usage: "Automatically cancel existing pending transactions",
},
optionConfig,
},
Action: func(c *cli.Context) error {
return bridgeToL1(c)
Expand Down Expand Up @@ -146,41 +134,15 @@ type preTransferConfig struct {
}

func preTransfer(c *cli.Context) preTransferConfig {
cfg := loadConfigFromEnv()

configFilePath := c.String(optionConfig.Name)

var cfg config
buf, err := os.ReadFile(configFilePath)
if err != nil {
log.Fatal().Err(err).Msg("failed to read config file at: " + configFilePath)
}

if err := yaml.Unmarshal(buf, &cfg); err != nil {
log.Fatal().Err(err).Msg("failed to unmarshal config file at: " + configFilePath)
}

if err := checkConfig(&cfg); err != nil {
if err := checkEnvConfig(&cfg); err != nil {
log.Fatal().Err(err).Msg("invalid config")
}
setupLogging(cfg.LogLevel)

lvl, err := zerolog.ParseLevel(cfg.LogLevel)
if err != nil {
log.Fatal().Err(err).Msg("failed to parse log level")
}
zerolog.SetGlobalLevel(lvl)
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})

privKeyFile := cfg.PrivKeyFile
if strings.HasPrefix(privKeyFile, "~/") {
homeDir, err := os.UserHomeDir()
if err != nil {
log.Err(err).Msg("failed to get user home dir")
}
privKeyFile = filepath.Join(homeDir, privKeyFile[2:])
}

privKey, err := crypto.LoadECDSA(privKeyFile)
privKeyTrimmed := strings.TrimPrefix(cfg.PrivKey, "0x")
privKey, err := crypto.HexToECDSA(privKeyTrimmed)
if err != nil {
log.Err(err).Msg("failed to load private key")
}
Expand All @@ -206,20 +168,44 @@ func preTransfer(c *cli.Context) preTransferConfig {
}
}

type config struct {
PrivKeyFile string `yaml:"priv_key_file"`
LogLevel string `yaml:"log_level" json:"log_level"`
L1RPCUrl string `yaml:"l1_rpc_url"`
SettlementRPCUrl string `yaml:"settlement_rpc_url"`
L1ChainID int `yaml:"l1_chain_id"`
SettlementChainID int `yaml:"settlement_chain_id"`
L1ContractAddr string `yaml:"l1_contract_addr"`
SettlementContractAddr string `yaml:"settlement_contract_addr"`
type envConfig struct {
PrivKey string
LogLevel string
L1RPCUrl string
SettlementRPCUrl string
L1ChainID int
SettlementChainID int
L1ContractAddr string
SettlementContractAddr string
}

func checkConfig(cfg *config) error {
if cfg.PrivKeyFile == "" {
return fmt.Errorf("priv_key_file is required")
func loadConfigFromEnv() envConfig {
l1ChainID := os.Getenv("L1_CHAIN_ID")
l1ChainIDInt, err := strconv.Atoi(l1ChainID)
if err != nil {
log.Fatal().Err(err).Msg("failed to convert L1_CHAIN_ID to int")
}
settlementChainID := os.Getenv("SETTLEMENT_CHAIN_ID")
settlementChainIDInt, err := strconv.Atoi(settlementChainID)
if err != nil {
log.Fatal().Err(err).Msg("failed to convert SETTLEMENT_CHAIN_ID to int")
}
cfg := envConfig{
PrivKey: os.Getenv("PRIVATE_KEY"),
LogLevel: os.Getenv("LOG_LEVEL"),
L1RPCUrl: os.Getenv("L1_RPC_URL"),
SettlementRPCUrl: os.Getenv("SETTLEMENT_RPC_URL"),
L1ChainID: l1ChainIDInt,
SettlementChainID: settlementChainIDInt,
L1ContractAddr: os.Getenv("L1_CONTRACT_ADDR"),
SettlementContractAddr: os.Getenv("SETTLEMENT_CONTRACT_ADDR"),
}
return cfg
}

func checkEnvConfig(cfg *envConfig) error {
if cfg.PrivKey == "" {
return fmt.Errorf("private_key is required")
}
if cfg.LogLevel == "" {
cfg.LogLevel = "info"
Expand All @@ -236,8 +222,6 @@ func checkConfig(cfg *config) error {
if !common.IsHexAddress(cfg.L1ContractAddr) || !common.IsHexAddress(cfg.SettlementContractAddr) {
return fmt.Errorf("both l1_contract_addr and settlement_contract_addr must be valid hex addresses")
}

// Create clients via url and cross check with expected chain id
l1Client, err := ethclient.Dial(cfg.L1RPCUrl)
if err != nil {
return fmt.Errorf("failed to create l1 client: %v", err)
Expand All @@ -249,7 +233,6 @@ func checkConfig(cfg *config) error {
if obtainedL1ChainID.Cmp(big.NewInt(int64(cfg.L1ChainID))) != 0 {
log.Fatal().Msgf("l1 chain id mismatch. Expected: %d, Obtained: %d", cfg.L1ChainID, obtainedL1ChainID)
}

settlementClient, err := ethclient.Dial(cfg.SettlementRPCUrl)
if err != nil {
return fmt.Errorf("failed to create settlement client: %v", err)
Expand All @@ -261,10 +244,19 @@ func checkConfig(cfg *config) error {
if obtainedSettlementChainID.Cmp(big.NewInt(int64(cfg.SettlementChainID))) != 0 {
log.Fatal().Msgf("settlement chain id mismatch. Expected: %d, Obtained: %d", cfg.SettlementChainID, obtainedSettlementChainID)
}

return nil
}

func setupLogging(logLevel string) {
lvl, err := zerolog.ParseLevel(logLevel)
if err != nil {
log.Fatal().Err(err).Msg("failed to parse log level")
}
zerolog.SetGlobalLevel(lvl)
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout})
}

func handlePendingTxes(
ctx context.Context,
privateKey *ecdsa.PrivateKey,
Expand Down
11 changes: 10 additions & 1 deletion standard/bridge-v1/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ services:
dockerfile: Dockerfile.relayer
networks:
primev_net:
ipv4_address: '172.29.0.102'
ipv4_address: '172.29.0.117'
geth-poa_l1_net:
ipv4_address: '172.14.0.5'

Expand All @@ -15,6 +15,15 @@ services:
build:
context: .
dockerfile: Dockerfile.user
environment:
PRIVATE_KEY: "0xe82a054e06f89598485134b4f2ce8a612ce7f7f7e14e650f9f20b30efddd0e57"
LOG_LEVEL: "debug"
L1_RPC_URL: "http://l1-bootnode:8545"
SETTLEMENT_RPC_URL: "http://sl-bootnode:8545"
L1_CHAIN_ID: "39999"
SETTLEMENT_CHAIN_ID: "17864"
L1_CONTRACT_ADDR: "0x1a18dfEc4f2B66207b1Ad30aB5c7A0d62Ef4A40b"
SETTLEMENT_CONTRACT_ADDR: "0xc1f93bE11D7472c9B9a4d87B41dD0a491F1fbc75"
networks:
primev_net:
ipv4_address: '172.29.0.103'
Expand Down
8 changes: 0 additions & 8 deletions standard/bridge-v1/example_config/user_config.yml

This file was deleted.

1 change: 0 additions & 1 deletion standard/bridge-v1/example_config/user_key

This file was deleted.

0 comments on commit 6fb57aa

Please sign in to comment.