From 37d670069bec6590e32f74071b94c0da4bb35aac Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 12 Feb 2020 13:36:10 +0000 Subject: [PATCH] add some parameters to suppport non-interactive mode --- cmd/puppeth/puppeth.go | 36 ++++++++++- cmd/puppeth/wizard.go | 33 ++++++++++ cmd/puppeth/wizard_genesis.go | 80 +++++++++++++++++------ cmd/puppeth/wizard_intro.go | 116 +++++++++++++++++++--------------- 4 files changed, 192 insertions(+), 73 deletions(-) diff --git a/cmd/puppeth/puppeth.go b/cmd/puppeth/puppeth.go index c3de5f9360..2eb72be07f 100644 --- a/cmd/puppeth/puppeth.go +++ b/cmd/puppeth/puppeth.go @@ -42,6 +42,31 @@ func main() { Value: 3, Usage: "log level to emit to the screen", }, + cli.StringFlag{ + Name: "consensusType", + Usage: "Which consensus engine to use? (default = null)\n \t\t1. Ethash - proof-of-work\n \t\t2. Clique - proof-of-authority", + }, + cli.IntFlag{ + Name: "blocksTime", + Usage: "log level to emit to the screen", + }, + cli.StringFlag{ + Name: "sealAccounts", + Usage: "Which accounts are allowed to seal? (mandatory at least one)", + }, + cli.StringFlag{ + Name: "preFundedAccounts", + Usage: "Which accounts should be pre-funded? (advisable at least one)", + }, + cli.StringFlag{ + Name: "preCmpAddressWithOneWei", + Usage: "Should the precompile-addresses (0x1 .. 0xff) be pre-funded with 1 wei?", + }, + cli.Uint64Flag{ + Name: "networkID", + Value: 0, + Usage: "Specify your chain/network ID if you want an explicit one (default = random)", + }, } app.Before = func(c *cli.Context) error { // Set up the logger to print everything and the random generator @@ -60,6 +85,15 @@ func runWizard(c *cli.Context) error { if strings.Contains(network, " ") || strings.Contains(network, "-") || strings.ToLower(network) != network { log.Crit("No spaces, hyphens or capital letters allowed in network name") } - makeWizard(c.String("network")).run() + consensusType := c.String("consensusType") + blocksTime := uint64(c.Int("blocksTime")) + sealAccounts := c.String("sealAccounts") + preFundedAccounts := c.String("preFundedAccounts") + preCmpAddOneWei := c.String("preCmpAddressWithOneWei") + networkID := c.Uint64("networkID") + + nonInteract := network != "" && consensusType != "" && blocksTime > 0 && sealAccounts != "" && preFundedAccounts != "" && preCmpAddOneWei != "" && networkID > 0 + + makeWizard(network, consensusType, blocksTime, sealAccounts, preFundedAccounts, preCmpAddOneWei, networkID, nonInteract).run() return nil } diff --git a/cmd/puppeth/wizard.go b/cmd/puppeth/wizard.go index 83536506c4..b203427fc3 100644 --- a/cmd/puppeth/wizard.go +++ b/cmd/puppeth/wizard.go @@ -78,6 +78,13 @@ type wizard struct { in *bufio.Reader // Wrapper around stdin to allow reading user input lock sync.Mutex // Lock to protect configs during concurrent service discovery + consensusType string + blocksTime uint64 + sealAccounts string + preFundedAccounts string + preCmpAddOneWei string + networkID uint64 + nonInteract bool } // read reads a single line from stdin, trimming if from spaces. @@ -109,6 +116,9 @@ func (w *wizard) readString() string { // an empty line is entered, the default value is returned. func (w *wizard) readDefaultString(def string) string { fmt.Printf("> ") + if w.nonInteract { + return def + } text, err := w.in.ReadString('\n') if err != nil { log.Crit("Failed to read user input", "err", err) @@ -305,6 +315,29 @@ func (w *wizard) readAddress() *common.Address { } } +// readAddress reads a single line from stdin, trimming if from spaces and converts +// it to an Ethereum address. +func (w *wizard) processAddress(address string) []common.Address { + // process the address from the string + var signers []common.Address + signerArray := strings.Split(address, ",") + for i := 0; i < len(signerArray); i++ { + text := strings.TrimSpace(signerArray[i]) + if text == "" { + continue + } + // Make sure it looks ok and return it if so + if len(text) != 40 { + log.Error("Invalid address length, please retry") + continue + } + bigaddr, _ := new(big.Int).SetString(text, 16) + address := common.BigToAddress(bigaddr) + signers = append(signers, address) + } + return signers +} + // readDefaultAddress reads a single line from stdin, trimming if from spaces and // converts it to an Ethereum address. If an empty line is entered, the default // value is returned. diff --git a/cmd/puppeth/wizard_genesis.go b/cmd/puppeth/wizard_genesis.go index ab3e2247b6..7cc0330ee6 100644 --- a/cmd/puppeth/wizard_genesis.go +++ b/cmd/puppeth/wizard_genesis.go @@ -60,7 +60,13 @@ func (w *wizard) makeGenesis() { fmt.Println(" 1. Ethash - proof-of-work") fmt.Println(" 2. Clique - proof-of-authority") - choice := w.read() + var choice string + if w.consensusType != "" { + choice = w.consensusType + fmt.Println(w.consensusType) + }else{ + choice = w.read() + } switch { case choice == "1": // In case of ethash, we're pretty much done @@ -76,20 +82,28 @@ func (w *wizard) makeGenesis() { } fmt.Println() fmt.Println("How many seconds should blocks take? (default = 15)") - genesis.Config.Clique.Period = uint64(w.readDefaultInt(15)) + if w.blocksTime > 0 { + genesis.Config.Clique.Period = w.blocksTime + }else{ + genesis.Config.Clique.Period = uint64(w.readDefaultInt(15)) + } // We also need the initial list of signers fmt.Println() fmt.Println("Which accounts are allowed to seal? (mandatory at least one)") var signers []common.Address - for { - if address := w.readAddress(); address != nil { - signers = append(signers, *address) - continue - } - if len(signers) > 0 { - break + if w.sealAccounts != "" { + signers = w.processAddress(w.sealAccounts) + } else { + for { + if address := w.readAddress(); address != nil { + signers = append(signers, *address) + continue + } + if len(signers) > 0 { + break + } } } // Sort the signers and embed into the extra-data section @@ -111,28 +125,49 @@ func (w *wizard) makeGenesis() { // Consensus all set, just ask for initial funds and go fmt.Println() fmt.Println("Which accounts should be pre-funded? (advisable at least one)") - for { - // Read the address of the account to fund - if address := w.readAddress(); address != nil { - genesis.Alloc[*address] = core.GenesisAccount{ - Balance: new(big.Int).Lsh(big.NewInt(1), 256-7), // 2^256 / 128 (allow many pre-funds without balance overflows) + if w.preFundedAccounts != "" { + preFunedAccounts := w.processAddress(w.preFundedAccounts) + for _, preFunedAccount := range preFunedAccounts { + genesis.Alloc[preFunedAccount] = core.GenesisAccount{ + Balance: new(big.Int).Lsh(big.NewInt(1), 256-7), // 2^256 / 128 (allow many pre-funds without balance overflows) + } + continue } - continue + }else{ + for { + // Read the address of the account to fund + if address := w.readAddress(); address != nil { + genesis.Alloc[*address] = core.GenesisAccount{ + Balance: new(big.Int).Lsh(big.NewInt(1), 256-7), // 2^256 / 128 (allow many pre-funds without balance overflows) + } + continue + } + break } - break } fmt.Println() fmt.Println("Should the precompile-addresses (0x1 .. 0xff) be pre-funded with 1 wei? (advisable yes)") - if w.readDefaultYesNo(true) { - // Add a batch of precompile balances to avoid them getting deleted + if w.preCmpAddOneWei == "true" { for i := int64(0); i < 256; i++ { genesis.Alloc[common.BigToAddress(big.NewInt(i))] = core.GenesisAccount{Balance: big.NewInt(1)} } + } else if w.preCmpAddOneWei == "" { + if w.readDefaultYesNo(true) { + // Add a batch of precompile balances to avoid them getting deleted + for i := int64(0); i < 256; i++ { + genesis.Alloc[common.BigToAddress(big.NewInt(i))] = core.GenesisAccount{Balance: big.NewInt(1)} + } + } } // Query the user for some custom extras fmt.Println() fmt.Println("Specify your chain/network ID if you want an explicit one (default = random)") - genesis.Config.ChainID = new(big.Int).SetUint64(uint64(w.readDefaultInt(rand.Intn(65536)))) + if w.networkID != 0 { + genesis.Config.ChainID = new(big.Int).SetUint64(w.networkID) + fmt.Println(w.networkID) + } else { + genesis.Config.ChainID = new(big.Int).SetUint64(uint64(w.readDefaultInt(rand.Intn(65536)))) + } // All done, store the genesis and flush to disk log.Info("Configured new genesis block") @@ -197,7 +232,12 @@ func (w *wizard) manageGenesis() { fmt.Println(" 2. Export genesis configurations") fmt.Println(" 3. Remove genesis configuration") - choice := w.read() + var choice string + if w.nonInteract { + choice = "2" + } else { + choice = w.read() + } switch choice { case "1": // Fork rule updating requested, iterate over each fork diff --git a/cmd/puppeth/wizard_intro.go b/cmd/puppeth/wizard_intro.go index 75fb04b76f..4a0585b91f 100644 --- a/cmd/puppeth/wizard_intro.go +++ b/cmd/puppeth/wizard_intro.go @@ -30,7 +30,7 @@ import ( ) // makeWizard creates and returns a new puppeth wizard. -func makeWizard(network string) *wizard { +func makeWizard(network string, consensusType string, blocksTime uint64, sealAccounts string, preFundedAccounts string, preCmpAddOneWei string, networkID uint64, nonInteract bool) *wizard { return &wizard{ network: network, conf: config{ @@ -39,6 +39,13 @@ func makeWizard(network string) *wizard { servers: make(map[string]*sshClient), services: make(map[string][]string), in: bufio.NewReader(os.Stdin), + consensusType: consensusType, + blocksTime: blocksTime, + sealAccounts: sealAccounts, + preFundedAccounts: preFundedAccounts, + preCmpAddOneWei: preCmpAddOneWei, + networkID: networkID, + nonInteract: nonInteract, } } @@ -104,66 +111,71 @@ func (w *wizard) run() { w.networkStats() } // Basics done, loop ad infinitum about what to do - for { - fmt.Println() - fmt.Println("What would you like to do? (default = stats)") - fmt.Println(" 1. Show network stats") - if w.conf.Genesis == nil { - fmt.Println(" 2. Configure new genesis") - } else { - fmt.Println(" 2. Manage existing genesis") - } - if len(w.servers) == 0 { - fmt.Println(" 3. Track new remote server") - } else { - fmt.Println(" 3. Manage tracked machines") - } - if len(w.services) == 0 { - fmt.Println(" 4. Deploy network components") - } else { - fmt.Println(" 4. Manage network components") - } - - choice := w.read() - switch { - case choice == "" || choice == "1": - w.networkStats() - - case choice == "2": + if w.nonInteract { + w.makeGenesis() + w.manageGenesis() + } else { + for { + fmt.Println() + fmt.Println("What would you like to do? (default = stats)") + fmt.Println(" 1. Show network stats") if w.conf.Genesis == nil { - fmt.Println() - fmt.Println("What would you like to do? (default = create)") - fmt.Println(" 1. Create new genesis from scratch") - fmt.Println(" 2. Import already existing genesis") - - choice := w.read() - switch { - case choice == "" || choice == "1": - w.makeGenesis() - case choice == "2": - w.importGenesis() - default: - log.Error("That's not something I can do") - } + fmt.Println(" 2. Configure new genesis") } else { - w.manageGenesis() + fmt.Println(" 2. Manage existing genesis") } - case choice == "3": if len(w.servers) == 0 { - if w.makeServer() != "" { - w.networkStats() - } + fmt.Println(" 3. Track new remote server") } else { - w.manageServers() + fmt.Println(" 3. Manage tracked machines") } - case choice == "4": if len(w.services) == 0 { - w.deployComponent() + fmt.Println(" 4. Deploy network components") } else { - w.manageComponents() + fmt.Println(" 4. Manage network components") + } + + choice := w.read() + switch { + case choice == "" || choice == "1": + w.networkStats() + + case choice == "2": + if w.conf.Genesis == nil { + fmt.Println() + fmt.Println("What would you like to do? (default = create)") + fmt.Println(" 1. Create new genesis from scratch") + fmt.Println(" 2. Import already existing genesis") + + choice := w.read() + switch { + case choice == "" || choice == "1": + w.makeGenesis() + case choice == "2": + w.importGenesis() + default: + log.Error("That's not something I can do") + } + } else { + w.manageGenesis() + } + case choice == "3": + if len(w.servers) == 0 { + if w.makeServer() != "" { + w.networkStats() + } + } else { + w.manageServers() + } + case choice == "4": + if len(w.services) == 0 { + w.deployComponent() + } else { + w.manageComponents() + } + default: + log.Error("That's not something I can do") } - default: - log.Error("That's not something I can do") } } }