diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 323dff4..3ff7454 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,3 +41,18 @@ jobs: with: go-version-file: go.mod - run: go build -o bin/apex ./cmd/apex + + e2e-submission: + name: E2E Submission + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: e2e/go.mod + cache-dependency-path: | + go.sum + e2e/go.sum + - working-directory: e2e + run: go test -race -count=1 -timeout 20m -run TestSubmissionViaJSONRPC ./... diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..8b492b2 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,128 @@ +# Apex — Celestia Namespace Indexer + +Lightweight indexer that watches Celestia namespaces, stores blobs/headers in SQLite, and exposes them via JSON-RPC, gRPC, and REST health endpoints. Includes Prometheus observability, a CLI client, and multi-stage Docker build. + +## Build Commands + +```bash +just build # compile to bin/apex +just test # go test -race ./... +just lint # golangci-lint run +just fmt # gofumpt -w . +just check # tidy + lint + test + build (CI equivalent) +just run # build and run +just clean # remove bin/ +just tidy # go mod tidy +``` + +## Architecture + +### Data Flow + +```text +Celestia Node → Fetcher → Sync Coordinator → Store (SQLite) + → Notifier → Subscribers + ↕ + API (JSON-RPC + gRPC + Health) +``` + +The sync coordinator runs in two phases: **backfill** (historical blocks in batches) then **streaming** (live via header subscription). Height observers publish events to the notifier which fans out to API subscribers. + +### File Structure + +```text +cmd/apex/ + main.go CLI entrypoint, server wiring, graceful shutdown + client.go Thin HTTP JSON-RPC client for CLI commands + status.go `apex status` command (health endpoint) + blob_cmd.go `apex blob get|list` commands + config_cmd.go `apex config validate|show` commands + +config/ + config.go Config structs (DataSource, Storage, RPC, Sync, Metrics, Log) + load.go YAML loading, validation, env var override, template generation + +pkg/types/ + types.go Domain types: Namespace, Blob, Header, SyncState, SyncStatus + +pkg/store/ + store.go Store interface (PutBlobs, GetBlobs, PutHeader, GetHeader, sync state) + sqlite.go SQLite implementation with metrics instrumentation + migrations/ SQL migration files + +pkg/fetch/ + fetcher.go DataFetcher + ProofForwarder interfaces + celestia_node.go Celestia node-api client (headers, blobs, subscriptions, proofs) + celestia_app.go Celestia-app gRPC client (headers, blobs, polling subscription) + +pkg/sync/ + coordinator.go Sync lifecycle: initialize → backfill → stream, tracks heights + backfill.go Concurrent batch backfill with configurable batch size/concurrency + subscription.go Header subscription manager for live streaming + +pkg/api/ + service.go API service layer (blob/header queries, proof forwarding, subscriptions) + notifier.go Event fan-out to subscribers with bounded buffers + health.go /health and /health/ready HTTP endpoints, HealthStatus JSON + jsonrpc/ JSON-RPC server (go-jsonrpc), blob/header/subscription handlers + grpc/ gRPC server, protobuf service implementations + gen/apex/v1/ Generated protobuf Go code + gen/cosmos/base/tendermint/v1beta1/ Generated Cosmos CometBFT service client + +pkg/metrics/ + metrics.go Recorder interface (nil-safe), nopRecorder, PromRecorder (Prometheus) + server.go HTTP server for /metrics endpoint + +proto/apex/v1/ Protobuf definitions (blob, header, types) +proto/cosmos/base/tendermint/v1beta1/ Minimal Cosmos SDK CometBFT service proto + +Dockerfile Multi-stage build (golang builder + distroless runtime) +``` + +### Key Interfaces + +- **`store.Store`** — persistence (SQLite impl, instrumented with metrics) +- **`fetch.DataFetcher`** — block data retrieval (Celestia node JSON-RPC or celestia-app gRPC) +- **`fetch.ProofForwarder`** — proof/inclusion forwarding to upstream node +- **`metrics.Recorder`** — nil-safe metrics abstraction (Prometheus or no-op) +- **`api.StatusProvider`** — sync status for health endpoints (implemented by coordinator) + +### Ports (defaults) + +| Port | Protocol | Purpose | +|-------|----------|------------------| +| :8080 | HTTP | JSON-RPC + health| +| :9090 | TCP | gRPC | +| :9091 | HTTP | Prometheus /metrics | + +### Config + +YAML with strict unknown-field rejection. Auth token via `APEX_AUTH_TOKEN` env var only (not in config file). See `config/config.go` for all fields and `DefaultConfig()` for defaults. + +## Conventions + +- Go 1.25+ (`go.mod` specifies 1.25.0) +- SQLite via `modernc.org/sqlite` (CGo-free) +- Config: YAML (`gopkg.in/yaml.v3`), strict unknown-field rejection +- Logging: `rs/zerolog` +- CLI: `spf13/cobra` +- Metrics: `prometheus/client_golang` behind nil-safe `Recorder` interface +- JSON-RPC: `filecoin-project/go-jsonrpc` +- gRPC: `google.golang.org/grpc` + `google.golang.org/protobuf` +- Protobuf codegen: `buf` (`buf.yaml` + `buf.gen.yaml`) +- Linter: golangci-lint v2 (.golangci.yml v2 format), gocyclo max 15 +- Formatter: gofumpt +- Build runner: just (justfile) + +## Dependencies + +- Only add deps that are strictly necessary +- Prefer stdlib where reasonable +- No CGo dependencies (cross-compilation constraint) + +## Testing + +- All tests use `-race` +- Table-driven tests preferred +- Test files alongside source (`_test.go`) +- No test frameworks beyond stdlib `testing` diff --git a/buf.yaml b/buf.yaml index 227c4a6..ce2346e 100644 --- a/buf.yaml +++ b/buf.yaml @@ -4,6 +4,9 @@ modules: lint: use: - DEFAULT + ignore_only: + PACKAGE_VERSION_SUFFIX: + - proto/cosmos/crypto/secp256k1/keys.proto breaking: use: - FILE diff --git a/cmd/apex/main.go b/cmd/apex/main.go index 418f345..461b7a0 100644 --- a/cmd/apex/main.go +++ b/cmd/apex/main.go @@ -25,6 +25,7 @@ import ( "github.com/evstack/apex/pkg/metrics" "github.com/evstack/apex/pkg/profile" "github.com/evstack/apex/pkg/store" + "github.com/evstack/apex/pkg/submit" syncer "github.com/evstack/apex/pkg/sync" "github.com/evstack/apex/pkg/types" ) @@ -113,6 +114,7 @@ func startCmd() *cobra.Command { startLog := log.Info(). Str("version", version). Str("datasource_type", cfg.DataSource.Type). + Bool("submission_enabled", cfg.Submission.Enabled). Int("namespaces", len(cfg.DataSource.Namespaces)) if cfg.DataSource.Type == dataSourceTypeApp { startLog = startLog.Str("app_grpc_addr", cfg.DataSource.CelestiaAppGRPCAddr) @@ -171,7 +173,12 @@ func setupProfiling(cfg *config.Config) *profile.Server { func openDataSource(ctx context.Context, cfg *config.Config) (fetch.DataFetcher, fetch.ProofForwarder, error) { switch cfg.DataSource.Type { case dataSourceTypeApp: - appFetcher, err := fetch.NewCelestiaAppFetcher(cfg.DataSource.CelestiaAppGRPCAddr, cfg.DataSource.AuthToken, log.Logger) + appFetcher, err := fetch.NewCelestiaAppFetcher( + cfg.DataSource.CelestiaAppGRPCAddr, + cfg.DataSource.AuthToken, + cfg.DataSource.CelestiaAppGRPCInsecure, + log.Logger, + ) if err != nil { return nil, nil, fmt.Errorf("create celestia-app fetcher: %w", err) } @@ -275,33 +282,18 @@ func runIndexer(ctx context.Context, cfg *config.Config) error { } defer dataFetcher.Close() //nolint:errcheck - // Set up API layer. - notifier := api.NewNotifier(cfg.Subscription.BufferSize, cfg.Subscription.MaxSubscribers, log.Logger) - notifier.SetMetrics(rec) - svc := api.NewService(db, dataFetcher, proofFwd, notifier, log.Logger) - - // Build and run the sync coordinator with observer hook. - coordOpts := []syncer.Option{ - syncer.WithStartHeight(cfg.Sync.StartHeight), - syncer.WithBatchSize(cfg.Sync.BatchSize), - syncer.WithConcurrency(cfg.Sync.Concurrency), - syncer.WithLogger(log.Logger), - syncer.WithMetrics(rec), - syncer.WithObserver(func(h uint64, hdr *types.Header, blobs []types.Blob) { - notifier.Publish(api.HeightEvent{Height: h, Header: hdr, Blobs: blobs}) - }), + svc, notifier, closeSubmitter, err := setupAPIService(cfg, db, dataFetcher, proofFwd, rec) + if err != nil { + return err } + defer closeSubmitter() - backfillOpt, closeBackfill, err := maybeBackfillSourceOption(cfg, log.Logger) + // Build and run the sync coordinator with observer hook. + coordOpts, closeBackfill, err := buildCoordinatorOptions(cfg, notifier, rec) if err != nil { return err } - if closeBackfill != nil { - defer closeBackfill() - } - if backfillOpt != nil { - coordOpts = append(coordOpts, backfillOpt) - } + defer closeBackfill() coord := syncer.New(db, dataFetcher, coordOpts...) @@ -360,6 +352,90 @@ func runIndexer(ctx context.Context, cfg *config.Config) error { return nil } +func openBlobSubmitter(cfg *config.Config) (*submit.DirectSubmitter, error) { + if !cfg.Submission.Enabled { + return nil, nil + } + + appClient, err := submit.NewGRPCAppClient( + cfg.Submission.CelestiaAppGRPCAddr, + cfg.Submission.CelestiaAppGRPCInsecure, + ) + if err != nil { + return nil, fmt.Errorf("create submission app client: %w", err) + } + + signer, err := submit.LoadSigner(cfg.Submission.SignerKey) + if err != nil { + _ = appClient.Close() + return nil, fmt.Errorf("load submission signer: %w", err) + } + + blobSubmitter, err := submit.NewDirectSubmitter(appClient, signer, submit.DirectConfig{ + ChainID: cfg.Submission.ChainID, + GasPrice: cfg.Submission.GasPrice, + MaxGasPrice: cfg.Submission.MaxGasPrice, + ConfirmationTimeout: time.Duration(cfg.Submission.ConfirmationTimeout) * time.Second, + }) + if err != nil { + _ = appClient.Close() + return nil, fmt.Errorf("configure submission backend: %w", err) + } + + return blobSubmitter, nil +} + +func setupAPIService(cfg *config.Config, db store.Store, dataFetcher fetch.DataFetcher, proofFwd fetch.ProofForwarder, rec metrics.Recorder) (*api.Service, *api.Notifier, func(), error) { + blobSubmitter, err := openBlobSubmitter(cfg) + if err != nil { + return nil, nil, nil, err + } + + closeSubmitter := func() {} + if blobSubmitter != nil { + closeSubmitter = func() { + _ = blobSubmitter.Close() + } + } + + notifier := api.NewNotifier(cfg.Subscription.BufferSize, cfg.Subscription.MaxSubscribers, log.Logger) + notifier.SetMetrics(rec) + + svcOpts := make([]api.ServiceOption, 0, 1) + if blobSubmitter != nil { + svcOpts = append(svcOpts, api.WithBlobSubmitter(blobSubmitter)) + } + + svc := api.NewService(db, dataFetcher, proofFwd, notifier, log.Logger, svcOpts...) + return svc, notifier, closeSubmitter, nil +} + +func buildCoordinatorOptions(cfg *config.Config, notifier *api.Notifier, rec metrics.Recorder) ([]syncer.Option, func(), error) { + coordOpts := []syncer.Option{ + syncer.WithStartHeight(cfg.Sync.StartHeight), + syncer.WithBatchSize(cfg.Sync.BatchSize), + syncer.WithConcurrency(cfg.Sync.Concurrency), + syncer.WithLogger(log.Logger), + syncer.WithMetrics(rec), + syncer.WithObserver(func(h uint64, hdr *types.Header, blobs []types.Blob) { + notifier.Publish(api.HeightEvent{Height: h, Header: hdr, Blobs: blobs}) + }), + } + + backfillOpt, closeBackfill, err := maybeBackfillSourceOption(cfg, log.Logger) + if err != nil { + return nil, nil, err + } + if closeBackfill == nil { + closeBackfill = func() {} + } + if backfillOpt != nil { + coordOpts = append(coordOpts, backfillOpt) + } + + return coordOpts, closeBackfill, nil +} + func gracefulShutdown(httpSrv *http.Server, grpcSrv *grpc.Server, metricsSrv *metrics.Server, profileSrv *profile.Server) { stopped := make(chan struct{}) go func() { diff --git a/config/config.go b/config/config.go index 3bf23bb..123e336 100644 --- a/config/config.go +++ b/config/config.go @@ -16,21 +16,23 @@ type Config struct { Metrics MetricsConfig `yaml:"metrics"` Profiling ProfilingConfig `yaml:"profiling"` Log LogConfig `yaml:"log"` + Submission SubmissionConfig `yaml:"submission"` } // DataSourceConfig configures the Celestia data source. // Type selects the backend: "node" (default) uses a Celestia DA node, // "app" uses a celestia-app consensus node via Cosmos SDK gRPC. type DataSourceConfig struct { - Type string `yaml:"type"` // "node" (default) or "app" - CelestiaNodeURL string `yaml:"celestia_node_url"` - CelestiaAppGRPCAddr string `yaml:"celestia_app_grpc_addr"` - BackfillSource string `yaml:"backfill_source"` // "rpc" (default) or "db" for app mode - CelestiaAppDBPath string `yaml:"celestia_app_db_path"` // required when backfill_source=db - CelestiaAppDBBackend string `yaml:"celestia_app_db_backend"` // auto|pebble|leveldb - CelestiaAppDBLayout string `yaml:"celestia_app_db_layout"` // auto|v1|v2 - AuthToken string `yaml:"-"` //nolint:gosec // populated only via APEX_AUTH_TOKEN env var; not a hardcoded credential - Namespaces []string `yaml:"namespaces"` + Type string `yaml:"type"` // "node" (default) or "app" + CelestiaNodeURL string `yaml:"celestia_node_url"` + CelestiaAppGRPCAddr string `yaml:"celestia_app_grpc_addr"` + CelestiaAppGRPCInsecure bool `yaml:"celestia_app_grpc_insecure"` // allow plaintext gRPC to non-loopback celestia-app endpoints + BackfillSource string `yaml:"backfill_source"` // "rpc" (default) or "db" for app mode + CelestiaAppDBPath string `yaml:"celestia_app_db_path"` // required when backfill_source=db + CelestiaAppDBBackend string `yaml:"celestia_app_db_backend"` // auto|pebble|leveldb + CelestiaAppDBLayout string `yaml:"celestia_app_db_layout"` // auto|v1|v2 + AuthToken string `yaml:"-"` //nolint:gosec // populated only via APEX_AUTH_TOKEN env var; not a hardcoded credential + Namespaces []string `yaml:"namespaces"` } // StorageConfig configures the persistence backend. @@ -92,6 +94,18 @@ type LogConfig struct { Format string `yaml:"format"` } +// SubmissionConfig contains settings for the future blob submission pipeline. +type SubmissionConfig struct { + Enabled bool `yaml:"enabled"` + CelestiaAppGRPCAddr string `yaml:"app_grpc_addr"` + CelestiaAppGRPCInsecure bool `yaml:"app_grpc_insecure"` // allow plaintext gRPC to non-loopback celestia-app endpoints + ChainID string `yaml:"chain_id"` + SignerKey string `yaml:"signer_key"` // path to a file containing the hex-encoded secp256k1 key + GasPrice float64 `yaml:"gas_price"` // 0 means unset; callers must provide gas_price per request + MaxGasPrice float64 `yaml:"max_gas_price"` // 0 disables the max gas price cap + ConfirmationTimeout int `yaml:"confirmation_timeout"` // seconds +} + // DefaultConfig returns a Config with sensible defaults. func DefaultConfig() Config { return Config{ @@ -120,6 +134,15 @@ func DefaultConfig() Config { BufferSize: 64, MaxSubscribers: 1024, }, + Submission: SubmissionConfig{ + Enabled: false, + CelestiaAppGRPCAddr: "", + ChainID: "", + SignerKey: "", + GasPrice: 0, + MaxGasPrice: 0, + ConfirmationTimeout: 30, + }, Metrics: MetricsConfig{ Enabled: true, ListenAddr: ":9091", @@ -143,6 +166,9 @@ func (c *Config) ParsedNamespaces() ([]types.Namespace, error) { if err != nil { return nil, fmt.Errorf("invalid namespace %q: %w", hex, err) } + if err := ns.ValidateForBlob(); err != nil { + return nil, fmt.Errorf("invalid namespace %q: %w", hex, err) + } namespaces = append(namespaces, ns) } return namespaces, nil diff --git a/config/load.go b/config/load.go index b449975..ca90809 100644 --- a/config/load.go +++ b/config/load.go @@ -5,6 +5,8 @@ import ( "errors" "fmt" "os" + "path/filepath" + "strings" "github.com/evstack/apex/pkg/types" "gopkg.in/yaml.v3" @@ -40,6 +42,8 @@ data_source: # Celestia-app Cosmos SDK gRPC endpoint (required when type: "app") # celestia_app_grpc_addr: "localhost:9090" + # Set true only when a non-loopback celestia-app endpoint is intentionally plaintext. + # celestia_app_grpc_insecure: false # Backfill source in app mode: "rpc" (default) or "db" (direct blockstore read) backfill_source: "rpc" @@ -57,6 +61,25 @@ data_source: # Namespaces to index (hex-encoded, 29 bytes = 58 hex chars each). namespaces: [] +submission: + # Enable direct blob submission (updates in development). + enabled: false + # Cosmos SDK gRPC endpoint for celestia-app submission. + app_grpc_addr: "" + # Set true only when a non-loopback celestia-app endpoint is intentionally plaintext. + app_grpc_insecure: false + # Chain ID that will be used when signing transactions. + chain_id: "" + # Path to a file containing the hex-encoded secp256k1 signing key. + signer_key: "/path/to/apex-submission.key" + # Default gas price to pay per unit when the request does not override it. + # Zero means "unset"; submission requests must then provide gas_price explicitly. + gas_price: 0 + # Maximum gas price that can be spent for a submission. Zero disables the cap. + max_gas_price: 0 + # Seconds to wait for transaction confirmation before timing out. + confirmation_timeout: 30 + storage: # Storage backend: "sqlite" (default) or "s3" type: "sqlite" @@ -139,15 +162,25 @@ func Load(path string) (*Config, error) { if token := os.Getenv("APEX_AUTH_TOKEN"); token != "" { cfg.DataSource.AuthToken = token } - if err := validate(&cfg); err != nil { return nil, fmt.Errorf("validating config: %w", err) } + if err := resolveSubmissionSignerKeyPath(&cfg.Submission, filepath.Dir(path)); err != nil { + return nil, fmt.Errorf("resolving submission signer key path: %w", err) + } return &cfg, nil } func validateDataSource(ds *DataSourceConfig) error { + ds.Type = strings.TrimSpace(ds.Type) + ds.CelestiaNodeURL = strings.TrimSpace(ds.CelestiaNodeURL) + ds.CelestiaAppGRPCAddr = strings.TrimSpace(ds.CelestiaAppGRPCAddr) + ds.BackfillSource = strings.TrimSpace(ds.BackfillSource) + ds.CelestiaAppDBPath = strings.TrimSpace(ds.CelestiaAppDBPath) + ds.CelestiaAppDBBackend = strings.TrimSpace(ds.CelestiaAppDBBackend) + ds.CelestiaAppDBLayout = strings.TrimSpace(ds.CelestiaAppDBLayout) + switch ds.Type { case "node", "": if ds.CelestiaNodeURL == "" { @@ -188,8 +221,16 @@ func validateDataSource(ds *DataSourceConfig) error { default: return fmt.Errorf("data_source.type %q is invalid; must be \"node\" or \"app\"", ds.Type) } - for _, ns := range ds.Namespaces { - if _, err := types.NamespaceFromHex(ns); err != nil { + return validateNamespaces(ds.Namespaces) +} + +func validateNamespaces(namespaces []string) error { + for _, ns := range namespaces { + parsed, err := types.NamespaceFromHex(ns) + if err != nil { + return fmt.Errorf("invalid namespace %q: %w", ns, err) + } + if err := parsed.ValidateForBlob(); err != nil { return fmt.Errorf("invalid namespace %q: %w", ns, err) } } @@ -246,6 +287,9 @@ func validate(cfg *Config) error { if err := validateProfiling(&cfg.Profiling); err != nil { return err } + if err := validateSubmission(&cfg.Submission); err != nil { + return err + } if !validLogLevels[cfg.Log.Level] { return fmt.Errorf("log.level %q is invalid; must be one of trace/debug/info/warn/error/fatal/panic", cfg.Log.Level) } @@ -305,3 +349,61 @@ func validateProfiling(p *ProfilingConfig) error { } return nil } + +func validateSubmission(s *SubmissionConfig) error { + if !s.Enabled { + return nil + } + s.CelestiaAppGRPCAddr = strings.TrimSpace(s.CelestiaAppGRPCAddr) + s.ChainID = strings.TrimSpace(s.ChainID) + s.SignerKey = strings.TrimSpace(s.SignerKey) + if s.CelestiaAppGRPCAddr == "" { + return errors.New("submission.app_grpc_addr is required when submission.enabled is true") + } + if s.ChainID == "" { + return errors.New("submission.chain_id is required when submission.enabled is true") + } + if s.SignerKey == "" { + return errors.New("submission.signer_key is required when submission.enabled is true") + } + if s.ConfirmationTimeout <= 0 { + return errors.New("submission.confirmation_timeout must be positive") + } + if s.GasPrice < 0 { + return errors.New("submission.gas_price must be non-negative") + } + if s.MaxGasPrice < 0 { + return errors.New("submission.max_gas_price must be non-negative") + } + if s.MaxGasPrice > 0 && s.GasPrice > s.MaxGasPrice { + return errors.New("submission.gas_price must not exceed submission.max_gas_price") + } + return nil +} + +func resolveSubmissionSignerKeyPath(s *SubmissionConfig, baseDir string) error { + if !s.Enabled { + return nil + } + keyPath := strings.TrimSpace(s.SignerKey) + s.SignerKey = keyPath + if keyPath == "" { + return nil + } + + if !filepath.IsAbs(keyPath) { + keyPath = filepath.Join(baseDir, keyPath) + } + keyPath = filepath.Clean(keyPath) + + info, err := os.Stat(keyPath) + if err != nil { + return fmt.Errorf("stat submission signer key %q: %w", keyPath, err) + } + if info.IsDir() { + return fmt.Errorf("submission signer key %q must be a file", keyPath) + } + + s.SignerKey = keyPath + return nil +} diff --git a/config/load_test.go b/config/load_test.go index 11e965e..9dad243 100644 --- a/config/load_test.go +++ b/config/load_test.go @@ -109,3 +109,224 @@ log: t.Fatalf("unexpected error: %v", err) } } + +func TestLoadRejectsReservedNamespace(t *testing.T) { + t.Parallel() + + dir := t.TempDir() + path := filepath.Join(dir, "config.yaml") + content := ` +data_source: + type: "node" + celestia_node_url: "http://localhost:26658" + namespaces: + - "0000000000000000000000000000000000000000000000000000000001" + +storage: + type: "sqlite" + db_path: "apex.db" + +rpc: + listen_addr: ":8080" + grpc_listen_addr: ":9090" + +sync: + start_height: 1 + batch_size: 64 + concurrency: 4 + +subscription: + buffer_size: 64 + +metrics: + enabled: true + listen_addr: ":9091" + +profiling: + enabled: false + listen_addr: "127.0.0.1:6061" + +log: + level: "info" + format: "json" +` + if err := os.WriteFile(path, []byte(content), 0o644); err != nil { + t.Fatalf("WriteFile: %v", err) + } + + _, err := Load(path) + if err == nil { + t.Fatal("expected validation error, got nil") + } + if !strings.Contains(err.Error(), "reserved") { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestSubmissionValidationRejectsIncompleteConfig(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + yaml string + wantError string + }{ + { + name: "missing app_grpc_addr", + yaml: ` +submission: + enabled: true + app_grpc_addr: "" + chain_id: "mychain" +`, + wantError: "submission.app_grpc_addr is required", + }, + { + name: "whitespace app_grpc_addr", + yaml: ` +submission: + enabled: true + app_grpc_addr: " " + chain_id: "mychain" + signer_key: "signer.key" +`, + wantError: "submission.app_grpc_addr is required", + }, + { + name: "missing chain_id", + yaml: ` +submission: + enabled: true + app_grpc_addr: "localhost:9090" + chain_id: "" +`, + wantError: "submission.chain_id is required", + }, + { + name: "whitespace chain_id", + yaml: ` +submission: + enabled: true + app_grpc_addr: "localhost:9090" + chain_id: " " + signer_key: "signer.key" +`, + wantError: "submission.chain_id is required", + }, + { + name: "missing signer_key", + yaml: ` +submission: + enabled: true + app_grpc_addr: "localhost:9090" + chain_id: "mychain" + signer_key: "" +`, + wantError: "submission.signer_key is required", + }, + { + name: "whitespace signer_key", + yaml: ` +submission: + enabled: true + app_grpc_addr: "localhost:9090" + chain_id: "mychain" + signer_key: " " +`, + wantError: "submission.signer_key is required", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + dir := t.TempDir() + path := filepath.Join(dir, "config.yaml") + content := tt.yaml + ` +log: + level: "info" + format: "json" +` + if err := os.WriteFile(path, []byte(content), 0o644); err != nil { + t.Fatalf("WriteFile: %v", err) + } + + _, err := Load(path) + if err == nil { + t.Fatal("expected validation error, got nil") + } + if !strings.Contains(err.Error(), tt.wantError) { + t.Fatalf("error = %v, want substring %q", err, tt.wantError) + } + }) + } +} + +func TestSubmissionLoadsSignerKeyFromFile(t *testing.T) { + t.Parallel() + + dir := t.TempDir() + keyPath := filepath.Join(dir, "submit.key") + if err := os.WriteFile(keyPath, []byte("00112233\n"), 0o600); err != nil { + t.Fatalf("WriteFile: %v", err) + } + path := filepath.Join(dir, "config.yaml") + content := ` +submission: + enabled: true + app_grpc_addr: " localhost:9090 " + chain_id: " mychain " + signer_key: " submit.key " + +log: + level: "info" + format: "json" +` + if err := os.WriteFile(path, []byte(content), 0o644); err != nil { + t.Fatalf("WriteFile: %v", err) + } + + cfg, err := Load(path) + if err != nil { + t.Fatalf("Load: %v", err) + } + if cfg.Submission.SignerKey != keyPath { + t.Fatalf("signer key path = %q, want %q", cfg.Submission.SignerKey, keyPath) + } + if cfg.Submission.CelestiaAppGRPCAddr != "localhost:9090" { + t.Fatalf("app grpc addr = %q, want %q", cfg.Submission.CelestiaAppGRPCAddr, "localhost:9090") + } + if cfg.Submission.ChainID != "mychain" { + t.Fatalf("chain id = %q, want %q", cfg.Submission.ChainID, "mychain") + } +} + +func TestSubmissionRejectsMissingSignerKeyFile(t *testing.T) { + t.Parallel() + + dir := t.TempDir() + path := filepath.Join(dir, "config.yaml") + content := ` +submission: + enabled: true + app_grpc_addr: "localhost:9090" + chain_id: "mychain" + signer_key: "missing.key" + +log: + level: "info" + format: "json" +` + if err := os.WriteFile(path, []byte(content), 0o644); err != nil { + t.Fatalf("WriteFile: %v", err) + } + + _, err := Load(path) + if err == nil { + t.Fatal("expected missing signer key file error, got nil") + } + if !strings.Contains(err.Error(), "submission signer key") { + t.Fatalf("unexpected error: %v", err) + } +} diff --git a/docs/running.md b/docs/running.md index 153de64..2a7c8b8 100644 --- a/docs/running.md +++ b/docs/running.md @@ -64,6 +64,12 @@ data_source: celestia_app_grpc_addr: "localhost:9090" # required when type: app namespaces: [] # hex-encoded, 29 bytes each +submission: + enabled: false # enable direct blob submission + app_grpc_addr: "localhost:9090" # celestia-app gRPC endpoint for submission + chain_id: "mocha-4" # chain ID used when signing transactions + signer_key: "/path/to/apex-submission.key" # file containing the hex-encoded secp256k1 key + storage: db_path: "apex.db" # SQLite database path diff --git a/e2e/go.mod b/e2e/go.mod new file mode 100644 index 0000000..fdf6300 --- /dev/null +++ b/e2e/go.mod @@ -0,0 +1,249 @@ +module github.com/evstack/apex/e2e + +go 1.25.6 + +replace ( + cosmossdk.io/x/upgrade => github.com/celestiaorg/cosmos-sdk/x/upgrade v0.1.0 + github.com/ChainSafe/go-schnorrkel => github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d + github.com/ChainSafe/go-schnorrkel/1 => github.com/ChainSafe/go-schnorrkel v1.0.0 + github.com/btcsuite/btcd/btcec/v2 => github.com/btcsuite/btcd/btcec/v2 v2.3.3 + github.com/cometbft/cometbft => github.com/celestiaorg/celestia-core v0.39.4 + github.com/cosmos/cosmos-sdk => github.com/celestiaorg/cosmos-sdk v0.51.2 + github.com/evstack/apex => .. + github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2 +) + +require ( + github.com/celestiaorg/go-square/merkle v0.0.0-20240627094109-7d01436067a3 + github.com/celestiaorg/go-square/v3 v3.0.2 + github.com/celestiaorg/tastora v0.16.0 + github.com/cosmos/cosmos-sdk v0.50.12 + github.com/cosmos/ibc-go/v8 v8.7.0 + github.com/evstack/apex v0.0.0-00010101000000-000000000000 +) + +require ( + cosmossdk.io/api v0.7.6 // indirect + cosmossdk.io/collections v0.4.0 // indirect + cosmossdk.io/core v0.11.1 // indirect + cosmossdk.io/depinject v1.1.0 // indirect + cosmossdk.io/errors v1.0.2 // indirect + cosmossdk.io/log v1.6.0 // indirect + cosmossdk.io/math v1.5.1 // indirect + cosmossdk.io/store v1.1.2 // indirect + cosmossdk.io/x/tx v0.13.8 // indirect + cosmossdk.io/x/upgrade v0.1.4 // indirect + filippo.io/edwards25519 v1.1.0 // indirect + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/99designs/keyring v1.2.2 // indirect + github.com/BurntSushi/toml v1.5.0 // indirect + github.com/DataDog/datadog-go v4.8.3+incompatible // indirect + github.com/DataDog/zstd v1.5.6 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/avast/retry-go/v4 v4.6.1 // indirect + github.com/aws/aws-sdk-go-v2 v1.41.1 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect + github.com/aws/aws-sdk-go-v2/config v1.32.9 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.9 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.17 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.8 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.17 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.96.0 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.10 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.14 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 // indirect + github.com/aws/smithy-go v1.24.0 // indirect + github.com/bcp-innovations/hyperlane-cosmos v1.0.1 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/speakeasy v0.2.0 // indirect + github.com/bits-and-blooms/bitset v1.20.0 // indirect + github.com/bytedance/gopkg v0.1.3 // indirect + github.com/bytedance/sonic v1.15.0 // indirect + github.com/bytedance/sonic/loader v0.5.0 // indirect + github.com/celestiaorg/nmt v0.24.2 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chzyer/readline v1.5.1 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/cockroachdb/apd/v3 v3.2.1 // indirect + github.com/cockroachdb/errors v1.11.3 // indirect + github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 // indirect + github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506 // indirect + github.com/cockroachdb/pebble v1.1.5 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/cometbft/cometbft v0.38.17 // indirect + github.com/cometbft/cometbft-db v1.0.4 // indirect + github.com/consensys/gnark-crypto v0.18.1 // indirect + github.com/containerd/errdefs v1.0.0 // indirect + github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/cosmos-db v1.1.1 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/gogogateway v1.2.0 // indirect + github.com/cosmos/gogoproto v1.7.0 // indirect + github.com/cosmos/iavl v1.2.6 // indirect + github.com/cosmos/ibc-go/modules/capability v1.0.1 // indirect + github.com/cosmos/ics23/go v0.11.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.15.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/danieljoos/wincred v1.2.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect + github.com/desertbit/timer v1.0.1 // indirect + github.com/dgraph-io/badger/v4 v4.5.1 // indirect + github.com/dgraph-io/ristretto/v2 v2.1.0 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v28.3.3+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/dvsekhvalnov/jose2go v1.7.0 // indirect + github.com/emicklei/dot v1.6.2 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect + github.com/ethereum/go-ethereum v1.16.3 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/fatih/color v1.18.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect + github.com/getsentry/sentry-go v0.31.1 // indirect + github.com/go-kit/kit v0.13.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gogo/googleapis v1.4.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/flatbuffers v25.1.24+incompatible // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/orderedcode v0.0.1 // indirect + github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/handlers v1.5.2 // indirect + github.com/gorilla/mux v1.8.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grafana/otel-profiling-go v0.5.1 // indirect + github.com/grafana/pyroscope-go v1.2.4 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-metrics v0.5.4 // indirect + github.com/hashicorp/go-plugin v1.6.3 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/hashicorp/yamux v0.1.2 // indirect + github.com/hdevalence/ed25519consensus v0.2.0 // indirect + github.com/holiman/uint256 v1.3.2 // indirect + github.com/huandu/skiplist v1.2.1 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + github.com/improbable-eng/grpc-web v0.15.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/cpuid/v2 v2.2.10 // indirect + github.com/klauspost/reedsolomon v1.12.5 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/linxGnu/grocksdb v1.9.8 // indirect + github.com/manifoldco/promptui v0.9.0 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/minio/highwayhash v1.0.3 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/moby v27.5.1+incompatible // indirect + github.com/moby/sys/sequential v0.6.0 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect + github.com/oklog/run v1.1.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.66.1 // indirect + github.com/prometheus/procfs v0.16.1 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/rs/cors v1.11.1 // indirect + github.com/rs/zerolog v1.34.0 // indirect + github.com/sagikazarmark/locafero v0.7.0 // indirect + github.com/sasha-s/go-deadlock v0.3.5 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/cast v1.7.1 // indirect + github.com/spf13/cobra v1.10.2 // indirect + github.com/spf13/pflag v1.0.9 // indirect + github.com/spf13/viper v1.20.0 // indirect + github.com/stretchr/testify v1.11.1 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/supranational/blst v0.3.14 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tidwall/btree v1.7.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v1.0.0 // indirect + go.etcd.io/bbolt v1.4.0 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect + go.opentelemetry.io/otel v1.42.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 // indirect + go.opentelemetry.io/otel/metric v1.42.0 // indirect + go.opentelemetry.io/otel/sdk v1.42.0 // indirect + go.opentelemetry.io/otel/trace v1.42.0 // indirect + go.opentelemetry.io/proto/otlp v1.9.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect + golang.org/x/arch v0.15.0 // indirect + golang.org/x/crypto v0.46.0 // indirect + golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect + golang.org/x/net v0.48.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/term v0.38.0 // indirect + golang.org/x/text v0.32.0 // indirect + google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d // indirect + google.golang.org/grpc v1.79.1 // indirect + google.golang.org/protobuf v1.36.11 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.2 // indirect + nhooyr.io/websocket v1.8.17 // indirect + pgregory.net/rapid v1.2.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect +) diff --git a/e2e/go.sum b/e2e/go.sum new file mode 100644 index 0000000..61e5bdd --- /dev/null +++ b/e2e/go.sum @@ -0,0 +1,1311 @@ +cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= +cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= +cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= +cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs= +cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q= +cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= +cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= +cloud.google.com/go/compute v1.29.0 h1:Lph6d8oPi38NHkOr6S55Nus/Pbbcp37m/J0ohgKAefs= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA= +cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= +cloud.google.com/go/monitoring v1.21.2 h1:FChwVtClH19E7pJ+e0xUhJPGksctZNVOk2UhMmblmdU= +cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU= +cloud.google.com/go/storage v1.49.0 h1:zenOPBOWHCnojRd9aJZAyQXBYqkJkdQS42dxL55CIMw= +cloud.google.com/go/storage v1.49.0/go.mod h1:k1eHhhpLvrPjVGfo0mOUPEJ4Y2+a/Hv5PiwehZI9qGU= +cosmossdk.io/api v0.7.6 h1:PC20PcXy1xYKH2KU4RMurVoFjjKkCgYRbVAD4PdqUuY= +cosmossdk.io/api v0.7.6/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/client/v2 v2.0.0-beta.8 h1:RXMJdA4V9H1H3/3BfMD6dAW3lF8W9DpNPPYnKD+ArxY= +cosmossdk.io/client/v2 v2.0.0-beta.8/go.mod h1:x+E2eji+ToMtUIqKzoJ5mJIhat+Zak47xZ8jOYjJQBA= +cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= +cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= +cosmossdk.io/core v0.11.1 h1:h9WfBey7NAiFfIcUhDVNS503I2P2HdZLebJlUIs8LPA= +cosmossdk.io/core v0.11.1/go.mod h1:OJzxcdC+RPrgGF8NJZR2uoQr56tc7gfBKhiKeDO7hH0= +cosmossdk.io/depinject v1.1.0 h1:wLan7LG35VM7Yo6ov0jId3RHWCGRhe8E8bsuARorl5E= +cosmossdk.io/depinject v1.1.0/go.mod h1:kkI5H9jCGHeKeYWXTqYdruogYrEeWvBQCw1Pj4/eCFI= +cosmossdk.io/errors v1.0.2 h1:wcYiJz08HThbWxd/L4jObeLaLySopyyuUFB5w4AGpCo= +cosmossdk.io/errors v1.0.2/go.mod h1:0rjgiHkftRYPj//3DrD6y8hcm40HcPv/dR4R/4efr0k= +cosmossdk.io/log v1.6.0 h1:SJIOmJ059wi1piyRgNRXKXhlDXGqnB5eQwhcZKv2tOk= +cosmossdk.io/log v1.6.0/go.mod h1:5cXXBvfBkR2/BcXmosdCSLXllvgSjphrrDVdfVRmBGM= +cosmossdk.io/math v1.5.1 h1:c6zo52nBRlqOeSIIQrn/zbxwcNwhaLjTMRn6e4vD7uc= +cosmossdk.io/math v1.5.1/go.mod h1:ToembcWID/wR94cucsMD+2gq6xrlBBOfWcGwC7ZdwZA= +cosmossdk.io/store v1.1.2 h1:3HOZG8+CuThREKv6cn3WSohAc6yccxO3hLzwK6rBC7o= +cosmossdk.io/store v1.1.2/go.mod h1:60rAGzTHevGm592kFhiUVkNC9w7gooSEn5iUBPzHQ6A= +cosmossdk.io/x/circuit v0.1.1 h1:KPJCnLChWrxD4jLwUiuQaf5mFD/1m7Omyo7oooefBVQ= +cosmossdk.io/x/circuit v0.1.1/go.mod h1:B6f/urRuQH8gjt4eLIXfZJucrbreuYrKh5CSjaOxr+Q= +cosmossdk.io/x/evidence v0.1.1 h1:Ks+BLTa3uftFpElLTDp9L76t2b58htjVbSZ86aoK/E4= +cosmossdk.io/x/evidence v0.1.1/go.mod h1:OoDsWlbtuyqS70LY51aX8FBTvguQqvFrt78qL7UzeNc= +cosmossdk.io/x/feegrant v0.1.1 h1:EKFWOeo/pup0yF0svDisWWKAA9Zags6Zd0P3nRvVvw8= +cosmossdk.io/x/feegrant v0.1.1/go.mod h1:2GjVVxX6G2fta8LWj7pC/ytHjryA6MHAJroBWHFNiEQ= +cosmossdk.io/x/tx v0.13.8 h1:dQwC8jMe7awx/edi1HPPZ40AjHnsix6KSO/jbKMUYKk= +cosmossdk.io/x/tx v0.13.8/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= +github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= +github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= +github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY= +github.com/DataDog/zstd v1.5.6/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 h1:8nn+rsCvTq9axyEh382S0PFLBeaFwNsT43IrPWzctRU= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1/go.mod h1:viRWSEhtMZqz1rhwmOVKkWl6SwmVowfL9O2YR5gI2PE= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= +github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= +github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/adlio/schema v1.3.9 h1:MLYk1VX1dn7xHW7Kdm1ywKKLjh19DRnrc65axS5xQA8= +github.com/adlio/schema v1.3.9/go.mod h1:GnxXztHzNh6pIc7qm3sw+jsmHrXgBy/x2RBSkKZ3L4w= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/avast/retry-go/v4 v4.6.1 h1:VkOLRubHdisGrHnTu89g08aQEWEgRU7LVEop3GbIcMk= +github.com/avast/retry-go/v4 v4.6.1/go.mod h1:V6oF8njAwxJ5gRo1Q7Cxab24xs5NCWZBeaHHBklR8mA= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= +github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/aws/aws-sdk-go-v2 v1.41.1 h1:ABlyEARCDLN034NhxlRUSZr4l71mh+T5KAeGh6cerhU= +github.com/aws/aws-sdk-go-v2 v1.41.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 h1:489krEF9xIGkOaaX3CE/Be2uWjiXrkCH6gUX+bZA/BU= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4/go.mod h1:IOAPF6oT9KCsceNTvvYMNHy0+kMF8akOjeDvPENWxp4= +github.com/aws/aws-sdk-go-v2/config v1.32.9 h1:ktda/mtAydeObvJXlHzyGpK1xcsLaP16zfUPDGoW90A= +github.com/aws/aws-sdk-go-v2/config v1.32.9/go.mod h1:U+fCQ+9QKsLW786BCfEjYRj34VVTbPdsLP3CHSYXMOI= +github.com/aws/aws-sdk-go-v2/credentials v1.19.9 h1:sWvTKsyrMlJGEuj/WgrwilpoJ6Xa1+KhIpGdzw7mMU8= +github.com/aws/aws-sdk-go-v2/credentials v1.19.9/go.mod h1:+J44MBhmfVY/lETFiKI+klz0Vym2aCmIjqgClMmW82w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 h1:I0GyV8wiYrP8XpA70g1HBcQO1JlQxCMTW9npl5UbDHY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17/go.mod h1:tyw7BOl5bBe/oqvoIeECFJjMdzXoa/dfVz3QQ5lgHGA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 h1:xOLELNKGp2vsiteLsvLPwxC+mYmO6OZ8PYgiuPJzF8U= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17/go.mod h1:5M5CI3D12dNOtH3/mk6minaRwI2/37ifCURZISxA/IQ= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 h1:WWLqlh79iO48yLkj1v3ISRNiv+3KdQoZ6JWyfcsyQik= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17/go.mod h1:EhG22vHRrvF8oXSTYStZhJc1aUgKtnJe+aOiFEV90cM= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.17 h1:JqcdRG//czea7Ppjb+g/n4o8i/R50aTBHkA7vu0lK+k= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.17/go.mod h1:CO+WeGmIdj/MlPel2KwID9Gt7CNq4M65HUfBW97liM0= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.8 h1:Z5EiPIzXKewUQK0QTMkutjiaPVeVYXX7KIqhXu/0fXs= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.8/go.mod h1:FsTpJtvC4U1fyDXk7c71XoDv3HlRm8V3NiYLeYLh5YE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 h1:RuNSMoozM8oXlgLG/n6WLaFGoea7/CddrCfIiSA+xdY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17/go.mod h1:F2xxQ9TZz5gDWsclCtPQscGpP0VUOc8RqgFM3vDENmU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.17 h1:bGeHBsGZx0Dvu/eJC0Lh9adJa3M1xREcndxLNZlve2U= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.17/go.mod h1:dcW24lbU0CzHusTE8LLHhRLI42ejmINN8Lcr22bwh/g= +github.com/aws/aws-sdk-go-v2/service/s3 v1.96.0 h1:oeu8VPlOre74lBA/PMhxa5vewaMIMmILM+RraSyB8KA= +github.com/aws/aws-sdk-go-v2/service/s3 v1.96.0/go.mod h1:5jggDlZ2CLQhwJBiZJb4vfk4f0GxWdEDruWKEJ1xOdo= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 h1:VrhDvQib/i0lxvr3zqlUwLwJP4fpmpyD9wYG1vfSu+Y= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.5/go.mod h1:k029+U8SY30/3/ras4G/Fnv/b88N4mAfliNn08Dem4M= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.10 h1:+VTRawC4iVY58pS/lzpo0lnoa/SYNGF4/B/3/U5ro8Y= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.10/go.mod h1:yifAsgBxgJWn3ggx70A3urX2AN49Y5sJTD1UQFlfqBw= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.14 h1:0jbJeuEHlwKJ9PfXtpSFc4MF+WIWORdhN1n30ITZGFM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.14/go.mod h1:sTGThjphYE4Ohw8vJiRStAcu3rbjtXRsdNB0TvZ5wwo= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 h1:5fFjR/ToSOzB2OQ/XqWpZBmNvmP/pJ1jOWYlFDJTjRQ= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.6/go.mod h1:qgFDZQSD/Kys7nJnVqYlWKnh0SSdMjAi0uSwON4wgYQ= +github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= +github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= +github.com/bcp-innovations/hyperlane-cosmos v1.0.1 h1:gT8OqyJ866Q6AHOlIXKxSdLjd0p8crKG9XXERIWoh4c= +github.com/bcp-innovations/hyperlane-cosmos v1.0.1/go.mod h1:3yfa0io5Ii6GmhHWsWl2LEAOEHsqWuMgw2R02+LPogw= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +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/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E= +github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU= +github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0= +github.com/btcsuite/btcd/btcec/v2 v2.3.3/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= +github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= +github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= +github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= +github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= +github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= +github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= +github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE= +github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/celestiaorg/celestia-core v0.39.4 h1:h0WaG8KsP0JyiAVhHipoIgvBP0CYLG/9whUccy1lDlY= +github.com/celestiaorg/celestia-core v0.39.4/go.mod h1:t7cSYwLFmpz5RjIBpC3QjpbRoa+RfQ0ULdh+LciKuq8= +github.com/celestiaorg/cosmos-sdk v0.51.2 h1:a9WguK7BaeuqCVnOa3m3ThwXKBL/RxQ46gRz+TP4yKQ= +github.com/celestiaorg/cosmos-sdk v0.51.2/go.mod h1:KSCi5EM7aWwZRtCHCOH4K51a9OcjEKt4i/pr1txrnRA= +github.com/celestiaorg/cosmos-sdk/x/upgrade v0.1.0 h1:+i3G5mP/kPgFEn83EEXGly29QDin2Gvdt0kgpmw/vTg= +github.com/celestiaorg/cosmos-sdk/x/upgrade v0.1.0/go.mod h1:T4K9O18zQNKNpt4YvTL3lcUt4aKOEU05ZIFWVdQi3Ak= +github.com/celestiaorg/go-square/merkle v0.0.0-20240627094109-7d01436067a3 h1:wP84mtwOCVNOTfS3zErICjxKLnh74Z1uf+tdrlSFjVM= +github.com/celestiaorg/go-square/merkle v0.0.0-20240627094109-7d01436067a3/go.mod h1:86qIYnEhmn/hfW+xvw98NOI3zGaDEB3x8JGjYo2FqLs= +github.com/celestiaorg/go-square/v3 v3.0.2 h1:eSQOgNII8inK9IhiBZ+6GADQeWbRq4HYY72BOgcduA4= +github.com/celestiaorg/go-square/v3 v3.0.2/go.mod h1:oFReMLsSDMRs82ICFEeFQFCqNvwdsbIM1BzCcb0f7dM= +github.com/celestiaorg/nmt v0.24.2 h1:LlpJSPOd6/Lw1Ig6HUhZuqiINHLka/ZSRTBzlNJpchg= +github.com/celestiaorg/nmt v0.24.2/go.mod h1:vgLBpWBi8F5KLxTdXSwb7AU4NhiIQ1AQRGa+PzdcLEA= +github.com/celestiaorg/tastora v0.16.0 h1:V4ctGcvVR8thy4ulvrHagrTfdNfuCHOTsCYoKVRQ75U= +github.com/celestiaorg/tastora v0.16.0/go.mod h1:C867PBm6Ne6e/1JlmsRqcLeJ6RHAuMoMRCvwJzV/q8g= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= +github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= +github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= +github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= +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/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 h1:pU88SPhIFid6/k0egdR5V6eALQYq2qbSmukrkgIh/0A= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506 h1:ASDL+UJcILMqgNeV5jiqR4j+sTuvQNHdf2chuKj1M5k= +github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506/go.mod h1:Mw7HqKr2kdtu6aYGn3tPmAftiP3QPX63LdK/zcariIo= +github.com/cockroachdb/pebble v1.1.5 h1:5AAWCBWbat0uE0blr8qzufZP5tBjkRyy/jWe1QWLnvw= +github.com/cockroachdb/pebble v1.1.5/go.mod h1:17wO9el1YEigxkP/YtV8NtCivQDgoCyBg5c4VR/eOWo= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/cometbft/cometbft-db v1.0.4 h1:cezb8yx/ZWcF124wqUtAFjAuDksS1y1yXedvtprUFxs= +github.com/cometbft/cometbft-db v1.0.4/go.mod h1:M+BtHAGU2XLrpUxo3Nn1nOCcnVCiLM9yx5OuT0u5SCA= +github.com/consensys/gnark-crypto v0.18.1 h1:RyLV6UhPRoYYzaFnPQA4qK3DyuDgkTgskDdoGqFt3fI= +github.com/consensys/gnark-crypto v0.18.1/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= +github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= +github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= +github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= +github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= +github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNCM= +github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= +github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= +github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= +github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= +github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= +github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= +github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= +github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= +github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= +github.com/cosmos/iavl v1.2.6 h1:Hs3LndJbkIB+rEvToKJFXZvKo6Vy0Ex1SJ54hhtioIs= +github.com/cosmos/iavl v1.2.6/go.mod h1:GiM43q0pB+uG53mLxLDzimxM9l/5N9UuSY3/D0huuVw= +github.com/cosmos/ibc-go/modules/capability v1.0.1 h1:ibwhrpJ3SftEEZRxCRkH0fQZ9svjthrX2+oXdZvzgGI= +github.com/cosmos/ibc-go/modules/capability v1.0.1/go.mod h1:rquyOV262nGJplkumH+/LeYs04P3eV8oB7ZM4Ygqk4E= +github.com/cosmos/ibc-go/v8 v8.7.0 h1:HqhVOkO8bDpClXE81DFQgFjroQcTvtpm0tCS7SQVKVY= +github.com/cosmos/ibc-go/v8 v8.7.0/go.mod h1:G2z+Q6ZQSMcyHI2+BVcJdvfOupb09M2h/tgpXOEdY6k= +github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= +github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= +github.com/cosmos/ledger-cosmos-go v0.15.0 h1:xmizkkEX19tyFLVL6PPMQNg21Jc9W9/bpbwxMDdtxXg= +github.com/cosmos/ledger-cosmos-go v0.15.0/go.mod h1:KJqW5U4/MMl8ICPO4WPjIAyC4TfYRnr28d9N9bBUKWc= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/crate-crypto/go-eth-kzg v1.3.0 h1:05GrhASN9kDAidaFJOda6A4BEvgvuXbazXg/0E3OOdI= +github.com/crate-crypto/go-eth-kzg v1.3.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= +github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA= +github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc= +github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= +github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= +github.com/desertbit/timer v1.0.1 h1:yRpYNn5Vaaj6QXecdLMPMJsW81JLiI1eokUft5nBmeo= +github.com/desertbit/timer v1.0.1/go.mod h1:htRrYeY5V/t4iu1xCJ5XsQvp4xve8QulXXctAzxqcwE= +github.com/dgraph-io/badger/v4 v4.5.1 h1:7DCIXrQjo1LKmM96YD+hLVJ2EEsyyoWxJfpdd56HLps= +github.com/dgraph-io/badger/v4 v4.5.1/go.mod h1:qn3Be0j3TfV4kPbVoK0arXCD1/nr1ftth6sbL5jxdoA= +github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I= +github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI= +github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +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 v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/dvsekhvalnov/jose2go v1.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9TzqvtQZPo= +github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= +github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= +github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= +github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= +github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= +github.com/ethereum/c-kzg-4844/v2 v2.1.0 h1:gQropX9YFBhl3g4HYhwE70zq3IHFRgbbNPw0Shwzf5w= +github.com/ethereum/c-kzg-4844/v2 v2.1.0/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E= +github.com/ethereum/go-ethereum v1.16.3 h1:nDoBSrmsrPbrDIVLTkDQCy1U9KdHN+F2PzvMbDoS42Q= +github.com/ethereum/go-ethereum v1.16.3/go.mod h1:Lrsc6bt9Gm9RyvhfFK53vboCia8kpF9nv+2Ukntnl+8= +github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= +github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY= +github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/getsentry/sentry-go v0.31.1 h1:ELVc0h7gwyhnXHDouXkhqTFSO5oslsRDk0++eyE0KJ4= +github.com/getsentry/sentry-go v0.31.1/go.mod h1:CYNcMMz73YigoHljQRG+qPF+eMq8gG72XcGN/p71BAY= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= +github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= +github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +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.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v25.1.24+incompatible h1:4wPqL3K7GzBd1CwyhSd3usxLKOaJN/AC6puCca6Jm7o= +github.com/google/flatbuffers v25.1.24+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +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.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/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.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= +github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= +github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8= +github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls= +github.com/grafana/pyroscope-go v1.2.4 h1:B22GMXz+O0nWLatxLuaP7o7L9dvP0clLvIpmeEQQM0Q= +github.com/grafana/pyroscope-go v1.2.4/go.mod h1:zzT9QXQAp2Iz2ZdS216UiV8y9uXJYQiGE1q8v1FyhqU= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-getter v1.7.9 h1:G9gcjrDixz7glqJ+ll5IWvggSBR+R0B54DSRt4qfdC4= +github.com/hashicorp/go-getter v1.7.9/go.mod h1:dyFCmT1AQkDfOIt9NH8pw9XBDqNrIKJT5ylbpi7zPNE= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-metrics v0.5.4 h1:8mmPiIJkTPPEbAiV97IxdAGNdRdaWwVap1BU6elejKY= +github.com/hashicorp/go-metrics v0.5.4/go.mod h1:CG5yz4NZ/AI/aQt9Ucm/vdBnbh7fvmv4lxZ350i+QQI= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg= +github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= +github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= +github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= +github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= +github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= +github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= +github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= +github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= +github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +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/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/klauspost/reedsolomon v1.12.5 h1:4cJuyH926If33BeDgiZpI5OU0pE+wUHZvMSyNGqN73Y= +github.com/klauspost/reedsolomon v1.12.5/go.mod h1:LkXRjLYGM8K/iQfujYnaPeDmhZLqkrGUyG9p7zs5L68= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +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/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/linxGnu/grocksdb v1.9.8 h1:vOIKv9/+HKiqJAElJIEYv3ZLcihRxyP7Suu/Mu8Dxjs= +github.com/linxGnu/grocksdb v1.9.8/go.mod h1:C3CNe9UYc9hlEM2pC82AqiGS3LRW537u9LFV4wIZuHk= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= +github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= +github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= +github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/moby v27.5.1+incompatible h1:/pN59F/t3U7Q4FPzV88nzqf7Fp0qqCSL2KzhZaiKcKw= +github.com/moby/moby v27.5.1+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc= +github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= +github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= +github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= +github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= +github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= +github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= +github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= +github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +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.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/opencontainers/runc v1.1.14 h1:rgSuzbmgz5DUJjeSnw337TxDbRuqjs6iqQck/2weR6w= +github.com/opencontainers/runc v1.1.14/go.mod h1:E4C2z+7BxR7GHXp0hAY53mek+x49X1LjPNeMTfRGvOA= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= +github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= +github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0= +github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ= +github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= +github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= +github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM= +github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= +github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= +github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= +github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= +github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= +github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY= +github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= +github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +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.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= +github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= +github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= +github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= +github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +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 v1.0.0 h1:BvNoksIyRqyQTW78rIZP9A44WwAminKiomQa7jXp9EI= +github.com/zondax/ledger-go v1.0.0/go.mod h1:HpgkgFh3Jkwi9iYLDATdyRxc8CxqxcywsFj6QerWzvo= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk= +go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK26LAGkNFw7RHv1DhE= +go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel v1.42.0 h1:lSQGzTgVR3+sgJDAU/7/ZMjN9Z+vUip7leaqBKy4sho= +go.opentelemetry.io/otel v1.42.0/go.mod h1:lJNsdRMxCUIWuMlVJWzecSMuNjE7dOYyWlqOXWkdqCc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 h1:THuZiwpQZuHPul65w4WcwEnkX2QIuMT+UFoOrygtoJw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0/go.mod h1:J2pvYM5NGHofZ2/Ru6zw/TNWnEQp5crgyDeSrYpXkAw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 h1:SNhVp/9q4Go/XHBkQ1/d5u9P/U+L1yaGPoi0x+mStaI= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0/go.mod h1:tx8OOlGH6R4kLV67YaYO44GFXloEjGPZuMjEkaaqIp4= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/metric v1.42.0 h1:2jXG+3oZLNXEPfNmnpxKDeZsFI5o4J+nz6xUlaFdF/4= +go.opentelemetry.io/otel/metric v1.42.0/go.mod h1:RlUN/7vTU7Ao/diDkEpQpnz3/92J9ko05BIwxYa2SSI= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/sdk v1.42.0 h1:LyC8+jqk6UJwdrI/8VydAq/hvkFKNHZVIWuslJXYsDo= +go.opentelemetry.io/otel/sdk v1.42.0/go.mod h1:rGHCAxd9DAph0joO4W6OPwxjNTYWghRWmkHuGbayMts= +go.opentelemetry.io/otel/sdk/metric v1.42.0 h1:D/1QR46Clz6ajyZ3G8SgNlTJKBdGp84q9RKCAZ3YGuA= +go.opentelemetry.io/otel/sdk/metric v1.42.0/go.mod h1:Ua6AAlDKdZ7tdvaQKfSmnFTdHx37+J4ba8MwVCYM5hc= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/otel/trace v1.42.0 h1:OUCgIPt+mzOnaUTpOQcBiM/PLQ/Op7oq6g4LenLmOYY= +go.opentelemetry.io/otel/trace v1.42.0/go.mod h1:f3K9S+IFqnumBkKhRJMeaZeNk9epyhnCmQh/EysQCdc= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= +go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw= +golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +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.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= +golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +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-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/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-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/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-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= +golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +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.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= +golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +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.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +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-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= +golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.215.0 h1:jdYF4qnyczlEz2ReWIsosNLDuzXyvFHJtI5gcr0J7t0= +google.golang.org/api v0.215.0/go.mod h1:fta3CVtuJYOEdugLNWm6WodzOS8KdFckABwN4I40hzY= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +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-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= +google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= +google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d h1:t/LOSXPJ9R0B6fnZNyALBRfZBH0Uy0gT+uR+SJ6syqQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= +google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +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.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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-20200902074654-038fdea0a05b/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +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/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +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.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/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= +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.0-20210107192922-496545a6307b/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.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +nhooyr.io/websocket v1.8.17 h1:KEVeLJkUywCKVsnLIDlD/5gtayKp8VoCkksHCGGfT9Y= +nhooyr.io/websocket v1.8.17/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= +pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= +pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/e2e/submission_test.go b/e2e/submission_test.go new file mode 100644 index 0000000..fe4eb28 --- /dev/null +++ b/e2e/submission_test.go @@ -0,0 +1,513 @@ +package e2e + +import ( + "bytes" + "context" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "net" + "net/http" + "os" + "os/exec" + "path/filepath" + "testing" + "time" + + "github.com/celestiaorg/go-square/merkle" + "github.com/celestiaorg/go-square/v3/inclusion" + gsquare "github.com/celestiaorg/go-square/v3/share" + tastoradocker "github.com/celestiaorg/tastora/framework/docker" + tastoracontainer "github.com/celestiaorg/tastora/framework/docker/container" + tastoracosmos "github.com/celestiaorg/tastora/framework/docker/cosmos" + sdkcrypto "github.com/cosmos/cosmos-sdk/crypto" + "github.com/cosmos/cosmos-sdk/types/module/testutil" + auth "github.com/cosmos/cosmos-sdk/x/auth" + bank "github.com/cosmos/cosmos-sdk/x/bank" + govmodule "github.com/cosmos/cosmos-sdk/x/gov" + ibctransfer "github.com/cosmos/ibc-go/v8/modules/apps/transfer" + "github.com/evstack/apex/pkg/types" +) + +const ( + submissionPollLimit = 60 + submissionPollInterval = time.Second + commitmentThreshold = 64 + celestiaAppImage = "ghcr.io/celestiaorg/celestia-app" + celestiaAppVersion = "v5.0.10" + celestiaAppUser = "10001:10001" + submissionGasPrice = 0.1 + submissionConfirmTimeout = 30 + chainStartupTimeout = 10 * time.Minute + apexReadyTimeout = 60 * time.Second +) + +func TestSubmissionViaJSONRPC(t *testing.T) { + if testing.Short() { + t.Skip("skipping Docker-backed e2e submission test in short mode") + } + + ctx, cancel := context.WithTimeout(context.Background(), chainStartupTimeout) + defer cancel() + + grpcAddr, chainID, signerKeyHex, signerAddress := startSubmissionTestChain(t, ctx) + namespace := testNamespace(t, []byte("apex-e2e")) + data := []byte("apex tastora submission e2e") + commitment := mustBlobCommitment(t, namespace, data) + + apexBinary := buildApexBinary(t) + apexRPCAddr := reserveTCPAddr(t) + apexGRPCAddr := reserveTCPAddr(t) + keyPath := writeSignerKey(t, signerKeyHex) + configPath := writeApexConfig(t, apexConfig{ + Namespace: namespace, + DataGRPCAddr: grpcAddr, + SubmissionGRPC: grpcAddr, + ChainID: chainID, + SignerKeyPath: keyPath, + StoragePath: filepath.Join(t.TempDir(), "apex.db"), + RPCListenAddr: apexRPCAddr, + GRPCListenAddr: apexGRPCAddr, + GasPrice: submissionGasPrice, + MaxGasPrice: submissionGasPrice, + ConfirmTimeoutS: submissionConfirmTimeout, + }) + + proc := startApexProcess(t, apexBinary, configPath) + defer proc.Stop(t) + + waitForApexHTTP(t, proc, apexRPCAddr) + + resp := doRPC( + t, + proc, + apexRPCAddr, + "blob.Submit", + []map[string]any{{ + "namespace": namespace, + "data": data, + "share_version": 0, + "commitment": commitment, + "index": -1, + }}, + map[string]any{ + "gas_price": submissionGasPrice, + "is_gas_price_set": true, + }, + ) + if resp.Error != nil { + t.Fatalf("blob.Submit RPC error: %s", resp.Error.Message) + } + + height := decodeSubmitHeight(t, resp.Result) + if height == 0 { + t.Fatal("submission height must be positive") + } + + waitForIndexedBlob(t, proc, apexRPCAddr, commitment, data, namespace, signerAddress) +} + +type apexConfig struct { + Namespace []byte + DataGRPCAddr string + SubmissionGRPC string + ChainID string + SignerKeyPath string + StoragePath string + RPCListenAddr string + GRPCListenAddr string + GasPrice float64 + MaxGasPrice float64 + ConfirmTimeoutS int +} + +func startSubmissionTestChain(t *testing.T, ctx context.Context) (grpcAddr string, chainID string, signerKeyHex string, signerAddress string) { + t.Helper() + + dockerClient, networkID := tastoradocker.Setup(t) + encodingConfig := testutil.MakeTestEncodingConfig( + auth.AppModuleBasic{}, + bank.AppModuleBasic{}, + ibctransfer.AppModuleBasic{}, + govmodule.AppModuleBasic{}, + ) + + builder := tastoracosmos.NewChainBuilderWithTestName(t, t.Name()). + WithDockerClient(dockerClient). + WithDockerNetworkID(networkID). + WithImage(tastoracontainer.NewImage(celestiaAppImage, celestiaAppVersion, celestiaAppUser)). + WithEncodingConfig(&encodingConfig). + WithAdditionalStartArgs( + "--force-no-bbr", + "--grpc.enable", + "--grpc.address", "0.0.0.0:9090", + "--rpc.grpc_laddr=tcp://0.0.0.0:9098", + "--timeout-commit", "1s", + "--minimum-gas-prices", "0utia", + ). + WithNode(tastoracosmos.NewChainNodeConfigBuilder().Build()) + + chain, err := builder.Build(ctx) + if err != nil { + t.Fatalf("build Tastora chain: %v", err) + } + if err := chain.Start(ctx); err != nil { + t.Fatalf("start Tastora chain: %v", err) + } + + networkInfo, err := chain.GetNetworkInfo(ctx) + if err != nil { + t.Fatalf("get chain network info: %v", err) + } + + faucetWallet := chain.GetFaucetWallet() + return networkInfo.External.GRPCAddress(), chain.GetChainID(), exportWalletPrivateKeyHex(t, chain, faucetWallet.GetKeyName()), faucetWallet.GetFormattedAddress() +} + +func exportWalletPrivateKeyHex(t *testing.T, chain *tastoracosmos.Chain, keyName string) string { + t.Helper() + + keyring, err := chain.GetNode().GetKeyring() + if err != nil { + t.Fatalf("get keyring: %v", err) + } + + armoredKey, err := keyring.ExportPrivKeyArmor(keyName, "") + if err != nil { + t.Fatalf("export private key: %v", err) + } + + privateKey, _, err := sdkcrypto.UnarmorDecryptPrivKey(armoredKey, "") + if err != nil { + t.Fatalf("decrypt private key: %v", err) + } + + return hex.EncodeToString(privateKey.Bytes()) +} + +func buildApexBinary(t *testing.T) string { + t.Helper() + + binaryPath := filepath.Join(t.TempDir(), "apex") + cmd := exec.Command("go", "build", "-C", "..", "-o", binaryPath, "./cmd/apex") + output, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("build apex binary: %v\n%s", err, output) + } + return binaryPath +} + +func writeSignerKey(t *testing.T, signerKeyHex string) string { + t.Helper() + + keyPath := filepath.Join(t.TempDir(), "submission.key") + if err := os.WriteFile(keyPath, []byte(signerKeyHex), 0o600); err != nil { + t.Fatalf("write signer key: %v", err) + } + return keyPath +} + +func writeApexConfig(t *testing.T, cfg apexConfig) string { + t.Helper() + + configPath := filepath.Join(t.TempDir(), "apex.yaml") + configYAML := fmt.Sprintf(`data_source: + type: "app" + celestia_app_grpc_addr: "%s" + backfill_source: "rpc" + namespaces: + - "%s" + +submission: + enabled: true + app_grpc_addr: "%s" + chain_id: "%s" + signer_key: "%s" + gas_price: %.6f + max_gas_price: %.6f + confirmation_timeout: %d + +storage: + type: "sqlite" + db_path: "%s" + +rpc: + listen_addr: "%s" + grpc_listen_addr: "%s" + read_timeout: 30 + write_timeout: 30 + +sync: + start_height: 1 + batch_size: 8 + concurrency: 1 + +subscription: + buffer_size: 16 + max_subscribers: 32 + +metrics: + enabled: false + +profiling: + enabled: false + +log: + level: "info" + format: "console" +`, + cfg.DataGRPCAddr, + hex.EncodeToString(cfg.Namespace), + cfg.SubmissionGRPC, + cfg.ChainID, + cfg.SignerKeyPath, + cfg.GasPrice, + cfg.MaxGasPrice, + cfg.ConfirmTimeoutS, + cfg.StoragePath, + cfg.RPCListenAddr, + cfg.GRPCListenAddr, + ) + + if err := os.WriteFile(configPath, []byte(configYAML), 0o600); err != nil { + t.Fatalf("write apex config: %v", err) + } + return configPath +} + +type apexProcess struct { + cmd *exec.Cmd + done chan struct{} + waitErr error + logs *bytes.Buffer +} + +func startApexProcess(t *testing.T, binaryPath string, configPath string) *apexProcess { + t.Helper() + + cmd := exec.Command(binaryPath, "--config", configPath, "start") + cmd.Dir = ".." + + var logs bytes.Buffer + cmd.Stdout = &logs + cmd.Stderr = &logs + + if err := cmd.Start(); err != nil { + t.Fatalf("start apex process: %v", err) + } + + proc := &apexProcess{ + cmd: cmd, + done: make(chan struct{}), + logs: &logs, + } + go func() { + proc.waitErr = cmd.Wait() + close(proc.done) + }() + return proc +} + +func (p *apexProcess) Stop(t *testing.T) { + t.Helper() + + if p == nil || p.cmd == nil || p.cmd.Process == nil { + return + } + + _ = p.cmd.Process.Kill() + select { + case <-p.done: + case <-time.After(5 * time.Second): + t.Fatalf("timed out stopping apex process\n%s", p.logs.String()) + } +} + +func waitForApexHTTP(t *testing.T, proc *apexProcess, rpcAddr string) { + t.Helper() + + client := &http.Client{Timeout: 2 * time.Second} + url := "http://" + rpcAddr + "/health" + + deadline := time.Now().Add(apexReadyTimeout) + for time.Now().Before(deadline) { + select { + case <-proc.done: + t.Fatalf("apex exited before becoming ready: %v\n%s", proc.waitErr, proc.logs.String()) + default: + } + + resp, err := client.Get(url) + if err == nil { + _ = resp.Body.Close() + return + } + time.Sleep(submissionPollInterval) + } + + t.Fatalf("apex HTTP endpoint did not become reachable at %s\n%s", url, proc.logs.String()) +} + +func mustBlobCommitment(t *testing.T, namespace []byte, data []byte) []byte { + t.Helper() + + blobNamespace, err := gsquare.NewNamespaceFromBytes(namespace) + if err != nil { + t.Fatalf("build blob namespace: %v", err) + } + if err := blobNamespace.ValidateForBlob(); err != nil { + t.Fatalf("validate blob namespace: %v", err) + } + + blob, err := gsquare.NewV0Blob(blobNamespace, data) + if err != nil { + t.Fatalf("build blob: %v", err) + } + + commitment, err := inclusion.CreateCommitment(blob, merkle.HashFromByteSlices, commitmentThreshold) + if err != nil { + t.Fatalf("create blob commitment: %v", err) + } + return commitment +} + +func waitForIndexedBlob(t *testing.T, proc *apexProcess, rpcAddr string, commitment []byte, wantData []byte, wantNamespace []byte, wantSigner string) { + t.Helper() + + for range submissionPollLimit { + select { + case <-proc.done: + t.Fatalf("apex exited before blob was indexed: %v\n%s", proc.waitErr, proc.logs.String()) + default: + } + + resp := doRPC(t, proc, rpcAddr, "blob.GetByCommitment", commitment) + if resp.Error == nil && len(resp.Result) > 0 && string(resp.Result) != "null" { + var blob rpcBlob + if err := json.Unmarshal(resp.Result, &blob); err != nil { + t.Fatalf("decode blob result: %v", err) + } + if !bytes.Equal(blob.Data, wantData) { + t.Fatalf("blob data = %q, want %q", blob.Data, wantData) + } + if !bytes.Equal(blob.Namespace, wantNamespace) { + t.Fatalf("blob namespace = %x, want %x", blob.Namespace, wantNamespace) + } + if !bytes.Equal(blob.Commitment, commitment) { + t.Fatalf("blob commitment = %x, want %x", blob.Commitment, commitment) + } + if string(blob.Signer) != wantSigner { + t.Fatalf("blob signer = %q, want %q", blob.Signer, wantSigner) + } + return + } + time.Sleep(submissionPollInterval) + } + + t.Fatalf("blob with commitment %x was not indexed by apex\n%s", commitment, proc.logs.String()) +} + +func decodeSubmitHeight(t *testing.T, raw json.RawMessage) uint64 { + t.Helper() + + var height uint64 + if err := json.Unmarshal(raw, &height); err != nil { + t.Fatalf("decode submit height: %v", err) + } + return height +} + +type jsonRPCRequest struct { + Jsonrpc string `json:"jsonrpc"` + Method string `json:"method"` + Params []any `json:"params"` + ID int `json:"id"` +} + +type jsonRPCResponse struct { + Jsonrpc string `json:"jsonrpc"` + Result json.RawMessage `json:"result"` + Error *jsonRPCError `json:"error,omitempty"` + ID int `json:"id"` +} + +type jsonRPCError struct { + Code int `json:"code"` + Message string `json:"message"` +} + +type rpcBlob struct { + Namespace []byte `json:"namespace"` + Data []byte `json:"data"` + ShareVersion uint32 `json:"share_version"` + Commitment []byte `json:"commitment"` + Signer []byte `json:"signer"` + Index int `json:"index"` +} + +func doRPC(t *testing.T, proc *apexProcess, rpcAddr string, method string, params ...any) jsonRPCResponse { + t.Helper() + + reqBody, err := json.Marshal(jsonRPCRequest{ + Jsonrpc: "2.0", + Method: method, + Params: params, + ID: 1, + }) + if err != nil { + t.Fatalf("marshal RPC request: %v", err) + } + + req, err := http.NewRequest(http.MethodPost, "http://"+rpcAddr+"/", bytes.NewReader(reqBody)) + if err != nil { + t.Fatalf("create RPC request: %v", err) + } + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Do(req) + if err != nil { + t.Fatalf("perform RPC request: %v\n%s", err, proc.logs.String()) + } + defer resp.Body.Close() //nolint:errcheck + + body, err := io.ReadAll(resp.Body) + if err != nil { + t.Fatalf("read RPC response: %v", err) + } + + var rpcResp jsonRPCResponse + if err := json.Unmarshal(body, &rpcResp); err != nil { + t.Fatalf("decode RPC response: %v (body: %s)", err, body) + } + return rpcResp +} + +func reserveTCPAddr(t *testing.T) string { + t.Helper() + + lis, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatalf("reserve TCP port: %v", err) + } + defer lis.Close() //nolint:errcheck + return lis.Addr().String() +} + +func testNamespace(t *testing.T, subID []byte) []byte { + t.Helper() + + namespace, err := gsquare.NewV0Namespace(subID) + if err != nil { + t.Fatalf("build namespace: %v", err) + } + if err := namespace.ValidateForBlob(); err != nil { + t.Fatalf("validate namespace: %v", err) + } + namespaceBytes := append([]byte(nil), namespace.Bytes()...) + if len(namespaceBytes) != types.NamespaceSize { + t.Fatalf("namespace size = %d, want %d", len(namespaceBytes), types.NamespaceSize) + } + return namespaceBytes +} diff --git a/go.mod b/go.mod index a8a14d7..e0519ca 100644 --- a/go.mod +++ b/go.mod @@ -7,9 +7,14 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.32.9 github.com/aws/aws-sdk-go-v2/credentials v1.19.9 github.com/aws/aws-sdk-go-v2/service/s3 v1.96.0 + github.com/btcsuite/btcd/btcutil v1.1.6 + github.com/celestiaorg/go-square/v3 v3.0.2 github.com/cockroachdb/pebble v1.1.5 + github.com/cosmos/btcutil v1.0.5 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 github.com/filecoin-project/go-jsonrpc v0.10.1 github.com/google/orderedcode v0.0.1 + github.com/gorilla/websocket v1.5.0 github.com/prometheus/client_golang v1.23.2 github.com/rs/zerolog v1.34.0 github.com/spf13/cobra v1.10.2 @@ -38,6 +43,9 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 // indirect github.com/aws/smithy-go v1.24.0 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd v0.24.2 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cockroachdb/errors v1.11.3 // indirect github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect @@ -50,7 +58,6 @@ require ( github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.4.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ipfs/go-log/v2 v2.0.8 // indirect github.com/klauspost/compress v1.18.0 // indirect @@ -72,6 +79,7 @@ require ( go.uber.org/multierr v1.5.0 // indirect go.uber.org/zap v1.14.1 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect + golang.org/x/crypto v0.46.0 // indirect golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect golang.org/x/net v0.48.0 // indirect golang.org/x/sys v0.41.0 // indirect diff --git a/go.sum b/go.sum index 3a3ce2b..73d76a7 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,7 @@ github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/aws/aws-sdk-go-v2 v1.41.1 h1:ABlyEARCDLN034NhxlRUSZr4l71mh+T5KAeGh6cerhU= github.com/aws/aws-sdk-go-v2 v1.41.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 h1:489krEF9xIGkOaaX3CE/Be2uWjiXrkCH6gUX+bZA/BU= @@ -44,6 +45,34 @@ github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= 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.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/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= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +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/celestiaorg/go-square/v3 v3.0.2 h1:eSQOgNII8inK9IhiBZ+6GADQeWbRq4HYY72BOgcduA4= +github.com/celestiaorg/go-square/v3 v3.0.2/go.mod h1:oFReMLsSDMRs82ICFEeFQFCqNvwdsbIM1BzCcb0f7dM= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -62,11 +91,21 @@ github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= +github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +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= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= +github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/filecoin-project/go-jsonrpc v0.10.1 h1:iEhgrjO0+rawwOZWRNgexLrWGLA+IEUyWiRRL134Ob8= @@ -113,8 +152,8 @@ github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -122,8 +161,12 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ipfs/go-log/v2 v2.0.8 h1:3b3YNopMHlj4AvyhWAx0pDxqSQWYi4/WuWO7yRV6/Qg= github.com/ipfs/go-log/v2 v2.0.8/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +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.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -148,9 +191,12 @@ github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJm github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 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= @@ -185,8 +231,14 @@ github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiT github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= @@ -220,10 +272,13 @@ go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= @@ -237,6 +292,7 @@ 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.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= +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= @@ -326,11 +382,13 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 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= 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= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/justfile b/justfile index cf06b49..1831d0a 100644 --- a/justfile +++ b/justfile @@ -42,3 +42,7 @@ proto: # Run all checks (CI equivalent) check: tidy-check lint test build + +# Run the Docker-backed submission e2e test in the isolated e2e module. +e2e-submission: + cd e2e && go test -race -count=1 -timeout 20m ./... diff --git a/pkg/api/grpc/gen/celestia/blob/v1/tx.pb.go b/pkg/api/grpc/gen/celestia/blob/v1/tx.pb.go new file mode 100644 index 0000000..f813405 --- /dev/null +++ b/pkg/api/grpc/gen/celestia/blob/v1/tx.pb.go @@ -0,0 +1,201 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: celestia/blob/v1/tx.proto + +package blobv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// MsgPayForBlobs is the Celestia message included in a Cosmos SDK tx for blob +// inclusion. Apex only needs the request shape for local tx construction. +type MsgPayForBlobs struct { + state protoimpl.MessageState `protogen:"open.v1"` + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` + Namespaces [][]byte `protobuf:"bytes,2,rep,name=namespaces,proto3" json:"namespaces,omitempty"` + BlobSizes []uint32 `protobuf:"varint,3,rep,packed,name=blob_sizes,json=blobSizes,proto3" json:"blob_sizes,omitempty"` + ShareCommitments [][]byte `protobuf:"bytes,4,rep,name=share_commitments,json=shareCommitments,proto3" json:"share_commitments,omitempty"` + ShareVersions []uint32 `protobuf:"varint,8,rep,packed,name=share_versions,json=shareVersions,proto3" json:"share_versions,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MsgPayForBlobs) Reset() { + *x = MsgPayForBlobs{} + mi := &file_celestia_blob_v1_tx_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MsgPayForBlobs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MsgPayForBlobs) ProtoMessage() {} + +func (x *MsgPayForBlobs) ProtoReflect() protoreflect.Message { + mi := &file_celestia_blob_v1_tx_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MsgPayForBlobs.ProtoReflect.Descriptor instead. +func (*MsgPayForBlobs) Descriptor() ([]byte, []int) { + return file_celestia_blob_v1_tx_proto_rawDescGZIP(), []int{0} +} + +func (x *MsgPayForBlobs) GetSigner() string { + if x != nil { + return x.Signer + } + return "" +} + +func (x *MsgPayForBlobs) GetNamespaces() [][]byte { + if x != nil { + return x.Namespaces + } + return nil +} + +func (x *MsgPayForBlobs) GetBlobSizes() []uint32 { + if x != nil { + return x.BlobSizes + } + return nil +} + +func (x *MsgPayForBlobs) GetShareCommitments() [][]byte { + if x != nil { + return x.ShareCommitments + } + return nil +} + +func (x *MsgPayForBlobs) GetShareVersions() []uint32 { + if x != nil { + return x.ShareVersions + } + return nil +} + +type MsgPayForBlobsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MsgPayForBlobsResponse) Reset() { + *x = MsgPayForBlobsResponse{} + mi := &file_celestia_blob_v1_tx_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MsgPayForBlobsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MsgPayForBlobsResponse) ProtoMessage() {} + +func (x *MsgPayForBlobsResponse) ProtoReflect() protoreflect.Message { + mi := &file_celestia_blob_v1_tx_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MsgPayForBlobsResponse.ProtoReflect.Descriptor instead. +func (*MsgPayForBlobsResponse) Descriptor() ([]byte, []int) { + return file_celestia_blob_v1_tx_proto_rawDescGZIP(), []int{1} +} + +var File_celestia_blob_v1_tx_proto protoreflect.FileDescriptor + +const file_celestia_blob_v1_tx_proto_rawDesc = "" + + "\n" + + "\x19celestia/blob/v1/tx.proto\x12\x10celestia.blob.v1\"\xbb\x01\n" + + "\x0eMsgPayForBlobs\x12\x16\n" + + "\x06signer\x18\x01 \x01(\tR\x06signer\x12\x1e\n" + + "\n" + + "namespaces\x18\x02 \x03(\fR\n" + + "namespaces\x12\x1d\n" + + "\n" + + "blob_sizes\x18\x03 \x03(\rR\tblobSizes\x12+\n" + + "\x11share_commitments\x18\x04 \x03(\fR\x10shareCommitments\x12%\n" + + "\x0eshare_versions\x18\b \x03(\rR\rshareVersions\"\x18\n" + + "\x16MsgPayForBlobsResponseBBZ@github.com/evstack/apex/pkg/api/grpc/gen/celestia/blob/v1;blobv1b\x06proto3" + +var ( + file_celestia_blob_v1_tx_proto_rawDescOnce sync.Once + file_celestia_blob_v1_tx_proto_rawDescData []byte +) + +func file_celestia_blob_v1_tx_proto_rawDescGZIP() []byte { + file_celestia_blob_v1_tx_proto_rawDescOnce.Do(func() { + file_celestia_blob_v1_tx_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_celestia_blob_v1_tx_proto_rawDesc), len(file_celestia_blob_v1_tx_proto_rawDesc))) + }) + return file_celestia_blob_v1_tx_proto_rawDescData +} + +var file_celestia_blob_v1_tx_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_celestia_blob_v1_tx_proto_goTypes = []any{ + (*MsgPayForBlobs)(nil), // 0: celestia.blob.v1.MsgPayForBlobs + (*MsgPayForBlobsResponse)(nil), // 1: celestia.blob.v1.MsgPayForBlobsResponse +} +var file_celestia_blob_v1_tx_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_celestia_blob_v1_tx_proto_init() } +func file_celestia_blob_v1_tx_proto_init() { + if File_celestia_blob_v1_tx_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_celestia_blob_v1_tx_proto_rawDesc), len(file_celestia_blob_v1_tx_proto_rawDesc)), + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_celestia_blob_v1_tx_proto_goTypes, + DependencyIndexes: file_celestia_blob_v1_tx_proto_depIdxs, + MessageInfos: file_celestia_blob_v1_tx_proto_msgTypes, + }.Build() + File_celestia_blob_v1_tx_proto = out.File + file_celestia_blob_v1_tx_proto_goTypes = nil + file_celestia_blob_v1_tx_proto_depIdxs = nil +} diff --git a/pkg/api/grpc/gen/cosmos/auth/v1beta1/auth.pb.go b/pkg/api/grpc/gen/cosmos/auth/v1beta1/auth.pb.go new file mode 100644 index 0000000..5b1e3e7 --- /dev/null +++ b/pkg/api/grpc/gen/cosmos/auth/v1beta1/auth.pb.go @@ -0,0 +1,152 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: cosmos/auth/v1beta1/auth.proto + +package authv1beta1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + anypb "google.golang.org/protobuf/types/known/anypb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type BaseAccount struct { + state protoimpl.MessageState `protogen:"open.v1"` + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + PubKey *anypb.Any `protobuf:"bytes,2,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` + AccountNumber uint64 `protobuf:"varint,3,opt,name=account_number,json=accountNumber,proto3" json:"account_number,omitempty"` + Sequence uint64 `protobuf:"varint,4,opt,name=sequence,proto3" json:"sequence,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BaseAccount) Reset() { + *x = BaseAccount{} + mi := &file_cosmos_auth_v1beta1_auth_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BaseAccount) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BaseAccount) ProtoMessage() {} + +func (x *BaseAccount) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_auth_v1beta1_auth_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BaseAccount.ProtoReflect.Descriptor instead. +func (*BaseAccount) Descriptor() ([]byte, []int) { + return file_cosmos_auth_v1beta1_auth_proto_rawDescGZIP(), []int{0} +} + +func (x *BaseAccount) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *BaseAccount) GetPubKey() *anypb.Any { + if x != nil { + return x.PubKey + } + return nil +} + +func (x *BaseAccount) GetAccountNumber() uint64 { + if x != nil { + return x.AccountNumber + } + return 0 +} + +func (x *BaseAccount) GetSequence() uint64 { + if x != nil { + return x.Sequence + } + return 0 +} + +var File_cosmos_auth_v1beta1_auth_proto protoreflect.FileDescriptor + +const file_cosmos_auth_v1beta1_auth_proto_rawDesc = "" + + "\n" + + "\x1ecosmos/auth/v1beta1/auth.proto\x12\x13cosmos.auth.v1beta1\x1a\x19google/protobuf/any.proto\"\x99\x01\n" + + "\vBaseAccount\x12\x18\n" + + "\aaddress\x18\x01 \x01(\tR\aaddress\x12-\n" + + "\apub_key\x18\x02 \x01(\v2\x14.google.protobuf.AnyR\x06pubKey\x12%\n" + + "\x0eaccount_number\x18\x03 \x01(\x04R\raccountNumber\x12\x1a\n" + + "\bsequence\x18\x04 \x01(\x04R\bsequenceBJZHgithub.com/evstack/apex/pkg/api/grpc/gen/cosmos/auth/v1beta1;authv1beta1b\x06proto3" + +var ( + file_cosmos_auth_v1beta1_auth_proto_rawDescOnce sync.Once + file_cosmos_auth_v1beta1_auth_proto_rawDescData []byte +) + +func file_cosmos_auth_v1beta1_auth_proto_rawDescGZIP() []byte { + file_cosmos_auth_v1beta1_auth_proto_rawDescOnce.Do(func() { + file_cosmos_auth_v1beta1_auth_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_cosmos_auth_v1beta1_auth_proto_rawDesc), len(file_cosmos_auth_v1beta1_auth_proto_rawDesc))) + }) + return file_cosmos_auth_v1beta1_auth_proto_rawDescData +} + +var file_cosmos_auth_v1beta1_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_cosmos_auth_v1beta1_auth_proto_goTypes = []any{ + (*BaseAccount)(nil), // 0: cosmos.auth.v1beta1.BaseAccount + (*anypb.Any)(nil), // 1: google.protobuf.Any +} +var file_cosmos_auth_v1beta1_auth_proto_depIdxs = []int32{ + 1, // 0: cosmos.auth.v1beta1.BaseAccount.pub_key:type_name -> google.protobuf.Any + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_cosmos_auth_v1beta1_auth_proto_init() } +func file_cosmos_auth_v1beta1_auth_proto_init() { + if File_cosmos_auth_v1beta1_auth_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_cosmos_auth_v1beta1_auth_proto_rawDesc), len(file_cosmos_auth_v1beta1_auth_proto_rawDesc)), + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_cosmos_auth_v1beta1_auth_proto_goTypes, + DependencyIndexes: file_cosmos_auth_v1beta1_auth_proto_depIdxs, + MessageInfos: file_cosmos_auth_v1beta1_auth_proto_msgTypes, + }.Build() + File_cosmos_auth_v1beta1_auth_proto = out.File + file_cosmos_auth_v1beta1_auth_proto_goTypes = nil + file_cosmos_auth_v1beta1_auth_proto_depIdxs = nil +} diff --git a/pkg/api/grpc/gen/cosmos/auth/v1beta1/query.pb.go b/pkg/api/grpc/gen/cosmos/auth/v1beta1/query.pb.go new file mode 100644 index 0000000..cd1957b --- /dev/null +++ b/pkg/api/grpc/gen/cosmos/auth/v1beta1/query.pb.go @@ -0,0 +1,176 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: cosmos/auth/v1beta1/query.proto + +package authv1beta1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type QueryAccountInfoRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *QueryAccountInfoRequest) Reset() { + *x = QueryAccountInfoRequest{} + mi := &file_cosmos_auth_v1beta1_query_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *QueryAccountInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryAccountInfoRequest) ProtoMessage() {} + +func (x *QueryAccountInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_auth_v1beta1_query_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryAccountInfoRequest.ProtoReflect.Descriptor instead. +func (*QueryAccountInfoRequest) Descriptor() ([]byte, []int) { + return file_cosmos_auth_v1beta1_query_proto_rawDescGZIP(), []int{0} +} + +func (x *QueryAccountInfoRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +type QueryAccountInfoResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Info *BaseAccount `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *QueryAccountInfoResponse) Reset() { + *x = QueryAccountInfoResponse{} + mi := &file_cosmos_auth_v1beta1_query_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *QueryAccountInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryAccountInfoResponse) ProtoMessage() {} + +func (x *QueryAccountInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_auth_v1beta1_query_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryAccountInfoResponse.ProtoReflect.Descriptor instead. +func (*QueryAccountInfoResponse) Descriptor() ([]byte, []int) { + return file_cosmos_auth_v1beta1_query_proto_rawDescGZIP(), []int{1} +} + +func (x *QueryAccountInfoResponse) GetInfo() *BaseAccount { + if x != nil { + return x.Info + } + return nil +} + +var File_cosmos_auth_v1beta1_query_proto protoreflect.FileDescriptor + +const file_cosmos_auth_v1beta1_query_proto_rawDesc = "" + + "\n" + + "\x1fcosmos/auth/v1beta1/query.proto\x12\x13cosmos.auth.v1beta1\x1a\x1ecosmos/auth/v1beta1/auth.proto\"3\n" + + "\x17QueryAccountInfoRequest\x12\x18\n" + + "\aaddress\x18\x01 \x01(\tR\aaddress\"P\n" + + "\x18QueryAccountInfoResponse\x124\n" + + "\x04info\x18\x01 \x01(\v2 .cosmos.auth.v1beta1.BaseAccountR\x04info2s\n" + + "\x05Query\x12j\n" + + "\vAccountInfo\x12,.cosmos.auth.v1beta1.QueryAccountInfoRequest\x1a-.cosmos.auth.v1beta1.QueryAccountInfoResponseBJZHgithub.com/evstack/apex/pkg/api/grpc/gen/cosmos/auth/v1beta1;authv1beta1b\x06proto3" + +var ( + file_cosmos_auth_v1beta1_query_proto_rawDescOnce sync.Once + file_cosmos_auth_v1beta1_query_proto_rawDescData []byte +) + +func file_cosmos_auth_v1beta1_query_proto_rawDescGZIP() []byte { + file_cosmos_auth_v1beta1_query_proto_rawDescOnce.Do(func() { + file_cosmos_auth_v1beta1_query_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_cosmos_auth_v1beta1_query_proto_rawDesc), len(file_cosmos_auth_v1beta1_query_proto_rawDesc))) + }) + return file_cosmos_auth_v1beta1_query_proto_rawDescData +} + +var file_cosmos_auth_v1beta1_query_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_cosmos_auth_v1beta1_query_proto_goTypes = []any{ + (*QueryAccountInfoRequest)(nil), // 0: cosmos.auth.v1beta1.QueryAccountInfoRequest + (*QueryAccountInfoResponse)(nil), // 1: cosmos.auth.v1beta1.QueryAccountInfoResponse + (*BaseAccount)(nil), // 2: cosmos.auth.v1beta1.BaseAccount +} +var file_cosmos_auth_v1beta1_query_proto_depIdxs = []int32{ + 2, // 0: cosmos.auth.v1beta1.QueryAccountInfoResponse.info:type_name -> cosmos.auth.v1beta1.BaseAccount + 0, // 1: cosmos.auth.v1beta1.Query.AccountInfo:input_type -> cosmos.auth.v1beta1.QueryAccountInfoRequest + 1, // 2: cosmos.auth.v1beta1.Query.AccountInfo:output_type -> cosmos.auth.v1beta1.QueryAccountInfoResponse + 2, // [2:3] is the sub-list for method output_type + 1, // [1:2] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_cosmos_auth_v1beta1_query_proto_init() } +func file_cosmos_auth_v1beta1_query_proto_init() { + if File_cosmos_auth_v1beta1_query_proto != nil { + return + } + file_cosmos_auth_v1beta1_auth_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_cosmos_auth_v1beta1_query_proto_rawDesc), len(file_cosmos_auth_v1beta1_query_proto_rawDesc)), + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_cosmos_auth_v1beta1_query_proto_goTypes, + DependencyIndexes: file_cosmos_auth_v1beta1_query_proto_depIdxs, + MessageInfos: file_cosmos_auth_v1beta1_query_proto_msgTypes, + }.Build() + File_cosmos_auth_v1beta1_query_proto = out.File + file_cosmos_auth_v1beta1_query_proto_goTypes = nil + file_cosmos_auth_v1beta1_query_proto_depIdxs = nil +} diff --git a/pkg/api/grpc/gen/cosmos/auth/v1beta1/query_grpc.pb.go b/pkg/api/grpc/gen/cosmos/auth/v1beta1/query_grpc.pb.go new file mode 100644 index 0000000..f362bfc --- /dev/null +++ b/pkg/api/grpc/gen/cosmos/auth/v1beta1/query_grpc.pb.go @@ -0,0 +1,121 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.1 +// - protoc (unknown) +// source: cosmos/auth/v1beta1/query.proto + +package authv1beta1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + Query_AccountInfo_FullMethodName = "/cosmos.auth.v1beta1.Query/AccountInfo" +) + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type QueryClient interface { + AccountInfo(ctx context.Context, in *QueryAccountInfoRequest, opts ...grpc.CallOption) (*QueryAccountInfoResponse, error) +} + +type queryClient struct { + cc grpc.ClientConnInterface +} + +func NewQueryClient(cc grpc.ClientConnInterface) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) AccountInfo(ctx context.Context, in *QueryAccountInfoRequest, opts ...grpc.CallOption) (*QueryAccountInfoResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(QueryAccountInfoResponse) + err := c.cc.Invoke(ctx, Query_AccountInfo_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +// All implementations must embed UnimplementedQueryServer +// for forward compatibility. +type QueryServer interface { + AccountInfo(context.Context, *QueryAccountInfoRequest) (*QueryAccountInfoResponse, error) + mustEmbedUnimplementedQueryServer() +} + +// UnimplementedQueryServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedQueryServer struct{} + +func (UnimplementedQueryServer) AccountInfo(context.Context, *QueryAccountInfoRequest) (*QueryAccountInfoResponse, error) { + return nil, status.Error(codes.Unimplemented, "method AccountInfo not implemented") +} +func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {} +func (UnimplementedQueryServer) testEmbeddedByValue() {} + +// UnsafeQueryServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to QueryServer will +// result in compilation errors. +type UnsafeQueryServer interface { + mustEmbedUnimplementedQueryServer() +} + +func RegisterQueryServer(s grpc.ServiceRegistrar, srv QueryServer) { + // If the following call panics, it indicates UnimplementedQueryServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&Query_ServiceDesc, srv) +} + +func _Query_AccountInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAccountInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AccountInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Query_AccountInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AccountInfo(ctx, req.(*QueryAccountInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Query_ServiceDesc is the grpc.ServiceDesc for Query service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Query_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "cosmos.auth.v1beta1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "AccountInfo", + Handler: _Query_AccountInfo_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cosmos/auth/v1beta1/query.proto", +} diff --git a/pkg/api/grpc/gen/cosmos/base/abci/v1beta1/abci.pb.go b/pkg/api/grpc/gen/cosmos/base/abci/v1beta1/abci.pb.go new file mode 100644 index 0000000..b582b05 --- /dev/null +++ b/pkg/api/grpc/gen/cosmos/base/abci/v1beta1/abci.pb.go @@ -0,0 +1,206 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: cosmos/base/abci/v1beta1/abci.proto + +package abciv1beta1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type TxResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Txhash string `protobuf:"bytes,2,opt,name=txhash,proto3" json:"txhash,omitempty"` + Codespace string `protobuf:"bytes,3,opt,name=codespace,proto3" json:"codespace,omitempty"` + Code uint32 `protobuf:"varint,4,opt,name=code,proto3" json:"code,omitempty"` + Data string `protobuf:"bytes,5,opt,name=data,proto3" json:"data,omitempty"` + RawLog string `protobuf:"bytes,6,opt,name=raw_log,json=rawLog,proto3" json:"raw_log,omitempty"` + Info string `protobuf:"bytes,8,opt,name=info,proto3" json:"info,omitempty"` + GasWanted int64 `protobuf:"varint,9,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"` + GasUsed int64 `protobuf:"varint,10,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"` + Timestamp string `protobuf:"bytes,12,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TxResponse) Reset() { + *x = TxResponse{} + mi := &file_cosmos_base_abci_v1beta1_abci_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TxResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TxResponse) ProtoMessage() {} + +func (x *TxResponse) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_base_abci_v1beta1_abci_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TxResponse.ProtoReflect.Descriptor instead. +func (*TxResponse) Descriptor() ([]byte, []int) { + return file_cosmos_base_abci_v1beta1_abci_proto_rawDescGZIP(), []int{0} +} + +func (x *TxResponse) GetHeight() int64 { + if x != nil { + return x.Height + } + return 0 +} + +func (x *TxResponse) GetTxhash() string { + if x != nil { + return x.Txhash + } + return "" +} + +func (x *TxResponse) GetCodespace() string { + if x != nil { + return x.Codespace + } + return "" +} + +func (x *TxResponse) GetCode() uint32 { + if x != nil { + return x.Code + } + return 0 +} + +func (x *TxResponse) GetData() string { + if x != nil { + return x.Data + } + return "" +} + +func (x *TxResponse) GetRawLog() string { + if x != nil { + return x.RawLog + } + return "" +} + +func (x *TxResponse) GetInfo() string { + if x != nil { + return x.Info + } + return "" +} + +func (x *TxResponse) GetGasWanted() int64 { + if x != nil { + return x.GasWanted + } + return 0 +} + +func (x *TxResponse) GetGasUsed() int64 { + if x != nil { + return x.GasUsed + } + return 0 +} + +func (x *TxResponse) GetTimestamp() string { + if x != nil { + return x.Timestamp + } + return "" +} + +var File_cosmos_base_abci_v1beta1_abci_proto protoreflect.FileDescriptor + +const file_cosmos_base_abci_v1beta1_abci_proto_rawDesc = "" + + "\n" + + "#cosmos/base/abci/v1beta1/abci.proto\x12\x18cosmos.base.abci.v1beta1\"\x87\x02\n" + + "\n" + + "TxResponse\x12\x16\n" + + "\x06height\x18\x01 \x01(\x03R\x06height\x12\x16\n" + + "\x06txhash\x18\x02 \x01(\tR\x06txhash\x12\x1c\n" + + "\tcodespace\x18\x03 \x01(\tR\tcodespace\x12\x12\n" + + "\x04code\x18\x04 \x01(\rR\x04code\x12\x12\n" + + "\x04data\x18\x05 \x01(\tR\x04data\x12\x17\n" + + "\araw_log\x18\x06 \x01(\tR\x06rawLog\x12\x12\n" + + "\x04info\x18\b \x01(\tR\x04info\x12\x1d\n" + + "\n" + + "gas_wanted\x18\t \x01(\x03R\tgasWanted\x12\x19\n" + + "\bgas_used\x18\n" + + " \x01(\x03R\agasUsed\x12\x1c\n" + + "\ttimestamp\x18\f \x01(\tR\ttimestampBOZMgithub.com/evstack/apex/pkg/api/grpc/gen/cosmos/base/abci/v1beta1;abciv1beta1b\x06proto3" + +var ( + file_cosmos_base_abci_v1beta1_abci_proto_rawDescOnce sync.Once + file_cosmos_base_abci_v1beta1_abci_proto_rawDescData []byte +) + +func file_cosmos_base_abci_v1beta1_abci_proto_rawDescGZIP() []byte { + file_cosmos_base_abci_v1beta1_abci_proto_rawDescOnce.Do(func() { + file_cosmos_base_abci_v1beta1_abci_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_cosmos_base_abci_v1beta1_abci_proto_rawDesc), len(file_cosmos_base_abci_v1beta1_abci_proto_rawDesc))) + }) + return file_cosmos_base_abci_v1beta1_abci_proto_rawDescData +} + +var file_cosmos_base_abci_v1beta1_abci_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_cosmos_base_abci_v1beta1_abci_proto_goTypes = []any{ + (*TxResponse)(nil), // 0: cosmos.base.abci.v1beta1.TxResponse +} +var file_cosmos_base_abci_v1beta1_abci_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_cosmos_base_abci_v1beta1_abci_proto_init() } +func file_cosmos_base_abci_v1beta1_abci_proto_init() { + if File_cosmos_base_abci_v1beta1_abci_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_cosmos_base_abci_v1beta1_abci_proto_rawDesc), len(file_cosmos_base_abci_v1beta1_abci_proto_rawDesc)), + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_cosmos_base_abci_v1beta1_abci_proto_goTypes, + DependencyIndexes: file_cosmos_base_abci_v1beta1_abci_proto_depIdxs, + MessageInfos: file_cosmos_base_abci_v1beta1_abci_proto_msgTypes, + }.Build() + File_cosmos_base_abci_v1beta1_abci_proto = out.File + file_cosmos_base_abci_v1beta1_abci_proto_goTypes = nil + file_cosmos_base_abci_v1beta1_abci_proto_depIdxs = nil +} diff --git a/pkg/api/grpc/gen/cosmos/base/v1beta1/coin.pb.go b/pkg/api/grpc/gen/cosmos/base/v1beta1/coin.pb.go new file mode 100644 index 0000000..071f1c9 --- /dev/null +++ b/pkg/api/grpc/gen/cosmos/base/v1beta1/coin.pb.go @@ -0,0 +1,131 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: cosmos/base/v1beta1/coin.proto + +package basev1beta1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Coin struct { + state protoimpl.MessageState `protogen:"open.v1"` + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` + Amount string `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Coin) Reset() { + *x = Coin{} + mi := &file_cosmos_base_v1beta1_coin_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Coin) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Coin) ProtoMessage() {} + +func (x *Coin) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_base_v1beta1_coin_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Coin.ProtoReflect.Descriptor instead. +func (*Coin) Descriptor() ([]byte, []int) { + return file_cosmos_base_v1beta1_coin_proto_rawDescGZIP(), []int{0} +} + +func (x *Coin) GetDenom() string { + if x != nil { + return x.Denom + } + return "" +} + +func (x *Coin) GetAmount() string { + if x != nil { + return x.Amount + } + return "" +} + +var File_cosmos_base_v1beta1_coin_proto protoreflect.FileDescriptor + +const file_cosmos_base_v1beta1_coin_proto_rawDesc = "" + + "\n" + + "\x1ecosmos/base/v1beta1/coin.proto\x12\x13cosmos.base.v1beta1\"4\n" + + "\x04Coin\x12\x14\n" + + "\x05denom\x18\x01 \x01(\tR\x05denom\x12\x16\n" + + "\x06amount\x18\x02 \x01(\tR\x06amountBJZHgithub.com/evstack/apex/pkg/api/grpc/gen/cosmos/base/v1beta1;basev1beta1b\x06proto3" + +var ( + file_cosmos_base_v1beta1_coin_proto_rawDescOnce sync.Once + file_cosmos_base_v1beta1_coin_proto_rawDescData []byte +) + +func file_cosmos_base_v1beta1_coin_proto_rawDescGZIP() []byte { + file_cosmos_base_v1beta1_coin_proto_rawDescOnce.Do(func() { + file_cosmos_base_v1beta1_coin_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_cosmos_base_v1beta1_coin_proto_rawDesc), len(file_cosmos_base_v1beta1_coin_proto_rawDesc))) + }) + return file_cosmos_base_v1beta1_coin_proto_rawDescData +} + +var file_cosmos_base_v1beta1_coin_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_cosmos_base_v1beta1_coin_proto_goTypes = []any{ + (*Coin)(nil), // 0: cosmos.base.v1beta1.Coin +} +var file_cosmos_base_v1beta1_coin_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_cosmos_base_v1beta1_coin_proto_init() } +func file_cosmos_base_v1beta1_coin_proto_init() { + if File_cosmos_base_v1beta1_coin_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_cosmos_base_v1beta1_coin_proto_rawDesc), len(file_cosmos_base_v1beta1_coin_proto_rawDesc)), + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_cosmos_base_v1beta1_coin_proto_goTypes, + DependencyIndexes: file_cosmos_base_v1beta1_coin_proto_depIdxs, + MessageInfos: file_cosmos_base_v1beta1_coin_proto_msgTypes, + }.Build() + File_cosmos_base_v1beta1_coin_proto = out.File + file_cosmos_base_v1beta1_coin_proto_goTypes = nil + file_cosmos_base_v1beta1_coin_proto_depIdxs = nil +} diff --git a/pkg/api/grpc/gen/cosmos/crypto/secp256k1/keys.pb.go b/pkg/api/grpc/gen/cosmos/crypto/secp256k1/keys.pb.go new file mode 100644 index 0000000..4d8d76b --- /dev/null +++ b/pkg/api/grpc/gen/cosmos/crypto/secp256k1/keys.pb.go @@ -0,0 +1,122 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: cosmos/crypto/secp256k1/keys.proto + +package secp256k1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type PubKey struct { + state protoimpl.MessageState `protogen:"open.v1"` + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PubKey) Reset() { + *x = PubKey{} + mi := &file_cosmos_crypto_secp256k1_keys_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PubKey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PubKey) ProtoMessage() {} + +func (x *PubKey) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_crypto_secp256k1_keys_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PubKey.ProtoReflect.Descriptor instead. +func (*PubKey) Descriptor() ([]byte, []int) { + return file_cosmos_crypto_secp256k1_keys_proto_rawDescGZIP(), []int{0} +} + +func (x *PubKey) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} + +var File_cosmos_crypto_secp256k1_keys_proto protoreflect.FileDescriptor + +const file_cosmos_crypto_secp256k1_keys_proto_rawDesc = "" + + "\n" + + "\"cosmos/crypto/secp256k1/keys.proto\x12\x17cosmos.crypto.secp256k1\"\x1a\n" + + "\x06PubKey\x12\x10\n" + + "\x03key\x18\x01 \x01(\fR\x03keyBLZJgithub.com/evstack/apex/pkg/api/grpc/gen/cosmos/crypto/secp256k1;secp256k1b\x06proto3" + +var ( + file_cosmos_crypto_secp256k1_keys_proto_rawDescOnce sync.Once + file_cosmos_crypto_secp256k1_keys_proto_rawDescData []byte +) + +func file_cosmos_crypto_secp256k1_keys_proto_rawDescGZIP() []byte { + file_cosmos_crypto_secp256k1_keys_proto_rawDescOnce.Do(func() { + file_cosmos_crypto_secp256k1_keys_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_cosmos_crypto_secp256k1_keys_proto_rawDesc), len(file_cosmos_crypto_secp256k1_keys_proto_rawDesc))) + }) + return file_cosmos_crypto_secp256k1_keys_proto_rawDescData +} + +var file_cosmos_crypto_secp256k1_keys_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_cosmos_crypto_secp256k1_keys_proto_goTypes = []any{ + (*PubKey)(nil), // 0: cosmos.crypto.secp256k1.PubKey +} +var file_cosmos_crypto_secp256k1_keys_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_cosmos_crypto_secp256k1_keys_proto_init() } +func file_cosmos_crypto_secp256k1_keys_proto_init() { + if File_cosmos_crypto_secp256k1_keys_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_cosmos_crypto_secp256k1_keys_proto_rawDesc), len(file_cosmos_crypto_secp256k1_keys_proto_rawDesc)), + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_cosmos_crypto_secp256k1_keys_proto_goTypes, + DependencyIndexes: file_cosmos_crypto_secp256k1_keys_proto_depIdxs, + MessageInfos: file_cosmos_crypto_secp256k1_keys_proto_msgTypes, + }.Build() + File_cosmos_crypto_secp256k1_keys_proto = out.File + file_cosmos_crypto_secp256k1_keys_proto_goTypes = nil + file_cosmos_crypto_secp256k1_keys_proto_depIdxs = nil +} diff --git a/pkg/api/grpc/gen/cosmos/tx/signing/v1beta1/signing.pb.go b/pkg/api/grpc/gen/cosmos/tx/signing/v1beta1/signing.pb.go new file mode 100644 index 0000000..2f0dfec --- /dev/null +++ b/pkg/api/grpc/gen/cosmos/tx/signing/v1beta1/signing.pb.go @@ -0,0 +1,125 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: cosmos/tx/signing/v1beta1/signing.proto + +package signingv1beta1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type SignMode int32 + +const ( + SignMode_SIGN_MODE_UNSPECIFIED SignMode = 0 + SignMode_SIGN_MODE_DIRECT SignMode = 1 +) + +// Enum value maps for SignMode. +var ( + SignMode_name = map[int32]string{ + 0: "SIGN_MODE_UNSPECIFIED", + 1: "SIGN_MODE_DIRECT", + } + SignMode_value = map[string]int32{ + "SIGN_MODE_UNSPECIFIED": 0, + "SIGN_MODE_DIRECT": 1, + } +) + +func (x SignMode) Enum() *SignMode { + p := new(SignMode) + *p = x + return p +} + +func (x SignMode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SignMode) Descriptor() protoreflect.EnumDescriptor { + return file_cosmos_tx_signing_v1beta1_signing_proto_enumTypes[0].Descriptor() +} + +func (SignMode) Type() protoreflect.EnumType { + return &file_cosmos_tx_signing_v1beta1_signing_proto_enumTypes[0] +} + +func (x SignMode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SignMode.Descriptor instead. +func (SignMode) EnumDescriptor() ([]byte, []int) { + return file_cosmos_tx_signing_v1beta1_signing_proto_rawDescGZIP(), []int{0} +} + +var File_cosmos_tx_signing_v1beta1_signing_proto protoreflect.FileDescriptor + +const file_cosmos_tx_signing_v1beta1_signing_proto_rawDesc = "" + + "\n" + + "'cosmos/tx/signing/v1beta1/signing.proto\x12\x19cosmos.tx.signing.v1beta1*;\n" + + "\bSignMode\x12\x19\n" + + "\x15SIGN_MODE_UNSPECIFIED\x10\x00\x12\x14\n" + + "\x10SIGN_MODE_DIRECT\x10\x01BSZQgithub.com/evstack/apex/pkg/api/grpc/gen/cosmos/tx/signing/v1beta1;signingv1beta1b\x06proto3" + +var ( + file_cosmos_tx_signing_v1beta1_signing_proto_rawDescOnce sync.Once + file_cosmos_tx_signing_v1beta1_signing_proto_rawDescData []byte +) + +func file_cosmos_tx_signing_v1beta1_signing_proto_rawDescGZIP() []byte { + file_cosmos_tx_signing_v1beta1_signing_proto_rawDescOnce.Do(func() { + file_cosmos_tx_signing_v1beta1_signing_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_cosmos_tx_signing_v1beta1_signing_proto_rawDesc), len(file_cosmos_tx_signing_v1beta1_signing_proto_rawDesc))) + }) + return file_cosmos_tx_signing_v1beta1_signing_proto_rawDescData +} + +var file_cosmos_tx_signing_v1beta1_signing_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_cosmos_tx_signing_v1beta1_signing_proto_goTypes = []any{ + (SignMode)(0), // 0: cosmos.tx.signing.v1beta1.SignMode +} +var file_cosmos_tx_signing_v1beta1_signing_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_cosmos_tx_signing_v1beta1_signing_proto_init() } +func file_cosmos_tx_signing_v1beta1_signing_proto_init() { + if File_cosmos_tx_signing_v1beta1_signing_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_cosmos_tx_signing_v1beta1_signing_proto_rawDesc), len(file_cosmos_tx_signing_v1beta1_signing_proto_rawDesc)), + NumEnums: 1, + NumMessages: 0, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_cosmos_tx_signing_v1beta1_signing_proto_goTypes, + DependencyIndexes: file_cosmos_tx_signing_v1beta1_signing_proto_depIdxs, + EnumInfos: file_cosmos_tx_signing_v1beta1_signing_proto_enumTypes, + }.Build() + File_cosmos_tx_signing_v1beta1_signing_proto = out.File + file_cosmos_tx_signing_v1beta1_signing_proto_goTypes = nil + file_cosmos_tx_signing_v1beta1_signing_proto_depIdxs = nil +} diff --git a/pkg/api/grpc/gen/cosmos/tx/v1beta1/service.pb.go b/pkg/api/grpc/gen/cosmos/tx/v1beta1/service.pb.go new file mode 100644 index 0000000..8d69fc0 --- /dev/null +++ b/pkg/api/grpc/gen/cosmos/tx/v1beta1/service.pb.go @@ -0,0 +1,346 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: cosmos/tx/v1beta1/service.proto + +package txv1beta1 + +import ( + v1beta1 "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/base/abci/v1beta1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type BroadcastMode int32 + +const ( + BroadcastMode_BROADCAST_MODE_UNSPECIFIED BroadcastMode = 0 + BroadcastMode_BROADCAST_MODE_BLOCK BroadcastMode = 1 + BroadcastMode_BROADCAST_MODE_SYNC BroadcastMode = 2 + BroadcastMode_BROADCAST_MODE_ASYNC BroadcastMode = 3 +) + +// Enum value maps for BroadcastMode. +var ( + BroadcastMode_name = map[int32]string{ + 0: "BROADCAST_MODE_UNSPECIFIED", + 1: "BROADCAST_MODE_BLOCK", + 2: "BROADCAST_MODE_SYNC", + 3: "BROADCAST_MODE_ASYNC", + } + BroadcastMode_value = map[string]int32{ + "BROADCAST_MODE_UNSPECIFIED": 0, + "BROADCAST_MODE_BLOCK": 1, + "BROADCAST_MODE_SYNC": 2, + "BROADCAST_MODE_ASYNC": 3, + } +) + +func (x BroadcastMode) Enum() *BroadcastMode { + p := new(BroadcastMode) + *p = x + return p +} + +func (x BroadcastMode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (BroadcastMode) Descriptor() protoreflect.EnumDescriptor { + return file_cosmos_tx_v1beta1_service_proto_enumTypes[0].Descriptor() +} + +func (BroadcastMode) Type() protoreflect.EnumType { + return &file_cosmos_tx_v1beta1_service_proto_enumTypes[0] +} + +func (x BroadcastMode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use BroadcastMode.Descriptor instead. +func (BroadcastMode) EnumDescriptor() ([]byte, []int) { + return file_cosmos_tx_v1beta1_service_proto_rawDescGZIP(), []int{0} +} + +type BroadcastTxRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + TxBytes []byte `protobuf:"bytes,1,opt,name=tx_bytes,json=txBytes,proto3" json:"tx_bytes,omitempty"` + Mode BroadcastMode `protobuf:"varint,2,opt,name=mode,proto3,enum=cosmos.tx.v1beta1.BroadcastMode" json:"mode,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BroadcastTxRequest) Reset() { + *x = BroadcastTxRequest{} + mi := &file_cosmos_tx_v1beta1_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BroadcastTxRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BroadcastTxRequest) ProtoMessage() {} + +func (x *BroadcastTxRequest) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_tx_v1beta1_service_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BroadcastTxRequest.ProtoReflect.Descriptor instead. +func (*BroadcastTxRequest) Descriptor() ([]byte, []int) { + return file_cosmos_tx_v1beta1_service_proto_rawDescGZIP(), []int{0} +} + +func (x *BroadcastTxRequest) GetTxBytes() []byte { + if x != nil { + return x.TxBytes + } + return nil +} + +func (x *BroadcastTxRequest) GetMode() BroadcastMode { + if x != nil { + return x.Mode + } + return BroadcastMode_BROADCAST_MODE_UNSPECIFIED +} + +type BroadcastTxResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + TxResponse *v1beta1.TxResponse `protobuf:"bytes,1,opt,name=tx_response,json=txResponse,proto3" json:"tx_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BroadcastTxResponse) Reset() { + *x = BroadcastTxResponse{} + mi := &file_cosmos_tx_v1beta1_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BroadcastTxResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BroadcastTxResponse) ProtoMessage() {} + +func (x *BroadcastTxResponse) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_tx_v1beta1_service_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BroadcastTxResponse.ProtoReflect.Descriptor instead. +func (*BroadcastTxResponse) Descriptor() ([]byte, []int) { + return file_cosmos_tx_v1beta1_service_proto_rawDescGZIP(), []int{1} +} + +func (x *BroadcastTxResponse) GetTxResponse() *v1beta1.TxResponse { + if x != nil { + return x.TxResponse + } + return nil +} + +type GetTxRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTxRequest) Reset() { + *x = GetTxRequest{} + mi := &file_cosmos_tx_v1beta1_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTxRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTxRequest) ProtoMessage() {} + +func (x *GetTxRequest) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_tx_v1beta1_service_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTxRequest.ProtoReflect.Descriptor instead. +func (*GetTxRequest) Descriptor() ([]byte, []int) { + return file_cosmos_tx_v1beta1_service_proto_rawDescGZIP(), []int{2} +} + +func (x *GetTxRequest) GetHash() string { + if x != nil { + return x.Hash + } + return "" +} + +type GetTxResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + TxResponse *v1beta1.TxResponse `protobuf:"bytes,2,opt,name=tx_response,json=txResponse,proto3" json:"tx_response,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTxResponse) Reset() { + *x = GetTxResponse{} + mi := &file_cosmos_tx_v1beta1_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTxResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTxResponse) ProtoMessage() {} + +func (x *GetTxResponse) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_tx_v1beta1_service_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTxResponse.ProtoReflect.Descriptor instead. +func (*GetTxResponse) Descriptor() ([]byte, []int) { + return file_cosmos_tx_v1beta1_service_proto_rawDescGZIP(), []int{3} +} + +func (x *GetTxResponse) GetTxResponse() *v1beta1.TxResponse { + if x != nil { + return x.TxResponse + } + return nil +} + +var File_cosmos_tx_v1beta1_service_proto protoreflect.FileDescriptor + +const file_cosmos_tx_v1beta1_service_proto_rawDesc = "" + + "\n" + + "\x1fcosmos/tx/v1beta1/service.proto\x12\x11cosmos.tx.v1beta1\x1a#cosmos/base/abci/v1beta1/abci.proto\"e\n" + + "\x12BroadcastTxRequest\x12\x19\n" + + "\btx_bytes\x18\x01 \x01(\fR\atxBytes\x124\n" + + "\x04mode\x18\x02 \x01(\x0e2 .cosmos.tx.v1beta1.BroadcastModeR\x04mode\"\\\n" + + "\x13BroadcastTxResponse\x12E\n" + + "\vtx_response\x18\x01 \x01(\v2$.cosmos.base.abci.v1beta1.TxResponseR\n" + + "txResponse\"\"\n" + + "\fGetTxRequest\x12\x12\n" + + "\x04hash\x18\x01 \x01(\tR\x04hash\"V\n" + + "\rGetTxResponse\x12E\n" + + "\vtx_response\x18\x02 \x01(\v2$.cosmos.base.abci.v1beta1.TxResponseR\n" + + "txResponse*|\n" + + "\rBroadcastMode\x12\x1e\n" + + "\x1aBROADCAST_MODE_UNSPECIFIED\x10\x00\x12\x18\n" + + "\x14BROADCAST_MODE_BLOCK\x10\x01\x12\x17\n" + + "\x13BROADCAST_MODE_SYNC\x10\x02\x12\x18\n" + + "\x14BROADCAST_MODE_ASYNC\x10\x032\xb3\x01\n" + + "\aService\x12\\\n" + + "\vBroadcastTx\x12%.cosmos.tx.v1beta1.BroadcastTxRequest\x1a&.cosmos.tx.v1beta1.BroadcastTxResponse\x12J\n" + + "\x05GetTx\x12\x1f.cosmos.tx.v1beta1.GetTxRequest\x1a .cosmos.tx.v1beta1.GetTxResponseBFZDgithub.com/evstack/apex/pkg/api/grpc/gen/cosmos/tx/v1beta1;txv1beta1b\x06proto3" + +var ( + file_cosmos_tx_v1beta1_service_proto_rawDescOnce sync.Once + file_cosmos_tx_v1beta1_service_proto_rawDescData []byte +) + +func file_cosmos_tx_v1beta1_service_proto_rawDescGZIP() []byte { + file_cosmos_tx_v1beta1_service_proto_rawDescOnce.Do(func() { + file_cosmos_tx_v1beta1_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_cosmos_tx_v1beta1_service_proto_rawDesc), len(file_cosmos_tx_v1beta1_service_proto_rawDesc))) + }) + return file_cosmos_tx_v1beta1_service_proto_rawDescData +} + +var file_cosmos_tx_v1beta1_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_cosmos_tx_v1beta1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_cosmos_tx_v1beta1_service_proto_goTypes = []any{ + (BroadcastMode)(0), // 0: cosmos.tx.v1beta1.BroadcastMode + (*BroadcastTxRequest)(nil), // 1: cosmos.tx.v1beta1.BroadcastTxRequest + (*BroadcastTxResponse)(nil), // 2: cosmos.tx.v1beta1.BroadcastTxResponse + (*GetTxRequest)(nil), // 3: cosmos.tx.v1beta1.GetTxRequest + (*GetTxResponse)(nil), // 4: cosmos.tx.v1beta1.GetTxResponse + (*v1beta1.TxResponse)(nil), // 5: cosmos.base.abci.v1beta1.TxResponse +} +var file_cosmos_tx_v1beta1_service_proto_depIdxs = []int32{ + 0, // 0: cosmos.tx.v1beta1.BroadcastTxRequest.mode:type_name -> cosmos.tx.v1beta1.BroadcastMode + 5, // 1: cosmos.tx.v1beta1.BroadcastTxResponse.tx_response:type_name -> cosmos.base.abci.v1beta1.TxResponse + 5, // 2: cosmos.tx.v1beta1.GetTxResponse.tx_response:type_name -> cosmos.base.abci.v1beta1.TxResponse + 1, // 3: cosmos.tx.v1beta1.Service.BroadcastTx:input_type -> cosmos.tx.v1beta1.BroadcastTxRequest + 3, // 4: cosmos.tx.v1beta1.Service.GetTx:input_type -> cosmos.tx.v1beta1.GetTxRequest + 2, // 5: cosmos.tx.v1beta1.Service.BroadcastTx:output_type -> cosmos.tx.v1beta1.BroadcastTxResponse + 4, // 6: cosmos.tx.v1beta1.Service.GetTx:output_type -> cosmos.tx.v1beta1.GetTxResponse + 5, // [5:7] is the sub-list for method output_type + 3, // [3:5] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_cosmos_tx_v1beta1_service_proto_init() } +func file_cosmos_tx_v1beta1_service_proto_init() { + if File_cosmos_tx_v1beta1_service_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_cosmos_tx_v1beta1_service_proto_rawDesc), len(file_cosmos_tx_v1beta1_service_proto_rawDesc)), + NumEnums: 1, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_cosmos_tx_v1beta1_service_proto_goTypes, + DependencyIndexes: file_cosmos_tx_v1beta1_service_proto_depIdxs, + EnumInfos: file_cosmos_tx_v1beta1_service_proto_enumTypes, + MessageInfos: file_cosmos_tx_v1beta1_service_proto_msgTypes, + }.Build() + File_cosmos_tx_v1beta1_service_proto = out.File + file_cosmos_tx_v1beta1_service_proto_goTypes = nil + file_cosmos_tx_v1beta1_service_proto_depIdxs = nil +} diff --git a/pkg/api/grpc/gen/cosmos/tx/v1beta1/service_grpc.pb.go b/pkg/api/grpc/gen/cosmos/tx/v1beta1/service_grpc.pb.go new file mode 100644 index 0000000..bbdc2bc --- /dev/null +++ b/pkg/api/grpc/gen/cosmos/tx/v1beta1/service_grpc.pb.go @@ -0,0 +1,159 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.1 +// - protoc (unknown) +// source: cosmos/tx/v1beta1/service.proto + +package txv1beta1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + Service_BroadcastTx_FullMethodName = "/cosmos.tx.v1beta1.Service/BroadcastTx" + Service_GetTx_FullMethodName = "/cosmos.tx.v1beta1.Service/GetTx" +) + +// ServiceClient is the client API for Service service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type ServiceClient interface { + BroadcastTx(ctx context.Context, in *BroadcastTxRequest, opts ...grpc.CallOption) (*BroadcastTxResponse, error) + GetTx(ctx context.Context, in *GetTxRequest, opts ...grpc.CallOption) (*GetTxResponse, error) +} + +type serviceClient struct { + cc grpc.ClientConnInterface +} + +func NewServiceClient(cc grpc.ClientConnInterface) ServiceClient { + return &serviceClient{cc} +} + +func (c *serviceClient) BroadcastTx(ctx context.Context, in *BroadcastTxRequest, opts ...grpc.CallOption) (*BroadcastTxResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(BroadcastTxResponse) + err := c.cc.Invoke(ctx, Service_BroadcastTx_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *serviceClient) GetTx(ctx context.Context, in *GetTxRequest, opts ...grpc.CallOption) (*GetTxResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetTxResponse) + err := c.cc.Invoke(ctx, Service_GetTx_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ServiceServer is the server API for Service service. +// All implementations must embed UnimplementedServiceServer +// for forward compatibility. +type ServiceServer interface { + BroadcastTx(context.Context, *BroadcastTxRequest) (*BroadcastTxResponse, error) + GetTx(context.Context, *GetTxRequest) (*GetTxResponse, error) + mustEmbedUnimplementedServiceServer() +} + +// UnimplementedServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedServiceServer struct{} + +func (UnimplementedServiceServer) BroadcastTx(context.Context, *BroadcastTxRequest) (*BroadcastTxResponse, error) { + return nil, status.Error(codes.Unimplemented, "method BroadcastTx not implemented") +} +func (UnimplementedServiceServer) GetTx(context.Context, *GetTxRequest) (*GetTxResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetTx not implemented") +} +func (UnimplementedServiceServer) mustEmbedUnimplementedServiceServer() {} +func (UnimplementedServiceServer) testEmbeddedByValue() {} + +// UnsafeServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ServiceServer will +// result in compilation errors. +type UnsafeServiceServer interface { + mustEmbedUnimplementedServiceServer() +} + +func RegisterServiceServer(s grpc.ServiceRegistrar, srv ServiceServer) { + // If the following call panics, it indicates UnimplementedServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&Service_ServiceDesc, srv) +} + +func _Service_BroadcastTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BroadcastTxRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ServiceServer).BroadcastTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Service_BroadcastTx_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ServiceServer).BroadcastTx(ctx, req.(*BroadcastTxRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Service_GetTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTxRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ServiceServer).GetTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Service_GetTx_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ServiceServer).GetTx(ctx, req.(*GetTxRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Service_ServiceDesc is the grpc.ServiceDesc for Service service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Service_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "cosmos.tx.v1beta1.Service", + HandlerType: (*ServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "BroadcastTx", + Handler: _Service_BroadcastTx_Handler, + }, + { + MethodName: "GetTx", + Handler: _Service_GetTx_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cosmos/tx/v1beta1/service.proto", +} diff --git a/pkg/api/grpc/gen/cosmos/tx/v1beta1/tx.pb.go b/pkg/api/grpc/gen/cosmos/tx/v1beta1/tx.pb.go new file mode 100644 index 0000000..8ece9bb --- /dev/null +++ b/pkg/api/grpc/gen/cosmos/tx/v1beta1/tx.pb.go @@ -0,0 +1,614 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: cosmos/tx/v1beta1/tx.proto + +package txv1beta1 + +import ( + v1beta1 "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/base/v1beta1" + v1beta11 "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/tx/signing/v1beta1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + anypb "google.golang.org/protobuf/types/known/anypb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type TxRaw struct { + state protoimpl.MessageState `protogen:"open.v1"` + BodyBytes []byte `protobuf:"bytes,1,opt,name=body_bytes,json=bodyBytes,proto3" json:"body_bytes,omitempty"` + AuthInfoBytes []byte `protobuf:"bytes,2,opt,name=auth_info_bytes,json=authInfoBytes,proto3" json:"auth_info_bytes,omitempty"` + Signatures [][]byte `protobuf:"bytes,3,rep,name=signatures,proto3" json:"signatures,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TxRaw) Reset() { + *x = TxRaw{} + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TxRaw) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TxRaw) ProtoMessage() {} + +func (x *TxRaw) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TxRaw.ProtoReflect.Descriptor instead. +func (*TxRaw) Descriptor() ([]byte, []int) { + return file_cosmos_tx_v1beta1_tx_proto_rawDescGZIP(), []int{0} +} + +func (x *TxRaw) GetBodyBytes() []byte { + if x != nil { + return x.BodyBytes + } + return nil +} + +func (x *TxRaw) GetAuthInfoBytes() []byte { + if x != nil { + return x.AuthInfoBytes + } + return nil +} + +func (x *TxRaw) GetSignatures() [][]byte { + if x != nil { + return x.Signatures + } + return nil +} + +type SignDoc struct { + state protoimpl.MessageState `protogen:"open.v1"` + BodyBytes []byte `protobuf:"bytes,1,opt,name=body_bytes,json=bodyBytes,proto3" json:"body_bytes,omitempty"` + AuthInfoBytes []byte `protobuf:"bytes,2,opt,name=auth_info_bytes,json=authInfoBytes,proto3" json:"auth_info_bytes,omitempty"` + ChainId string `protobuf:"bytes,3,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + AccountNumber uint64 `protobuf:"varint,4,opt,name=account_number,json=accountNumber,proto3" json:"account_number,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SignDoc) Reset() { + *x = SignDoc{} + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SignDoc) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignDoc) ProtoMessage() {} + +func (x *SignDoc) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignDoc.ProtoReflect.Descriptor instead. +func (*SignDoc) Descriptor() ([]byte, []int) { + return file_cosmos_tx_v1beta1_tx_proto_rawDescGZIP(), []int{1} +} + +func (x *SignDoc) GetBodyBytes() []byte { + if x != nil { + return x.BodyBytes + } + return nil +} + +func (x *SignDoc) GetAuthInfoBytes() []byte { + if x != nil { + return x.AuthInfoBytes + } + return nil +} + +func (x *SignDoc) GetChainId() string { + if x != nil { + return x.ChainId + } + return "" +} + +func (x *SignDoc) GetAccountNumber() uint64 { + if x != nil { + return x.AccountNumber + } + return 0 +} + +type TxBody struct { + state protoimpl.MessageState `protogen:"open.v1"` + Messages []*anypb.Any `protobuf:"bytes,1,rep,name=messages,proto3" json:"messages,omitempty"` + Memo string `protobuf:"bytes,2,opt,name=memo,proto3" json:"memo,omitempty"` + TimeoutHeight uint64 `protobuf:"varint,3,opt,name=timeout_height,json=timeoutHeight,proto3" json:"timeout_height,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TxBody) Reset() { + *x = TxBody{} + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TxBody) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TxBody) ProtoMessage() {} + +func (x *TxBody) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TxBody.ProtoReflect.Descriptor instead. +func (*TxBody) Descriptor() ([]byte, []int) { + return file_cosmos_tx_v1beta1_tx_proto_rawDescGZIP(), []int{2} +} + +func (x *TxBody) GetMessages() []*anypb.Any { + if x != nil { + return x.Messages + } + return nil +} + +func (x *TxBody) GetMemo() string { + if x != nil { + return x.Memo + } + return "" +} + +func (x *TxBody) GetTimeoutHeight() uint64 { + if x != nil { + return x.TimeoutHeight + } + return 0 +} + +type AuthInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + SignerInfos []*SignerInfo `protobuf:"bytes,1,rep,name=signer_infos,json=signerInfos,proto3" json:"signer_infos,omitempty"` + Fee *Fee `protobuf:"bytes,2,opt,name=fee,proto3" json:"fee,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AuthInfo) Reset() { + *x = AuthInfo{} + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AuthInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AuthInfo) ProtoMessage() {} + +func (x *AuthInfo) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AuthInfo.ProtoReflect.Descriptor instead. +func (*AuthInfo) Descriptor() ([]byte, []int) { + return file_cosmos_tx_v1beta1_tx_proto_rawDescGZIP(), []int{3} +} + +func (x *AuthInfo) GetSignerInfos() []*SignerInfo { + if x != nil { + return x.SignerInfos + } + return nil +} + +func (x *AuthInfo) GetFee() *Fee { + if x != nil { + return x.Fee + } + return nil +} + +type SignerInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + PublicKey *anypb.Any `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` + ModeInfo *ModeInfo `protobuf:"bytes,2,opt,name=mode_info,json=modeInfo,proto3" json:"mode_info,omitempty"` + Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SignerInfo) Reset() { + *x = SignerInfo{} + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SignerInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignerInfo) ProtoMessage() {} + +func (x *SignerInfo) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignerInfo.ProtoReflect.Descriptor instead. +func (*SignerInfo) Descriptor() ([]byte, []int) { + return file_cosmos_tx_v1beta1_tx_proto_rawDescGZIP(), []int{4} +} + +func (x *SignerInfo) GetPublicKey() *anypb.Any { + if x != nil { + return x.PublicKey + } + return nil +} + +func (x *SignerInfo) GetModeInfo() *ModeInfo { + if x != nil { + return x.ModeInfo + } + return nil +} + +func (x *SignerInfo) GetSequence() uint64 { + if x != nil { + return x.Sequence + } + return 0 +} + +type ModeInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Sum: + // + // *ModeInfo_Single_ + Sum isModeInfo_Sum `protobuf_oneof:"sum"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ModeInfo) Reset() { + *x = ModeInfo{} + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ModeInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ModeInfo) ProtoMessage() {} + +func (x *ModeInfo) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ModeInfo.ProtoReflect.Descriptor instead. +func (*ModeInfo) Descriptor() ([]byte, []int) { + return file_cosmos_tx_v1beta1_tx_proto_rawDescGZIP(), []int{5} +} + +func (x *ModeInfo) GetSum() isModeInfo_Sum { + if x != nil { + return x.Sum + } + return nil +} + +func (x *ModeInfo) GetSingle() *ModeInfo_Single { + if x != nil { + if x, ok := x.Sum.(*ModeInfo_Single_); ok { + return x.Single + } + } + return nil +} + +type isModeInfo_Sum interface { + isModeInfo_Sum() +} + +type ModeInfo_Single_ struct { + Single *ModeInfo_Single `protobuf:"bytes,1,opt,name=single,proto3,oneof"` +} + +func (*ModeInfo_Single_) isModeInfo_Sum() {} + +type Fee struct { + state protoimpl.MessageState `protogen:"open.v1"` + Amount []*v1beta1.Coin `protobuf:"bytes,1,rep,name=amount,proto3" json:"amount,omitempty"` + GasLimit uint64 `protobuf:"varint,2,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty"` + Payer string `protobuf:"bytes,3,opt,name=payer,proto3" json:"payer,omitempty"` + Granter string `protobuf:"bytes,4,opt,name=granter,proto3" json:"granter,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Fee) Reset() { + *x = Fee{} + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Fee) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Fee) ProtoMessage() {} + +func (x *Fee) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Fee.ProtoReflect.Descriptor instead. +func (*Fee) Descriptor() ([]byte, []int) { + return file_cosmos_tx_v1beta1_tx_proto_rawDescGZIP(), []int{6} +} + +func (x *Fee) GetAmount() []*v1beta1.Coin { + if x != nil { + return x.Amount + } + return nil +} + +func (x *Fee) GetGasLimit() uint64 { + if x != nil { + return x.GasLimit + } + return 0 +} + +func (x *Fee) GetPayer() string { + if x != nil { + return x.Payer + } + return "" +} + +func (x *Fee) GetGranter() string { + if x != nil { + return x.Granter + } + return "" +} + +type ModeInfo_Single struct { + state protoimpl.MessageState `protogen:"open.v1"` + Mode v1beta11.SignMode `protobuf:"varint,1,opt,name=mode,proto3,enum=cosmos.tx.signing.v1beta1.SignMode" json:"mode,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ModeInfo_Single) Reset() { + *x = ModeInfo_Single{} + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ModeInfo_Single) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ModeInfo_Single) ProtoMessage() {} + +func (x *ModeInfo_Single) ProtoReflect() protoreflect.Message { + mi := &file_cosmos_tx_v1beta1_tx_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ModeInfo_Single.ProtoReflect.Descriptor instead. +func (*ModeInfo_Single) Descriptor() ([]byte, []int) { + return file_cosmos_tx_v1beta1_tx_proto_rawDescGZIP(), []int{5, 0} +} + +func (x *ModeInfo_Single) GetMode() v1beta11.SignMode { + if x != nil { + return x.Mode + } + return v1beta11.SignMode(0) +} + +var File_cosmos_tx_v1beta1_tx_proto protoreflect.FileDescriptor + +const file_cosmos_tx_v1beta1_tx_proto_rawDesc = "" + + "\n" + + "\x1acosmos/tx/v1beta1/tx.proto\x12\x11cosmos.tx.v1beta1\x1a\x1ecosmos/base/v1beta1/coin.proto\x1a'cosmos/tx/signing/v1beta1/signing.proto\x1a\x19google/protobuf/any.proto\"n\n" + + "\x05TxRaw\x12\x1d\n" + + "\n" + + "body_bytes\x18\x01 \x01(\fR\tbodyBytes\x12&\n" + + "\x0fauth_info_bytes\x18\x02 \x01(\fR\rauthInfoBytes\x12\x1e\n" + + "\n" + + "signatures\x18\x03 \x03(\fR\n" + + "signatures\"\x92\x01\n" + + "\aSignDoc\x12\x1d\n" + + "\n" + + "body_bytes\x18\x01 \x01(\fR\tbodyBytes\x12&\n" + + "\x0fauth_info_bytes\x18\x02 \x01(\fR\rauthInfoBytes\x12\x19\n" + + "\bchain_id\x18\x03 \x01(\tR\achainId\x12%\n" + + "\x0eaccount_number\x18\x04 \x01(\x04R\raccountNumber\"u\n" + + "\x06TxBody\x120\n" + + "\bmessages\x18\x01 \x03(\v2\x14.google.protobuf.AnyR\bmessages\x12\x12\n" + + "\x04memo\x18\x02 \x01(\tR\x04memo\x12%\n" + + "\x0etimeout_height\x18\x03 \x01(\x04R\rtimeoutHeight\"v\n" + + "\bAuthInfo\x12@\n" + + "\fsigner_infos\x18\x01 \x03(\v2\x1d.cosmos.tx.v1beta1.SignerInfoR\vsignerInfos\x12(\n" + + "\x03fee\x18\x02 \x01(\v2\x16.cosmos.tx.v1beta1.FeeR\x03fee\"\x97\x01\n" + + "\n" + + "SignerInfo\x123\n" + + "\n" + + "public_key\x18\x01 \x01(\v2\x14.google.protobuf.AnyR\tpublicKey\x128\n" + + "\tmode_info\x18\x02 \x01(\v2\x1b.cosmos.tx.v1beta1.ModeInfoR\bmodeInfo\x12\x1a\n" + + "\bsequence\x18\x03 \x01(\x04R\bsequence\"\x92\x01\n" + + "\bModeInfo\x12<\n" + + "\x06single\x18\x01 \x01(\v2\".cosmos.tx.v1beta1.ModeInfo.SingleH\x00R\x06single\x1aA\n" + + "\x06Single\x127\n" + + "\x04mode\x18\x01 \x01(\x0e2#.cosmos.tx.signing.v1beta1.SignModeR\x04modeB\x05\n" + + "\x03sum\"\x85\x01\n" + + "\x03Fee\x121\n" + + "\x06amount\x18\x01 \x03(\v2\x19.cosmos.base.v1beta1.CoinR\x06amount\x12\x1b\n" + + "\tgas_limit\x18\x02 \x01(\x04R\bgasLimit\x12\x14\n" + + "\x05payer\x18\x03 \x01(\tR\x05payer\x12\x18\n" + + "\agranter\x18\x04 \x01(\tR\agranterBFZDgithub.com/evstack/apex/pkg/api/grpc/gen/cosmos/tx/v1beta1;txv1beta1b\x06proto3" + +var ( + file_cosmos_tx_v1beta1_tx_proto_rawDescOnce sync.Once + file_cosmos_tx_v1beta1_tx_proto_rawDescData []byte +) + +func file_cosmos_tx_v1beta1_tx_proto_rawDescGZIP() []byte { + file_cosmos_tx_v1beta1_tx_proto_rawDescOnce.Do(func() { + file_cosmos_tx_v1beta1_tx_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_cosmos_tx_v1beta1_tx_proto_rawDesc), len(file_cosmos_tx_v1beta1_tx_proto_rawDesc))) + }) + return file_cosmos_tx_v1beta1_tx_proto_rawDescData +} + +var file_cosmos_tx_v1beta1_tx_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_cosmos_tx_v1beta1_tx_proto_goTypes = []any{ + (*TxRaw)(nil), // 0: cosmos.tx.v1beta1.TxRaw + (*SignDoc)(nil), // 1: cosmos.tx.v1beta1.SignDoc + (*TxBody)(nil), // 2: cosmos.tx.v1beta1.TxBody + (*AuthInfo)(nil), // 3: cosmos.tx.v1beta1.AuthInfo + (*SignerInfo)(nil), // 4: cosmos.tx.v1beta1.SignerInfo + (*ModeInfo)(nil), // 5: cosmos.tx.v1beta1.ModeInfo + (*Fee)(nil), // 6: cosmos.tx.v1beta1.Fee + (*ModeInfo_Single)(nil), // 7: cosmos.tx.v1beta1.ModeInfo.Single + (*anypb.Any)(nil), // 8: google.protobuf.Any + (*v1beta1.Coin)(nil), // 9: cosmos.base.v1beta1.Coin + (v1beta11.SignMode)(0), // 10: cosmos.tx.signing.v1beta1.SignMode +} +var file_cosmos_tx_v1beta1_tx_proto_depIdxs = []int32{ + 8, // 0: cosmos.tx.v1beta1.TxBody.messages:type_name -> google.protobuf.Any + 4, // 1: cosmos.tx.v1beta1.AuthInfo.signer_infos:type_name -> cosmos.tx.v1beta1.SignerInfo + 6, // 2: cosmos.tx.v1beta1.AuthInfo.fee:type_name -> cosmos.tx.v1beta1.Fee + 8, // 3: cosmos.tx.v1beta1.SignerInfo.public_key:type_name -> google.protobuf.Any + 5, // 4: cosmos.tx.v1beta1.SignerInfo.mode_info:type_name -> cosmos.tx.v1beta1.ModeInfo + 7, // 5: cosmos.tx.v1beta1.ModeInfo.single:type_name -> cosmos.tx.v1beta1.ModeInfo.Single + 9, // 6: cosmos.tx.v1beta1.Fee.amount:type_name -> cosmos.base.v1beta1.Coin + 10, // 7: cosmos.tx.v1beta1.ModeInfo.Single.mode:type_name -> cosmos.tx.signing.v1beta1.SignMode + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name +} + +func init() { file_cosmos_tx_v1beta1_tx_proto_init() } +func file_cosmos_tx_v1beta1_tx_proto_init() { + if File_cosmos_tx_v1beta1_tx_proto != nil { + return + } + file_cosmos_tx_v1beta1_tx_proto_msgTypes[5].OneofWrappers = []any{ + (*ModeInfo_Single_)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_cosmos_tx_v1beta1_tx_proto_rawDesc), len(file_cosmos_tx_v1beta1_tx_proto_rawDesc)), + NumEnums: 0, + NumMessages: 8, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_cosmos_tx_v1beta1_tx_proto_goTypes, + DependencyIndexes: file_cosmos_tx_v1beta1_tx_proto_depIdxs, + MessageInfos: file_cosmos_tx_v1beta1_tx_proto_msgTypes, + }.Build() + File_cosmos_tx_v1beta1_tx_proto = out.File + file_cosmos_tx_v1beta1_tx_proto_goTypes = nil + file_cosmos_tx_v1beta1_tx_proto_depIdxs = nil +} diff --git a/pkg/api/grpc/server_test.go b/pkg/api/grpc/server_test.go index f0fb109..f73444a 100644 --- a/pkg/api/grpc/server_test.go +++ b/pkg/api/grpc/server_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + gsquare "github.com/celestiaorg/go-square/v3/share" "github.com/rs/zerolog" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -129,8 +130,9 @@ func (f *mockFetcher) SubscribeHeaders(_ context.Context) (<-chan *types.Header, func (f *mockFetcher) Close() error { return nil } func testNamespace(b byte) types.Namespace { + namespace := gsquare.MustNewV0Namespace([]byte("apexns" + string([]byte{b}))) var ns types.Namespace - ns[types.NamespaceSize-1] = b + copy(ns[:], namespace.Bytes()) return ns } diff --git a/pkg/api/jsonrpc/blob.go b/pkg/api/jsonrpc/blob.go index 79357c1..f3b6f80 100644 --- a/pkg/api/jsonrpc/blob.go +++ b/pkg/api/jsonrpc/blob.go @@ -3,9 +3,10 @@ package jsonrpc import ( "context" "encoding/json" - "fmt" + "errors" "github.com/evstack/apex/pkg/api" + "github.com/evstack/apex/pkg/submit" "github.com/evstack/apex/pkg/types" ) @@ -96,16 +97,19 @@ func (h *BlobHandler) GetCommitmentProof(_ context.Context, _ uint64, _ []byte, return nil, errNotSupported } -// Submit is not supported — apex is read-only. -func (h *BlobHandler) Submit(_ context.Context, _ json.RawMessage, _ json.RawMessage) (json.RawMessage, error) { - return nil, errReadOnly +// Submit validates the JSON-RPC payload and delegates to the configured +// submission backend when write support is enabled. +func (h *BlobHandler) Submit(ctx context.Context, blobs json.RawMessage, options json.RawMessage) (json.RawMessage, error) { + raw, err := h.svc.BlobSubmit(ctx, blobs, options) + if errors.Is(err, submit.ErrDisabled) { + return nil, errReadOnly + } + if err != nil { + return nil, err + } + return raw, nil } func bytesToNamespace(b []byte) (types.Namespace, error) { - if len(b) != types.NamespaceSize { - return types.Namespace{}, fmt.Errorf("invalid namespace size: got %d, want %d", len(b), types.NamespaceSize) - } - var ns types.Namespace - copy(ns[:], b) - return ns, nil + return types.NamespaceFromBytes(b) } diff --git a/pkg/api/jsonrpc/server_test.go b/pkg/api/jsonrpc/server_test.go index a4006cf..3ffc54e 100644 --- a/pkg/api/jsonrpc/server_test.go +++ b/pkg/api/jsonrpc/server_test.go @@ -10,10 +10,12 @@ import ( "net/http/httptest" "testing" + gsquare "github.com/celestiaorg/go-square/v3/share" "github.com/rs/zerolog" "github.com/evstack/apex/pkg/api" "github.com/evstack/apex/pkg/store" + "github.com/evstack/apex/pkg/submit" "github.com/evstack/apex/pkg/types" ) @@ -125,9 +127,24 @@ func (f *mockFetcher) SubscribeHeaders(_ context.Context) (<-chan *types.Header, func (f *mockFetcher) Close() error { return nil } +type mockSubmitter struct { + result *submit.Result + err error + last *submit.Request +} + +func (m *mockSubmitter) Submit(_ context.Context, req *submit.Request) (*submit.Result, error) { + m.last = req + if m.err != nil { + return nil, m.err + } + return m.result, nil +} + func testNamespace(b byte) types.Namespace { + namespace := gsquare.MustNewV0Namespace([]byte("apexns" + string([]byte{b}))) var ns types.Namespace - ns[types.NamespaceSize-1] = b + copy(ns[:], namespace.Bytes()) return ns } @@ -366,3 +383,71 @@ func TestJSONRPCStubMethods(t *testing.T) { }) } } + +func TestJSONRPCBlobSubmitReadOnlyByDefault(t *testing.T) { + notifier := api.NewNotifier(16, 1024, zerolog.Nop()) + svc := api.NewService(newMockStore(), &mockFetcher{}, nil, notifier, zerolog.Nop()) + srv := NewServer(svc, zerolog.Nop()) + + resp := doRPC(t, srv, "blob.Submit", []map[string]any{}, nil) + if resp.Error == nil { + t.Fatal("expected read-only error") + } + if resp.Error.Message != errReadOnly.Error() { + t.Fatalf("error = %q, want %q", resp.Error.Message, errReadOnly.Error()) + } +} + +func TestJSONRPCBlobSubmitDelegates(t *testing.T) { + notifier := api.NewNotifier(16, 1024, zerolog.Nop()) + submitter := &mockSubmitter{result: &submit.Result{Height: 77}} + svc := api.NewService( + newMockStore(), + &mockFetcher{}, + nil, + notifier, + zerolog.Nop(), + api.WithBlobSubmitter(submitter), + ) + srv := NewServer(svc, zerolog.Nop()) + + ns := testNamespace(9) + blobSigner := []byte("01234567890123456789") + resp := doRPC(t, srv, "blob.Submit", []map[string]any{{ + "namespace": ns[:], + "data": []byte("hello"), + "share_version": 1, + "commitment": []byte("c1"), + "signer": blobSigner, + "index": -1, + }}, map[string]any{ + "gas_price": 0.1, + "is_gas_price_set": true, + "max_gas_price": 1.5, + "tx_priority": int(submit.PriorityHigh), + }) + if resp.Error != nil { + t.Fatalf("RPC error: %s", resp.Error.Message) + } + if string(resp.Result) != "77" { + t.Fatalf("result = %s, want 77", resp.Result) + } + if submitter.last == nil { + t.Fatal("submitter request = nil") + } + if len(submitter.last.Blobs) != 1 { + t.Fatalf("blob count = %d, want 1", len(submitter.last.Blobs)) + } + if submitter.last.Blobs[0].Namespace != ns { + t.Fatalf("namespace = %x, want %x", submitter.last.Blobs[0].Namespace, ns) + } + if string(submitter.last.Blobs[0].Data) != "hello" { + t.Fatalf("data = %q, want %q", submitter.last.Blobs[0].Data, "hello") + } + if string(submitter.last.Blobs[0].Signer) != string(blobSigner) { + t.Fatalf("signer = %x, want %x", submitter.last.Blobs[0].Signer, blobSigner) + } + if submitter.last.Options == nil || submitter.last.Options.TxPriority != submit.PriorityHigh { + t.Fatalf("options = %#v, want high priority", submitter.last.Options) + } +} diff --git a/pkg/api/notifier_test.go b/pkg/api/notifier_test.go index fddece8..64029e0 100644 --- a/pkg/api/notifier_test.go +++ b/pkg/api/notifier_test.go @@ -4,14 +4,16 @@ import ( "testing" "time" + gsquare "github.com/celestiaorg/go-square/v3/share" "github.com/rs/zerolog" "github.com/evstack/apex/pkg/types" ) func testNamespace(b byte) types.Namespace { + namespace := gsquare.MustNewV0Namespace([]byte("apexns" + string([]byte{b}))) var ns types.Namespace - ns[types.NamespaceSize-1] = b + copy(ns[:], namespace.Bytes()) return ns } diff --git a/pkg/api/service.go b/pkg/api/service.go index d39c456..b172113 100644 --- a/pkg/api/service.go +++ b/pkg/api/service.go @@ -11,6 +11,7 @@ import ( "github.com/evstack/apex/pkg/fetch" "github.com/evstack/apex/pkg/store" + "github.com/evstack/apex/pkg/submit" "github.com/evstack/apex/pkg/types" ) @@ -18,23 +19,38 @@ import ( // handlers. It reads from the store, forwards proofs upstream, and manages // subscriptions via the Notifier. type Service struct { - store store.Store - fetcher fetch.DataFetcher - proof fetch.ProofForwarder - notifier *Notifier - log zerolog.Logger + store store.Store + fetcher fetch.DataFetcher + proof fetch.ProofForwarder + submitter submit.Submitter + notifier *Notifier + log zerolog.Logger +} + +// ServiceOption configures optional service behavior. +type ServiceOption func(*Service) + +// WithBlobSubmitter installs an optional blob submission backend. +func WithBlobSubmitter(submitter submit.Submitter) ServiceOption { + return func(s *Service) { + s.submitter = submitter + } } // NewService creates a new API service. proof may be nil if upstream proof // forwarding is not available. -func NewService(s store.Store, f fetch.DataFetcher, proof fetch.ProofForwarder, n *Notifier, log zerolog.Logger) *Service { - return &Service{ +func NewService(s store.Store, f fetch.DataFetcher, proof fetch.ProofForwarder, n *Notifier, log zerolog.Logger, opts ...ServiceOption) *Service { + svc := &Service{ store: s, fetcher: f, proof: proof, notifier: n, log: log.With().Str("component", "api-service").Logger(), } + for _, opt := range opts { + opt(svc) + } + return svc } // BlobGet returns a single blob matching the namespace and commitment at the @@ -151,6 +167,25 @@ func (s *Service) BlobIncluded(ctx context.Context, height uint64, namespace []b return s.proof.Included(ctx, height, namespace, proof, commitment) } +// BlobSubmit validates the JSON-RPC request, delegates to the configured +// submitter, and returns the JSON-RPC-compatible confirmation height. +func (s *Service) BlobSubmit(ctx context.Context, blobsRaw, optionsRaw json.RawMessage) (json.RawMessage, error) { + if s.submitter == nil { + return nil, submit.ErrDisabled + } + + req, err := submit.DecodeRequest(blobsRaw, optionsRaw) + if err != nil { + return nil, err + } + + result, err := s.submitter.Submit(ctx, req) + if err != nil { + return nil, err + } + return submit.MarshalResult(result) +} + // BlobSubscribe creates a subscription for blobs in the given namespace. func (s *Service) BlobSubscribe(namespace types.Namespace) (*Subscription, error) { return s.notifier.Subscribe([]types.Namespace{namespace}) @@ -232,6 +267,7 @@ type blobJSON struct { Data []byte `json:"data"` ShareVersion uint32 `json:"share_version"` Commitment []byte `json:"commitment"` + Signer []byte `json:"signer,omitempty"` Index int `json:"index"` } @@ -242,6 +278,7 @@ func MarshalBlob(b *types.Blob) json.RawMessage { Data: b.Data, ShareVersion: b.ShareVersion, Commitment: b.Commitment, + Signer: b.Signer, Index: b.Index, }) return raw diff --git a/pkg/api/service_test.go b/pkg/api/service_test.go index 9ae9d08..d96129b 100644 --- a/pkg/api/service_test.go +++ b/pkg/api/service_test.go @@ -10,6 +10,7 @@ import ( "github.com/rs/zerolog" "github.com/evstack/apex/pkg/store" + "github.com/evstack/apex/pkg/submit" "github.com/evstack/apex/pkg/types" ) @@ -125,13 +126,27 @@ func (m *mockFetcher) SubscribeHeaders(_ context.Context) (<-chan *types.Header, func (m *mockFetcher) Close() error { return nil } +type mockSubmitter struct { + result *submit.Result + err error + last *submit.Request +} + +func (m *mockSubmitter) Submit(_ context.Context, req *submit.Request) (*submit.Result, error) { + m.last = req + if m.err != nil { + return nil, m.err + } + return m.result, nil +} + func TestServiceBlobGet(t *testing.T) { st := newMockStore() ns := testNamespace(1) commitment := []byte("c1") st.blobs[10] = []types.Blob{ - {Height: 10, Namespace: ns, Data: []byte("d1"), Commitment: commitment, Index: 0}, + {Height: 10, Namespace: ns, Data: []byte("d1"), Commitment: commitment, Signer: []byte("signer"), Index: 0}, {Height: 10, Namespace: ns, Data: []byte("d2"), Commitment: []byte("c2"), Index: 1}, } @@ -149,6 +164,9 @@ func TestServiceBlobGet(t *testing.T) { if _, ok := m["commitment"]; !ok { t.Error("blob JSON missing 'commitment' field") } + if _, ok := m["signer"]; !ok { + t.Error("blob JSON missing 'signer' field") + } } func TestServiceBlobGetByCommitment(t *testing.T) { @@ -314,3 +332,95 @@ func TestServiceProofForwardingUnavailable(t *testing.T) { t.Fatal("expected error for nil proof forwarder") } } + +func TestServiceBlobSubmitRequiresSubmitter(t *testing.T) { + svc := NewService(newMockStore(), &mockFetcher{}, nil, NewNotifier(16, 1024, zerolog.Nop()), zerolog.Nop()) + + _, err := svc.BlobSubmit(context.Background(), json.RawMessage(`[]`), nil) + if !errors.Is(err, submit.ErrDisabled) { + t.Fatalf("expected submit.ErrDisabled, got %v", err) + } +} + +func TestServiceBlobSubmitDelegates(t *testing.T) { + ns := testNamespace(5) + blobSigner := []byte("01234567890123456789") + submitter := &mockSubmitter{result: &submit.Result{Height: 42}} + svc := NewService( + newMockStore(), + &mockFetcher{}, + nil, + NewNotifier(16, 1024, zerolog.Nop()), + zerolog.Nop(), + WithBlobSubmitter(submitter), + ) + + blobsRaw, err := json.Marshal([]map[string]any{{ + "namespace": ns[:], + "data": []byte("hello"), + "share_version": 1, + "commitment": []byte("c1"), + "signer": blobSigner, + "index": -1, + }}) + if err != nil { + t.Fatalf("marshal blobs: %v", err) + } + optionsRaw, err := json.Marshal(map[string]any{ + "gas_price": 0.1, + "is_gas_price_set": true, + "max_gas_price": 1.5, + "tx_priority": int(submit.PriorityHigh), + "signer_address": "celestia1test", + }) + if err != nil { + t.Fatalf("marshal options: %v", err) + } + + raw, err := svc.BlobSubmit(context.Background(), blobsRaw, optionsRaw) + if err != nil { + t.Fatalf("BlobSubmit: %v", err) + } + if string(raw) != "42" { + t.Fatalf("result = %s, want 42", raw) + } + if submitter.last == nil { + t.Fatal("submitter request = nil") + } + if len(submitter.last.Blobs) != 1 { + t.Fatalf("got %d blobs, want 1", len(submitter.last.Blobs)) + } + assertSubmittedBlob(t, submitter.last.Blobs[0], ns, blobSigner) + assertSubmittedOptions(t, submitter.last.Options) +} + +func assertSubmittedBlob(t *testing.T, blob submit.Blob, wantNamespace types.Namespace, wantSigner []byte) { + t.Helper() + + if blob.Namespace != wantNamespace { + t.Fatalf("namespace = %x, want %x", blob.Namespace, wantNamespace) + } + if string(blob.Data) != "hello" { + t.Fatalf("data = %q, want %q", blob.Data, "hello") + } + if string(blob.Commitment) != "c1" { + t.Fatalf("commitment = %q, want %q", blob.Commitment, "c1") + } + if string(blob.Signer) != string(wantSigner) { + t.Fatalf("signer = %x, want %x", blob.Signer, wantSigner) + } +} + +func assertSubmittedOptions(t *testing.T, opts *submit.TxConfig) { + t.Helper() + + if opts == nil || opts.TxPriority != submit.PriorityHigh { + t.Fatalf("options = %#v, want high priority", opts) + } + if opts.GasPrice != 0.1 || !opts.IsGasPriceSet { + t.Fatalf("gas options = %#v, want gas price override", opts) + } + if opts.SignerAddress != "celestia1test" { + t.Fatalf("signer address = %q, want %q", opts.SignerAddress, "celestia1test") + } +} diff --git a/pkg/fetch/blobtx.go b/pkg/fetch/blobtx.go index 26ac795..5b78d07 100644 --- a/pkg/fetch/blobtx.go +++ b/pkg/fetch/blobtx.go @@ -9,12 +9,14 @@ import ( "github.com/evstack/apex/pkg/types" ) -// blobTxTypeID is the trailing byte that identifies a BlobTx. -// Defined in celestia-app as 0x62 ('b'). -const blobTxTypeID = 0x62 - -// msgPayForBlobsTypeURL is the protobuf Any type URL for MsgPayForBlobs. -const msgPayForBlobsTypeURL = "/celestia.blob.v1.MsgPayForBlobs" +const ( + // legacyBlobTxTypeID is the trailing byte used by older BlobTx encodings. + legacyBlobTxTypeID = 0x62 + // protoBlobTxTypeID is the current protobuf type identifier used by Celestia. + protoBlobTxTypeID = types.ProtoBlobTxTypeID + // msgPayForBlobsTypeURL is the protobuf Any type URL for MsgPayForBlobs. + msgPayForBlobsTypeURL = "/celestia.blob.v1.MsgPayForBlobs" +) // rawBlob holds the fields parsed from a BlobTx blob proto message. type rawBlob struct { @@ -38,31 +40,129 @@ type parsedBlobTx struct { PFB pfbData } -// parseBlobTx decodes a Celestia BlobTx envelope and extracts both the -// blobs and the MsgPayForBlobs data (commitments, signer) from the inner tx. -// -// BlobTx wire format: -// -// inner_tx (length-prefixed) || blob1 (length-prefixed) || blob2 ... || 0x62 +// parseBlobTx decodes either the current protobuf BlobTx envelope or the older +// legacy envelope and extracts both the blobs and the MsgPayForBlobs data +// (commitments, signer) from the inner tx. func parseBlobTx(raw []byte) (*parsedBlobTx, error) { if len(raw) == 0 { return nil, errors.New("empty BlobTx") } - if raw[len(raw)-1] != blobTxTypeID { - return nil, fmt.Errorf("not a BlobTx: trailing byte 0x%02x, want 0x%02x", raw[len(raw)-1], blobTxTypeID) + + parsed, protoErr := parseProtoBlobTx(raw) + if protoErr == nil { + return parsed, nil + } + + parsed, legacyErr := parseLegacyBlobTx(raw) + if legacyErr == nil { + return parsed, nil + } + + return nil, fmt.Errorf("decode blob tx: %w", errors.Join(protoErr, legacyErr)) +} + +func parseProtoBlobTx(raw []byte) (*parsedBlobTx, error) { + envelope := protoBlobTxEnvelope{} + + data := raw + for len(data) > 0 { + next, err := envelope.consume(data) + if err != nil { + return nil, err + } + data = next + } + + if err := envelope.validate(); err != nil { + return nil, err + } + + pfb, err := parsePFBFromTx(envelope.innerTx) + if err != nil { + return nil, fmt.Errorf("parse inner tx: %w", err) + } + + return &parsedBlobTx{Blobs: envelope.blobs, PFB: pfb}, nil +} + +type protoBlobTxEnvelope struct { + innerTx []byte + blobs []rawBlob + typeID string +} + +func (e *protoBlobTxEnvelope) consume(data []byte) ([]byte, error) { + num, typ, n := protowire.ConsumeTag(data) + if n < 0 { + return nil, errors.New("invalid proto tag") + } + data = data[n:] + + switch { + case num == 1 && typ == protowire.BytesType: + val, n := protowire.ConsumeBytes(data) + if n < 0 { + return nil, errors.New("decode inner tx: invalid bytes") + } + e.innerTx = append([]byte(nil), val...) + return data[n:], nil + case num == 2 && typ == protowire.BytesType: + val, n := protowire.ConsumeBytes(data) + if n < 0 { + return nil, fmt.Errorf("decode blob %d: invalid bytes", len(e.blobs)) + } + + b, err := parseRawBlob(val) + if err != nil { + return nil, fmt.Errorf("parse blob %d: %w", len(e.blobs), err) + } + e.blobs = append(e.blobs, b) + return data[n:], nil + case num == 3 && typ == protowire.BytesType: + val, n := protowire.ConsumeBytes(data) + if n < 0 { + return nil, errors.New("decode BlobTx type_id: invalid bytes") + } + e.typeID = string(val) + return data[n:], nil + default: + n = protowire.ConsumeFieldValue(num, typ, data) + if n < 0 { + return nil, fmt.Errorf("field %d: invalid value for wire type %d", num, typ) + } + return data[n:], nil + } +} + +func (e protoBlobTxEnvelope) validate() error { + if e.typeID != protoBlobTxTypeID { + return fmt.Errorf("not a proto BlobTx: type_id %q", e.typeID) + } + if len(e.innerTx) == 0 { + return errors.New("BlobTx has no inner tx") + } + if len(e.blobs) == 0 { + return errors.New("BlobTx has no blobs") + } + return nil +} + +// parseLegacyBlobTx decodes the older BlobTx wire format: +// +// inner_tx (length-prefixed) || blob1 (length-prefixed) || blob2 ... || 0x62 +func parseLegacyBlobTx(raw []byte) (*parsedBlobTx, error) { + if raw[len(raw)-1] != legacyBlobTxTypeID { + return nil, fmt.Errorf("not a legacy BlobTx: trailing byte 0x%02x, want 0x%02x", raw[len(raw)-1], legacyBlobTxTypeID) } - // Strip trailing type byte. data := raw[:len(raw)-1] - // Read inner SDK tx (length-prefixed). innerTx, n := protowire.ConsumeBytes(data) if n < 0 { return nil, errors.New("decode inner tx: invalid length prefix") } data = data[n:] - // Parse MsgPayForBlobs from the inner Cosmos SDK tx. pfb, err := parsePFBFromTx(innerTx) if err != nil { return nil, fmt.Errorf("parse inner tx: %w", err) @@ -273,7 +373,7 @@ func extractBlobsFromBlock(txs [][]byte, namespaces []types.Namespace, height ui blobIndex := 0 for _, tx := range txs { - if len(tx) == 0 || tx[len(tx)-1] != blobTxTypeID { + if len(tx) == 0 { continue } @@ -284,12 +384,11 @@ func extractBlobsFromBlock(txs [][]byte, namespaces []types.Namespace, height ui } for i, rb := range parsed.Blobs { - if len(rb.Namespace) != types.NamespaceSize { + ns, ok := namespaceFromRawBlob(rb) + if !ok { blobIndex++ continue } - var ns types.Namespace - copy(ns[:], rb.Namespace) if _, ok := nsSet[ns]; !ok { blobIndex++ @@ -330,6 +429,25 @@ func ExtractBlobsFromBlock(txs [][]byte, namespaces []types.Namespace, height ui return extractBlobsFromBlock(txs, namespaces, height) } +func namespaceFromRawBlob(blob rawBlob) (types.Namespace, bool) { + switch len(blob.Namespace) { + case types.NamespaceSize: + var ns types.Namespace + copy(ns[:], blob.Namespace) + return ns, true + case types.NamespaceSize - 1: + if blob.NamespaceVersion > 0xff { + return types.Namespace{}, false + } + var ns types.Namespace + ns[0] = byte(blob.NamespaceVersion) + copy(ns[1:], blob.Namespace) + return ns, true + default: + return types.Namespace{}, false + } +} + // extractBytesField returns the first occurrence of a bytes-typed field. func extractBytesField(data []byte, target protowire.Number) ([]byte, error) { for len(data) > 0 { diff --git a/pkg/fetch/blobtx_submit_test.go b/pkg/fetch/blobtx_submit_test.go new file mode 100644 index 0000000..d4c875f --- /dev/null +++ b/pkg/fetch/blobtx_submit_test.go @@ -0,0 +1,73 @@ +package fetch + +import ( + "testing" + + gsquare "github.com/celestiaorg/go-square/v3/share" + "github.com/evstack/apex/pkg/submit" + "github.com/evstack/apex/pkg/types" + "google.golang.org/protobuf/types/known/anypb" +) + +func TestParseBlobTxFromSubmitMarshaller(t *testing.T) { + t.Parallel() + + namespace := testNamespaceType(3) + blob := submit.Blob{ + Namespace: namespace, + Data: []byte("payload"), + ShareVersion: 1, + Commitment: []byte("commitment"), + Signer: []byte("01234567890123456789"), + } + pfb, err := submit.BuildMsgPayForBlobs("celestia1submitter", []submit.Blob{blob}) + if err != nil { + t.Fatalf("BuildMsgPayForBlobs: %v", err) + } + msg, err := submit.MarshalMsgPayForBlobsAny(pfb) + if err != nil { + t.Fatalf("MarshalMsgPayForBlobsAny: %v", err) + } + bodyBytes, err := submit.MarshalTxBody([]*anypb.Any{msg}, "", 0) + if err != nil { + t.Fatalf("MarshalTxBody: %v", err) + } + innerTx, err := submit.MarshalTxRaw(bodyBytes, []byte("auth"), []byte("signature")) + if err != nil { + t.Fatalf("MarshalTxRaw: %v", err) + } + raw, err := submit.MarshalBlobTx(innerTx, []submit.Blob{blob}) + if err != nil { + t.Fatalf("MarshalBlobTx: %v", err) + } + + parsed, err := parseBlobTx(raw) + if err != nil { + t.Fatalf("parseBlobTx: %v", err) + } + if len(parsed.Blobs) != 1 { + t.Fatalf("got %d blobs, want 1", len(parsed.Blobs)) + } + if ns, ok := namespaceFromRawBlob(parsed.Blobs[0]); !ok || ns != namespace { + t.Fatalf("namespace = %x, want %x", ns, namespace) + } + if string(parsed.Blobs[0].Data) != "payload" { + t.Fatalf("data = %q", parsed.Blobs[0].Data) + } + if parsed.Blobs[0].ShareVersion != 1 { + t.Fatalf("share version = %d, want 1", parsed.Blobs[0].ShareVersion) + } + if string(parsed.PFB.Signer) != "celestia1submitter" { + t.Fatalf("signer = %q", parsed.PFB.Signer) + } + if string(parsed.PFB.ShareCommitments[0]) != "commitment" { + t.Fatalf("commitment = %q", parsed.PFB.ShareCommitments[0]) + } +} + +func testNamespaceType(b byte) types.Namespace { + namespace := gsquare.MustNewV0Namespace([]byte("apexns" + string([]byte{b}))) + var ns types.Namespace + copy(ns[:], namespace.Bytes()) + return ns +} diff --git a/pkg/fetch/blobtx_test.go b/pkg/fetch/blobtx_test.go index 591abc7..7780e22 100644 --- a/pkg/fetch/blobtx_test.go +++ b/pkg/fetch/blobtx_test.go @@ -12,8 +12,18 @@ import ( func buildBlobProto(b rawBlob) []byte { var out []byte if len(b.Namespace) > 0 { + namespaceField := b.Namespace + namespaceVersion := b.NamespaceVersion + if len(b.Namespace) == types.NamespaceSize { + namespaceVersion = uint32(b.Namespace[0]) + namespaceField = b.Namespace[1:] + } out = protowire.AppendTag(out, 1, protowire.BytesType) - out = protowire.AppendBytes(out, b.Namespace) + out = protowire.AppendBytes(out, namespaceField) + if namespaceVersion > 0 { + out = protowire.AppendTag(out, 4, protowire.VarintType) + out = protowire.AppendVarint(out, uint64(namespaceVersion)) + } } if len(b.Data) > 0 { out = protowire.AppendTag(out, 2, protowire.BytesType) @@ -23,10 +33,6 @@ func buildBlobProto(b rawBlob) []byte { out = protowire.AppendTag(out, 3, protowire.VarintType) out = protowire.AppendVarint(out, uint64(b.ShareVersion)) } - if b.NamespaceVersion > 0 { - out = protowire.AppendTag(out, 4, protowire.VarintType) - out = protowire.AppendVarint(out, uint64(b.NamespaceVersion)) - } if len(b.Signer) > 0 { out = protowire.AppendTag(out, 5, protowire.BytesType) out = protowire.AppendBytes(out, b.Signer) @@ -85,20 +91,32 @@ func buildInnerSDKTx(signer string, commitments [][]byte) []byte { return buildTx(body) } -// buildBlobTx constructs a valid BlobTx wire-format message with proper +// buildBlobTx constructs the current protobuf BlobTx envelope with proper // MsgPayForBlobs containing commitments and signer. func buildBlobTx(signer string, commitments [][]byte, blobs ...rawBlob) []byte { innerTx := buildInnerSDKTx(signer, commitments) var out []byte - // Length-prefixed inner tx. + out = protowire.AppendTag(out, 1, protowire.BytesType) out = protowire.AppendBytes(out, innerTx) - // Length-prefixed blob protos. for _, b := range blobs { blobProto := buildBlobProto(b) + out = protowire.AppendTag(out, 2, protowire.BytesType) out = protowire.AppendBytes(out, blobProto) } - // Trailing BlobTx type byte. - out = append(out, blobTxTypeID) + out = protowire.AppendTag(out, 3, protowire.BytesType) + out = protowire.AppendBytes(out, []byte(protoBlobTxTypeID)) + return out +} + +func buildLegacyBlobTx(signer string, commitments [][]byte, blobs ...rawBlob) []byte { + innerTx := buildInnerSDKTx(signer, commitments) + var out []byte + out = protowire.AppendBytes(out, innerTx) + for _, b := range blobs { + blobProto := buildBlobProto(b) + out = protowire.AppendBytes(out, blobProto) + } + out = append(out, legacyBlobTxTypeID) return out } @@ -165,6 +183,32 @@ func TestParseBlobTxMultiBlob(t *testing.T) { } } +func TestParseBlobTxLegacyFormat(t *testing.T) { + tx := buildLegacyBlobTx("legacy-signer", [][]byte{[]byte("legacy-commit")}, + rawBlob{Namespace: testNS(9), Data: []byte("legacy")}, + ) + + parsed, err := parseBlobTx(tx) + if err != nil { + t.Fatalf("parseBlobTx legacy: %v", err) + } + if len(parsed.Blobs) != 1 { + t.Fatalf("got %d blobs, want 1", len(parsed.Blobs)) + } + if string(parsed.Blobs[0].Data) != "legacy" { + t.Fatalf("blob data = %q, want %q", parsed.Blobs[0].Data, "legacy") + } + if string(parsed.PFB.Signer) != "legacy-signer" { + t.Fatalf("signer = %q, want %q", parsed.PFB.Signer, "legacy-signer") + } + if len(parsed.PFB.ShareCommitments) != 1 { + t.Fatalf("got %d commitments, want 1", len(parsed.PFB.ShareCommitments)) + } + if string(parsed.PFB.ShareCommitments[0]) != "legacy-commit" { + t.Fatalf("commitment = %q, want %q", parsed.PFB.ShareCommitments[0], "legacy-commit") + } +} + func TestParseBlobTxNotBlobTx(t *testing.T) { _, err := parseBlobTx([]byte{0x01, 0x02, 0x03}) if err == nil { diff --git a/pkg/fetch/celestia_app.go b/pkg/fetch/celestia_app.go index 7c00d0f..7151e16 100644 --- a/pkg/fetch/celestia_app.go +++ b/pkg/fetch/celestia_app.go @@ -11,9 +11,9 @@ import ( "github.com/rs/zerolog" "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" cometpb "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/base/tendermint/v1beta1" + "github.com/evstack/apex/pkg/grpcutil" "github.com/evstack/apex/pkg/types" ) @@ -46,9 +46,9 @@ func (b bearerCreds) RequireTransportSecurity() bool { return false } // NewCelestiaAppFetcher creates a fetcher that reads from celestia-app's // Cosmos SDK gRPC endpoint. No connection is established at construction time. -func NewCelestiaAppFetcher(grpcAddr, authToken string, log zerolog.Logger) (*CelestiaAppFetcher, error) { +func NewCelestiaAppFetcher(grpcAddr, authToken string, allowInsecure bool, log zerolog.Logger) (*CelestiaAppFetcher, error) { opts := []grpc.DialOption{ - grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithTransportCredentials(grpcutil.TransportCredentials(grpcAddr, allowInsecure)), } if authToken != "" { opts = append(opts, grpc.WithPerRPCCredentials(newBearerCreds(authToken))) diff --git a/pkg/fetch/celestia_app_test.go b/pkg/fetch/celestia_app_test.go index 8e84214..dec74c5 100644 --- a/pkg/fetch/celestia_app_test.go +++ b/pkg/fetch/celestia_app_test.go @@ -234,7 +234,7 @@ func TestSubscribeHeaders(t *testing.T) { } func TestCloseIdempotent(t *testing.T) { - f, err := NewCelestiaAppFetcher("localhost:26657", "", zerolog.Nop()) + f, err := NewCelestiaAppFetcher("localhost:26657", "", false, zerolog.Nop()) if err != nil { t.Fatalf("NewCelestiaAppFetcher: %v", err) } diff --git a/pkg/grpcutil/transport.go b/pkg/grpcutil/transport.go new file mode 100644 index 0000000..908c8dc --- /dev/null +++ b/pkg/grpcutil/transport.go @@ -0,0 +1,54 @@ +package grpcutil + +import ( + "crypto/tls" + "net" + "strings" + + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/insecure" +) + +// TransportCredentials returns plaintext credentials for loopback targets and +// explicit insecure opt-ins, and TLS credentials for non-local targets. +func TransportCredentials(grpcAddr string, allowInsecure bool) credentials.TransportCredentials { + if allowInsecure || isLocalTarget(grpcAddr) { + return insecure.NewCredentials() + } + return credentials.NewTLS(&tls.Config{MinVersion: tls.VersionTLS12}) +} + +func isLocalTarget(grpcAddr string) bool { + target := strings.TrimSpace(grpcAddr) + if target == "" { + return false + } + if strings.HasPrefix(target, "/") || strings.HasPrefix(target, "unix://") || strings.HasPrefix(target, "unix:") { + return true + } + if idx := strings.LastIndex(target, "://"); idx >= 0 { + target = target[idx+3:] + } + target = strings.TrimLeft(target, "/") + if idx := strings.LastIndex(target, "/"); idx >= 0 { + target = target[idx+1:] + } + if strings.HasPrefix(target, ":") { + return true + } + + host := target + if parsedHost, _, err := net.SplitHostPort(target); err == nil { + host = parsedHost + } + host = strings.Trim(host, "[]") + if host == "" { + return false + } + if strings.EqualFold(host, "localhost") || strings.HasSuffix(strings.ToLower(host), ".localhost") { + return true + } + + ip := net.ParseIP(host) + return ip != nil && ip.IsLoopback() +} diff --git a/pkg/grpcutil/transport_test.go b/pkg/grpcutil/transport_test.go new file mode 100644 index 0000000..4053282 --- /dev/null +++ b/pkg/grpcutil/transport_test.go @@ -0,0 +1,47 @@ +package grpcutil + +import "testing" + +func TestTransportCredentials(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + addr string + allowInsecure bool + wantProtocol string + }{ + { + name: "loopback host uses insecure", + addr: "localhost:9090", + wantProtocol: "insecure", + }, + { + name: "loopback ip uses insecure", + addr: "127.0.0.1:9090", + wantProtocol: "insecure", + }, + { + name: "remote host uses tls", + addr: "celestia.example.com:9090", + wantProtocol: "tls", + }, + { + name: "remote host can opt into insecure", + addr: "celestia.example.com:9090", + allowInsecure: true, + wantProtocol: "insecure", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + creds := TransportCredentials(tt.addr, tt.allowInsecure) + if got := creds.Info().SecurityProtocol; got != tt.wantProtocol { + t.Fatalf("security protocol = %q, want %q", got, tt.wantProtocol) + } + }) + } +} diff --git a/pkg/submit/app_client.go b/pkg/submit/app_client.go new file mode 100644 index 0000000..e8a39eb --- /dev/null +++ b/pkg/submit/app_client.go @@ -0,0 +1,126 @@ +package submit + +import ( + "context" + "fmt" + + authv1beta1 "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/auth/v1beta1" + txv1beta1 "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/tx/v1beta1" + "github.com/evstack/apex/pkg/grpcutil" + "google.golang.org/grpc" +) + +// AccountInfo is the Apex-owned account view returned by celestia-app. +type AccountInfo struct { + Address string + AccountNumber uint64 + Sequence uint64 +} + +// TxStatus is the Apex-owned subset of tx execution status used by the submit +// pipeline for broadcast and confirmation. +type TxStatus struct { + Height int64 + Hash string + Code uint32 + Codespace string + RawLog string + GasWanted int64 + GasUsed int64 +} + +// AppClient is the narrow direct-to-celestia-app transport surface needed by +// the submission pipeline. +type AppClient interface { + AccountInfo(ctx context.Context, address string) (*AccountInfo, error) + BroadcastTx(ctx context.Context, txBytes []byte) (*TxStatus, error) + GetTx(ctx context.Context, hash string) (*TxStatus, error) + Close() error +} + +// GRPCAppClient implements AppClient against celestia-app's Cosmos SDK gRPC. +type GRPCAppClient struct { + conn *grpc.ClientConn + auth authv1beta1.QueryClient + tx txv1beta1.ServiceClient +} + +// NewGRPCAppClient opens a gRPC client for direct celestia-app submission +// primitives. +func NewGRPCAppClient(grpcAddr string, allowInsecure bool) (*GRPCAppClient, error) { + conn, err := grpc.NewClient( + grpcAddr, + grpc.WithTransportCredentials(grpcutil.TransportCredentials(grpcAddr, allowInsecure)), + ) + if err != nil { + return nil, fmt.Errorf("create celestia-app submit client: %w", err) + } + return &GRPCAppClient{ + conn: conn, + auth: authv1beta1.NewQueryClient(conn), + tx: txv1beta1.NewServiceClient(conn), + }, nil +} + +func (c *GRPCAppClient) AccountInfo(ctx context.Context, address string) (*AccountInfo, error) { + resp, err := c.auth.AccountInfo(ctx, &authv1beta1.QueryAccountInfoRequest{Address: address}) + if err != nil { + return nil, fmt.Errorf("query account info: %w", err) + } + info := resp.GetInfo() + if info == nil { + return nil, fmt.Errorf("query account info: empty response for %q", address) + } + return &AccountInfo{ + Address: info.GetAddress(), + AccountNumber: info.GetAccountNumber(), + Sequence: info.GetSequence(), + }, nil +} + +func (c *GRPCAppClient) BroadcastTx(ctx context.Context, txBytes []byte) (*TxStatus, error) { + resp, err := c.tx.BroadcastTx(ctx, &txv1beta1.BroadcastTxRequest{ + TxBytes: txBytes, + Mode: txv1beta1.BroadcastMode_BROADCAST_MODE_SYNC, + }) + if err != nil { + return nil, fmt.Errorf("broadcast tx: %w", err) + } + return mapTxStatus(resp.GetTxResponse()), nil +} + +func (c *GRPCAppClient) GetTx(ctx context.Context, hash string) (*TxStatus, error) { + resp, err := c.tx.GetTx(ctx, &txv1beta1.GetTxRequest{Hash: hash}) + if err != nil { + return nil, fmt.Errorf("get tx: %w", err) + } + return mapTxStatus(resp.GetTxResponse()), nil +} + +func (c *GRPCAppClient) Close() error { + return c.conn.Close() +} + +func mapTxStatus(resp interface { + GetHeight() int64 + GetTxhash() string + GetCode() uint32 + GetCodespace() string + GetRawLog() string + GetGasWanted() int64 + GetGasUsed() int64 +}, +) *TxStatus { + if resp == nil { + return nil + } + return &TxStatus{ + Height: resp.GetHeight(), + Hash: resp.GetTxhash(), + Code: resp.GetCode(), + Codespace: resp.GetCodespace(), + RawLog: resp.GetRawLog(), + GasWanted: resp.GetGasWanted(), + GasUsed: resp.GetGasUsed(), + } +} diff --git a/pkg/submit/app_client_test.go b/pkg/submit/app_client_test.go new file mode 100644 index 0000000..3223a87 --- /dev/null +++ b/pkg/submit/app_client_test.go @@ -0,0 +1,169 @@ +package submit + +import ( + "bytes" + "context" + "net" + "testing" + + authv1beta1 "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/auth/v1beta1" + abciv1beta1 "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/base/abci/v1beta1" + txv1beta1 "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/tx/v1beta1" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/test/bufconn" +) + +const bufSize = 1024 * 1024 + +type authServer struct { + authv1beta1.UnimplementedQueryServer + info *authv1beta1.QueryAccountInfoResponse + lastAddress string +} + +func (s *authServer) AccountInfo(_ context.Context, req *authv1beta1.QueryAccountInfoRequest) (*authv1beta1.QueryAccountInfoResponse, error) { + s.lastAddress = req.GetAddress() + return s.info, nil +} + +type txServer struct { + txv1beta1.UnimplementedServiceServer + broadcast *txv1beta1.BroadcastTxResponse + getTx *txv1beta1.GetTxResponse + lastBroadcastReq *txv1beta1.BroadcastTxRequest + lastGetTxHash string +} + +func (s *txServer) BroadcastTx(_ context.Context, req *txv1beta1.BroadcastTxRequest) (*txv1beta1.BroadcastTxResponse, error) { + s.lastBroadcastReq = req + return s.broadcast, nil +} + +func (s *txServer) GetTx(_ context.Context, req *txv1beta1.GetTxRequest) (*txv1beta1.GetTxResponse, error) { + s.lastGetTxHash = req.GetHash() + return s.getTx, nil +} + +func TestGRPCAppClient(t *testing.T) { + t.Parallel() + + client, authSrv, txSrv := newTestGRPCAppClient(t) + defer client.Close() //nolint:errcheck + + info, err := client.AccountInfo(context.Background(), "celestia1test") + if err != nil { + t.Fatalf("AccountInfo: %v", err) + } + assertAccountInfoResponse(t, info, authSrv) + + broadcast, err := client.BroadcastTx(context.Background(), []byte("tx")) + if err != nil { + t.Fatalf("BroadcastTx: %v", err) + } + assertBroadcastResponse(t, broadcast, txSrv) + + queried, err := client.GetTx(context.Background(), "ABC") + if err != nil { + t.Fatalf("GetTx: %v", err) + } + assertGetTxResponse(t, queried, txSrv) +} + +func newTestGRPCAppClient(t *testing.T) (*GRPCAppClient, *authServer, *txServer) { + t.Helper() + + lis := bufconn.Listen(bufSize) + srv := grpc.NewServer() + authSrv := &authServer{ + info: &authv1beta1.QueryAccountInfoResponse{ + Info: &authv1beta1.BaseAccount{ + Address: "celestia1test", + AccountNumber: 7, + Sequence: 11, + }, + }, + } + txSrv := &txServer{ + broadcast: &txv1beta1.BroadcastTxResponse{ + TxResponse: &abciv1beta1.TxResponse{ + Height: 101, + Txhash: "ABC", + Code: 0, + RawLog: "", + GasWanted: 200, + GasUsed: 180, + }, + }, + getTx: &txv1beta1.GetTxResponse{ + TxResponse: &abciv1beta1.TxResponse{ + Height: 102, + Txhash: "DEF", + Code: 3, + RawLog: "failed", + GasWanted: 250, + GasUsed: 190, + }, + }, + } + authv1beta1.RegisterQueryServer(srv, authSrv) + txv1beta1.RegisterServiceServer(srv, txSrv) + go func() { + _ = srv.Serve(lis) + }() + t.Cleanup(srv.Stop) + + conn, err := grpc.NewClient("passthrough:///bufconn", + grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { + return lis.Dial() + }), + grpc.WithTransportCredentials(insecure.NewCredentials()), + ) + if err != nil { + t.Fatalf("grpc.NewClient: %v", err) + } + return &GRPCAppClient{ + conn: conn, + auth: authv1beta1.NewQueryClient(conn), + tx: txv1beta1.NewServiceClient(conn), + }, authSrv, txSrv +} + +func assertAccountInfoResponse(t *testing.T, info *AccountInfo, authSrv *authServer) { + t.Helper() + + if info.AccountNumber != 7 || info.Sequence != 11 { + t.Fatalf("info = %#v", info) + } + if authSrv.lastAddress != "celestia1test" { + t.Fatalf("account lookup address = %q, want %q", authSrv.lastAddress, "celestia1test") + } +} + +func assertBroadcastResponse(t *testing.T, broadcast *TxStatus, txSrv *txServer) { + t.Helper() + + if broadcast.Hash != "ABC" || broadcast.Height != 101 { + t.Fatalf("broadcast = %#v", broadcast) + } + if txSrv.lastBroadcastReq == nil { + t.Fatal("broadcast request = nil") + } + if !bytes.Equal(txSrv.lastBroadcastReq.GetTxBytes(), []byte("tx")) { + t.Fatalf("broadcast tx bytes = %x, want %x", txSrv.lastBroadcastReq.GetTxBytes(), []byte("tx")) + } + if txSrv.lastBroadcastReq.GetMode() != txv1beta1.BroadcastMode_BROADCAST_MODE_SYNC { + t.Fatalf("broadcast mode = %v, want %v", txSrv.lastBroadcastReq.GetMode(), txv1beta1.BroadcastMode_BROADCAST_MODE_SYNC) + } +} + +func assertGetTxResponse(t *testing.T, queried *TxStatus, txSrv *txServer) { + t.Helper() + + if queried.Hash != "DEF" || queried.Code != 3 { + t.Fatalf("queried = %#v", queried) + } + if txSrv.lastGetTxHash != "ABC" { + t.Fatalf("GetTx hash = %q, want %q", txSrv.lastGetTxHash, "ABC") + } +} diff --git a/pkg/submit/blobtx.go b/pkg/submit/blobtx.go new file mode 100644 index 0000000..cfa1ccf --- /dev/null +++ b/pkg/submit/blobtx.go @@ -0,0 +1,49 @@ +package submit + +import ( + "errors" + + share "github.com/celestiaorg/go-square/v3/share" + celestiatx "github.com/celestiaorg/go-square/v3/tx" +) + +const ( + baseBlobTxGas = 65_000 + firstSequenceGasOverhead = 10_000 + gasPerBlobByte = 8 +) + +// MarshalBlobTx wraps a signed Cosmos SDK tx together with its blob payloads +// using Celestia's BlobTx wire format. +func MarshalBlobTx(innerTx []byte, blobs []Blob) ([]byte, error) { + if len(innerTx) == 0 { + return nil, errors.New("inner tx is required") + } + squareBlobs, err := convertSquareBlobs(blobs) + if err != nil { + return nil, err + } + return celestiatx.MarshalBlobTx(innerTx, squareBlobs...) +} + +// EstimateGas returns the deterministic gas limit used for direct celestia-app +// submission. It mirrors the public Celestia guidance for PayForBlobs: +// a fixed base cost plus a share-count-based byte charge. +func EstimateGas(blobs []Blob, sequence uint64) (uint64, error) { + squareBlobs, err := convertSquareBlobs(blobs) + if err != nil { + return 0, err + } + + gas := uint64(baseBlobTxGas) + if sequence == 0 { + gas += firstSequenceGasOverhead + } + + for _, blob := range squareBlobs { + shares := share.SparseSharesNeeded(uint32(blob.DataLen()), blob.HasSigner()) + gas += uint64(shares * share.ShareSize * gasPerBlobByte) + } + + return gas, nil +} diff --git a/pkg/submit/blobtx_test.go b/pkg/submit/blobtx_test.go new file mode 100644 index 0000000..b6a5f57 --- /dev/null +++ b/pkg/submit/blobtx_test.go @@ -0,0 +1,179 @@ +package submit + +import ( + "bytes" + "testing" + + "github.com/evstack/apex/pkg/types" + "google.golang.org/protobuf/encoding/protowire" +) + +func TestEstimateGas(t *testing.T) { + t.Parallel() + + gas, err := EstimateGas([]Blob{{ + Namespace: testNamespace(1), + Data: make([]byte, 600), + Commitment: []byte("c1"), + }}, 0) + if err != nil { + t.Fatalf("EstimateGas: %v", err) + } + if gas != 83192 { + t.Fatalf("gas = %d, want 83192", gas) + } +} + +func TestMarshalBlobTx(t *testing.T) { + t.Parallel() + + blob := Blob{ + Namespace: testNamespace(2), + Data: []byte("payload"), + ShareVersion: 1, + Signer: testBlobSigner(), + } + raw, err := MarshalBlobTx([]byte("inner"), []Blob{blob}) + if err != nil { + t.Fatalf("MarshalBlobTx: %v", err) + } + inner, blobs, typeID := decodeBlobTxEnvelope(t, raw) + if string(inner) != "inner" { + t.Fatalf("inner tx = %q", inner) + } + if len(blobs) != 1 { + t.Fatalf("blob count = %d, want 1", len(blobs)) + } + decoded := decodeBlobProto(t, blobs[0]) + if !bytes.Equal(decoded.namespaceID, blob.Namespace[1:]) { + t.Fatalf("namespace id = %x, want %x", decoded.namespaceID, blob.Namespace[1:]) + } + if decoded.namespaceVersion != uint64(blob.Namespace[0]) { + t.Fatalf("namespace version = %d, want %d", decoded.namespaceVersion, blob.Namespace[0]) + } + if !bytes.Equal(decoded.data, blob.Data) { + t.Fatalf("data = %q, want %q", decoded.data, blob.Data) + } + if decoded.shareVersion != uint64(blob.ShareVersion) { + t.Fatalf("share version = %d, want %d", decoded.shareVersion, blob.ShareVersion) + } + if !bytes.Equal(decoded.signer, blob.Signer) { + t.Fatalf("signer = %q, want %q", decoded.signer, blob.Signer) + } + if typeID != types.ProtoBlobTxTypeID { + t.Fatalf("type_id = %q, want %q", typeID, types.ProtoBlobTxTypeID) + } +} + +func TestMarshalBlobTxRejectsMissingInput(t *testing.T) { + t.Parallel() + + if _, err := MarshalBlobTx(nil, []Blob{{Data: []byte("payload")}}); err == nil { + t.Fatal("expected error when inner tx is missing") + } + if _, err := MarshalBlobTx([]byte("inner"), nil); err == nil { + t.Fatal("expected error when blobs are missing") + } +} + +func decodeBlobTxEnvelope(t *testing.T, raw []byte) ([]byte, [][]byte, string) { + t.Helper() + + var ( + innerTx []byte + blobs [][]byte + typeID string + ) + + data := raw + for len(data) > 0 { + num, typ, n := protowire.ConsumeTag(data) + if n < 0 { + t.Fatal("failed to decode BlobTx tag") + } + data = data[n:] + + if typ != protowire.BytesType { + t.Fatalf("unexpected wire type %d for field %d", typ, num) + } + + value, n := protowire.ConsumeBytes(data) + if n < 0 { + t.Fatalf("failed to decode BlobTx field %d", num) + } + data = data[n:] + + switch num { + case 1: + innerTx = value + case 2: + blobs = append(blobs, value) + case 3: + typeID = string(value) + default: + t.Fatalf("unexpected BlobTx field %d", num) + } + } + + return innerTx, blobs, typeID +} + +type blobProtoFields struct { + namespaceID []byte + data []byte + shareVersion uint64 + namespaceVersion uint64 + signer []byte +} + +func decodeBlobProto(t *testing.T, raw []byte) blobProtoFields { + t.Helper() + + var fields blobProtoFields + + data := raw + for len(data) > 0 { + num, typ, n := protowire.ConsumeTag(data) + if n < 0 { + t.Fatal("failed to decode blob proto tag") + } + data = data[n:] + + switch typ { + case protowire.BytesType: + value, n := protowire.ConsumeBytes(data) + if n < 0 { + t.Fatalf("failed to decode blob proto field %d", num) + } + data = data[n:] + switch num { + case 1: + fields.namespaceID = value + case 2: + fields.data = value + case 5: + fields.signer = value + default: + t.Fatalf("unexpected blob proto bytes field %d", num) + } + case protowire.VarintType: + value, n := protowire.ConsumeVarint(data) + if n < 0 { + t.Fatalf("failed to decode blob proto field %d", num) + } + data = data[n:] + switch num { + case 3: + fields.shareVersion = value + case 4: + fields.namespaceVersion = value + default: + t.Fatalf("unexpected blob proto varint field %d", num) + } + default: + t.Fatalf("unexpected blob proto wire type %d for field %d", typ, num) + } + } + + return fields +} diff --git a/pkg/submit/celestia_blob.go b/pkg/submit/celestia_blob.go new file mode 100644 index 0000000..630f1fb --- /dev/null +++ b/pkg/submit/celestia_blob.go @@ -0,0 +1,43 @@ +package submit + +import ( + "fmt" + + share "github.com/celestiaorg/go-square/v3/share" +) + +func convertSquareBlob(blob Blob) (*share.Blob, error) { + namespace, err := share.NewNamespaceFromBytes(blob.Namespace[:]) + if err != nil { + return nil, fmt.Errorf("build namespace: %w", err) + } + if err := namespace.ValidateForBlob(); err != nil { + return nil, fmt.Errorf("invalid blob namespace: %w", err) + } + if blob.ShareVersion > uint32(share.MaxShareVersion) { + return nil, fmt.Errorf("unsupported share version %d", blob.ShareVersion) + } + + signer := blob.Signer + if len(signer) == 0 { + signer = nil + } + + squareBlob, err := share.NewBlob(namespace, blob.Data, uint8(blob.ShareVersion), signer) + if err != nil { + return nil, fmt.Errorf("build celestia blob: %w", err) + } + return squareBlob, nil +} + +func convertSquareBlobs(blobs []Blob) ([]*share.Blob, error) { + converted := make([]*share.Blob, len(blobs)) + for i := range blobs { + blob, err := convertSquareBlob(blobs[i]) + if err != nil { + return nil, fmt.Errorf("blob %d: %w", i, err) + } + converted[i] = blob + } + return converted, nil +} diff --git a/pkg/submit/direct.go b/pkg/submit/direct.go new file mode 100644 index 0000000..9040759 --- /dev/null +++ b/pkg/submit/direct.go @@ -0,0 +1,344 @@ +package submit + +import ( + "context" + "errors" + "fmt" + "strings" + "sync" + "time" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/anypb" +) + +const ( + defaultFeeDenom = "utia" + defaultPollInterval = time.Second + maxSequenceRetryRounds = 2 +) + +var errSequenceMismatch = errors.New("account sequence mismatch") + +// DirectConfig contains the fixed submission settings Apex owns for direct +// celestia-app writes. +type DirectConfig struct { + ChainID string + GasPrice float64 + MaxGasPrice float64 + ConfirmationTimeout time.Duration +} + +// DirectSubmitter signs and submits Celestia BlobTx payloads directly to +// celestia-app over Cosmos SDK gRPC. +type DirectSubmitter struct { + app AppClient + signer *Signer + chainID string + gasPrice float64 + maxGasPrice float64 + confirmationTimeout time.Duration + pollInterval time.Duration + feeDenom string + mu sync.Mutex +} + +// NewDirectSubmitter builds a concrete single-account submitter. +func NewDirectSubmitter(app AppClient, signer *Signer, cfg DirectConfig) (*DirectSubmitter, error) { + if app == nil { + return nil, errors.New("submission app client is required") + } + if signer == nil { + return nil, errors.New("submission signer is required") + } + if cfg.ChainID == "" { + return nil, errors.New("submission chain id is required") + } + if cfg.ConfirmationTimeout <= 0 { + return nil, errors.New("submission confirmation timeout must be positive") + } + if cfg.GasPrice < 0 { + return nil, errors.New("submission gas price must be non-negative") + } + if cfg.MaxGasPrice < 0 { + return nil, errors.New("submission max gas price must be non-negative") + } + if cfg.MaxGasPrice > 0 && cfg.GasPrice > cfg.MaxGasPrice { + return nil, errors.New("submission gas price must not exceed the max gas price") + } + + return &DirectSubmitter{ + app: app, + signer: signer, + chainID: cfg.ChainID, + gasPrice: cfg.GasPrice, + maxGasPrice: cfg.MaxGasPrice, + confirmationTimeout: cfg.ConfirmationTimeout, + pollInterval: defaultPollInterval, + feeDenom: defaultFeeDenom, + }, nil +} + +func (s *DirectSubmitter) Close() error { + if s == nil || s.app == nil { + return nil + } + return s.app.Close() +} + +// Submit serializes submissions for the configured signer so sequence handling +// stays bounded and explicit in v1. +func (s *DirectSubmitter) Submit(ctx context.Context, req *Request) (*Result, error) { + if err := validateSubmitRequest(req); err != nil { + return nil, err + } + + s.mu.Lock() + defer s.mu.Unlock() + + var lastErr error + for range maxSequenceRetryRounds { + result, err := s.submitOnce(ctx, req) + if err == nil { + return result, nil + } + lastErr = err + if !errors.Is(err, errSequenceMismatch) { + return nil, err + } + } + + return nil, lastErr +} + +func validateSubmitRequest(req *Request) error { + if req == nil { + return errors.New("submission request is required") + } + if len(req.Blobs) == 0 { + return errors.New("at least one blob is required") + } + for i := range req.Blobs { + if _, err := convertSquareBlob(req.Blobs[i]); err != nil { + return fmt.Errorf("validate submission blob %d: %w", i, err) + } + } + return nil +} + +func (s *DirectSubmitter) submitOnce(ctx context.Context, req *Request) (*Result, error) { + account, err := s.app.AccountInfo(ctx, s.signer.Address()) + if err != nil { + return nil, fmt.Errorf("query submission account: %w", err) + } + if account == nil { + return nil, errors.New("query submission account: empty response") + } + + txBytes, err := s.buildBlobTx(req, account) + if err != nil { + return nil, err + } + + broadcast, err := s.app.BroadcastTx(ctx, txBytes) + if err != nil { + if isSequenceMismatchText(err.Error()) { + return nil, fmt.Errorf("%w: %w", errSequenceMismatch, err) + } + return nil, fmt.Errorf("broadcast blob tx: %w", err) + } + if err := checkTxStatus("broadcast", broadcast); err != nil { + return nil, err + } + + return s.waitForConfirmation(ctx, broadcast.Hash) +} + +func (s *DirectSubmitter) buildBlobTx(req *Request, account *AccountInfo) ([]byte, error) { + pfb, err := BuildMsgPayForBlobs(s.signer.Address(), req.Blobs) + if err != nil { + return nil, fmt.Errorf("build pay-for-blobs message: %w", err) + } + msg, err := MarshalMsgPayForBlobsAny(pfb) + if err != nil { + return nil, err + } + + gasLimit, gasPrice, err := s.resolveFees(req.Blobs, req.Options, account.Sequence) + if err != nil { + return nil, err + } + feeAmount, err := FeeAmountFromGasPrice(gasLimit, gasPrice) + if err != nil { + return nil, err + } + + signerInfo, err := BuildSignerInfo(s.signer.PublicKey(), account.Sequence) + if err != nil { + return nil, err + } + authInfo, err := BuildAuthInfo(signerInfo, s.feeDenom, feeAmount, gasLimit, "", feeGranter(req.Options)) + if err != nil { + return nil, err + } + authInfoBytes, err := MarshalAuthInfo(authInfo) + if err != nil { + return nil, err + } + bodyBytes, err := MarshalTxBody([]*anypb.Any{msg}, "", 0) + if err != nil { + return nil, err + } + signDocBytes, err := BuildSignDoc(bodyBytes, authInfoBytes, s.chainID, account.AccountNumber) + if err != nil { + return nil, err + } + signature, err := s.signer.Sign(signDocBytes) + if err != nil { + return nil, fmt.Errorf("sign pay-for-blobs tx: %w", err) + } + + innerTx, err := MarshalTxRaw(bodyBytes, authInfoBytes, signature) + if err != nil { + return nil, err + } + return MarshalBlobTx(innerTx, req.Blobs) +} + +func (s *DirectSubmitter) resolveFees(blobs []Blob, opts *TxConfig, sequence uint64) (uint64, float64, error) { + if err := s.validateOptions(opts); err != nil { + return 0, 0, err + } + + gasPrice, err := resolveGasPrice(s.gasPrice, opts) + if err != nil { + return 0, 0, err + } + + effectiveMaxGasPrice, err := resolveMaxGasPrice(s.maxGasPrice, opts) + if err != nil { + return 0, 0, err + } + if effectiveMaxGasPrice > 0 && gasPrice > effectiveMaxGasPrice { + return 0, 0, fmt.Errorf("submission gas price %.6f exceeds the max gas price %.6f", gasPrice, effectiveMaxGasPrice) + } + + if opts != nil && opts.Gas > 0 { + return opts.Gas, gasPrice, nil + } + + gasLimit, err := EstimateGas(blobs, sequence) + if err != nil { + return 0, 0, err + } + return gasLimit, gasPrice, nil +} + +func (s *DirectSubmitter) validateOptions(opts *TxConfig) error { + if opts == nil { + return nil + } + if opts.KeyName != "" { + return errors.New("submission tx option key_name is not supported by the direct submitter") + } + if opts.TxPriority != 0 { + return errors.New("submission tx option tx_priority is not supported by the direct submitter") + } + if opts.SignerAddress != "" && opts.SignerAddress != s.signer.Address() { + return fmt.Errorf("submission signer_address %q does not match configured signer %q", opts.SignerAddress, s.signer.Address()) + } + return nil +} + +func resolveGasPrice(defaultGasPrice float64, opts *TxConfig) (float64, error) { + gasPrice := defaultGasPrice + if opts != nil && (opts.IsGasPriceSet || opts.GasPrice > 0) { + gasPrice = opts.GasPrice + } + if gasPrice <= 0 { + return 0, errors.New("submission gas price must be configured or provided per request") + } + return gasPrice, nil +} + +func resolveMaxGasPrice(defaultMaxGasPrice float64, opts *TxConfig) (float64, error) { + effectiveMaxGasPrice := defaultMaxGasPrice + if opts == nil { + return effectiveMaxGasPrice, nil + } + if opts.MaxGasPrice < 0 { + return 0, errors.New("submission tx option max_gas_price must be non-negative") + } + if opts.MaxGasPrice > 0 && (effectiveMaxGasPrice == 0 || opts.MaxGasPrice < effectiveMaxGasPrice) { + effectiveMaxGasPrice = opts.MaxGasPrice + } + return effectiveMaxGasPrice, nil +} + +func feeGranter(opts *TxConfig) string { + if opts == nil { + return "" + } + return opts.FeeGranterAddress +} + +func (s *DirectSubmitter) waitForConfirmation(parent context.Context, hash string) (*Result, error) { + if hash == "" { + return nil, errors.New("broadcast returned an empty tx hash") + } + + ctx, cancel := context.WithTimeout(parent, s.confirmationTimeout) + defer cancel() + + ticker := time.NewTicker(s.pollInterval) + defer ticker.Stop() + + for { + tx, err := s.app.GetTx(ctx, hash) + if err == nil { + if err := checkTxStatus("confirm", tx); err != nil { + return nil, err + } + if tx.Height <= 0 { + return nil, fmt.Errorf("confirm tx %s returned an invalid height %d", hash, tx.Height) + } + return &Result{Height: uint64(tx.Height)}, nil + } + if !isTxNotFound(err) { + return nil, fmt.Errorf("confirm blob tx %s: %w", hash, err) + } + + select { + case <-ctx.Done(): + return nil, fmt.Errorf("confirm blob tx %s: %w", hash, ctx.Err()) + case <-ticker.C: + } + } +} + +func checkTxStatus(stage string, tx *TxStatus) error { + if tx == nil { + return fmt.Errorf("%s blob tx returned an empty response", stage) + } + if tx.Code == 0 { + return nil + } + + if isSequenceMismatchText(tx.RawLog) { + return fmt.Errorf("%w: %s", errSequenceMismatch, tx.RawLog) + } + if tx.Codespace != "" { + return fmt.Errorf("%s blob tx failed with code %d (%s): %s", stage, tx.Code, tx.Codespace, tx.RawLog) + } + return fmt.Errorf("%s blob tx failed with code %d: %s", stage, tx.Code, tx.RawLog) +} + +func isSequenceMismatchText(text string) bool { + text = strings.ToLower(text) + return strings.Contains(text, "account sequence mismatch") || strings.Contains(text, "incorrect account sequence") +} + +func isTxNotFound(err error) bool { + return status.Code(err) == codes.NotFound +} diff --git a/pkg/submit/direct_test.go b/pkg/submit/direct_test.go new file mode 100644 index 0000000..5944143 --- /dev/null +++ b/pkg/submit/direct_test.go @@ -0,0 +1,321 @@ +package submit + +import ( + "context" + "errors" + "strings" + "testing" + "time" + + "github.com/evstack/apex/pkg/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type fakeAppClient struct { + accountInfos []*AccountInfo + accountErrs []error + broadcastStatuses []*TxStatus + broadcastErrs []error + getTxStatuses []*TxStatus + getTxErrs []error + broadcastRequests [][]byte + accountCalls int + broadcastCalls int + getTxCalls int +} + +func (f *fakeAppClient) AccountInfo(_ context.Context, _ string) (*AccountInfo, error) { + call := f.accountCalls + f.accountCalls++ + if err := queueErr(f.accountErrs, call); err != nil { + return nil, err + } + return queueAccount(f.accountInfos, call), nil +} + +func (f *fakeAppClient) BroadcastTx(_ context.Context, txBytes []byte) (*TxStatus, error) { + call := f.broadcastCalls + f.broadcastCalls++ + f.broadcastRequests = append(f.broadcastRequests, append([]byte(nil), txBytes...)) + if err := queueErr(f.broadcastErrs, call); err != nil { + return nil, err + } + return queueTxStatus(f.broadcastStatuses, call), nil +} + +func (f *fakeAppClient) GetTx(_ context.Context, _ string) (*TxStatus, error) { + call := f.getTxCalls + f.getTxCalls++ + if err := queueErr(f.getTxErrs, call); err != nil { + return nil, err + } + if len(f.getTxStatuses) == 0 && len(f.getTxErrs) > 0 { + return nil, f.getTxErrs[len(f.getTxErrs)-1] + } + return queueTxStatus(f.getTxStatuses, call), nil +} + +func (*fakeAppClient) Close() error { + return nil +} + +func TestDirectSubmitterSubmit(t *testing.T) { + t.Parallel() + + signer := mustSigner(t) + client := &fakeAppClient{ + accountInfos: []*AccountInfo{{ + Address: signer.Address(), + AccountNumber: 7, + Sequence: 1, + }}, + broadcastStatuses: []*TxStatus{{ + Hash: "ABC123", + }}, + getTxErrs: []error{ + status.Error(codes.NotFound, "not found"), + }, + getTxStatuses: []*TxStatus{{ + Hash: "ABC123", + Height: 55, + }}, + } + + submitter, err := NewDirectSubmitter(client, signer, DirectConfig{ + ChainID: "mocha-4", + GasPrice: 0.002, + MaxGasPrice: 0.01, + ConfirmationTimeout: 100 * time.Millisecond, + }) + if err != nil { + t.Fatalf("NewDirectSubmitter: %v", err) + } + submitter.pollInterval = time.Millisecond + + result, err := submitter.Submit(context.Background(), testRequest()) + if err != nil { + t.Fatalf("Submit: %v", err) + } + if result.Height != 55 { + t.Fatalf("height = %d, want 55", result.Height) + } + if client.broadcastCalls != 1 { + t.Fatalf("broadcast calls = %d, want 1", client.broadcastCalls) + } + _, _, typeID := decodeBlobTxEnvelope(t, client.broadcastRequests[0]) + if typeID != types.ProtoBlobTxTypeID { + t.Fatalf("blob tx type_id = %q, want %q", typeID, types.ProtoBlobTxTypeID) + } +} + +func TestDirectSubmitterRetriesSequenceMismatch(t *testing.T) { + t.Parallel() + + signer := mustSigner(t) + client := &fakeAppClient{ + accountInfos: []*AccountInfo{ + {Address: signer.Address(), AccountNumber: 7, Sequence: 1}, + {Address: signer.Address(), AccountNumber: 7, Sequence: 2}, + }, + broadcastStatuses: []*TxStatus{ + {Code: 32, RawLog: "account sequence mismatch, expected 2, got 1"}, + {Hash: "DEF456"}, + }, + getTxStatuses: []*TxStatus{{ + Hash: "DEF456", + Height: 77, + }}, + } + + submitter, err := NewDirectSubmitter(client, signer, DirectConfig{ + ChainID: "mocha-4", + GasPrice: 0.002, + ConfirmationTimeout: 100 * time.Millisecond, + }) + if err != nil { + t.Fatalf("NewDirectSubmitter: %v", err) + } + submitter.pollInterval = time.Millisecond + + result, err := submitter.Submit(context.Background(), testRequest()) + if err != nil { + t.Fatalf("Submit: %v", err) + } + if result.Height != 77 { + t.Fatalf("height = %d, want 77", result.Height) + } + if client.accountCalls != 2 { + t.Fatalf("account calls = %d, want 2", client.accountCalls) + } + if client.broadcastCalls != 2 { + t.Fatalf("broadcast calls = %d, want 2", client.broadcastCalls) + } +} + +func TestDirectSubmitterRejectsSignerMismatch(t *testing.T) { + t.Parallel() + + signer := mustSigner(t) + client := &fakeAppClient{ + accountInfos: []*AccountInfo{{ + Address: signer.Address(), + AccountNumber: 7, + Sequence: 1, + }}, + } + + submitter, err := NewDirectSubmitter(client, signer, DirectConfig{ + ChainID: "mocha-4", + GasPrice: 0.002, + ConfirmationTimeout: time.Second, + }) + if err != nil { + t.Fatalf("NewDirectSubmitter: %v", err) + } + + _, err = submitter.Submit(context.Background(), &Request{ + Blobs: testRequest().Blobs, + Options: &TxConfig{ + SignerAddress: "celestia1different", + }, + }) + if err == nil { + t.Fatal("expected error, got nil") + } + if !strings.Contains(err.Error(), "does not match") { + t.Fatalf("expected signer mismatch error, got: %v", err) + } + if client.broadcastCalls != 0 { + t.Fatalf("broadcast calls = %d, want 0", client.broadcastCalls) + } +} + +func TestDirectSubmitterRejectsPerRequestMaxGasPrice(t *testing.T) { + t.Parallel() + + signer := mustSigner(t) + client := &fakeAppClient{ + accountInfos: []*AccountInfo{{ + Address: signer.Address(), + AccountNumber: 7, + Sequence: 1, + }}, + } + + submitter, err := NewDirectSubmitter(client, signer, DirectConfig{ + ChainID: "mocha-4", + GasPrice: 0.002, + MaxGasPrice: 0.01, + ConfirmationTimeout: time.Second, + }) + if err != nil { + t.Fatalf("NewDirectSubmitter: %v", err) + } + + _, err = submitter.Submit(context.Background(), &Request{ + Blobs: testRequest().Blobs, + Options: &TxConfig{ + GasPrice: 0.002, + IsGasPriceSet: true, + MaxGasPrice: 0.001, + }, + }) + if err == nil { + t.Fatal("expected error, got nil") + } + if !strings.Contains(err.Error(), "exceeds the max gas price") { + t.Fatalf("expected max gas price error, got: %v", err) + } + if client.broadcastCalls != 0 { + t.Fatalf("broadcast calls = %d, want 0", client.broadcastCalls) + } +} + +func TestDirectSubmitterConfirmationTimeout(t *testing.T) { + t.Parallel() + + signer := mustSigner(t) + client := &fakeAppClient{ + accountInfos: []*AccountInfo{{ + Address: signer.Address(), + AccountNumber: 7, + Sequence: 1, + }}, + broadcastStatuses: []*TxStatus{{ + Hash: "ABC123", + }}, + getTxErrs: []error{ + status.Error(codes.NotFound, "not found"), + }, + } + + submitter, err := NewDirectSubmitter(client, signer, DirectConfig{ + ChainID: "mocha-4", + GasPrice: 0.002, + ConfirmationTimeout: 5 * time.Millisecond, + }) + if err != nil { + t.Fatalf("NewDirectSubmitter: %v", err) + } + submitter.pollInterval = time.Millisecond + + _, err = submitter.Submit(context.Background(), testRequest()) + if err == nil { + t.Fatal("expected timeout error, got nil") + } + if !errors.Is(err, context.DeadlineExceeded) { + t.Fatalf("error = %v", err) + } +} + +func mustSigner(t *testing.T) *Signer { + t.Helper() + + signer, err := LoadSigner(writeSignerKey(t, testSignerKeyHex)) + if err != nil { + t.Fatalf("LoadSigner: %v", err) + } + return signer +} + +func testRequest() *Request { + return &Request{ + Blobs: []Blob{{ + Namespace: testNamespace(1), + Data: []byte("hello world"), + ShareVersion: 0, + Commitment: []byte("commitment-1"), + }}, + } +} + +func queueErr(errs []error, idx int) error { + if len(errs) == 0 { + return nil + } + if idx >= len(errs) { + return nil + } + return errs[idx] +} + +func queueAccount(accounts []*AccountInfo, idx int) *AccountInfo { + if len(accounts) == 0 { + return nil + } + if idx >= len(accounts) { + return accounts[len(accounts)-1] + } + return accounts[idx] +} + +func queueTxStatus(statuses []*TxStatus, idx int) *TxStatus { + if len(statuses) == 0 { + return nil + } + if idx >= len(statuses) { + return statuses[len(statuses)-1] + } + return statuses[idx] +} diff --git a/pkg/submit/signer.go b/pkg/submit/signer.go new file mode 100644 index 0000000..d374a07 --- /dev/null +++ b/pkg/submit/signer.go @@ -0,0 +1,121 @@ +package submit + +import ( + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + "os" + "strings" + + "github.com/btcsuite/btcd/btcutil" + "github.com/cosmos/btcutil/bech32" + secp256k1 "github.com/decred/dcrd/dcrec/secp256k1/v4" + ecdsa "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" + + "github.com/evstack/apex/pkg/types" +) + +const defaultAddressPrefix = "celestia" + +// Signer owns the local secp256k1 key material for direct blob submission. +type Signer struct { + address string + privateKey *secp256k1.PrivateKey + publicKey []byte +} + +// LoadSigner reads a file containing a hex-encoded secp256k1 private key and +// derives the corresponding Cosmos-style address and compressed public key. +func LoadSigner(keyPath string) (*Signer, error) { + keyPath = strings.TrimSpace(keyPath) + if keyPath == "" { + return nil, errors.New("submission signer key path is required") + } + + keyBytes, err := os.ReadFile(keyPath) + if err != nil { + return nil, fmt.Errorf("read submission signer key %q: %w", keyPath, err) + } + + privKeyBytes, err := decodePrivateKeyHex(string(keyBytes)) + if err != nil { + return nil, err + } + + var scalar secp256k1.ModNScalar + if scalar.SetByteSlice(privKeyBytes) { + return nil, errors.New("submission private key exceeds the secp256k1 curve order") + } + if scalar.IsZero() { + return nil, errors.New("submission private key must not be zero") + } + + privateKey := secp256k1.NewPrivateKey(&scalar) + publicKey := privateKey.PubKey().SerializeCompressed() + address, err := pubKeyAddress(publicKey, defaultAddressPrefix) + if err != nil { + return nil, err + } + + return &Signer{ + address: address, + privateKey: privateKey, + publicKey: publicKey, + }, nil +} + +func (s *Signer) Address() string { + return s.address +} + +func (s *Signer) PublicKey() []byte { + return append([]byte(nil), s.publicKey...) +} + +func (s *Signer) Sign(message []byte) ([]byte, error) { + if s == nil || s.privateKey == nil { + return nil, errors.New("signer is required") + } + + hash := sha256.Sum256(message) + signature := ecdsa.Sign(s.privateKey, hash[:]) + return marshalSignature(signature), nil +} + +func decodePrivateKeyHex(raw string) ([]byte, error) { + raw = strings.TrimSpace(types.StripHexPrefix(raw)) + if raw == "" { + return nil, errors.New("submission private key is required") + } + + privKeyBytes, err := hex.DecodeString(raw) + if err != nil { + return nil, fmt.Errorf("decode submission private key hex: %w", err) + } + if len(privKeyBytes) != secp256k1.PrivKeyBytesLen { + return nil, fmt.Errorf("submission private key must be %d bytes, got %d", secp256k1.PrivKeyBytesLen, len(privKeyBytes)) + } + return privKeyBytes, nil +} + +func pubKeyAddress(publicKey []byte, prefix string) (string, error) { + fiveBit, err := bech32.ConvertBits(btcutil.Hash160(publicKey), 8, 5, true) + if err != nil { + return "", fmt.Errorf("convert address bits: %w", err) + } + address, err := bech32.Encode(prefix, fiveBit) + if err != nil { + return "", fmt.Errorf("bech32 encode address: %w", err) + } + return address, nil +} + +func marshalSignature(signature *ecdsa.Signature) []byte { + var raw [64]byte + r := signature.R() + s := signature.S() + r.PutBytesUnchecked(raw[:32]) + s.PutBytesUnchecked(raw[32:]) + return raw[:] +} diff --git a/pkg/submit/signer_test.go b/pkg/submit/signer_test.go new file mode 100644 index 0000000..cbcc75d --- /dev/null +++ b/pkg/submit/signer_test.go @@ -0,0 +1,114 @@ +package submit + +import ( + "crypto/sha256" + "os" + "path/filepath" + "strings" + "testing" + + secp256k1 "github.com/decred/dcrd/dcrec/secp256k1/v4" + ecdsa "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" +) + +const testSignerKeyHex = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20" + +func TestLoadSigner(t *testing.T) { + t.Parallel() + + signer, err := LoadSigner(writeSignerKey(t, testSignerKeyHex+"\n")) + if err != nil { + t.Fatalf("LoadSigner: %v", err) + } + if got := signer.Address(); !strings.HasPrefix(got, "celestia1") { + t.Fatalf("address = %q, want celestia bech32 prefix", got) + } + pubKeyBytes := signer.PublicKey() + if got := len(pubKeyBytes); got != 33 { + t.Fatalf("public key length = %d, want 33", got) + } + pubKey, err := secp256k1.ParsePubKey(pubKeyBytes) + if err != nil { + t.Fatalf("ParsePubKey: %v", err) + } + + message := []byte("hello") + signature, err := signer.Sign(message) + if err != nil { + t.Fatalf("Sign: %v", err) + } + if len(signature) != 64 { + t.Fatalf("signature length = %d, want 64", len(signature)) + } + hash := sha256.Sum256(message) + if !parseCompactSignature(t, signature).Verify(hash[:], pubKey) { + t.Fatal("signature did not verify against the derived public key") + } +} + +func TestLoadSignerRejectsWrongLength(t *testing.T) { + t.Parallel() + + _, err := LoadSigner(writeSignerKey(t, "abcd")) + if err == nil { + t.Fatal("expected error, got nil") + } +} + +func TestLoadSignerRejectsZeroKey(t *testing.T) { + t.Parallel() + + _, err := LoadSigner(writeSignerKey(t, strings.Repeat("0", secp256k1.PrivKeyBytesLen*2))) + if err == nil { + t.Fatal("expected error for zero private key") + } +} + +func TestLoadSignerRejectsMissingFile(t *testing.T) { + t.Parallel() + + _, err := LoadSigner(filepath.Join(t.TempDir(), "missing.key")) + if err == nil { + t.Fatal("expected error for missing signer key file") + } +} + +func TestDecodePrivateKeyHexStripsPrefix(t *testing.T) { + t.Parallel() + + raw, err := decodePrivateKeyHex("0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20") + if err != nil { + t.Fatalf("decodePrivateKeyHex: %v", err) + } + if len(raw) != secp256k1.PrivKeyBytesLen { + t.Fatalf("private key length = %d", len(raw)) + } +} + +func parseCompactSignature(t *testing.T, raw []byte) *ecdsa.Signature { + t.Helper() + + if len(raw) != 64 { + t.Fatalf("compact signature length = %d, want 64", len(raw)) + } + + var r secp256k1.ModNScalar + if r.SetByteSlice(raw[:32]) { + t.Fatal("signature r overflowed secp256k1 scalar") + } + var s secp256k1.ModNScalar + if s.SetByteSlice(raw[32:]) { + t.Fatal("signature s overflowed secp256k1 scalar") + } + return ecdsa.NewSignature(&r, &s) +} + +func writeSignerKey(t *testing.T, signerKeyHex string) string { + t.Helper() + + keyPath := filepath.Join(t.TempDir(), "submission.key") + if err := os.WriteFile(keyPath, []byte(signerKeyHex), 0o600); err != nil { + t.Fatalf("WriteFile: %v", err) + } + return keyPath +} diff --git a/pkg/submit/submit.go b/pkg/submit/submit.go new file mode 100644 index 0000000..df7049c --- /dev/null +++ b/pkg/submit/submit.go @@ -0,0 +1,169 @@ +package submit + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + + "github.com/evstack/apex/pkg/types" +) + +// ErrDisabled reports that no submission backend is configured. +var ErrDisabled = errors.New("blob submission not configured") + +// Priority mirrors celestia-node's JSON tx priority values. +type Priority int + +const ( + PriorityLow Priority = iota + 1 + PriorityMedium + PriorityHigh +) + +// Blob is the Apex-owned wire shape for blob submission requests. +// It intentionally matches celestia-node's JSON-RPC payload fields without +// depending on celestia-node or cosmos-sdk types. +type Blob struct { + Namespace types.Namespace + Data []byte + ShareVersion uint32 + Commitment []byte + Signer []byte + Index int +} + +// TxConfig mirrors celestia-node's JSON submit options. +type TxConfig struct { + GasPrice float64 `json:"gas_price,omitempty"` + IsGasPriceSet bool `json:"is_gas_price_set,omitempty"` + MaxGasPrice float64 `json:"max_gas_price"` + Gas uint64 `json:"gas,omitempty"` + TxPriority Priority `json:"tx_priority,omitempty"` + KeyName string `json:"key_name,omitempty"` + SignerAddress string `json:"signer_address,omitempty"` + FeeGranterAddress string `json:"fee_granter_address,omitempty"` +} + +// Request is the typed input for a blob submission. +type Request struct { + Blobs []Blob + Options *TxConfig +} + +// Result is the typed result for a confirmed blob submission. +type Result struct { + Height uint64 +} + +// Submitter is the Apex-owned submission boundary. Implementations may be +// dependency-free or backed by a separate module, but callers only see these +// local types. +type Submitter interface { + Submit(ctx context.Context, req *Request) (*Result, error) +} + +type jsonBlob struct { + Namespace []byte `json:"namespace"` + Data []byte `json:"data"` + ShareVersion uint32 `json:"share_version"` + Commitment []byte `json:"commitment"` + Signer []byte `json:"signer,omitempty"` + Index int `json:"index"` +} + +// DecodeRequest converts JSON-RPC blob.Submit params into Apex-owned types. +func DecodeRequest(blobsRaw, optionsRaw json.RawMessage) (*Request, error) { + blobs, err := decodeBlobs(blobsRaw) + if err != nil { + return nil, err + } + opts, err := decodeOptions(optionsRaw) + if err != nil { + return nil, err + } + return &Request{ + Blobs: blobs, + Options: opts, + }, nil +} + +// MarshalResult encodes a submission result using the JSON-RPC-compatible +// return shape expected by blob.Submit. +func MarshalResult(result *Result) (json.RawMessage, error) { + if result == nil { + return nil, errors.New("submission result is required") + } + raw, err := json.Marshal(result.Height) + if err != nil { + return nil, fmt.Errorf("marshal submit result: %w", err) + } + return raw, nil +} + +func decodeBlobs(raw json.RawMessage) ([]Blob, error) { + var blobsJSON []jsonBlob + if err := json.Unmarshal(raw, &blobsJSON); err != nil { + return nil, fmt.Errorf("decode submit blobs: %w", err) + } + + blobs := make([]Blob, len(blobsJSON)) + for i := range blobsJSON { + ns, err := types.NamespaceFromBytes(blobsJSON[i].Namespace) + if err != nil { + return nil, fmt.Errorf("decode submit blob %d namespace: %w", i, err) + } + blobs[i] = Blob{ + Namespace: ns, + Data: blobsJSON[i].Data, + ShareVersion: blobsJSON[i].ShareVersion, + Commitment: blobsJSON[i].Commitment, + Signer: blobsJSON[i].Signer, + Index: blobsJSON[i].Index, + } + if _, err := convertSquareBlob(blobs[i]); err != nil { + return nil, fmt.Errorf("decode submit blob %d: %w", i, err) + } + } + + return blobs, nil +} + +func decodeOptions(raw json.RawMessage) (*TxConfig, error) { + trimmed := bytes.TrimSpace(raw) + if len(trimmed) == 0 || bytes.Equal(trimmed, []byte("null")) { + return nil, nil + } + + var cfg TxConfig + if err := json.Unmarshal(trimmed, &cfg); err != nil { + return nil, fmt.Errorf("decode submit options: %w", err) + } + if err := validateTxConfig(&cfg); err != nil { + return nil, err + } + return &cfg, nil +} + +func validateTxConfig(cfg *TxConfig) error { + if cfg == nil { + return nil + } + if cfg.GasPrice < 0 { + return errors.New("decode submit options: gas_price must be non-negative") + } + if cfg.MaxGasPrice < 0 { + return errors.New("decode submit options: max_gas_price must be non-negative") + } + if cfg.MaxGasPrice > 0 && (cfg.IsGasPriceSet || cfg.GasPrice > 0) && cfg.GasPrice > cfg.MaxGasPrice { + return errors.New("decode submit options: gas_price must not exceed max_gas_price") + } + if cfg.TxPriority != 0 && + cfg.TxPriority != PriorityLow && + cfg.TxPriority != PriorityMedium && + cfg.TxPriority != PriorityHigh { + return fmt.Errorf("decode submit options: invalid tx_priority %d", cfg.TxPriority) + } + return nil +} diff --git a/pkg/submit/submit_test.go b/pkg/submit/submit_test.go new file mode 100644 index 0000000..cba9299 --- /dev/null +++ b/pkg/submit/submit_test.go @@ -0,0 +1,207 @@ +package submit + +import ( + "encoding/json" + "testing" + + gsquare "github.com/celestiaorg/go-square/v3/share" + "github.com/evstack/apex/pkg/types" +) + +func TestDecodeRequestConvertsNamespace(t *testing.T) { + t.Parallel() + + ns := testNamespace(7) + blobsRaw, err := json.Marshal([]map[string]any{{ + "namespace": ns[:], + "data": []byte("hello"), + "share_version": 0, + "commitment": []byte("c1"), + "index": 0, + }}) + if err != nil { + t.Fatalf("marshal blobs: %v", err) + } + + req, err := DecodeRequest(blobsRaw, nil) + if err != nil { + t.Fatalf("DecodeRequest: %v", err) + } + if len(req.Blobs) != 1 { + t.Fatalf("got %d blobs, want 1", len(req.Blobs)) + } + if req.Blobs[0].Namespace != ns { + t.Fatalf("namespace = %x, want %x", req.Blobs[0].Namespace, ns) + } +} + +func TestDecodeRequestRejectsInvalidNamespace(t *testing.T) { + t.Parallel() + + // AQI= is base64 for [1, 2] — only 2 bytes, not 29. + blobsRaw := json.RawMessage(`[{"namespace":"AQI=","data":"aGVsbG8=","share_version":0,"commitment":"YzE=","index":0}]`) + + _, err := DecodeRequest(blobsRaw, nil) + if err == nil { + t.Fatal("expected error for short namespace") + } +} + +func TestDecodeRequestRejectsReservedNamespace(t *testing.T) { + t.Parallel() + + ns := reservedNamespace() + blobsRaw, err := json.Marshal([]map[string]any{{ + "namespace": ns[:], + "data": []byte("hello"), + "share_version": 0, + "commitment": []byte("c1"), + "index": 0, + }}) + if err != nil { + t.Fatalf("marshal blobs: %v", err) + } + + _, err = DecodeRequest(blobsRaw, nil) + if err == nil { + t.Fatal("expected error for reserved namespace") + } +} + +func TestDecodeRequestRejectsShareVersionOneWithoutSigner(t *testing.T) { + t.Parallel() + + ns := testNamespace(7) + blobsRaw, err := json.Marshal([]map[string]any{{ + "namespace": ns[:], + "data": []byte("hello"), + "share_version": 1, + "commitment": []byte("c1"), + "index": 0, + }}) + if err != nil { + t.Fatalf("marshal blobs: %v", err) + } + + _, err = DecodeRequest(blobsRaw, nil) + if err == nil { + t.Fatal("expected error for share version one without signer") + } +} + +func TestDecodeRequestAcceptsShareVersionOneSigner(t *testing.T) { + t.Parallel() + + ns := testNamespace(8) + wantSigner := testBlobSigner() + blobsRaw, err := json.Marshal([]map[string]any{{ + "namespace": ns[:], + "data": []byte("hello"), + "share_version": 1, + "commitment": []byte("c1"), + "signer": wantSigner, + "index": 0, + }}) + if err != nil { + t.Fatalf("marshal blobs: %v", err) + } + + req, err := DecodeRequest(blobsRaw, nil) + if err != nil { + t.Fatalf("DecodeRequest: %v", err) + } + if string(req.Blobs[0].Signer) != string(wantSigner) { + t.Fatalf("signer = %x, want %x", req.Blobs[0].Signer, wantSigner) + } +} + +func TestDecodeRequestTreatsWhitespaceNullOptionsAsNil(t *testing.T) { + t.Parallel() + + ns := testNamespace(7) + blobsRaw, err := json.Marshal([]map[string]any{{ + "namespace": ns[:], + "data": []byte("hello"), + "share_version": 0, + "commitment": []byte("c1"), + "index": 0, + }}) + if err != nil { + t.Fatalf("marshal blobs: %v", err) + } + + req, err := DecodeRequest(blobsRaw, json.RawMessage(" \n null \t ")) + if err != nil { + t.Fatalf("DecodeRequest: %v", err) + } + if req.Options != nil { + t.Fatalf("options = %#v, want nil", req.Options) + } +} + +func TestDecodeRequestRejectsNegativeMaxGasPrice(t *testing.T) { + t.Parallel() + + ns := testNamespace(7) + blobsRaw, err := json.Marshal([]map[string]any{{ + "namespace": ns[:], + "data": []byte("hello"), + "share_version": 0, + "commitment": []byte("c1"), + "index": 0, + }}) + if err != nil { + t.Fatalf("marshal blobs: %v", err) + } + + _, err = DecodeRequest(blobsRaw, json.RawMessage(`{"max_gas_price":-1}`)) + if err == nil { + t.Fatal("expected error for negative max_gas_price") + } +} + +func TestDecodeRequestRejectsInvalidPriority(t *testing.T) { + t.Parallel() + + ns := testNamespace(7) + blobsRaw, err := json.Marshal([]map[string]any{{ + "namespace": ns[:], + "data": []byte("hello"), + "share_version": 0, + "commitment": []byte("c1"), + "index": 0, + }}) + if err != nil { + t.Fatalf("marshal blobs: %v", err) + } + + _, err = DecodeRequest(blobsRaw, json.RawMessage(`{"tx_priority":99}`)) + if err == nil { + t.Fatal("expected error for invalid tx_priority") + } +} + +func TestMarshalResultRejectsNil(t *testing.T) { + t.Parallel() + + if _, err := MarshalResult(nil); err == nil { + t.Fatal("expected error for nil result") + } +} + +func testNamespace(b byte) types.Namespace { + namespace := gsquare.MustNewV0Namespace([]byte("apexns" + string([]byte{b}))) + var ns types.Namespace + copy(ns[:], namespace.Bytes()) + return ns +} + +func reservedNamespace() types.Namespace { + var ns types.Namespace + ns[types.NamespaceSize-1] = 1 + return ns +} + +func testBlobSigner() []byte { + return []byte("01234567890123456789") +} diff --git a/pkg/submit/tx_builder.go b/pkg/submit/tx_builder.go new file mode 100644 index 0000000..23024c1 --- /dev/null +++ b/pkg/submit/tx_builder.go @@ -0,0 +1,201 @@ +package submit + +import ( + "errors" + "fmt" + "math" + + blobv1 "github.com/evstack/apex/pkg/api/grpc/gen/celestia/blob/v1" + basev1beta1 "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/base/v1beta1" + secp256k1pb "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/crypto/secp256k1" + signingv1beta1 "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/tx/signing/v1beta1" + txv1beta1 "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/tx/v1beta1" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" +) + +const ( + // MsgPayForBlobsTypeURL is the protobuf Any type URL for Celestia blob txs. + MsgPayForBlobsTypeURL = "/celestia.blob.v1.MsgPayForBlobs" + // Secp256k1PubKeyTypeURL is the protobuf Any type URL for Cosmos secp256k1 pubkeys. + Secp256k1PubKeyTypeURL = "/cosmos.crypto.secp256k1.PubKey" +) + +// BuildMsgPayForBlobs converts submitted blobs into the Celestia +// MsgPayForBlobs request shape used inside the signed Cosmos SDK tx. +func BuildMsgPayForBlobs(signer string, blobs []Blob) (*blobv1.MsgPayForBlobs, error) { + if signer == "" { + return nil, errors.New("signer is required") + } + if len(blobs) == 0 { + return nil, errors.New("at least one blob is required") + } + + namespaces := make([][]byte, len(blobs)) + blobSizes := make([]uint32, len(blobs)) + commitments := make([][]byte, len(blobs)) + shareVersions := make([]uint32, len(blobs)) + for i := range blobs { + if len(blobs[i].Commitment) == 0 { + return nil, fmt.Errorf("blob %d commitment is required", i) + } + squareBlob, err := convertSquareBlob(blobs[i]) + if err != nil { + return nil, fmt.Errorf("blob %d: %w", i, err) + } + namespaces[i] = squareBlob.Namespace().Bytes() + blobSizes[i] = uint32(squareBlob.DataLen()) + commitments[i] = blobs[i].Commitment + shareVersions[i] = uint32(squareBlob.ShareVersion()) + } + + return &blobv1.MsgPayForBlobs{ + Signer: signer, + Namespaces: namespaces, + BlobSizes: blobSizes, + ShareCommitments: commitments, + ShareVersions: shareVersions, + }, nil +} + +// MarshalMsgPayForBlobsAny packs MsgPayForBlobs into a protobuf Any suitable +// for inclusion in cosmos.tx.v1beta1.TxBody. +func MarshalMsgPayForBlobsAny(msg *blobv1.MsgPayForBlobs) (*anypb.Any, error) { + if msg == nil { + return nil, errors.New("pay-for-blobs message is required") + } + msgBytes, err := proto.Marshal(msg) + if err != nil { + return nil, fmt.Errorf("marshal pay-for-blobs message: %w", err) + } + return &anypb.Any{ + TypeUrl: MsgPayForBlobsTypeURL, + Value: msgBytes, + }, nil +} + +// BuildSignerInfo constructs a direct-signing signer record using a raw +// secp256k1 public key. +func BuildSignerInfo(pubKey []byte, sequence uint64) (*txv1beta1.SignerInfo, error) { + if len(pubKey) == 0 { + return nil, errors.New("public key is required") + } + pubKeyBytes, err := proto.Marshal(&secp256k1pb.PubKey{Key: pubKey}) + if err != nil { + return nil, fmt.Errorf("marshal secp256k1 pubkey: %w", err) + } + return &txv1beta1.SignerInfo{ + PublicKey: &anypb.Any{ + TypeUrl: Secp256k1PubKeyTypeURL, + Value: pubKeyBytes, + }, + ModeInfo: &txv1beta1.ModeInfo{ + Sum: &txv1beta1.ModeInfo_Single_{ + Single: &txv1beta1.ModeInfo_Single{ + Mode: signingv1beta1.SignMode_SIGN_MODE_DIRECT, + }, + }, + }, + Sequence: sequence, + }, nil +} + +// BuildAuthInfo creates an AuthInfo for a single direct signer and fee payer. +func BuildAuthInfo(signerInfo *txv1beta1.SignerInfo, feeDenom string, feeAmount string, gasLimit uint64, payer, granter string) (*txv1beta1.AuthInfo, error) { + if signerInfo == nil { + return nil, errors.New("signer info is required") + } + if gasLimit == 0 { + return nil, errors.New("gas limit must be positive") + } + + fee := &txv1beta1.Fee{ + GasLimit: gasLimit, + Payer: payer, + Granter: granter, + } + if feeDenom != "" || feeAmount != "" { + if feeDenom == "" || feeAmount == "" { + return nil, errors.New("fee denom and amount must be provided together") + } + fee.Amount = []*basev1beta1.Coin{{ + Denom: feeDenom, + Amount: feeAmount, + }} + } + + return &txv1beta1.AuthInfo{ + SignerInfos: []*txv1beta1.SignerInfo{signerInfo}, + Fee: fee, + }, nil +} + +func MarshalTxBody(messages []*anypb.Any, memo string, timeoutHeight uint64) ([]byte, error) { + body := &txv1beta1.TxBody{ + Messages: messages, + Memo: memo, + TimeoutHeight: timeoutHeight, + } + raw, err := proto.Marshal(body) + if err != nil { + return nil, fmt.Errorf("marshal tx body: %w", err) + } + return raw, nil +} + +func MarshalAuthInfo(authInfo *txv1beta1.AuthInfo) ([]byte, error) { + if authInfo == nil { + return nil, errors.New("auth info is required") + } + raw, err := proto.Marshal(authInfo) + if err != nil { + return nil, fmt.Errorf("marshal auth info: %w", err) + } + return raw, nil +} + +func BuildSignDoc(bodyBytes, authInfoBytes []byte, chainID string, accountNumber uint64) ([]byte, error) { + if chainID == "" { + return nil, errors.New("chain id is required") + } + doc := &txv1beta1.SignDoc{ + BodyBytes: bodyBytes, + AuthInfoBytes: authInfoBytes, + ChainId: chainID, + AccountNumber: accountNumber, + } + raw, err := proto.Marshal(doc) + if err != nil { + return nil, fmt.Errorf("marshal sign doc: %w", err) + } + return raw, nil +} + +// MarshalTxRaw creates the final raw transaction bytes to broadcast. +func MarshalTxRaw(bodyBytes, authInfoBytes, signature []byte) ([]byte, error) { + if len(signature) == 0 { + return nil, errors.New("signature is required") + } + raw, err := proto.Marshal(&txv1beta1.TxRaw{ + BodyBytes: bodyBytes, + AuthInfoBytes: authInfoBytes, + Signatures: [][]byte{signature}, + }) + if err != nil { + return nil, fmt.Errorf("marshal tx raw: %w", err) + } + return raw, nil +} + +// FeeAmountFromGasPrice computes the integer fee amount using a gas limit and +// decimal gas price. The result is rounded up to avoid underpaying. +func FeeAmountFromGasPrice(gasLimit uint64, gasPrice float64) (string, error) { + if gasLimit == 0 { + return "", errors.New("gas limit must be positive") + } + if gasPrice < 0 { + return "", errors.New("gas price must be non-negative") + } + fee := math.Ceil(float64(gasLimit) * gasPrice) + return fmt.Sprintf("%.0f", fee), nil +} diff --git a/pkg/submit/tx_builder_test.go b/pkg/submit/tx_builder_test.go new file mode 100644 index 0000000..4bd2b6a --- /dev/null +++ b/pkg/submit/tx_builder_test.go @@ -0,0 +1,181 @@ +package submit + +import ( + "bytes" + "testing" + + blobv1 "github.com/evstack/apex/pkg/api/grpc/gen/celestia/blob/v1" + secp256k1pb "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/crypto/secp256k1" + txv1beta1 "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/tx/v1beta1" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" +) + +const testSignerAddress = "celestia1test" + +func TestBuildMsgPayForBlobs(t *testing.T) { + ns1 := testNamespace(1) + ns2 := testNamespace(2) + msg, err := BuildMsgPayForBlobs("celestia1test", []Blob{ + {Namespace: ns1, Data: []byte("abc"), Commitment: []byte("c1"), ShareVersion: 0}, + {Namespace: ns2, Data: []byte("hello"), Commitment: []byte("c2"), ShareVersion: 1, Signer: testBlobSigner()}, + }) + if err != nil { + t.Fatalf("BuildMsgPayForBlobs: %v", err) + } + if got, want := len(msg.GetNamespaces()), 2; got != want { + t.Fatalf("namespaces = %d, want %d", got, want) + } + if !bytes.Equal(msg.GetNamespaces()[0], ns1[:]) || !bytes.Equal(msg.GetNamespaces()[1], ns2[:]) { + t.Fatalf("namespaces = %x, want [%x %x]", msg.GetNamespaces(), ns1, ns2) + } + if msg.GetBlobSizes()[0] != 3 || msg.GetBlobSizes()[1] != 5 { + t.Fatalf("blob sizes = %v", msg.GetBlobSizes()) + } + if !bytes.Equal(msg.GetShareCommitments()[0], []byte("c1")) || !bytes.Equal(msg.GetShareCommitments()[1], []byte("c2")) { + t.Fatalf("commitments = %q", msg.GetShareCommitments()) + } + if msg.GetShareVersions()[1] != 1 { + t.Fatalf("share versions = %v", msg.GetShareVersions()) + } +} + +func TestMarshalMsgPayForBlobsAny(t *testing.T) { + anyMsg, err := MarshalMsgPayForBlobsAny(&blobv1.MsgPayForBlobs{Signer: testSignerAddress}) + if err != nil { + t.Fatalf("MarshalMsgPayForBlobsAny: %v", err) + } + if anyMsg.GetTypeUrl() != MsgPayForBlobsTypeURL { + t.Fatalf("type URL = %q", anyMsg.GetTypeUrl()) + } + var decoded blobv1.MsgPayForBlobs + if err := proto.Unmarshal(anyMsg.GetValue(), &decoded); err != nil { + t.Fatalf("unmarshal Any payload: %v", err) + } + if decoded.GetSigner() != testSignerAddress { + t.Fatalf("decoded signer = %q, want %q", decoded.GetSigner(), testSignerAddress) + } +} + +func TestBuildSignerInfoAndTxEncoding(t *testing.T) { + signerInfo, err := BuildSignerInfo([]byte{1, 2, 3}, 9) + if err != nil { + t.Fatalf("BuildSignerInfo: %v", err) + } + assertSignerInfo(t, signerInfo) + + authInfo, err := BuildAuthInfo(signerInfo, "utia", "123", 456, testSignerAddress, "") + if err != nil { + t.Fatalf("BuildAuthInfo: %v", err) + } + authInfoBytes, err := MarshalAuthInfo(authInfo) + if err != nil { + t.Fatalf("MarshalAuthInfo: %v", err) + } + assertAuthInfoBytes(t, authInfoBytes) + + bodyBytes, err := MarshalTxBody(nil, "memo", 99) + if err != nil { + t.Fatalf("MarshalTxBody: %v", err) + } + assertTxBodyBytes(t, bodyBytes) + signDocBytes, err := BuildSignDoc(bodyBytes, authInfoBytes, "mocha-4", 7) + if err != nil { + t.Fatalf("BuildSignDoc: %v", err) + } + assertSignDocBytes(t, signDocBytes, bodyBytes, authInfoBytes) + + txRawBytes, err := MarshalTxRaw(bodyBytes, authInfoBytes, []byte("signature")) + if err != nil { + t.Fatalf("MarshalTxRaw: %v", err) + } + assertTxRawBytes(t, txRawBytes, bodyBytes, authInfoBytes) +} + +func TestFeeAmountFromGasPrice(t *testing.T) { + fee, err := FeeAmountFromGasPrice(1001, 0.001) + if err != nil { + t.Fatalf("FeeAmountFromGasPrice: %v", err) + } + if fee != "2" { + t.Fatalf("fee = %q, want 2", fee) + } +} + +func assertSignerInfo(t *testing.T, signerInfo *txv1beta1.SignerInfo) { + t.Helper() + + if signerInfo.GetSequence() != 9 { + t.Fatalf("sequence = %d", signerInfo.GetSequence()) + } + pubKey := &secp256k1pb.PubKey{} + if err := anypb.UnmarshalTo(signerInfo.GetPublicKey(), pubKey, proto.UnmarshalOptions{}); err != nil { + t.Fatalf("unmarshal pubkey any: %v", err) + } + if got := pubKey.GetKey(); len(got) != 3 { + t.Fatalf("pubkey = %v", got) + } +} + +func assertAuthInfoBytes(t *testing.T, authInfoBytes []byte) { + t.Helper() + + authInfoProto := &txv1beta1.AuthInfo{} + if err := proto.Unmarshal(authInfoBytes, authInfoProto); err != nil { + t.Fatalf("unmarshal auth info: %v", err) + } + if authInfoProto.GetFee().GetGasLimit() != 456 { + t.Fatalf("gas limit = %d, want 456", authInfoProto.GetFee().GetGasLimit()) + } + if authInfoProto.GetFee().GetPayer() != testSignerAddress { + t.Fatalf("payer = %q, want %q", authInfoProto.GetFee().GetPayer(), testSignerAddress) + } + if got := authInfoProto.GetFee().GetAmount(); len(got) != 1 || got[0].GetDenom() != "utia" || got[0].GetAmount() != "123" { + t.Fatalf("fee amount = %#v", got) + } +} + +func assertTxBodyBytes(t *testing.T, bodyBytes []byte) { + t.Helper() + + body := &txv1beta1.TxBody{} + if err := proto.Unmarshal(bodyBytes, body); err != nil { + t.Fatalf("unmarshal tx body: %v", err) + } + if body.GetMemo() != "memo" || body.GetTimeoutHeight() != 99 { + t.Fatalf("tx body = %#v", body) + } +} + +func assertSignDocBytes(t *testing.T, signDocBytes, bodyBytes, authInfoBytes []byte) { + t.Helper() + + signDoc := &txv1beta1.SignDoc{} + if err := proto.Unmarshal(signDocBytes, signDoc); err != nil { + t.Fatalf("unmarshal sign doc: %v", err) + } + if signDoc.GetChainId() != "mocha-4" || signDoc.GetAccountNumber() != 7 { + t.Fatalf("sign doc = %#v", signDoc) + } + if !bytes.Equal(signDoc.GetBodyBytes(), bodyBytes) || !bytes.Equal(signDoc.GetAuthInfoBytes(), authInfoBytes) { + t.Fatalf("sign doc bytes do not match input payloads") + } +} + +func assertTxRawBytes(t *testing.T, txRawBytes, bodyBytes, authInfoBytes []byte) { + t.Helper() + + txRaw := &txv1beta1.TxRaw{} + if err := proto.Unmarshal(txRawBytes, txRaw); err != nil { + t.Fatalf("unmarshal tx raw: %v", err) + } + if got, want := len(txRaw.GetSignatures()), 1; got != want { + t.Fatalf("signatures = %d, want %d", got, want) + } + if !bytes.Equal(txRaw.GetBodyBytes(), bodyBytes) || !bytes.Equal(txRaw.GetAuthInfoBytes(), authInfoBytes) { + t.Fatalf("tx raw bytes do not match input payloads") + } + if !bytes.Equal(txRaw.GetSignatures()[0], []byte("signature")) { + t.Fatalf("signature = %q, want %q", txRaw.GetSignatures()[0], "signature") + } +} diff --git a/pkg/types/namespace_blob.go b/pkg/types/namespace_blob.go new file mode 100644 index 0000000..fa57f87 --- /dev/null +++ b/pkg/types/namespace_blob.go @@ -0,0 +1,20 @@ +package types + +import ( + "fmt" + + share "github.com/celestiaorg/go-square/v3/share" +) + +// ValidateForBlob checks whether the namespace is valid for user-specified +// Celestia blob data. +func (n Namespace) ValidateForBlob() error { + ns, err := share.NewNamespaceFromBytes(n[:]) + if err != nil { + return fmt.Errorf("invalid namespace: %w", err) + } + if err := ns.ValidateForBlob(); err != nil { + return fmt.Errorf("invalid blob namespace: %w", err) + } + return nil +} diff --git a/pkg/types/types.go b/pkg/types/types.go index 62f67ae..9b4e67e 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -10,6 +10,9 @@ import ( // NamespaceSize is the size of a Celestia namespace in bytes. const NamespaceSize = 29 +// ProtoBlobTxTypeID is the protobuf type identifier used by Celestia BlobTx envelopes. +const ProtoBlobTxTypeID = "BLOB" + // Namespace is a 29-byte Celestia namespace identifier. type Namespace [NamespaceSize]byte @@ -33,6 +36,16 @@ func NamespaceFromHex(s string) (Namespace, error) { return ns, nil } +// NamespaceFromBytes converts a byte slice into a Namespace. +func NamespaceFromBytes(b []byte) (Namespace, error) { + if len(b) != NamespaceSize { + return Namespace{}, fmt.Errorf("invalid namespace size: got %d, want %d", len(b), NamespaceSize) + } + var ns Namespace + copy(ns[:], b) + return ns, nil +} + // String returns the hex-encoded namespace. func (n Namespace) String() string { return hex.EncodeToString(n[:]) diff --git a/proto/celestia/blob/v1/tx.proto b/proto/celestia/blob/v1/tx.proto new file mode 100644 index 0000000..19ea5a0 --- /dev/null +++ b/proto/celestia/blob/v1/tx.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +package celestia.blob.v1; + +option go_package = "github.com/evstack/apex/pkg/api/grpc/gen/celestia/blob/v1;blobv1"; + +// MsgPayForBlobs is the Celestia message included in a Cosmos SDK tx for blob +// inclusion. Apex only needs the request shape for local tx construction. +message MsgPayForBlobs { + string signer = 1; + repeated bytes namespaces = 2; + repeated uint32 blob_sizes = 3; + repeated bytes share_commitments = 4; + repeated uint32 share_versions = 8; +} + +message MsgPayForBlobsResponse {} diff --git a/proto/cosmos/auth/v1beta1/auth.proto b/proto/cosmos/auth/v1beta1/auth.proto new file mode 100644 index 0000000..cbc707a --- /dev/null +++ b/proto/cosmos/auth/v1beta1/auth.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +package cosmos.auth.v1beta1; + +import "google/protobuf/any.proto"; + +option go_package = "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/auth/v1beta1;authv1beta1"; + +message BaseAccount { + string address = 1; + google.protobuf.Any pub_key = 2; + uint64 account_number = 3; + uint64 sequence = 4; +} diff --git a/proto/cosmos/auth/v1beta1/query.proto b/proto/cosmos/auth/v1beta1/query.proto new file mode 100644 index 0000000..257b1cb --- /dev/null +++ b/proto/cosmos/auth/v1beta1/query.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +package cosmos.auth.v1beta1; + +import "cosmos/auth/v1beta1/auth.proto"; + +option go_package = "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/auth/v1beta1;authv1beta1"; + +service Query { + rpc AccountInfo(QueryAccountInfoRequest) returns (QueryAccountInfoResponse); +} + +message QueryAccountInfoRequest { + string address = 1; +} + +message QueryAccountInfoResponse { + BaseAccount info = 1; +} diff --git a/proto/cosmos/base/abci/v1beta1/abci.proto b/proto/cosmos/base/abci/v1beta1/abci.proto new file mode 100644 index 0000000..562ac42 --- /dev/null +++ b/proto/cosmos/base/abci/v1beta1/abci.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package cosmos.base.abci.v1beta1; + +option go_package = "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/base/abci/v1beta1;abciv1beta1"; + +message TxResponse { + int64 height = 1; + string txhash = 2; + string codespace = 3; + uint32 code = 4; + string data = 5; + string raw_log = 6; + string info = 8; + int64 gas_wanted = 9; + int64 gas_used = 10; + string timestamp = 12; +} diff --git a/proto/cosmos/base/v1beta1/coin.proto b/proto/cosmos/base/v1beta1/coin.proto new file mode 100644 index 0000000..635082c --- /dev/null +++ b/proto/cosmos/base/v1beta1/coin.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +package cosmos.base.v1beta1; + +option go_package = "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/base/v1beta1;basev1beta1"; + +message Coin { + string denom = 1; + string amount = 2; +} diff --git a/proto/cosmos/crypto/secp256k1/keys.proto b/proto/cosmos/crypto/secp256k1/keys.proto new file mode 100644 index 0000000..ad4f5df --- /dev/null +++ b/proto/cosmos/crypto/secp256k1/keys.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +package cosmos.crypto.secp256k1; + +option go_package = "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/crypto/secp256k1;secp256k1"; + +message PubKey { + bytes key = 1; +} diff --git a/proto/cosmos/tx/signing/v1beta1/signing.proto b/proto/cosmos/tx/signing/v1beta1/signing.proto new file mode 100644 index 0000000..e670535 --- /dev/null +++ b/proto/cosmos/tx/signing/v1beta1/signing.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +package cosmos.tx.signing.v1beta1; + +option go_package = "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/tx/signing/v1beta1;signingv1beta1"; + +enum SignMode { + SIGN_MODE_UNSPECIFIED = 0; + SIGN_MODE_DIRECT = 1; +} diff --git a/proto/cosmos/tx/v1beta1/service.proto b/proto/cosmos/tx/v1beta1/service.proto new file mode 100644 index 0000000..2fbfa66 --- /dev/null +++ b/proto/cosmos/tx/v1beta1/service.proto @@ -0,0 +1,36 @@ +syntax = "proto3"; + +package cosmos.tx.v1beta1; + +import "cosmos/base/abci/v1beta1/abci.proto"; + +option go_package = "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/tx/v1beta1;txv1beta1"; + +service Service { + rpc BroadcastTx(BroadcastTxRequest) returns (BroadcastTxResponse); + rpc GetTx(GetTxRequest) returns (GetTxResponse); +} + +message BroadcastTxRequest { + bytes tx_bytes = 1; + BroadcastMode mode = 2; +} + +enum BroadcastMode { + BROADCAST_MODE_UNSPECIFIED = 0; + BROADCAST_MODE_BLOCK = 1; + BROADCAST_MODE_SYNC = 2; + BROADCAST_MODE_ASYNC = 3; +} + +message BroadcastTxResponse { + cosmos.base.abci.v1beta1.TxResponse tx_response = 1; +} + +message GetTxRequest { + string hash = 1; +} + +message GetTxResponse { + cosmos.base.abci.v1beta1.TxResponse tx_response = 2; +} diff --git a/proto/cosmos/tx/v1beta1/tx.proto b/proto/cosmos/tx/v1beta1/tx.proto new file mode 100644 index 0000000..1b4fd44 --- /dev/null +++ b/proto/cosmos/tx/v1beta1/tx.proto @@ -0,0 +1,56 @@ +syntax = "proto3"; + +package cosmos.tx.v1beta1; + +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos/tx/signing/v1beta1/signing.proto"; +import "google/protobuf/any.proto"; + +option go_package = "github.com/evstack/apex/pkg/api/grpc/gen/cosmos/tx/v1beta1;txv1beta1"; + +message TxRaw { + bytes body_bytes = 1; + bytes auth_info_bytes = 2; + repeated bytes signatures = 3; +} + +message SignDoc { + bytes body_bytes = 1; + bytes auth_info_bytes = 2; + string chain_id = 3; + uint64 account_number = 4; +} + +message TxBody { + repeated google.protobuf.Any messages = 1; + string memo = 2; + uint64 timeout_height = 3; +} + +message AuthInfo { + repeated SignerInfo signer_infos = 1; + Fee fee = 2; +} + +message SignerInfo { + google.protobuf.Any public_key = 1; + ModeInfo mode_info = 2; + uint64 sequence = 3; +} + +message ModeInfo { + message Single { + cosmos.tx.signing.v1beta1.SignMode mode = 1; + } + + oneof sum { + Single single = 1; + } +} + +message Fee { + repeated cosmos.base.v1beta1.Coin amount = 1; + uint64 gas_limit = 2; + string payer = 3; + string granter = 4; +}