Skip to content

Commit

Permalink
Merge branch 'main' into MinimumStake
Browse files Browse the repository at this point in the history
  • Loading branch information
kehiy authored Aug 7, 2023
2 parents 232ea13 + cac4908 commit 0e162f9
Show file tree
Hide file tree
Showing 198 changed files with 7,402 additions and 5,206 deletions.
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ Briefly describe the changes introduced by this pull request.
## Related issue(s)

If this Pull Request is related to an issue, mention it here.
- Fixes #(issue number)
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Pactus blockchain
Copyright (c) 2020 Pactus blockchain

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
14 changes: 7 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ BUILD_LDFLAGS= -ldflags "-X github.com/pactus-project/pactus/version.build=`git

ifneq (,$(filter $(OS),Windows_NT MINGW64))
EXE = .exe
RM = del /q
else
RM = rm -rf
endif


all: build test

########################################
Expand All @@ -16,7 +20,7 @@ devtools:
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@v2.12
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
go install github.com/bufbuild/buf/cmd/buf@v1.8
go install github.com/bufbuild/buf/cmd/buf@v1.25.0
go install github.com/rakyll/statik@v0.1

########################################
Expand Down Expand Up @@ -47,13 +51,9 @@ docker:
########################################
### proto
proto:
cd www/grpc/ && rm -rf gen && buf generate \
--path ./proto/blockchain.proto \
--path ./proto/network.proto \
--path ./proto/transaction.proto \
--path ./proto/wallet.proto
cd www/grpc/ && $(RM) gen && buf generate proto

# Generate static assets for Swagger-UI
# Generate static assets for Swagger-UI
cd www/grpc/ && statik -m -f -src swagger-ui/

########################################
Expand Down
158 changes: 74 additions & 84 deletions cmd/daemon/init.go
Original file line number Diff line number Diff line change
@@ -1,106 +1,96 @@
package main

import (
"fmt"
"path/filepath"

cli "github.com/jawher/mow.cli"
"github.com/pactus-project/pactus/cmd"
"github.com/pactus-project/pactus/genesis"
"github.com/pactus-project/pactus/util"
"github.com/pactus-project/pactus/wallet"
"github.com/spf13/cobra"
)

