-
Notifications
You must be signed in to change notification settings - Fork 3
make it so that config is configured during setup. #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4743f91
5ab9ac2
aca039e
4fbcf72
04cfc81
dd30a63
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| name: Build Arbiter Signer | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ main ] | ||
| tags: | ||
| - 'v*' # Trigger on version tags | ||
| pull_request: | ||
| branches: [ main ] | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
| build: | ||
| name: Build for ${{ matrix.os }} | ||
| runs-on: ${{ matrix.os }} | ||
| strategy: | ||
| matrix: | ||
| include: | ||
| - os: ubuntu-latest | ||
| output_name: arbiter-linux | ||
| goarch: amd64 | ||
| - os: windows-latest | ||
| output_name: arbiter-windows.exe | ||
| goarch: amd64 | ||
| - os: macos-latest | ||
| output_name: arbiter-macos-amd64 | ||
| goarch: amd64 | ||
| - os: macos-latest | ||
| output_name: arbiter-macos-arm64 | ||
| goarch: arm64 | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Go | ||
| uses: actions/setup-go@v4 | ||
| with: | ||
| go-version: '1.21' | ||
|
|
||
| - name: Go Mod Tidy | ||
| run: go mod tidy | ||
|
|
||
| - name: Build | ||
| env: | ||
| GOOS: ${{ matrix.os == 'windows-latest' && 'windows' || matrix.os == 'ubuntu-latest' && 'linux' || 'darwin' }} | ||
| GOARCH: ${{ matrix.goarch }} | ||
| run: go build -o ${{ matrix.output_name }} ./app/arbiter | ||
|
|
||
| - name: Upload Artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: ${{ matrix.output_name }} | ||
| path: ${{ matrix.output_name }} | ||
|
|
||
| release: | ||
| needs: build | ||
| runs-on: ubuntu-latest | ||
| if: startsWith(github.ref, 'refs/tags/v') | ||
| steps: | ||
| - name: Download all artifacts | ||
| uses: actions/download-artifact@v4 | ||
|
|
||
| - name: Create Release | ||
| uses: softprops/action-gh-release@v1 | ||
| with: | ||
| files: | | ||
| */arbiter-linux | ||
| */arbiter-windows.exe | ||
| */arbiter-macos-amd64 | ||
| */arbiter-macos-arm64 | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,24 +3,241 @@ | |
| package main | ||
|
|
||
| import ( | ||
| "bufio" | ||
| "context" | ||
| "encoding/hex" | ||
| "fmt" | ||
| "os" | ||
| "path/filepath" | ||
| "strconv" | ||
| "strings" | ||
| "sync" | ||
|
|
||
| "gopkg.in/yaml.v2" | ||
|
|
||
| _ "github.com/gogf/gf/contrib/drivers/pgsql/v2" | ||
| "github.com/gogf/gf/os/gfile" | ||
| "github.com/gogf/gf/v2/frame/g" | ||
| "github.com/gogf/gf/v2/os/gcfg" | ||
| "github.com/gogf/gf/v2/os/gctx" | ||
|
|
||
| "github.com/BeL2Labs/Arbiter_Signer/app/arbiter/config" | ||
| "github.com/BeL2Labs/Arbiter_Signer/app/arbiter/arbiter" | ||
| "github.com/BeL2Labs/Arbiter_Signer/app/arbiter/config" | ||
| "golang.org/x/term" | ||
| ) | ||
|
|
||
| func main() { | ||
| type ConfigFile struct { | ||
| Chain struct { | ||
| Esc string `yaml:"esc"` | ||
| } `yaml:"chain"` | ||
| Arbiter struct { | ||
| Listener bool `yaml:"listener"` | ||
| Signer bool `yaml:"signer"` | ||
| Network string `yaml:"network"` | ||
| EscStartHeight uint64 `yaml:"escStartHeight"` | ||
| EscArbiterContractAddress string `yaml:"escArbiterContractAddress"` | ||
| EscArbiterManagerContractAddress string `yaml:"escArbiterManagerContractAddress"` | ||
| DataPath string `yaml:"dataPath"` | ||
| KeyFilePath string `yaml:"keyFilePath"` | ||
| EscArbiterAddress string `yaml:"escArbiterAddress"` | ||
| EscPrivateKey string `yaml:"escPrivateKey"` | ||
| BtcPrivateKey string `yaml:"btcPrivateKey"` | ||
| } `yaml:"arbiter"` | ||
| } | ||
|
|
||
| func getDefaultConfig() ConfigFile { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is not possible to enforce that config.yaml be placed in the current location: If you place a config.yaml file in the '.' directory, it will override the config.yaml under the manifest directory. |
||
| var cfg ConfigFile | ||
| cfg.Chain.Esc = "https://api.elastos.io/esc" | ||
| cfg.Arbiter.Listener = true | ||
| cfg.Arbiter.Signer = true | ||
| cfg.Arbiter.Network = "mainnet" | ||
| cfg.Arbiter.EscStartHeight = 28437808 | ||
| cfg.Arbiter.EscArbiterContractAddress = "0xA10b92006743Ef3B12077da67e465963743b03D3" | ||
| cfg.Arbiter.EscArbiterManagerContractAddress = "0x9963b5214434776D043A4e98Bc7f33321F6aaCfc" | ||
|
|
||
| // Get executable directory for portable paths | ||
| execPath, err := os.Executable() | ||
| if err != nil { | ||
| execPath = "." | ||
| } | ||
| execDir := filepath.Dir(execPath) | ||
|
|
||
| cfg.Arbiter.DataPath = filepath.Join(execDir, "data") | ||
| cfg.Arbiter.KeyFilePath = filepath.Join(execDir, "key") | ||
| cfg.Arbiter.EscArbiterAddress = "" | ||
| cfg.Arbiter.EscPrivateKey = "" | ||
| cfg.Arbiter.BtcPrivateKey = "" | ||
|
|
||
| return cfg | ||
| } | ||
|
|
||
| func setupConfig() error { | ||
| configPath := "config.yaml" | ||
|
|
||
| // Check if config already exists and warn user | ||
| if _, err := os.Stat(configPath); err == nil { | ||
| fmt.Println("Warning: Config file already exists and will be overwritten.") | ||
| fmt.Println("Press Enter to continue or Ctrl+C to abort...") | ||
| bufio.NewReader(os.Stdin).ReadString('\n') | ||
| } | ||
|
|
||
| cfg := getDefaultConfig() | ||
| reader := bufio.NewReader(os.Stdin) | ||
|
|
||
| fmt.Println("\nPress Enter to keep the default value, or type a new value:") | ||
|
|
||
| // Chain configuration | ||
| fmt.Printf("ESC Chain URL [%s]: ", cfg.Chain.Esc) | ||
| if input, _ := reader.ReadString('\n'); strings.TrimSpace(input) != "" { | ||
| cfg.Chain.Esc = strings.TrimSpace(input) | ||
| } | ||
|
|
||
| // Arbiter configuration | ||
| fmt.Printf("Listener enabled [%v]: ", cfg.Arbiter.Listener) | ||
| if input, _ := reader.ReadString('\n'); strings.TrimSpace(input) != "" { | ||
| cfg.Arbiter.Listener = strings.ToLower(strings.TrimSpace(input)) == "true" | ||
| } | ||
|
|
||
| fmt.Printf("Signer enabled [%v]: ", cfg.Arbiter.Signer) | ||
| if input, _ := reader.ReadString('\n'); strings.TrimSpace(input) != "" { | ||
| cfg.Arbiter.Signer = strings.ToLower(strings.TrimSpace(input)) == "true" | ||
| } | ||
|
|
||
| fmt.Printf("Network [%s]: ", cfg.Arbiter.Network) | ||
| if input, _ := reader.ReadString('\n'); strings.TrimSpace(input) != "" { | ||
| cfg.Arbiter.Network = strings.TrimSpace(input) | ||
| } | ||
|
|
||
| fmt.Printf("ESC Start Height [%d]: ", cfg.Arbiter.EscStartHeight) | ||
| if input, _ := reader.ReadString('\n'); strings.TrimSpace(input) != "" { | ||
| if height, err := strconv.ParseUint(strings.TrimSpace(input), 10, 64); err == nil { | ||
| cfg.Arbiter.EscStartHeight = height | ||
| } | ||
| } | ||
|
|
||
| fmt.Printf("ESC Arbiter Contract Address [%s]: ", cfg.Arbiter.EscArbiterContractAddress) | ||
| if input, _ := reader.ReadString('\n'); strings.TrimSpace(input) != "" { | ||
| cfg.Arbiter.EscArbiterContractAddress = strings.TrimSpace(input) | ||
| } | ||
|
|
||
| fmt.Printf("ESC Arbiter Manager Contract Address [%s]: ", cfg.Arbiter.EscArbiterManagerContractAddress) | ||
| if input, _ := reader.ReadString('\n'); strings.TrimSpace(input) != "" { | ||
| cfg.Arbiter.EscArbiterManagerContractAddress = strings.TrimSpace(input) | ||
| } | ||
|
|
||
| fmt.Printf("Data Path [%s]: ", cfg.Arbiter.DataPath) | ||
| if input, _ := reader.ReadString('\n'); strings.TrimSpace(input) != "" { | ||
| cfg.Arbiter.DataPath = strings.TrimSpace(input) | ||
| } | ||
|
|
||
| fmt.Printf("Key File Path [%s]: ", cfg.Arbiter.KeyFilePath) | ||
| if input, _ := reader.ReadString('\n'); strings.TrimSpace(input) != "" { | ||
| cfg.Arbiter.KeyFilePath = strings.TrimSpace(input) | ||
| } | ||
|
|
||
| fmt.Printf("ESC Arbiter Address [%s]: ", cfg.Arbiter.EscArbiterAddress) | ||
| if input, _ := reader.ReadString('\n'); strings.TrimSpace(input) != "" { | ||
| cfg.Arbiter.EscArbiterAddress = strings.TrimSpace(input) | ||
| } | ||
|
|
||
| // Create directories | ||
| os.MkdirAll(cfg.Arbiter.DataPath, 0755) | ||
| os.MkdirAll(cfg.Arbiter.KeyFilePath, 0755) | ||
|
|
||
| // Write config file | ||
| yamlData, err := yaml.Marshal(cfg) | ||
| if err != nil { | ||
| return fmt.Errorf("error marshaling config: %v", err) | ||
| } | ||
|
|
||
| err = os.WriteFile(configPath, yamlData, 0644) | ||
| if err != nil { | ||
| return fmt.Errorf("error writing config file: %v", err) | ||
| } | ||
|
|
||
| // Always recreate key files | ||
| return createKeyFiles(cfg) | ||
| } | ||
|
|
||
| func createKeyFiles(cfg ConfigFile) error { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Users should not be prompted to input during the running process, as the current deployment is automated through scripts or Docker. Any process that requires user input will disrupt the deployment. If it is indeed necessary, it should be changed to: 'If the key file exists, use the key file.' |
||
| // Create ESC key file | ||
| escKeyFile := filepath.Join(cfg.Arbiter.KeyFilePath, "escKey.json") | ||
| if _, err := os.Stat(escKeyFile); err == nil { | ||
| fmt.Println("\nWarning: ESC key file already exists and will be overwritten.") | ||
| } | ||
|
|
||
| // Loop until valid ESC key is provided | ||
| var escKey string | ||
| for { | ||
| fmt.Print("\nEnter ESC private key (64 hex characters): ") | ||
| // Read password without echo | ||
| keyBytes, err := term.ReadPassword(int(os.Stdin.Fd())) | ||
| if err != nil { | ||
| return fmt.Errorf("error reading private key: %v", err) | ||
| } | ||
| fmt.Println() // Add newline after hidden input | ||
|
|
||
| escKey = strings.TrimSpace(string(keyBytes)) | ||
|
|
||
| // Validate hex format and length | ||
| if len(escKey) != 64 { | ||
| fmt.Println("Error: Private key must be exactly 64 hex characters") | ||
| continue | ||
| } | ||
| if _, err := hex.DecodeString(escKey); err != nil { | ||
| fmt.Println("Error: Private key must be in hex format") | ||
| continue | ||
| } | ||
| break | ||
| } | ||
|
|
||
| // Correct key file format | ||
| keyData := fmt.Sprintf(`{"privKey":"%s"}`, escKey) | ||
| if err := os.WriteFile(escKeyFile, []byte(keyData), 0600); err != nil { | ||
| return fmt.Errorf("failed to create ESC key file: %v", err) | ||
| } | ||
|
|
||
| // Create BTC key file | ||
| btcKeyFile := filepath.Join(cfg.Arbiter.KeyFilePath, "btcKey.json") | ||
| if _, err := os.Stat(btcKeyFile); err == nil { | ||
| fmt.Println("\nWarning: BTC key file already exists and will be overwritten.") | ||
| } | ||
|
|
||
| // Loop until valid BTC key is provided | ||
| var btcKey string | ||
| for { | ||
| fmt.Print("\nEnter BTC private key (64 hex characters): ") | ||
| // Read password without echo | ||
| keyBytes, err := term.ReadPassword(int(os.Stdin.Fd())) | ||
| if err != nil { | ||
| return fmt.Errorf("error reading private key: %v", err) | ||
| } | ||
| fmt.Println() // Add newline after hidden input | ||
|
|
||
| btcKey = strings.TrimSpace(string(keyBytes)) | ||
|
|
||
| // Validate hex format and length | ||
| if len(btcKey) != 64 { | ||
| fmt.Println("Error: Private key must be exactly 64 hex characters") | ||
| continue | ||
| } | ||
| if _, err := hex.DecodeString(btcKey); err != nil { | ||
| fmt.Println("Error: Private key must be in hex format") | ||
| continue | ||
| } | ||
| break | ||
| } | ||
|
|
||
| // Correct key file format | ||
| keyData = fmt.Sprintf(`{"privKey":"%s"}`, btcKey) | ||
| if err := os.WriteFile(btcKeyFile, []byte(keyData), 0600); err != nil { | ||
| return fmt.Errorf("failed to create BTC key file: %v", err) | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func main() { | ||
| if len(os.Args) > 1 { | ||
| operation := os.Args[1] | ||
| switch strings.ToLower(operation) { | ||
|
|
@@ -36,9 +253,19 @@ func main() { | |
| } | ||
| } | ||
|
|
||
| // Run setup first | ||
| if err := setupConfig(); err != nil { | ||
| fmt.Printf("Setup failed: %v\n", err) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| ctx := gctx.New() | ||
| var wg sync.WaitGroup | ||
| wg.Add(1) | ||
|
|
||
| // Initialize config file path for gf framework | ||
| g.Cfg().GetAdapter().(*gcfg.AdapterFile).SetPath(".") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove it, useless code does not affect GoFrame's own configuration retrieval |
||
|
|
||
| // start arbiter | ||
| g.Log().Info(ctx, "Starting arbiter...") | ||
| arb := arbiter.NewArbiter(ctx, initConfig(ctx)) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,12 +4,14 @@ chain: | |
|
|
||
| # Arbiter | ||
| arbiter: | ||
| listener: true, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good! |
||
| signer: true, | ||
| listener: true | ||
| signer: true | ||
| network: "mainnet" | ||
| escStartHeight: 28437808 | ||
| escArbiterContractAddress: "0xA10b92006743Ef3B12077da67e465963743b03D3" | ||
| escArbiterManagerContractAddress: "0x9963b5214434776D043A4e98Bc7f33321F6aaCfc" | ||
| escArbiterAddress: "0x0262aB0ED65373cC855C34529fDdeAa0e686D913" | ||
| dataPath: "./app/arbiter/data" | ||
| keyFilePath: "./app/arbiter/data/keys/" | ||
| dataPath: "./data" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to modify the default values here
|
||
| keyFilePath: "./key" | ||
| escArbiterAddress: "" | ||
| escPrivateKey: "" | ||
| btcPrivateKey: "" | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job, but there are a few points that need adjustment: