Skip to content

Commit

Permalink
fixed default snapshot and statesync dirs
Browse files Browse the repository at this point in the history
Sanitize path config.

Co-authored-by: charithabandi <chbandi302@gmail.com>
  • Loading branch information
brennanjl and charithabandi authored Jun 21, 2024
1 parent 8a9318f commit 3785397
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 88 deletions.
4 changes: 2 additions & 2 deletions build/package/docker/kwild.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ RUN GOWORK=off GIT_VERSION=$version GIT_COMMIT=$git_commit BUILD_TIME=$build_tim
RUN GOWORK=off GIT_VERSION=$version GIT_COMMIT=$git_commit BUILD_TIME=$build_time CGO_ENABLED=0 TARGET="/app/dist" GO_RACEFLAG=$go_race ./scripts/build/binary kwil-cli
RUN chmod +x /app/dist/kwild /app/dist/kwil-admin /app/dist/kwil-cli

FROM alpine:3.19
FROM ubuntu:24.04
WORKDIR /app
RUN mkdir -p /var/run/kwil && chmod 777 /var/run/kwil
RUN apk --no-cache add postgresql-client
RUN apt update && apt install -y postgresql-client
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /app/dist/kwild ./kwild
COPY --from=build /app/dist/kwil-admin ./kwil-admin
Expand Down
7 changes: 5 additions & 2 deletions cmd/kwil-admin/nodecfg/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ func WriteConfigFile(configFilePath string, cfg *config.KwildConfig) error {
}

