Skip to content

Commit

Permalink
Merge branch 'main' into feat/PIP-23
Browse files Browse the repository at this point in the history
  • Loading branch information
ZigBalthazar authored Jul 11, 2024
2 parents 081cc8a + 6318fad commit e6b65bb
Show file tree
Hide file tree
Showing 76 changed files with 1,364 additions and 584 deletions.
65 changes: 33 additions & 32 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,34 +361,14 @@ func CreateNode(numValidators int, chain genesis.ChainType, workingDir string,
func StartNode(workingDir string, passwordFetcher func(*wallet.Wallet) (string, bool)) (
*node.Node, *wallet.Wallet, error,
) {
gen, err := genesis.LoadFromFile(PactusGenesisPath(workingDir))
if err != nil {
return nil, nil, err
}

if !gen.ChainType().IsMainnet() {
crypto.AddressHRP = "tpc"
crypto.PublicKeyHRP = "tpublic"
crypto.PrivateKeyHRP = "tsecret"
crypto.XPublicKeyHRP = "txpublic"
crypto.XPrivateKeyHRP = "txsecret"
}

walletsDir := PactusWalletDir(workingDir)
confPath := PactusConfigPath(workingDir)

conf, err := MakeConfig(gen, confPath, walletsDir)
if err != nil {
return nil, nil, err
}

err = conf.BasicCheck()
conf, gen, err := MakeConfig(workingDir)
if err != nil {
return nil, nil, err
}

defaultWalletPath := PactusDefaultWalletPath(workingDir)
walletInstance, err := wallet.Open(defaultWalletPath, true)
walletInstance, err := wallet.Open(defaultWalletPath, true,
wallet.WithCustomServers([]string{conf.GRPC.Listen}))
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -451,13 +431,30 @@ func makeLocalGenesis(w wallet.Wallet) *genesis.Genesis {
return gen
}

// MakeConfig opens the given config file and creates the appropriate configuration per chain type.
// The chain type is determined from the genesis document.
// It also updates some private configurations, like "wallets directory".
// TODO: write test for me.
func MakeConfig(genDoc *genesis.Genesis, confPath, walletsDir string) (*config.Config, error) {
// MakeConfig attempts to load the configuration file and
// returns an instance of the configuration along with the genesis document.
// The genesis document is required to determine the chain type, which influences the configuration settings.
// The function sets various private configurations, such as the "wallets directory" and chain-specific HRP values.
// If the configuration file cannot be loaded, it tries to recover or restore the configuration.
func MakeConfig(workingDir string) (*config.Config, *genesis.Genesis, error) {
gen, err := genesis.LoadFromFile(PactusGenesisPath(workingDir))
if err != nil {
return nil, nil, err
}

if !gen.ChainType().IsMainnet() {
crypto.AddressHRP = "tpc"
crypto.PublicKeyHRP = "tpublic"
crypto.PrivateKeyHRP = "tsecret"
crypto.XPublicKeyHRP = "txpublic"
crypto.XPrivateKeyHRP = "txsecret"
}

walletsDir := PactusWalletDir(workingDir)
confPath := PactusConfigPath(workingDir)

var defConf *config.Config
chainType := genDoc.ChainType()
chainType := gen.ChainType()

switch chainType {
case genesis.Mainnet:
Expand All @@ -475,12 +472,12 @@ func MakeConfig(genDoc *genesis.Genesis, confPath, walletsDir string) (*config.C

conf, err = RecoverConfig(confPath, defConf, chainType)
if err != nil {
return nil, err
return nil, nil, err
}
}

// Now we can update the private filed, if any
genParams := genDoc.Params()
genParams := gen.Params()

conf.Store.TxCacheSize = genParams.TransactionToLiveInterval
conf.Store.SortitionCacheSize = genParams.SortitionInterval
Expand All @@ -493,7 +490,11 @@ func MakeConfig(genDoc *genesis.Genesis, confPath, walletsDir string) (*config.C
conf.WalletManager.ChainType = chainType
conf.WalletManager.WalletsDir = walletsDir

return conf, nil
if err := conf.BasicCheck(); err != nil {
return nil, nil, err
}

return conf, gen, nil
}

func RecoverConfig(confPath string, defConf *config.Config, chainType genesis.ChainType) (*config.Config, error) {
Expand Down
4 changes: 2 additions & 2 deletions cmd/daemon/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ func buildInitCmd(parentCmd *cobra.Command) {
Short: "initialize the Pactus Blockchain node",
}
parentCmd.AddCommand(initCmd)
workingDirOpt := initCmd.Flags().StringP("working-dir", "w", cmd.PactusDefaultHomeDir(),
"a path to the working directory to save the wallet and node files")

workingDirOpt := addWorkingDirOption(initCmd)

testnetOpt := initCmd.Flags().Bool("testnet", false,
"initialize working directory for joining the testnet")
Expand Down
6 changes: 6 additions & 0 deletions cmd/daemon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,15 @@ func main() {
buildVersionCmd(rootCmd)
buildInitCmd(rootCmd)
buildStartCmd(rootCmd)
buildPruneCmd(rootCmd)

err := rootCmd.Execute()
if err != nil {
cmd.PrintErrorMsgf("%s", err)
}
}

func addWorkingDirOption(c *cobra.Command) *string {
return c.Flags().StringP("working-dir", "w", cmd.PactusDefaultHomeDir(),
"the path to the working directory that keeps the wallets and node files")
}
115 changes: 115 additions & 0 deletions cmd/daemon/prune.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package main

import (
"fmt"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"

"github.com/gofrs/flock"
"github.com/pactus-project/pactus/cmd"
"github.com/pactus-project/pactus/store"
"github.com/spf13/cobra"
)

func buildPruneCmd(parentCmd *cobra.Command) {
pruneCmd := &cobra.Command{
Use: "prune",
Short: "prune old blocks and transactions from client",
Long: "The prune command optimizes blockchain storage by removing outdated blocks and transactions, " +
"freeing up disk space and enhancing client performance.",
}
parentCmd.AddCommand(pruneCmd)

workingDirOpt := addWorkingDirOption(pruneCmd)

pruneCmd.Run = func(_ *cobra.Command, _ []string) {
workingDir, _ := filepath.Abs(*workingDirOpt)
// change working directory
err := os.Chdir(workingDir)
cmd.FatalErrorCheck(err)

// Define the lock file path
lockFilePath := filepath.Join(workingDir, ".pactus.lock")
fileLock := flock.New(lockFilePath)

locked, err := fileLock.TryLock()
if err != nil {
// handle unable to attempt to acquire lock
cmd.FatalErrorCheck(err)
}

if !locked {
cmd.PrintWarnMsgf("Could not lock '%s', another instance is running?", lockFilePath)

return
}

conf, _, err := cmd.MakeConfig(workingDir)
cmd.FatalErrorCheck(err)

cmd.PrintLine()
cmd.PrintWarnMsgf("This command removes all the blocks and transactions up to %d days ago "+
"and converts the node to prune mode.", conf.Store.RetentionDays)
cmd.PrintLine()
confirmed := cmd.PromptConfirm("Do you want to continue")
if !confirmed {
return
}
cmd.PrintLine()

str, err := store.NewStore(conf.Store)
cmd.FatalErrorCheck(err)

prunedCount := uint32(0)
skippedCount := uint32(0)
totalCount := uint32(0)

interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)

go func() {
<-interrupt
str.Close()
_ = fileLock.Unlock()
}()

err = str.Prune(func(pruned, skipped, pruningHeight uint32) {
prunedCount += pruned
skippedCount += skipped

if totalCount == 0 {
totalCount = pruningHeight
}

pruningProgressBar(prunedCount, skippedCount, totalCount)
})
cmd.PrintLine()
cmd.FatalErrorCheck(err)

str.Close()
_ = fileLock.Unlock()

cmd.PrintLine()
cmd.PrintInfoMsgf("✅ Your node successfully pruned and changed to prune mode.")
cmd.PrintLine()
cmd.PrintInfoMsgf("You can start the node by running this command:")
cmd.PrintInfoMsgf("./pactus-daemon start -w %v", workingDir)
}
}

func pruningProgressBar(prunedCount, skippedCount, totalCount uint32) {
percentage := float64(prunedCount+skippedCount) / float64(totalCount) * 100
if percentage > 100 {
percentage = 100
}

barLength := 40
filledLength := int(float64(barLength) * percentage / 100)

bar := strings.Repeat("=", filledLength) + strings.Repeat(" ", barLength-filledLength)
fmt.Printf("\r [%s] %.0f%% Pruned: %d | Skipped: %d", //nolint
bar, percentage, prunedCount, skippedCount)
}
3 changes: 1 addition & 2 deletions cmd/daemon/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ func buildStartCmd(parentCmd *cobra.Command) {

parentCmd.AddCommand(startCmd)

workingDirOpt := startCmd.Flags().StringP("working-dir", "w", cmd.PactusDefaultHomeDir(),
"the path to the working directory to load the wallet and node files")
workingDirOpt := addWorkingDirOption(startCmd)

passwordOpt := startCmd.Flags().StringP("password", "p", "",
"the wallet password")
Expand Down
2 changes: 0 additions & 2 deletions cmd/gtk/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,6 @@ func run(n *node.Node, wlt *wallet.Wallet, app *gtk.Application) {
grpcAddr := n.GRPC().Address()
cmd.PrintInfoMsgf("connect wallet to grpc server: %s\n", grpcAddr)

wlt.SetServerAddr(grpcAddr)

nodeModel := newNodeModel(n)
walletModel := newWalletModel(wlt, n)

Expand Down
29 changes: 20 additions & 9 deletions cmd/wallet/main.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package main

import (
"time"

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

var (
pathOpt *string
offlineOpt *bool
serverAddrOpt *string
pathOpt *string
offlineOpt *bool
serverAddrsOpt *[]string
timeoutOpt *int
)

func addPasswordOption(c *cobra.Command) *string {
Expand All @@ -18,13 +21,19 @@ func addPasswordOption(c *cobra.Command) *string {
}

func openWallet() (*wallet.Wallet, error) {
wlt, err := wallet.Open(*pathOpt, *offlineOpt)
if err != nil {
return nil, err
opts := make([]wallet.Option, 0)

if *serverAddrsOpt != nil {
opts = append(opts, wallet.WithCustomServers(*serverAddrsOpt))
}

if *serverAddrOpt != "" {
wlt.SetServerAddr(*serverAddrOpt)
if *timeoutOpt > 0 {
opts = append(opts, wallet.WithTimeout(time.Duration(*timeoutOpt)*time.Second))
}

wlt, err := wallet.Open(*pathOpt, *offlineOpt, opts...)
if err != nil {
return nil, err
}

return wlt, err
Expand All @@ -43,7 +52,9 @@ func main() {
pathOpt = rootCmd.PersistentFlags().String("path",
cmd.PactusDefaultWalletPath(cmd.PactusDefaultHomeDir()), "the path to the wallet file")
offlineOpt = rootCmd.PersistentFlags().Bool("offline", false, "offline mode")
serverAddrOpt = rootCmd.PersistentFlags().String("server", "", "server gRPC address")
serverAddrsOpt = rootCmd.PersistentFlags().StringSlice("servers", []string{}, "servers gRPC address")
timeoutOpt = rootCmd.PersistentFlags().Int("timeout", 1,
"specifies the timeout duration for the client connection in seconds")

buildCreateCmd(rootCmd)
buildRecoverCmd(rootCmd)
Expand Down
5 changes: 5 additions & 0 deletions config/example_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
# Default is `"data"`.
path = "data"

# `retention_days` this parameter indicates the number of days for which the node should keep or retain the blocks
# before pruning them. It is only applicable if the node is in Prune Mode.
# Default is `10`.
retention_days = 10

# `network` contains configuration options for the network module, which manages communication between nodes.
[network]

Expand Down
Loading

0 comments on commit e6b65bb

Please sign in to comment.