// Init initializes a node for the Pactus blockchain.
func Init() func(c *cli.Cmd) {
return func(c *cli.Cmd) {
workingDirOpt := c.String(cli.StringOpt{
Name: "w working-dir",
Desc: "A path to the working directory to save the wallet and node files",
Value: cmd.PactusHomeDir(),
})
testnetOpt := c.Bool(cli.BoolOpt{
Name: "testnet",
Desc: "Initialize working directory for joining the testnet",
Value: true, // TODO: make it false after mainnet launch
})
localnetOpt := c.Bool(cli.BoolOpt{
Name: "localnet",
Desc: "Initialize working directory for localnet (for developers)",
Value: false,
})
restoreOpt := c.String(cli.StringOpt{
Name: "restore",
Desc: "Restore the default_wallet using a mnemonic (seed phrase)",
Value: "",
})
// BuildInitCmd builds the init command for the Pactus blockchain.
func buildInitCmd(parentCmd *cobra.Command) {
var initCmd = &cobra.Command{
Use: "init",
Short: "Initialize the Pactus blockchain",
}
parentCmd.AddCommand(initCmd)
workingDirOpt := initCmd.Flags().StringP("working-dir", "w",
cmd.PactusHomeDir(), "A path to the working directory to save the wallet and node files")

c.LongDesc = "Initializing the working directory"
c.Before = func() { fmt.Println(cmd.Pactus) }
c.Action = func() {
workingDir, _ := filepath.Abs(*workingDirOpt)
if !util.IsDirNotExistsOrEmpty(workingDir) {
cmd.PrintErrorMsg("The working directory is not empty: %s", workingDir)
return
}
mnemonic := ""
if len(*restoreOpt) == 0 {
mnemonic = wallet.GenerateMnemonic(128)
cmd.PrintLine()
cmd.PrintInfoMsg("Your wallet seed is:")
cmd.PrintInfoMsgBold(" " + mnemonic)
cmd.PrintLine()
cmd.PrintWarnMsg("Write down this seed on a piece of paper to recover your validator key in future.")
cmd.PrintLine()
confirmed := cmd.PromptConfirm("Do you want to continue")
if !confirmed {
return
}
} else {
mnemonic = *restoreOpt
err := wallet.CheckMnemonic(*restoreOpt)
cmd.FatalErrorCheck(err)
}
cmd.PrintLine()
cmd.PrintInfoMsg("Enter a password for wallet")
password := cmd.PromptPassword("Password", true)
testnetOpt := initCmd.Flags().Bool("testnet", true,
"Initialize working directory for joining the testnet") // TODO: make it false after mainnet launch

cmd.PrintLine()
cmd.PrintInfoMsgBold("How many validators do you want to create?")
cmd.PrintInfoMsg("Each node can run up to 32 validators, and each validator can hold up to 1000 staked coins.")
cmd.PrintInfoMsg("You can define validators based on the amount of coins you want to stake.")
numValidators := cmd.PromptInputWithRange("Number of Validators", 7, 1, 32)
localnetOpt := initCmd.Flags().Bool("localnet", false,
"Initialize working directory for localnet (for developers)")

chain := genesis.Mainnet
// The order of checking the network (chain type) matters here.
if *testnetOpt {
chain = genesis.Testnet
}
if *localnetOpt {
chain = genesis.Localnet
}
validatorAddrs, rewardAddrs, err := cmd.CreateNode(numValidators, chain, workingDir, mnemonic, password)
cmd.FatalErrorCheck(err)
restoreOpt := initCmd.Flags().String("restore", "", "Restore the default_wallet using a mnemonic (seed phrase)")

initCmd.Run = func(_ *cobra.Command, _ []string) {
workingDir, _ := filepath.Abs(*workingDirOpt)
if !util.IsDirNotExistsOrEmpty(workingDir) {
cmd.PrintErrorMsg("The working directory is not empty: %s", workingDir)
return
}
mnemonic := ""
if len(*restoreOpt) == 0 {
mnemonic = wallet.GenerateMnemonic(128)
cmd.PrintLine()
cmd.PrintInfoMsgBold("Validator addresses:")
for i, addr := range validatorAddrs {
cmd.PrintInfoMsg("%v- %s", i+1, addr)
}
cmd.PrintInfoMsg("Your wallet seed is:")
cmd.PrintInfoMsgBold(" " + mnemonic)
cmd.PrintLine()

cmd.PrintInfoMsgBold("Reward addresses:")
for i, addr := range rewardAddrs {
cmd.PrintInfoMsg("%v- %s", i+1, addr)
cmd.PrintWarnMsg("Write down this seed on a piece of paper to recover your validator key in future.")
cmd.PrintLine()
confirmed := cmd.PromptConfirm("Do you want to continue")
if !confirmed {
return
}
} else {
mnemonic = *restoreOpt
err := wallet.CheckMnemonic(*restoreOpt)
cmd.FatalErrorCheck(err)
}
cmd.PrintLine()
cmd.PrintInfoMsg("Enter a password for wallet")
password := cmd.PromptPassword("Password", true)

cmd.PrintLine()
cmd.PrintInfoMsgBold("Network: %v", chain.String())
cmd.PrintLine()
cmd.PrintSuccessMsg("A pactus node is successfully initialized at %v", workingDir)
cmd.PrintLine()
cmd.PrintInfoMsg("You can start the node by running this command:")
cmd.PrintInfoMsg("./pactus-daemon start -w %v", workingDir)
cmd.PrintLine()
cmd.PrintInfoMsgBold("How many validators do you want to create?")
cmd.PrintInfoMsg("Each node can run up to 32 validators, and each validator can hold up to 1000 staked coins.")
cmd.PrintInfoMsg("You can define validators based on the amount of coins you want to stake.")
numValidators := cmd.PromptInputWithRange("Number of Validators", 7, 1, 32)

chain := genesis.Mainnet
// The order of checking the network (chain type) matters here.
if *testnetOpt {
chain = genesis.Testnet
}
if *localnetOpt {
chain = genesis.Localnet
}
validatorAddrs, rewardAddrs, err := cmd.CreateNode(numValidators, chain, workingDir, mnemonic, password)
cmd.FatalErrorCheck(err)

cmd.PrintLine()
cmd.PrintInfoMsgBold("Validator addresses:")
for i, addr := range validatorAddrs {
cmd.PrintInfoMsg("%v- %s", i+1, addr)
}
cmd.PrintLine()

cmd.PrintInfoMsgBold("Reward addresses:")
for i, addr := range rewardAddrs {
cmd.PrintInfoMsg("%v- %s", i+1, addr)
}

cmd.PrintLine()
cmd.PrintInfoMsgBold("Network: %v", chain.String())
cmd.PrintLine()
cmd.PrintSuccessMsg("A pactus node is successfully initialized at %v", workingDir)
cmd.PrintLine()
cmd.PrintInfoMsg("You can start the node by running this command:")
cmd.PrintInfoMsg("./pactus-daemon start -w %v", workingDir)
}
}
22 changes: 14 additions & 8 deletions cmd/daemon/main.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
package main

import (
"os"
"fmt"

cli "github.com/jawher/mow.cli"
"github.com/spf13/cobra"
)

func main() {
app := cli.App("pactus-daemon", "Pactus daemon")

app.Command("init", "Initialize the Pactus blockchain", Init())
app.Command("start", "Start the Pactus blockchain", Start())
app.Command("version", "Print the Pactus version", Version())
var rootCmd = &cobra.Command{
Use: "pactus-daemon",
Short: "Pactus daemon",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("use --help")
},
}

if err := app.Run(os.Args); err != nil {
buildVersionCmd(rootCmd)
buildInitCmd(rootCmd)
buildStartCmd(rootCmd)
err := rootCmd.Execute()
if err != nil {
panic(err)
}
}
105 changes: 50 additions & 55 deletions cmd/daemon/start.go
Original file line number Diff line number Diff line change
@@ -1,79 +1,74 @@
package main

import (
"fmt"
"net/http"
_ "net/http/pprof" // #nosec
"os"
"path/filepath"
"time"

cli "github.com/jawher/mow.cli"
"github.com/pactus-project/pactus/cmd"
"github.com/pactus-project/pactus/wallet"
"github.com/spf13/cobra"
)

// Start starts the pactus node.
func Start() func(c *cli.Cmd) {
return func(c *cli.Cmd) {
workingDirOpt := c.String(cli.StringOpt{
Name: "w working-dir",
Desc: "A path to the working directory to read the wallet and node files",
Value: cmd.PactusHomeDir(),
})
passwordOpt := c.String(cli.StringOpt{
Name: "p password",
Desc: "The wallet password",
})
pprofOpt := c.String(cli.StringOpt{
Name: "pprof",
Desc: "debug pprof server address(not recommended to expose to internet)",
})
func buildStartCmd(parentCmd *cobra.Command) {
var startCmd = &cobra.Command{
Use: "start",
Short: "Start the Pactus blockchain",
}

c.LongDesc = "Starting the node from working directory"
c.Before = func() { fmt.Println(cmd.Pactus) }
c.Action = func() {
workingDir, _ := filepath.Abs(*workingDirOpt)
// change working directory
err := os.Chdir(workingDir)
cmd.FatalErrorCheck(err)
parentCmd.AddCommand(startCmd)

if *pprofOpt != "" {
cmd.PrintWarnMsg("Starting Debug pprof server on: http://%s/debug/pprof/", *pprofOpt)
server := &http.Server{
Addr: *pprofOpt,
ReadHeaderTimeout: 3 * time.Second,
}
go func() {
err := server.ListenAndServe()
cmd.FatalErrorCheck(err)
}()
}
workingDirOpt := startCmd.Flags().StringP("working-dir", "w",
cmd.PactusHomeDir(), "A path to the working directory to read the wallet and node files")

passwordOpt := startCmd.Flags().StringP("password", "p", "", "The wallet password")

pprofOpt := startCmd.Flags().String("pprof", "", "debug pprof server address(not recommended to expose to internet)")

passwordFetcher := func(wallet *wallet.Wallet) (string, bool) {
if !wallet.IsEncrypted() {
return "", true
}
startCmd.Run = func(_ *cobra.Command, _ []string) {
workingDir, _ := filepath.Abs(*workingDirOpt)
// change working directory
err := os.Chdir(workingDir)
cmd.FatalErrorCheck(err)

var password string
if *passwordOpt != "" {
password = *passwordOpt
} else {
password = cmd.PromptPassword("Wallet password", false)
}
return password, true
if *pprofOpt != "" {
cmd.PrintWarnMsg("Starting Debug pprof server on: http://%s/debug/pprof/", *pprofOpt)
server := &http.Server{
Addr: *pprofOpt,
ReadHeaderTimeout: 3 * time.Second,
}
node, _, err := cmd.StartNode(
workingDir, passwordFetcher)
cmd.FatalErrorCheck(err)
go func() {
err := server.ListenAndServe()
cmd.FatalErrorCheck(err)
}()
}

cmd.TrapSignal(func() {
node.Stop()
cmd.PrintInfoMsg("Exiting ...")
})
passwordFetcher := func(wallet *wallet.Wallet) (string, bool) {
if !wallet.IsEncrypted() {
return "", true
}

// run forever (the node will not be returned)
select {}
var password string
if *passwordOpt != "" {
password = *passwordOpt
} else {
password = cmd.PromptPassword("Wallet password", false)
}
return password, true
}
node, _, err := cmd.StartNode(
workingDir, passwordFetcher)
cmd.FatalErrorCheck(err)

cmd.TrapSignal(func() {
node.Stop()
cmd.PrintInfoMsg("Exiting ...")
})

// run forever (the node will not be returned)
select {}
}
}
Loading

0 comments on commit 0e162f9

Please sign in to comment.