Skip to content

Commit

Permalink
Changes coinbases flag to support toml
Browse files Browse the repository at this point in the history
  • Loading branch information
robschleusner committed Jan 10, 2024
1 parent ab3cadd commit 36398a1
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 28 deletions.
134 changes: 107 additions & 27 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package utils

import (
"encoding/json"
"errors"
"fmt"
"math"
"math/big"
"os"
"path/filepath"
"regexp"
godebug "runtime/debug"
"strconv"
"strings"
Expand All @@ -25,6 +25,7 @@ import (
"github.com/dominant-strategies/go-quai/params"
"github.com/dominant-strategies/go-quai/quai/gasprice"
"github.com/dominant-strategies/go-quai/quai/quaiconfig"
"github.com/pelletier/go-toml/v2"
gopsutil "github.com/shirou/gopsutil/mem"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand Down Expand Up @@ -621,45 +622,124 @@ var (
Usage: "Subordinate chain websocket urls" + generateEnvDoc("sub.urls"),
}
CoinbaseAddressFlag = Flag{
Name: "coinbase",
Value: "./coinbases.json",
Usage: "Coinbase addresses" + generateEnvDoc("coinbase"),
Name: "coinbases",
Value: "",
Usage: "Input TOML string or path to TOML file" + generateEnvDoc("coinbase"),
}
)

/*
ParseCoinbaseAddresses parses the coinbase addresses from different sources based on the user input.
It handles three scenarios:
1. File Path Input:
If the user specifies a file path, the function expects a TOML file containing the coinbase addresses.
The file should have a 'coinbases' section with shard-address mappings.
Example:
Command: --coinbases /path/to/coinbases.toml
TOML Content:
[coinbases]
"00" = "0xAddress00"
"01" = "0xAddress01"
...
2. Direct String Input:
If the user doesn't specify a file path but provides a string, the function expects a string in the format 'shard=address'.
Each shard-address pair should be separated by a comma.
Example:
Command: --coinbases "00=0xAddress00,01=0xAddress01"
3. Default Config File:
If no input is provided for the coinbase flag, the function falls back to the config file specified by the 'config-dir' flag.
Example:
In Config TOML:
...
[coinbases]
"00" = "0xDefaultAddress00"
"01" = "0xDefaultAddress01"
...
The function reads the coinbase addresses and performs necessary validation as per the above scenarios.
*/
func ParseCoinbaseAddresses() (map[string]string, error) {
coinbaseInput := viper.GetString(CoinbaseAddressFlag.Name)
coinbaseMap := make(map[string]string)

// Try to parse the input as JSON
if err := json.Unmarshal([]byte(coinbaseInput), &coinbaseMap); err != nil {
// If JSON parsing fails, treat it as a file path
fileContent, fileErr := os.ReadFile(coinbaseInput)
if fileErr != nil {
log.Fatalf("Failed to parse input as JSON and failed to read file: %s", fileErr)
return nil, fileErr
}
coinbaseInput := viper.GetString("coinbases")
coinbaseConfig := struct {
Coinbases map[string]string `toml:"coinbases"`
}{
Coinbases: make(map[string]string),
}

// Try to unmarshal the file content
if err := json.Unmarshal(fileContent, &coinbaseMap); err != nil {
log.Fatalf("Invalid JSON in file: %s", err)
// Scenario 1: User specifies a file path
if _, err := os.Stat(coinbaseInput); err == nil {
fileContent, err := os.ReadFile(coinbaseInput)
if err != nil {
log.Fatalf("Failed to read coinbase file: %s", err)
return nil, err
}
if err := toml.Unmarshal(fileContent, &coinbaseConfig); err != nil {
log.Fatalf("Invalid TOML in coinbase file: %s", err)
return err
}
} else if coinbaseInput != "" {
// Scenario 2: User provides direct string input
for _, coinbase := range strings.Split(coinbaseInput, ",") {
parts := strings.Split(strings.TrimSpace(coinbase), "=")
if len(parts) == 2 {
coinbaseConfig.Coinbases[parts[0]] = parts[1]
} else {
log.Fatalf("Invalid coinbase format: %s", coinbase)
return nil, fmt.Errorf("invalid coinbase format: %s", coinbase)
}
}
} else {
// Scenario 3: Fallback to default config file
log.Info("No coinbases specified, falling back to node config file")
defaultConfigPath := viper.GetString("config-dir") + "config.toml"
if defaultConfigPath != "" {
configFileContent, err := os.ReadFile(defaultConfigPath)
if err != nil {
log.Fatalf("Failed to read config file: %s", err)
return nil, err
}
if err := toml.Unmarshal(configFileContent, &coinbaseConfig); err != nil {
log.Fatalf("Invalid TOML in config file: %s", err)
return err
}
}
}

// Fill in missing addresses with defaults
for i := 0; i < Width; i++ {
for j := 0; j < Width; j++ {
hexKey := fmt.Sprintf("%X%X", i, j)
if _, exists := coinbaseMap[hexKey]; !exists {
coinbaseMap[hexKey] = DefaultCoinbaseMap[hexKey]
}
if len(coinbaseConfig.Coinbases) == 0 {
log.Fatalf("No coinbase addresses provided")
return nil, fmt.Errorf("no coinbase addresses provided")
}

log.Info("Coinbase addresses:", coinbaseConfig.Coinbases)

// Validates all addresses in coinbaseMap
for shard, address := range coinbaseConfig.Coinbases {
if err := isValidAddress(address, shard); err != nil {
return nil, err
}
}

log.Infof("Coinbase Addresses: %v", coinbaseMap)
log.Infof("Coinbase Addresses: %v", coinbaseConfig.Coinbases)

return coinbaseConfig.Coinbases, nil
}

return coinbaseMap, nil
func isValidAddress(address string, shard string) error {
re := regexp.MustCompile(`^(0x)?[0-9a-fA-F]{40}$`)
if !re.MatchString(address) {
log.Fatalf("Invalid Ethereum address: %s", address)
return fmt.Errorf("invalid Ethereum address: %s", address)
}
// Trim "0x" prefix if present and check if the first byte matches the key
trimmedAddress := strings.TrimPrefix(address, "0x")
if !strings.HasPrefix(trimmedAddress, shard) {
log.Fatalf("Shard Location %s does not match the first byte of the address %s", shard, address)
return fmt.Errorf("shard location %s does not match the first byte of the address %s", shard, address)
}
return nil
}

func CreateAndBindFlag(flag Flag, cmd *cobra.Command) {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ require (
github.com/opencontainers/runtime-spec v1.1.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,8 @@ github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhM
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down

0 comments on commit 36398a1

Please sign in to comment.