const defaultConfigTemplate = `
# NOTE: Any path below can be absolute (e.g. "/var/myawesomeapp/data") or
# relative to the home directory (e.g. "data")
# NOTE: Any path below can be absolute (e.g. "/app/data", "~/app/data) or
# relative to the root directory (e.g. "data")
# Root Directory Structure:
# RootDir/
Expand Down Expand Up @@ -167,6 +167,7 @@ hostname = "{{ .AppCfg.Hostname }}"
# Path to the snapshot file to restore the database from.
# Used during the network migration process.
# Might be either absolute path or path related to the kwild root directory.
genesis_state = "{{ .AppCfg.GenesisState }}"
#######################################################################
Expand Down Expand Up @@ -202,6 +203,7 @@ genesis_state = "{{ .AppCfg.GenesisState }}"
enabled = {{.AppCfg.Snapshots.Enabled}}
# Path to the snapshots directory
# Might be either absolute path or path related to the kwild root directory.
snapshot_dir = "{{.AppCfg.Snapshots.SnapshotDir}}"
# Specifies the block heights(multiples of recurring_height) at which the snapshot should be taken
Expand Down Expand Up @@ -339,6 +341,7 @@ cache_size = {{ .ChainCfg.Mempool.CacheSize }}
enable = {{ .ChainCfg.StateSync.Enable }}
# SnapshotDir is the directory to store the received snapshot chunks.
# Might be either absolute path or path related to the kwild root directory.
snapshot_dir = "{{ .ChainCfg.StateSync.SnapshotDir }}"
# Trusted snapshot providers (comma-separated chain RPC servers) are the source-of-truth for the snapshot integrity.
Expand Down
60 changes: 33 additions & 27 deletions cmd/kwild/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@ func DefaultConfig() *KwildConfig {
JSONRPCListenAddress: "0.0.0.0:8484",
HTTPListenAddress: "0.0.0.0:8080",
AdminListenAddress: "/tmp/kwild.socket", // Or, suggested, 127.0.0.1:8485
PrivateKeyPath: PrivateKeyFileName,
DBHost: "127.0.0.1",
DBPort: "5432", // ignored with unix socket, but applies if IP used for DBHost
DBUser: "kwild",
Expand Down Expand Up @@ -638,15 +639,19 @@ func EmptyConfig() *KwildConfig {
}
}

func (cfg *KwildConfig) LogConfig() *log.Config {
func (cfg *KwildConfig) LogConfig() (*log.Config, error) {
// Rootify any relative paths.
outputPaths := make([]string, 0, len(cfg.Logging.OutputPaths))
for _, path := range cfg.Logging.OutputPaths {
switch path {
case "stdout", "stderr":
outputPaths = append(outputPaths, path)
default:
outputPaths = append(outputPaths, rootify(path, cfg.RootDir))
updatedPath, err := rootify(path, cfg.RootDir)
if err != nil {
return nil, err
}
outputPaths = append(outputPaths, updatedPath)
}
}
// log.Config <== config.Logging
Expand All @@ -655,59 +660,60 @@ func (cfg *KwildConfig) LogConfig() *log.Config {
OutputPaths: outputPaths,
Format: cfg.Logging.Format,
EncodeTime: cfg.Logging.TimeEncoding,
}
}, nil
}

func (cfg *KwildConfig) configureCerts() {
func (cfg *KwildConfig) configureCerts() error {
if cfg.AppCfg.TLSCertFile == "" {
cfg.AppCfg.TLSCertFile = DefaultTLSCertFile
}
cfg.AppCfg.TLSCertFile = rootify(cfg.AppCfg.TLSCertFile, cfg.RootDir)
path, err := rootify(cfg.AppCfg.TLSCertFile, cfg.RootDir)
if err != nil {
return err
}
cfg.AppCfg.TLSCertFile = path

if cfg.AppCfg.TLSKeyFile == "" {
cfg.AppCfg.TLSKeyFile = defaultTLSKeyFile
}
cfg.AppCfg.TLSKeyFile = rootify(cfg.AppCfg.TLSKeyFile, cfg.RootDir)
path, err = rootify(cfg.AppCfg.TLSKeyFile, cfg.RootDir)
if err != nil {
return err
}
cfg.AppCfg.TLSKeyFile = path
return nil
}

func (cfg *KwildConfig) sanitizeCfgPaths() error {
rootDir := cfg.RootDir

if cfg.AppCfg.PrivateKeyPath != "" {
cfg.AppCfg.PrivateKeyPath = rootify(cfg.AppCfg.PrivateKeyPath, rootDir)
} else {
cfg.AppCfg.PrivateKeyPath = filepath.Join(rootDir, PrivateKeyFileName)
path, err := rootify(cfg.AppCfg.PrivateKeyPath, rootDir)
if err != nil {
return fmt.Errorf("failed to expand private key path \"%v\": %v", cfg.AppCfg.PrivateKeyPath, err)
}
cfg.AppCfg.PrivateKeyPath = path
fmt.Println("Private key path:", cfg.AppCfg.PrivateKeyPath)

if cfg.AppCfg.Snapshots.Enabled {
if cfg.AppCfg.Snapshots.SnapshotDir == "" {
cfg.AppCfg.Snapshots.SnapshotDir = filepath.Join(rootDir, SnapshotDirName)
} else {
dir, err := ExpandPath(cfg.AppCfg.Snapshots.SnapshotDir)
if err != nil {
return fmt.Errorf("failed to expand snapshot directory \"%v\": %v", cfg.AppCfg.Snapshots.SnapshotDir, err)
}
cfg.AppCfg.Snapshots.SnapshotDir = dir
path, err := rootify(cfg.AppCfg.Snapshots.SnapshotDir, rootDir)
if err != nil {
return fmt.Errorf("failed to expand snapshot directory \"%v\": %v", cfg.AppCfg.Snapshots.SnapshotDir, err)
}
cfg.AppCfg.Snapshots.SnapshotDir = path
fmt.Println("Snapshot directory:", cfg.AppCfg.Snapshots.SnapshotDir)
}

if cfg.ChainCfg.StateSync.Enable {
if cfg.ChainCfg.StateSync.SnapshotDir == "" {
cfg.ChainCfg.StateSync.SnapshotDir = filepath.Join(rootDir, ReceivedSnapsDirName)
} else {
dir, err := ExpandPath(cfg.ChainCfg.StateSync.SnapshotDir)
if err != nil {
return fmt.Errorf("failed to expand snapshot directory \"%v\": %v", cfg.ChainCfg.StateSync.SnapshotDir, err)
}
cfg.ChainCfg.StateSync.SnapshotDir = dir
path, err := rootify(cfg.ChainCfg.StateSync.SnapshotDir, rootDir)
if err != nil {
return fmt.Errorf("failed to expand state sync snapshots directory \"%v\": %v", cfg.ChainCfg.StateSync.SnapshotDir, err)
}
cfg.ChainCfg.StateSync.SnapshotDir = path
fmt.Println("State sync received snapshots directory:", cfg.ChainCfg.StateSync.SnapshotDir)
}

if cfg.AppCfg.GenesisState != "" {
path, err := ExpandPath(cfg.AppCfg.GenesisState)
path, err := rootify(cfg.AppCfg.GenesisState, rootDir)
if err != nil {
return fmt.Errorf("failed to expand snapshot file path \"%v\": %v", cfg.AppCfg.GenesisState, err)
}
Expand Down
56 changes: 56 additions & 0 deletions cmd/kwild/config/config_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package config

import (
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func Test_Config_Toml(t *testing.T) {
Expand Down Expand Up @@ -106,3 +108,57 @@ func Test_cleanListenAddr(t *testing.T) {
})
}
}

func Test_Rootify(t *testing.T) {
homeDir, err := os.UserHomeDir()
require.NoError(t, err)

rootDir := "/app/kwild"

cwd, err := os.Getwd()
require.NoError(t, err)

testcases := []struct {
name string
addr string
rootifyPath string
expandPath string
}{
{
name: "absolute path",
addr: "/app/kwild",
rootifyPath: "/app/kwild",
expandPath: "/app/kwild",
},
{
name: "absolute path with tilde",
addr: "~/kwild",
rootifyPath: filepath.Join(homeDir, "kwild"),
expandPath: filepath.Join(homeDir, "kwild"),
},
{
name: "relative path",
addr: "genesis.json",
rootifyPath: "/app/kwild/genesis.json",
expandPath: filepath.Join(cwd, "genesis.json"),
},
{
name: "relative path with ../",
addr: "../conf/genesis.json",
rootifyPath: "/app/conf/genesis.json",
expandPath: filepath.Join(cwd, "../conf/genesis.json"),
},
}

for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
got, err := rootify(tc.addr, rootDir)
require.NoError(t, err)
assert.Equal(t, tc.rootifyPath, got)

got, err = ExpandPath(tc.addr)
require.NoError(t, err)
assert.Equal(t, tc.expandPath, got)
})
}
}
58 changes: 31 additions & 27 deletions cmd/kwild/config/default_config.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# The is an example config file for kwild.

# NOTE: Any path below can be absolute (e.g. "/var/myawesomeapp/data") or
# relative to the root directory (e.g. "data"). The root directory is
# "$HOME/.kwild" by default, but could be changed via $KWILD_HOME env variable
# or via --home command line flag.
# NOTE: Any path below can be absolute (e.g. "/app/data", "~/app/data) or
# relative to the root directory (e.g. "data")
# Order of preference: command line flag, env variable, default value.

# Root Directory Structure:
Expand Down Expand Up @@ -91,6 +89,11 @@ tls_key_file = ""
# Kwild Server hostname
hostname = ""

# Path to the snapshot file to restore the database from.
# Used during the network migration process.
# Might be either absolute path or path related to the kwild root directory.
genesis_state = ""

#######################################################################
### Extension Configuration ###
#######################################################################
Expand All @@ -101,21 +104,18 @@ hostname = ""
#######################################################################
[app.snapshots]

# Toggle to enable snapshot store
# This would snapshot the application state at every recurring_height blocks
# and keep max_snapshots number of snapshots in the snapshot_dir
# Application state includes the databases deployed, accounts and the Validators db
# Enables snapshots
enabled = false

# The height at which the snapshot is taken
recurring_height = 100000
# Path to the snapshots directory
# Might be either absolute path or path related to the kwild root directory.
snapshot_dir = "snapshots"

# Maximum number of snapshots to be kept in the snapshot_dir.
# If max limit is reached, the oldest would be deleted and replaced by the latest snapshot
max_snapshots = 3
# Specifies the block heights(multiples of recurring_height) at which the snapshot should be taken
recurring_height = 10000

# The directory where the snapshots are stored. Can be absolute or relative to the kwild root directory
snapshot_dir = "snapshots"
# Maximum number of snapshots to store
max_snapshots = 3

#######################################################################
### Logging Config Options ###
Expand Down Expand Up @@ -264,21 +264,25 @@ cache_size = 10000
# starting from the height of the snapshot.
enable = false

# RPC servers (comma-separated) for light client verification of the synced state machine and
# retrieval of state data for node bootstrapping. Also needs a trusted height and corresponding
# header hash obtained from a trusted source, and a period during which validators can be trusted.
#
# For Cosmos SDK-based chains, trust_period should usually be about 2/3 of the unbonding time (~2
# weeks) during which they can be financially punished (slashed) for misbehavior.
rpc_servers = ""
# SnapshotDir is the directory to store the received snapshot chunks.
# Might be either absolute path or path related to the kwild root directory.
snapshot_dir = "rcvdSnaps"

# Temporary directory for state sync snapshot chunks, defaults to the OS tempdir (typically /tmp).
# Will create a new, randomly named directory within, and remove it when done.
temp_dir = ""
# Trusted snapshot providers (comma-separated chain RPC servers) are the source-of-truth for the snapshot integrity.
# Snapshots are accepted for statesync only after verifying the snapshot metadata (snapshot hash, chunk count, height etc.)
# with these trusted snapshot providers. At least 1 trusted snapshot provider is required for enabling state sync.
rpc_servers = ""

# Time to spend discovering snapshots before initiating a restore.
# Time spent discovering snapshots before offering the best(latest) snapshot to the application.
# If no snapshots are discovered, the node will redo the discovery process until snapshots are found.
# If network has no snapshots, restart the node with state sync disabled to sync with the network.
# Current default is 15s, as only snapshot metadata is requested in the discovery process.
# Adjust this value according to the network latencies of your peers.
discovery_time = "15s"

# The timeout duration before re-requesting a chunk, possibly from a different
# peer (default: 1 minute).
# peer (default: 1 minute), if the current peer is unresponsive to the chunk request.
chunk_request_timeout = "10s"

# Note: If the requested chunk is not received for a duration of 2 minutes (hard-coded default),
# the state sync process is aborted and the node will fall back to the regular block sync process.
25 changes: 21 additions & 4 deletions cmd/kwild/config/reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,28 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/kwilteam/kwil-db/internal/abci/cometbft"
)

func rootify(path, rootDir string) string {
func rootify(path, rootDir string) (string, error) {
// If the path is already absolute, return it as is.
if filepath.IsAbs(path) {
return path
return path, nil
}
return filepath.Join(rootDir, path)

// If the path is ~/..., expand it to the user's home directory.
if tail, cut := strings.CutPrefix(path, "~/"); cut {
homeDir, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(homeDir, tail), nil
}

// Otherwise, treat it as relative to the root directory.
return filepath.Join(rootDir, path), nil
}

func ResetChainState(rootDir string) error {
Expand Down Expand Up @@ -72,7 +85,11 @@ func ResetAll(rootDir, snapshotDir string) error {

// TODO: support postgres database drop or schema drops

snapshotDir = rootify(snapshotDir, rootDir)
snapshotDir, err := rootify(snapshotDir, rootDir)
if err != nil {
return err
}

if err := os.RemoveAll(snapshotDir); err == nil {
fmt.Println("Removed all snapshots", "dir", snapshotDir)
} else {
Expand Down
Loading

0 comments on commit 3785397

Please sign in to comment.