diff --git a/.github/workflows/portal-loop.yml b/.github/workflows/portal-loop.yml new file mode 100644 index 00000000000..7e8b54faa5d --- /dev/null +++ b/.github/workflows/portal-loop.yml @@ -0,0 +1,48 @@ +name: portal-loop + +on: + push: + paths: + - misc/loop + - .github/workflows/portal-loop.yml + branches: + - "master" + - "ops/portal-loop" + tags: + - "v*" + +permissions: + contents: read + packages: write + +jobs: + portal-loop: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Docker metadata portalloopd + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }}/portalloopd + tags: | + type=raw,value=latest + type=semver,pattern=v{{version}} + + - name: Build and push + uses: docker/build-push-action@v4 + with: + context: ./misc/loop + target: portalloopd + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/misc/loop/.gitignore b/misc/loop/.gitignore new file mode 100644 index 00000000000..641b553abe6 --- /dev/null +++ b/misc/loop/.gitignore @@ -0,0 +1,3 @@ +/portalloopd +/backups +/traefik/letsencrypt diff --git a/misc/loop/Dockerfile b/misc/loop/Dockerfile new file mode 100644 index 00000000000..219a47927db --- /dev/null +++ b/misc/loop/Dockerfile @@ -0,0 +1,19 @@ +FROM golang:alpine AS builder + +COPY . /go/src/github.com/gnolang/gno/misc/loop + +WORKDIR /go/src/github.com/gnolang/gno/misc/loop + +RUN --mount=type=cache,target=/root/.cache/go-build \ + --mount=type=cache,target=/root/go/pkg/mod \ + go build -o /build/portalloopd ./cmd + +# Final image for portalloopd +FROM docker AS portalloopd + +RUN apk add bash curl jq + +COPY --from=builder /build/portalloopd /usr/bin/portalloopd + +ENTRYPOINT [ "/usr/bin/portalloopd" ] +CMD [ "serve" ] diff --git a/misc/loop/Makefile b/misc/loop/Makefile index d18c83fb84a..3966cd42323 100644 --- a/misc/loop/Makefile +++ b/misc/loop/Makefile @@ -1,44 +1,22 @@ -# The startup delay (waits until the node is "ready") -DELAY ?= 10 # seconds -# The temporary backup file for transactions -BACKUP_FILE ?= $(abspath ./txs_backup.log) -# The entire txs history across all iterations -HISTORY_OUTPUT := $(abspath ./txs_history.log) +all: docker.start -# The gnoland binary -gnoland_bin := go run github.com/gnolang/gno/gno.land/cmd/gnoland -# The tx archive binary -tx_bin := go run github.com/gnolang/tx-archive/cmd +docker.start: # Start the portal loop + docker compose up -d -# The relative gno.land directory -gnoland_dir := $(abspath ../../gno.land) +docker.stop: # Stop the portal loop + docker compose down + docker rm -f $(docker ps -aq --filter "label=the-portal-loop") -all: loop +docker.build: # (re)Build snapshotter image + docker compose build -start.gnoland: - cd $(gnoland_dir) && $(gnoland_bin) start -skip-failing-genesis-txs -genesis-txs-file $(HISTORY_OUTPUT) -clean.gnoland: - make -C $(gnoland_dir) fclean -.PHONY: start.gnoland clean.gnoland +docker.pull: # Pull new images to update versions + docker compose pull -# Starts the backup service -# and backs up transactions into a file -# that is wiped on every loop -tx.backup: - sleep $(DELAY) - $(tx_bin) backup -legacy -watch -overwrite -output-path "$(BACKUP_FILE)" -.PHONY: tx.backup +portalloopd.bash: # Get a bash command inside of the portalloopd container + docker compose exec portalloopd bash -# Saves the history from previous iterations into -# a temporary transactions log -save.history: - @test -e $(BACKUP_FILE) || (echo "No existing backup file not found: '$(BACKUP_FILE)'"; exit 1) - cat $(BACKUP_FILE) >> $(HISTORY_OUTPUT) -.PHONY: save.history +switch: portalloopd.switch -loop: clean.gnoland - # backup history, if needed - $(MAKE) save.history || true - # run our dev loop - ./run_loop.sh -.PHONY: loop +portalloopd.switch: # Force switch the portal loop with latest image + docker compose exec portalloopd switch diff --git a/misc/loop/README.md b/misc/loop/README.md new file mode 100644 index 00000000000..ce02c83b67c --- /dev/null +++ b/misc/loop/README.md @@ -0,0 +1,42 @@ +# The portal loop :infinity: + +## What is it? + +It's a Gnoland node that aim to run with always the latest version of gno and never loose transactions history. + +For more information, see issue on github [gnolang/gno#1239](https://github.com/gnolang/gno/issues/1239) + + +## How to use + +Start the loop with: + +```sh +$ docker compose up -d + +# or using the Makefile + +$ make +``` + +The [`portalloopd`](./cmd/portalloopd) binary is starting inside of the docker container `portalloopd` + +This script is doing: + +- Setup the current portal-loop in read only mode +- Pull the latest version of [ghcr.io/gnolang/gno]() +- Backup the txs using [gnolang/tx-archive](https://github.com/gnolang/tx-archive) +- Start a new docker container with the backups files +- Changing the proxy (traefik) to redirect to the new portal loop +- Unlock read only mode +- Stop the previous loop + +### Makefile helper + +You can find a [Makefile](./Makefile) to help you interact with the portal loop + +- Force switch of the portal loop with a new version + +```bash +make portalloopd.switch +``` diff --git a/misc/loop/backups/.keep b/misc/loop/backups/.keep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/misc/loop/cmd/cmd_backup.go b/misc/loop/cmd/cmd_backup.go new file mode 100644 index 00000000000..f95e1e15a4a --- /dev/null +++ b/misc/loop/cmd/cmd_backup.go @@ -0,0 +1,85 @@ +package main + +import ( + "context" + "flag" + "os" + + "github.com/docker/docker/client" + "github.com/gnolang/gno/tm2/pkg/commands" +) + +type backupCfg struct { + rpcAddr string + traefikGnoFile string + backupDir string + hostPWD string +} + +func (c *backupCfg) RegisterFlags(fs *flag.FlagSet) { + if os.Getenv("HOST_PWD") == "" { + os.Setenv("HOST_PWD", os.Getenv("PWD")) + } + + if os.Getenv("BACKUP_DIR") == "" { + os.Setenv("BACKUP_DIR", "./backups") + } + + if os.Getenv("RPC_URL") == "" { + os.Setenv("RPC_URL", "http://rpc.portal.gno.local:26657") + } + + if os.Getenv("PROM_ADDR") == "" { + os.Setenv("PROM_ADDR", ":9090") + } + + if os.Getenv("TRAEFIK_GNO_FILE") == "" { + os.Setenv("TRAEFIK_GNO_FILE", "./traefik/gno.yml") + } + + fs.StringVar(&c.rpcAddr, "rpc", os.Getenv("RPC_URL"), "tendermint rpc url") + fs.StringVar(&c.traefikGnoFile, "traefik-gno-file", os.Getenv("TRAEFIK_GNO_FILE"), "traefik gno file") + fs.StringVar(&c.backupDir, "backup-dir", os.Getenv("BACKUP_DIR"), "backup directory") + fs.StringVar(&c.hostPWD, "pwd", os.Getenv("HOST_PWD"), "host pwd (for docker usage)") +} + +func newBackupCmd(io commands.IO) *commands.Command { + cfg := &backupCfg{} + + return commands.NewCommand( + commands.Metadata{ + Name: "backup", + ShortUsage: "backup [flags]", + }, + cfg, + func(ctx context.Context, _ []string) error { + return execBackup(ctx, cfg) + }, + ) +} + +func execBackup(ctx context.Context, cfg *backupCfg) error { + dockerClient, err := client.NewEnvClient() + if err != nil { + return err + } + + portalLoop := &snapshotter{} + + portalLoop, err = NewSnapshotter(dockerClient, config{ + backupDir: cfg.backupDir, + rpcAddr: cfg.rpcAddr, + hostPWD: cfg.hostPWD, + traefikGnoFile: cfg.traefikGnoFile, + }) + if err != nil { + return err + } + + err = StartPortalLoop(ctx, portalLoop, false) + if err != nil { + return err + } + + return portalLoop.backupTXs(ctx, portalLoop.url) +} diff --git a/misc/loop/cmd/cmd_serve.go b/misc/loop/cmd/cmd_serve.go new file mode 100644 index 00000000000..cdcfcf30c73 --- /dev/null +++ b/misc/loop/cmd/cmd_serve.go @@ -0,0 +1,116 @@ +package main + +import ( + "context" + "flag" + "net/http" + "os" + "time" + + "github.com/docker/docker/client" + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/sirupsen/logrus" +) + +type serveCfg struct { + rpcAddr string + traefikGnoFile string + backupDir string + hostPWD string +} + +type serveService struct { + cfg serveCfg + + // TODO(albttx): put getter on it with RMutex + portalLoop *snapshotter + + portalLoopURL string +} + +func (c *serveCfg) RegisterFlags(fs *flag.FlagSet) { + if os.Getenv("HOST_PWD") == "" { + os.Setenv("HOST_PWD", os.Getenv("PWD")) + } + + if os.Getenv("BACKUP_DIR") == "" { + os.Setenv("BACKUP_DIR", "./backups") + } + + if os.Getenv("RPC_URL") == "" { + os.Setenv("RPC_URL", "http://rpc.portal.gno.local:26657") + } + + if os.Getenv("PROM_ADDR") == "" { + os.Setenv("PROM_ADDR", ":9090") + } + + if os.Getenv("TRAEFIK_GNO_FILE") == "" { + os.Setenv("TRAEFIK_GNO_FILE", "./traefik/gno.yml") + } + + fs.StringVar(&c.rpcAddr, "rpc", os.Getenv("RPC_URL"), "tendermint rpc url") + fs.StringVar(&c.traefikGnoFile, "traefik-gno-file", os.Getenv("TRAEFIK_GNO_FILE"), "traefik gno file") + fs.StringVar(&c.backupDir, "backup-dir", os.Getenv("BACKUP_DIR"), "backup directory") + fs.StringVar(&c.hostPWD, "pwd", os.Getenv("HOST_PWD"), "host pwd (for docker usage)") +} + +func newServeCmd(io commands.IO) *commands.Command { + cfg := &serveCfg{} + + return commands.NewCommand( + commands.Metadata{ + Name: "serve", + ShortUsage: "serve [flags]", + }, + cfg, + func(ctx context.Context, args []string) error { + return execServe(ctx, cfg, args) + }, + ) +} + +func execServe(ctx context.Context, cfg *serveCfg, args []string) error { + dockerClient, err := client.NewEnvClient() + if err != nil { + return err + } + + portalLoop := &snapshotter{} + + // Serve monitoring + go func() { + s := &monitoringService{ + portalLoop: portalLoop, + } + + for portalLoop.url == "" { + time.Sleep(time.Second * 1) + } + + go s.recordMetrics() + + http.Handle("/metrics", promhttp.Handler()) + http.ListenAndServe(os.Getenv("PROM_ADDR"), nil) + }() + + // the loop + for { + portalLoop, err = NewSnapshotter(dockerClient, config{ + backupDir: cfg.backupDir, + rpcAddr: cfg.rpcAddr, + hostPWD: cfg.hostPWD, + traefikGnoFile: cfg.traefikGnoFile, + }) + if err != nil { + return err + } + + err = StartPortalLoop(ctx, portalLoop, false) + if err != nil { + logrus.WithError(err).Error() + } + time.Sleep(time.Second * 120) + } +} diff --git a/misc/loop/cmd/cmd_switch.go b/misc/loop/cmd/cmd_switch.go new file mode 100644 index 00000000000..02f770cb61c --- /dev/null +++ b/misc/loop/cmd/cmd_switch.go @@ -0,0 +1,80 @@ +package main + +import ( + "context" + "flag" + "os" + + "github.com/docker/docker/client" + "github.com/gnolang/gno/tm2/pkg/commands" +) + +type switchCfg struct { + rpcAddr string + traefikGnoFile string + backupDir string + hostPWD string +} + +func (c *switchCfg) RegisterFlags(fs *flag.FlagSet) { + if os.Getenv("HOST_PWD") == "" { + os.Setenv("HOST_PWD", os.Getenv("PWD")) + } + + if os.Getenv("BACKUP_DIR") == "" { + os.Setenv("BACKUP_DIR", "./backups") + } + + if os.Getenv("RPC_URL") == "" { + os.Setenv("RPC_URL", "http://rpc.portal.gno.local:26657") + } + + if os.Getenv("PROM_ADDR") == "" { + os.Setenv("PROM_ADDR", ":9090") + } + + if os.Getenv("TRAEFIK_GNO_FILE") == "" { + os.Setenv("TRAEFIK_GNO_FILE", "./traefik/gno.yml") + } + + fs.StringVar(&c.rpcAddr, "rpc", os.Getenv("RPC_URL"), "tendermint rpc url") + fs.StringVar(&c.traefikGnoFile, "traefik-gno-file", os.Getenv("TRAEFIK_GNO_FILE"), "traefik gno file") + fs.StringVar(&c.backupDir, "backup-dir", os.Getenv("BACKUP_DIR"), "backup directory") + fs.StringVar(&c.hostPWD, "pwd", os.Getenv("HOST_PWD"), "host pwd (for docker usage)") +} + +func newSwitchCmd(io commands.IO) *commands.Command { + cfg := &switchCfg{} + + return commands.NewCommand( + commands.Metadata{ + Name: "switch", + ShortUsage: "switch [flags]", + }, + cfg, + func(ctx context.Context, _ []string) error { + return execSwitch(ctx, cfg) + }, + ) +} + +func execSwitch(ctx context.Context, cfg *switchCfg) error { + dockerClient, err := client.NewEnvClient() + if err != nil { + return err + } + + portalLoop := &snapshotter{} + + portalLoop, err = NewSnapshotter(dockerClient, config{ + backupDir: cfg.backupDir, + rpcAddr: cfg.rpcAddr, + hostPWD: cfg.hostPWD, + traefikGnoFile: cfg.traefikGnoFile, + }) + if err != nil { + return err + } + + return StartPortalLoop(ctx, portalLoop, true) +} diff --git a/misc/loop/cmd/main.go b/misc/loop/cmd/main.go new file mode 100644 index 00000000000..83061d2a3f5 --- /dev/null +++ b/misc/loop/cmd/main.go @@ -0,0 +1,37 @@ +package main + +import ( + "context" + "os" + + "github.com/gnolang/gno/tm2/pkg/commands" +) + +type service struct { + // TODO(albttx): put getter on it with RMutex + portalLoop *snapshotter + + portalLoopURL string +} + +func main() { + cliIO := commands.NewDefaultIO() + + cmd := commands.NewCommand( + commands.Metadata{ + Name: "portalloopd", + ShortUsage: " [flags] [...]", + LongHelp: "Portalloop commands interactions", + }, + commands.NewEmptyConfig(), + commands.HelpExec, + ) + + cmd.AddSubCommands( + newServeCmd(cliIO), + newBackupCmd(cliIO), + newSwitchCmd(cliIO), + ) + + cmd.Execute(context.Background(), os.Args[1:]) +} diff --git a/misc/loop/cmd/monitoring.go b/misc/loop/cmd/monitoring.go new file mode 100644 index 00000000000..bd439c5b3fd --- /dev/null +++ b/misc/loop/cmd/monitoring.go @@ -0,0 +1,68 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "time" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + "github.com/sirupsen/logrus" +) + +// Monitoring to export +// - Number of lines in backups.jsonl +// - Uptime of last version + +type monitoringService struct { + portalLoop *snapshotter +} + +type metrics struct { + backupTXS prometheus.Gauge +} + +func (s *monitoringService) getBackupsFileMetrics(m *metrics) error { + f, err := os.Open(s.portalLoop.backupFile) + if err != nil { + return fmt.Errorf("monitoring: %w, file: %s", err, s.portalLoop.backupFile) + } + + fileScanner := bufio.NewScanner(f) + fileScanner.Split(bufio.ScanLines) + + backedUpTxs := 0 + for fileScanner.Scan() { + backedUpTxs += 1 + + // TODO(albttx): Increment a counter if tx is a new realm + // content := fileScanner.Text() + // fmt.Println(content) + } + + m.backupTXS.Set(float64(backedUpTxs)) + + return nil +} + +func (s *monitoringService) recordMetrics() { + m := metrics{} + + m.backupTXS = promauto.NewGauge(prometheus.GaugeOpts{ + Name: "portal_loop_backup_txs", + Help: "The number of line backed up", + ConstLabels: prometheus.Labels{ + "portal_loop_container_name": s.portalLoop.containerName, + }, + }) + + // Start infinite loop of metrics getter + for { + if err := s.getBackupsFileMetrics(&m); err != nil { + logrus.WithError(err).Error() + } + + time.Sleep(time.Second * 5) + } +} diff --git a/misc/loop/cmd/portal-loop.go b/misc/loop/cmd/portal-loop.go new file mode 100644 index 00000000000..a3e93aca2fc --- /dev/null +++ b/misc/loop/cmd/portal-loop.go @@ -0,0 +1,177 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "strconv" + "strings" + "time" + + "github.com/docker/docker/api/types" + "github.com/sirupsen/logrus" +) + +func StartPortalLoop(ctx context.Context, portalLoop *snapshotter, force bool) error { + l := logrus.WithFields(logrus.Fields{}) + + // 1. Pull latest docker image + isNew, err := portalLoop.pullLatestImage(ctx) + if err != nil { + return err + } + l.WithField("is_new", isNew).Info("Starting the Portal Loop") + + // 2. Get existing portal loop + containers, err := portalLoop.getPortalLoopContainers(ctx) + if err != nil { + return err + } + l.WithField("containers", containers).Info("Get containers") + + if len(containers) == 0 { + logrus.Info("No portal loop instance found, starting one") + // Portal loop isn't running, Starting it + container, err := portalLoop.startPortalLoopContainer(context.Background()) + if err != nil { + return err + } + containers = []types.Container{*container} + force = true + } + + for _, p := range containers[0].Ports { + if p.Type == "tcp" && p.PrivatePort == uint16(26657) { + ip := containers[0].NetworkSettings.Networks["portal-loop"].IPAddress + portalLoop.url = fmt.Sprintf("http://%s:%d", ip, int(p.PrivatePort)) + portalLoop.switchTraefikPortalLoop(portalLoop.url) + break + } + } + + l = l.WithFields(logrus.Fields{ + "portal.url": portalLoop.url, + }) + l.Info("Current portal loop") + + // 3. Check if there is a new image + if !isNew && !force { + return nil + } + + l.Info("Set read only mode") + // 4. Set traefik in READ ONLY mode + err = portalLoop.switchTraefikMode(setReadOnly) + if err != nil { + return err + } + + defer func() { + l.Info("Unset read only mode") + err = portalLoop.switchTraefikMode(unsetReadOnly) + if err != nil { + logrus.WithError(err).Error() + } + }() + + l.Info("Backup txs") + // 5. Backup TXs + err = portalLoop.backupTXs(ctx, portalLoop.url) + if err != nil { + return err + } + + // 6. Start a new portal loop + container, err := portalLoop.startPortalLoopContainer(context.Background()) + if err != nil { + return err + } + for _, p := range container.Ports { + if p.Type == "tcp" && p.PrivatePort == uint16(26657) { + ip := container.NetworkSettings.Networks["portal-loop"].IPAddress + portalLoop.url = fmt.Sprintf("http://%s:%d", ip, int(p.PrivatePort)) + break + } + } + l = l.WithFields(logrus.Fields{ + "new_portal.url": portalLoop.url, + }) + l.Info("setup new portal loop") + + // 7. Wait 5 blocks new portal loop to be ready + now := time.Now() + for { + if time.Since(now) > time.Second*120 { + return fmt.Errorf("timeout getting latest block") + } + err := func() error { + resp, err := http.Get(portalLoop.url + "/status") + if err != nil { + return err + } + defer resp.Body.Close() + + tmStatus := struct { + Result struct { + SyncInfo struct { + LatestBlockHeight string `json:"latest_block_height"` + } `json:"sync_info"` + } `json:"result"` + }{} + if err := json.NewDecoder(resp.Body).Decode(&tmStatus); err != nil { + return err + } + + currentBlock, err := strconv.Atoi(tmStatus.Result.SyncInfo.LatestBlockHeight) + if err != nil { + return err + } + l.WithField("new_portal.current_block", currentBlock) + + if currentBlock >= 5 { + return nil + } + return fmt.Errorf("blocks: %d/5", currentBlock) + }() + if err == nil { + break + } + + if !strings.HasPrefix(err.Error(), "blocks: ") { + logrus.WithError(err).Error() + } + time.Sleep(time.Second * 2) + } + + l.Info("update traefik portal loop url") + // 8. Update traefik portal loop rpc url + if err := portalLoop.switchTraefikPortalLoop(portalLoop.url); err != nil { + return err + } + + // 9. Remove old portal loop + for _, c := range containers { + l.WithFields(logrus.Fields{ + "container.id": c.ID, + "container.ports": c.Ports, + }).Infof("remove container") + err = portalLoop.dockerClient.ContainerRemove(ctx, c.ID, types.ContainerRemoveOptions{ + Force: true, // Force the removal of a running container + RemoveVolumes: true, // Remove the volumes associated with the container + RemoveLinks: false, // Remove the specified link and not the underlying container + }) + if err != nil { + return err + } + for _, mount := range c.Mounts { + if mount.Type == "volume" { + err = portalLoop.dockerClient.VolumeRemove(ctx, mount.Name, true) + if err != nil { + return err + } + } + } + } + return nil +} diff --git a/misc/loop/cmd/snapshotter.go b/misc/loop/cmd/snapshotter.go new file mode 100644 index 00000000000..2de28906e7e --- /dev/null +++ b/misc/loop/cmd/snapshotter.go @@ -0,0 +1,243 @@ +package main + +import ( + "bytes" + "context" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "regexp" + "strings" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/volume" + "github.com/docker/docker/client" + "github.com/docker/go-connections/nat" + "github.com/gnolang/tx-archive/backup" + "github.com/gnolang/tx-archive/backup/client/http" + "github.com/gnolang/tx-archive/backup/writer/legacy" +) + +const ( + setReadOnly = `middlewares: ["ipwhitelist"]` + unsetReadOnly = `middlewares: []` +) + +type snapshotter struct { + dockerClient *client.Client + + containerName string + backupFile string + instanceBackupFile string + + cfg config + + url string +} + +type config struct { + rpcAddr string + traefikGnoFile string + backupDir string + hostPWD string +} + +func NewSnapshotter(dockerClient *client.Client, cfg config) (*snapshotter, error) { + timenow := time.Now() + now := fmt.Sprintf("%s_%v", timenow.Format("2006-01-02_"), timenow.UnixNano()) + + backupFile, err := filepath.Abs(cfg.backupDir + "/backup.jsonl") + if err != nil { + return nil, err + } + instanceBackupFile, err := filepath.Abs(fmt.Sprintf("%s/backup_%s.jsonl", cfg.backupDir, now)) + if err != nil { + return nil, err + } + return &snapshotter{ + dockerClient: dockerClient, + + cfg: cfg, + + containerName: "gno-" + now, + backupFile: backupFile, + instanceBackupFile: instanceBackupFile, + }, nil +} + +// pullLatestImage get latest version of the docker image +func (s snapshotter) pullLatestImage(ctx context.Context) (bool, error) { + reader, err := s.dockerClient.ImagePull(ctx, "ghcr.io/gnolang/gno", types.ImagePullOptions{}) + if err != nil { + return false, err + } + var b bytes.Buffer + defer reader.Close() + + _, err = io.Copy(&b, reader) + if err != nil { + return false, err + } + + return !strings.Contains(b.String(), "Image is up to date"), nil +} + +func (s snapshotter) switchTraefikMode(replaceStr string) error { + input, err := ioutil.ReadFile(s.cfg.traefikGnoFile) + if err != nil { + return err + } + + regex := regexp.MustCompile(`middlewares: \[.*\]`) + output := regex.ReplaceAllLiteral(input, []byte(replaceStr)) + + return ioutil.WriteFile(s.cfg.traefikGnoFile, output, 0655) +} + +func (s snapshotter) switchTraefikPortalLoop(url string) error { + input, err := ioutil.ReadFile(s.cfg.traefikGnoFile) + if err != nil { + return err + } + + regex := regexp.MustCompile(`http://.*:[0-9]+`) + output := regex.ReplaceAllLiteral(input, []byte(url)) + + return ioutil.WriteFile(s.cfg.traefikGnoFile, output, 0655) +} + +func (s snapshotter) getPortalLoopContainers(ctx context.Context) ([]types.Container, error) { + // Check if a portal loop is running + containers, err := s.dockerClient.ContainerList(ctx, types.ContainerListOptions{}) + if err != nil { + return []types.Container{}, err + } + + portalLoopContainers := make([]types.Container, 0) + + for _, container := range containers { + if _, exists := container.Labels["the-portal-loop"]; exists { + portalLoopContainers = append(portalLoopContainers, container) + } + } + + return portalLoopContainers, nil +} + +func (s snapshotter) startPortalLoopContainer(ctx context.Context) (*types.Container, error) { + // Create Docker volume + _, err := s.dockerClient.VolumeCreate(ctx, volume.CreateOptions{ + Name: s.containerName, + }) + if err != nil { + return nil, err + } + + // Run Docker container + container, err := s.dockerClient.ContainerCreate(ctx, &container.Config{ + Image: "ghcr.io/gnolang/gno", + Labels: map[string]string{ + "the-portal-loop": s.containerName, + }, + Env: []string{ + "MONIKER=the-portal-loop", + "GENESIS_BACKUP_FILE=/backups/backup.jsonl", + }, + Cmd: []string{"/scripts/start.sh"}, + ExposedPorts: nat.PortSet{ + "26656/tcp": struct{}{}, + "26657/tcp": struct{}{}, + }, + }, &container.HostConfig{ + PublishAllPorts: true, + PortBindings: nat.PortMap{ + "26657/tcp": []nat.PortBinding{ + {HostIP: "127.0.0.1"}, + }, + }, + Binds: []string{ + fmt.Sprintf("%s/scripts:/scripts", s.cfg.hostPWD), + fmt.Sprintf("%s/backups:/backups", s.cfg.hostPWD), + fmt.Sprintf("%s:/opt/gno/src/testdir", s.containerName), + }, + }, nil, nil, s.containerName) + if err != nil { + return nil, err + } + + err = s.dockerClient.NetworkConnect(ctx, "portal-loop", container.ID, nil) + if err != nil { + return nil, err + } + + if err := s.dockerClient.ContainerStart(ctx, container.ID, types.ContainerStartOptions{}); err != nil { + return nil, err + } + time.Sleep(time.Second * 5) + + containers, err := s.getPortalLoopContainers(ctx) + if err != nil { + return nil, err + } + for _, c := range containers { + if c.ID == container.ID { + return &c, nil + } + } + + return nil, fmt.Errorf("container not found") +} + +func (s snapshotter) backupTXs(ctx context.Context, rpcURL string) error { + cfg := backup.DefaultConfig() + cfg.FromBlock = 1 + cfg.Watch = false + + instanceBackupFile, err := os.Create(s.instanceBackupFile) + if err != nil { + return err + } + defer instanceBackupFile.Close() + + w := legacy.NewWriter(instanceBackupFile) + // client := http.NewClient(s.cfg.rpcAddr) + client := http.NewClient(rpcURL) + + backupService := backup.NewService(client, w) + + // Run the backup service + if backupErr := backupService.ExecuteBackup(ctx, cfg); backupErr != nil { + return fmt.Errorf("unable to execute backup, %w", backupErr) + } + + if err := instanceBackupFile.Sync(); err != nil { + return err + } + + info, err := instanceBackupFile.Stat() + if err != nil { + return err + } else if info.Size() == 0 { + return os.Remove(instanceBackupFile.Name()) + } + + // Append to backup file + backupFile, err := os.OpenFile(s.backupFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + return fmt.Errorf("unable to open file %s, %w", s.backupFile, err) + } + defer backupFile.Close() + + // NOTE(albttx): Impossible to use io.ReadAll(instanceBackupFile) + output, err := ioutil.ReadFile(s.instanceBackupFile) + if err != nil { + return err + } + + _, err = backupFile.Write(output) + return err +} diff --git a/misc/loop/docker-compose.production.yml b/misc/loop/docker-compose.production.yml new file mode 100644 index 00000000000..1c7cf146792 --- /dev/null +++ b/misc/loop/docker-compose.production.yml @@ -0,0 +1,142 @@ +version: "3" + +networks: + portal-loop: + name: portal-loop + driver: bridge + ipam: + config: + - subnet: 172.177.0.0/16 + +services: + traefik: + image: "traefik:v2.10" + restart: unless-stopped + command: + - "--api.insecure=true" + - "--providers.file=true" + - "--providers.file.watch=true" + - "--providers.file.directory=/etc/traefik/configs" + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=false" + - "--entrypoints.web.address=:80" + - "--entrypoints.rpc.address=:26657" + - "--entrypoints.web.http.redirections.entrypoint.to=websecure" + - "--entrypoints.web.http.redirections.entrypoint.scheme=https" + - "--entrypoints.web.http.redirections.entrypoint.permanent=true" + - "--entryPoints.web.forwardedHeaders.insecure" + - "--entrypoints.traefik.address=:8080" + + - "--entrypoints.websecure.address=:443" + # - "--certificatesresolvers.le.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory" + - "--certificatesresolvers.le.acme.tlschallenge=true" + - "--certificatesresolvers.le.acme.email=dev@gno.land" + - "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json" + networks: + - portal-loop + ports: + - "80:80" + - "443:443" + - "26657:26657" + volumes: + - "/var/run/docker.sock:/var/run/docker.sock:ro" + - ./traefik:/etc/traefik/configs + - ./traefik/letsencrypt:/letsencrypt + + gnoweb: + image: ghcr.io/gnolang/gno/gnoweb-slim + restart: unless-stopped + env_file: ".env" + entrypoint: + - gnoweb + - --bind=0.0.0.0:8888 + - --remote=traefik:26657 + - --faucet-url=https://faucet-api.portal.gnoteam.com + - --captcha-site=$CAPTCHA_SITE_KEY + - --with-analytics + - --help-chainid=portal-loop + - --help-remote=https://rpc.gno.land:443 + networks: + - portal-loop + labels: + com.centurylinklabs.watchtower.enable: "true" + traefik.enable: "true" + traefik.http.routers.gnoweb.entrypoints: "web,websecure" + traefik.http.routers.gnoweb.rule: "Host(`gno.land`) || Host(`portal.gnoteam.com`)" + traefik.http.routers.gnoweb.tls: "true" + traefik.http.routers.gnoweb.tls.certresolver: "le" + + gnofaucet: + image: ghcr.io/gnolang/gno/gnofaucet-slim + networks: + - portal-loop + command: + - "serve" + - "--listen-address=0.0.0.0:5050" + - "--chain-id=portal-loop" + - "--is-behind-proxy=true" + - "--mnemonic=${FAUCET_MNEMONIC}" + - "--num-accounts=1" + - "--remote=http://traefik:26657" + - "--captcha-secret=${CAPTCHA_SECRET_KEY}" + env_file: ".env" + # environment: + # from .env + # - RECAPTCHA_SECRET_KEY + labels: + com.centurylinklabs.watchtower.enable: "true" + traefik.enable: "true" + traefik.http.routers.gnofaucet-api.entrypoints: "websecure" + # traefik.http.routers.gnofaucet-api.rule: "Host(`faucet-api.gno.land`) || Host(`faucet-api.portal.gnoteam.com`)" + traefik.http.routers.gnofaucet-api.rule: "Host(`faucet-api.portal.gnoteam.com`)" + traefik.http.routers.gnofaucet-api.tls: "true" + traefik.http.routers.gnofaucet-api.tls.certresolver: "le" + traefik.http.middlewares.gnofaucet-ratelimit.ratelimit.average: "6" + traefik.http.middlewares.gnofaucet-ratelimit.ratelimit.period: "1m" + + portalloopd: + # image: ghcr.io/gnolang/gno/portalloopd + image: ghcr.io/albttx/gno/portalloopd + restart: unless-stopped + volumes: + - ./scripts:/scripts + - ./backups:/backups + - ./traefik:/etc/traefik/configs + - "/var/run/docker.sock:/var/run/docker.sock:ro" + networks: + - portal-loop + ports: + - 127.0.0.1:9090:9090 + environment: + HOST_PWD: $PWD + BACKUP_DIR: "/backups" + RPC_URL: "http://traefik:26657" + PROM_ADDR: "0.0.0.0:9090" + TRAEFIK_GNO_FILE: "/etc/traefik/configs/gno.yml" + extra_hosts: + - host.docker.internal:host-gateway + labels: + - "com.centurylinklabs.watchtower.enable=true" + + autocounterd: + image: ghcr.io/albttx/gno/autocounterd + restart: unless-stopped + env_file: ".env" + command: + - "start" + - "--mnemonic=${COUNTER_MNEMONIC}" + - "--rpc=http://traefik:26657" + networks: + - portal-loop + labels: + com.centurylinklabs.watchtower.enable: "true" + + watchtower: + image: containrrr/watchtower + command: --interval 30 --http-api-metrics --label-enable + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + WATCHTOWER_HTTP_API_TOKEN: "mytoken" + ports: + - 127.0.0.1:8000:8080 diff --git a/misc/loop/docker-compose.yml b/misc/loop/docker-compose.yml new file mode 100644 index 00000000000..1475b6699fe --- /dev/null +++ b/misc/loop/docker-compose.yml @@ -0,0 +1,90 @@ +version: "3" + +networks: + portal-loop: + name: portal-loop + driver: bridge + ipam: + driver: default + config: + - subnet: 172.42.0.0/16 + +services: + traefik: + image: "traefik:v2.10" + restart: unless-stopped + command: + - "--api.insecure=true" + - "--providers.file=true" + - "--providers.file.watch=true" + - "--providers.file.directory=/etc/traefik/configs" + - "--entrypoints.web.address=:80" + - "--entrypoints.private.address=:26657" + - "--entrypoints.traefik.address=:8080" + networks: + - portal-loop + ports: + - "80:80" + - "8080:8080" + - "26657:26657" + volumes: + - ./traefik:/etc/traefik/configs + + gnoweb: + image: ghcr.io/gnolang/gno/gnoweb-slim + restart: unless-stopped + networks: + - portal-loop + ports: + - 8888:8888 + entrypoint: + - gnoweb + - --bind=0.0.0.0:8888 + - --remote=traefik:26657 + - --faucet-url + - "http://localhost:5050" + - --help-chainid + - portal-loop + - --help-remote + - http://127.0.0.1:26657 + + gnofaucet: + image: ghcr.io/gnolang/gno/gnofaucet-slim + networks: + - portal-loop + ports: + - 5050:5050 + command: + - "serve" + - "--listen-address=0.0.0.0:5050" + - "--chain-id=portal-loop" + # - "--is-behind-proxy=true" + - "--mnemonic=${MNEMONIC}" + # - "--num-accounts=1" + - "--remote=http://traefik:26657" + environment: + # from .env + - RECAPTCHA_SECRET_KEY + + portalloopd: + build: + context: . + target: portalloopd + restart: unless-stopped + volumes: + - ./scripts:/scripts + - ./backups:/backups + - ./traefik:/etc/traefik/configs + - "/var/run/docker.sock:/var/run/docker.sock:ro" + networks: + - portal-loop + ports: + - 9090:9090 + environment: + HOST_PWD: $PWD + BACKUP_DIR: "/backups" + RPC_URL: "http://traefik:26657" + PROM_ADDR: "0.0.0.0:9090" + TRAEFIK_GNO_FILE: "/etc/traefik/configs/gno.yml" + extra_hosts: + - host.docker.internal:host-gateway diff --git a/misc/loop/go.mod b/misc/loop/go.mod index da95e7f5f28..edf64092736 100644 --- a/misc/loop/go.mod +++ b/misc/loop/go.mod @@ -3,29 +3,62 @@ module loop go 1.21 require ( - github.com/gnolang/gno v0.0.0-20231112174927-b1a53c018ea4 + github.com/docker/docker v24.0.7+incompatible + github.com/docker/go-connections v0.4.0 + github.com/gnolang/gno v0.0.0-20240125181217-b6193518e278 github.com/gnolang/tx-archive v0.1.1 + github.com/prometheus/client_golang v1.17.0 + github.com/sirupsen/logrus v1.9.3 ) require ( dario.cat/mergo v1.0.0 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cockroachdb/apd/v3 v3.2.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/dgraph-io/badger/v3 v3.2103.5 // indirect + github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/distribution/reference v0.5.0 // indirect + github.com/docker/distribution v2.8.3+incompatible // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect github.com/gnolang/goleveldb v0.0.9 // indirect github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/glog v1.1.2 // indirect + github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/flatbuffers v1.12.1 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/jaekwon/testify v1.6.1 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/klauspost/compress v1.12.3 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/linxGnu/grocksdb v1.8.11 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/peterbourgon/ff/v3 v3.4.0 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.11.1 // indirect github.com/rs/cors v1.10.1 // indirect github.com/stretchr/testify v1.8.4 // indirect + github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect + go.etcd.io/bbolt v1.3.8 // indirect + go.opencensus.io v0.22.5 // indirect go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.26.0 // indirect go.uber.org/zap/exp v0.2.0 // indirect @@ -35,11 +68,9 @@ require ( golang.org/x/net v0.21.0 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/term v0.17.0 // indirect + golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.18.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect - google.golang.org/grpc v1.60.1 // indirect google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.1 // indirect ) - -replace github.com/gnolang/gno => ../../ diff --git a/misc/loop/go.sum b/misc/loop/go.sum index 00cabcfd2d1..c9dee625290 100644 --- a/misc/loop/go.sum +++ b/misc/loop/go.sum @@ -1,6 +1,17 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA= @@ -14,8 +25,9 @@ github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUB github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -25,10 +37,18 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= -github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= -github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -40,38 +60,81 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeC github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg= +github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw= +github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= +github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= +github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= +github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= +github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gnolang/gno v0.0.0-20240125181217-b6193518e278 h1:CxF7gG3iqSeYVygTSYsB7Beg+Fpvka06TuTI2a0p+6s= +github.com/gnolang/gno v0.0.0-20240125181217-b6193518e278/go.mod h1:mOhpUTFaKk5CQj90qmjWfI9po2eapqziEu4D+fAtisc= github.com/gnolang/goleveldb v0.0.9 h1:Q7rGko9oXMKtQA+Apeeed5a3sjba/mcDhzJGoTVLCKE= github.com/gnolang/goleveldb v0.0.9/go.mod h1:Dz6p9bmpy/FBESTgduiThZt5mToVDipcHGzj/zUOo8E= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 h1:GKvsK3oLWG9B1GL7WP/VqwM6C92j5tIvB844oggL9Lk= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:xJhtEL7ahjM1WJipt89gel8tHzfIl/LyMY+lCYh38d8= github.com/gnolang/tx-archive v0.1.1 h1:maVdRFsc1ptVhwVw1p5scvu2Rus8Yk3o9qlss5+SRCw= github.com/gnolang/tx-archive v0.1.1/go.mod h1:MrUmRaU6GB9tOPy+5pCe/x1z1fGYtAypVJzKOExeUHY= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= +github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jaekwon/testify v1.6.1 h1:4AtAJcR9GzXN5W4DdY7ie74iCPiJV1JJUJL90t2ZUyw= github.com/jaekwon/testify v1.6.1/go.mod h1:Oun0RXIHI7osufabQ60i4Lqkj0GXLbqI1I7kgzBNm1U= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -79,17 +142,33 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/linxGnu/grocksdb v1.8.4 h1:ZMsBpPpJNtRLHiKKp0mI7gW+NT4s7UgfD5xHxx1jVRo= -github.com/linxGnu/grocksdb v1.8.4/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/linxGnu/grocksdb v1.8.11 h1:BGol9e5gB1BrsTvOxloC88pe70TCqgrfLNwkyWW0kD8= +github.com/linxGnu/grocksdb v1.8.11/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= @@ -103,6 +182,11 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= @@ -111,22 +195,48 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= -github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= -github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= @@ -136,31 +246,61 @@ go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= go.uber.org/zap/exp v0.2.0 h1:FtGenNNeCATRB3CmB/yEUnjEFeJWpB/pMcy7e2bKPYs= go.uber.org/zap/exp v0.2.0/go.mod h1:t0gqAIdh1MfKv9EwN/dLwfZnJxe9ITAZN78HEWPFWDQ= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= @@ -170,31 +310,47 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -202,3 +358,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/misc/loop/run_loop.sh b/misc/loop/run_loop.sh deleted file mode 100755 index 4b186df9a71..00000000000 --- a/misc/loop/run_loop.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -# This script is meant to orchestrate -# a parallel execution of a gno.land node -# and a backup tool that preserves -# transactions that happen on-chain while -# the node is running. Additionally, the -# script also closes down any hanging process -# if either the node / backup tool fail - -set -e # exit on error - -# Set up the kill signal callback -teardown() { - echo "Stopping background processes..." - kill 0 -} - -echo "Running local development setup" - -# Start the gnoland node (fresh chain), and in parallel -# - start the backup service for transactions -( - echo "Starting Gno node..." - make start.gnoland - teardown -) & -( - echo "Starting backup..." - make tx.backup - teardown -) & - -# Trap all kill signals -trap 'teardown' INT - -# Wait for all background processes to finish -wait diff --git a/misc/loop/scripts/start.sh b/misc/loop/scripts/start.sh new file mode 100755 index 00000000000..d50b3175932 --- /dev/null +++ b/misc/loop/scripts/start.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env sh + +MONIKER=${MONIKER:-"gnode"} +P2P_LADDR=${P2P_LADDR:-"tcp://0.0.0.0:26656"} +RPC_LADDR=${RPC_LADDR:-"tcp://0.0.0.0:26657"} + +CHAIN_ID=${CHAIN_ID:-"portal-loop"} + +GENESIS_BACKUP_FILE=${GENESIS_BACKUP_FILE:-""} + +SEEDS=${SEEDS:-""} +PERSISTENT_PEERS=${PERSISTENT_PEERS:-""} + +echo "" >> /opt/gno/src/gno.land/genesis/genesis_txs.jsonl +cat ${GENESIS_BACKUP_FILE} >> /opt/gno/src/gno.land/genesis/genesis_txs.jsonl + +gnoland start \ + --chainid="${CHAIN_ID}" \ + --skip-start=true \ + --skip-failing-genesis-txs + +sed -i "s#^moniker = \".*\"#moniker = \"${MONIKER}\"#" ./testdir/config/config.toml +sed -i "s#laddr = \".*:26656\"#laddr = \"${P2P_LADDR}\"#" ./testdir/config/config.toml +sed -i "s#laddr = \".*:26657\"#laddr = \"${RPC_LADDR}\"#" ./testdir/config/config.toml + +sed -i "s#seeds = \".*\"#seeds = \"${SEEDS}\"#" ./testdir/config/config.toml +sed -i "s#persistent_peers = \".*\"#persistent_peers = \"${PERSISTENT_PEERS}\"#" ./testdir/config/config.toml + +exec gnoland start --skip-failing-genesis-txs diff --git a/misc/loop/traefik/gno.yml b/misc/loop/traefik/gno.yml new file mode 100644 index 00000000000..59ed91bf62c --- /dev/null +++ b/misc/loop/traefik/gno.yml @@ -0,0 +1,29 @@ +--- +http: + middlewares: + ipwhitelist: + ipWhiteList: + sourceRange: + - "127.0.0.1/32" + - "172.42.0.1/32" + + routers: + gno-portal-loop-local: + service: gno-portal-loop + rule: "PathPrefix(`/`)" + entrypoints: ["private"] + middlewares: [] + + gno-portal-loop: + service: gno-portal-loop + tls: + certResolver: le + rule: "Host(`rpc.gno.land`) || Host(`rpc.portal.gnoteam.com`)" + entrypoints: ["web", "websecure"] + middlewares: [] + + services: + gno-portal-loop: + loadBalancer: + servers: + - url: "http://172.42.0.5:26657" diff --git a/misc/loop/traefik/gnofaucet.yml b/misc/loop/traefik/gnofaucet.yml new file mode 100644 index 00000000000..25dd092a504 --- /dev/null +++ b/misc/loop/traefik/gnofaucet.yml @@ -0,0 +1,22 @@ +--- +http: + routers: + gnofaucet-local: + service: gnofaucet + rule: "Host(`faucet.portal.gno.local`)" + entrypoints: ["web", "websecure", "private"] + middlewares: [] + + gnofaucet: + service: gnofaucet + rule: "Host(`faucet.gno.land`) || Host(`faucet.portal.gnoteam.com`)" + tls: + certResolver: le + entrypoints: ["web", "websecure"] + middlewares: [] + + services: + gnofaucet: + loadBalancer: + servers: + - url: "http://localhost:9000" diff --git a/misc/loop/traefik/gnoweb.yml b/misc/loop/traefik/gnoweb.yml new file mode 100644 index 00000000000..8bce0f4bfb6 --- /dev/null +++ b/misc/loop/traefik/gnoweb.yml @@ -0,0 +1,22 @@ +--- +http: + routers: + gnoweb-local: + service: gnoweb + rule: "Host(`portal.gno.local`)" + entrypoints: ["web", "websecure", "private"] + middlewares: [] + + gnoweb: + service: gnoweb + rule: "Host(`gno.land`) || Host(`portal.gnoteam.com`)" + tls: + certResolver: le + entrypoints: ["web", "websecure"] + middlewares: [] + + services: + gnoweb: + loadBalancer: + servers: + - url: "http://localhost:8888"