From 7cf7cecc241c8269f470072c3ee5a75b1b154338 Mon Sep 17 00:00:00 2001 From: webpiratt <213060745+webpiratt@users.noreply.github.com> Date: Tue, 1 Jul 2025 20:22:39 +0300 Subject: [PATCH 1/3] remove legacy tx history --- .github/workflows/migration-test.yml | 2 +- api/plugin.go | 18 -- api/server.go | 46 ----- internal/types/transaction.go | 40 ---- service/policy.go | 17 -- storage/db.go | 8 - storage/postgres/db.go | 172 ------------------ ...20250102180600_add_transaction_history.sql | 34 ---- storage/postgres/schema/schema.sql | 39 ---- 9 files changed, 1 insertion(+), 375 deletions(-) delete mode 100644 internal/types/transaction.go delete mode 100644 storage/postgres/migrations/plugin/20250102180600_add_transaction_history.sql diff --git a/.github/workflows/migration-test.yml b/.github/workflows/migration-test.yml index fcfd9b0..e12b4c3 100644 --- a/.github/workflows/migration-test.yml +++ b/.github/workflows/migration-test.yml @@ -107,7 +107,7 @@ jobs: fi # Check if migrations ran successfully by verifying tables exist - PGPASSWORD=mypassword psql -h localhost -U myuser -d vultisig-plugin -c "\dt" | grep -E "(plugin_policies|time_triggers|transaction_history) | wc -l" > /dev/null + PGPASSWORD=mypassword psql -h localhost -U myuser -d vultisig-plugin -c "\dt" | grep -E "(plugin_policies|time_triggers) | wc -l" > /dev/null if [ $? -ne 0 ]; then echo "Migrations did not run successfully - expected tables not found" kill $DCA_PID diff --git a/api/plugin.go b/api/plugin.go index 0886a91..9775fc7 100644 --- a/api/plugin.go +++ b/api/plugin.go @@ -302,24 +302,6 @@ func (s *Server) GetRecipeSpecification(c echo.Context) error { return c.JSON(http.StatusOK, &recipeSpec) } -func (s *Server) GetPluginPolicyTransactionHistory(c echo.Context) error { - policyID := c.Param("policyId") - - if policyID == "" { - return c.JSON(http.StatusBadRequest, NewErrorResponse("invalid policy ID")) - } - - policyHistory, err := s.policyService.GetPluginPolicyTransactionHistory(c.Request().Context(), policyID) - if err != nil { - s.logger.WithError(err). - WithField("policy_id", policyID). - Error("Failed to get plugin policy transaction history") - return c.JSON(http.StatusInternalServerError, NewErrorResponse("failed to get policy transaction history")) - } - - return c.JSON(http.StatusOK, policyHistory) -} - func (s *Server) verifyPolicySignature(policy vtypes.PluginPolicy) bool { msgBytes, err := common.PolicyToMessageHex(policy) if err != nil { diff --git a/api/server.go b/api/server.go index 300ee56..e95e9de 100644 --- a/api/server.go +++ b/api/server.go @@ -22,7 +22,6 @@ import ( "github.com/vultisig/plugin/internal/scheduler" "github.com/vultisig/plugin/internal/tasks" - "github.com/vultisig/plugin/internal/types" vv "github.com/vultisig/plugin/internal/vultisig_validator" "github.com/vultisig/plugin/service" "github.com/vultisig/plugin/storage" @@ -345,48 +344,3 @@ func (s *Server) ExistVault(c echo.Context) error { } return c.NoContent(http.StatusOK) } - -func (s *Server) CreateTransaction(c echo.Context) error { - var reqTx types.TransactionHistory - if err := c.Bind(&reqTx); err != nil { - return c.NoContent(http.StatusBadRequest) - } - - existingTx, _ := s.db.GetTransactionByHash(c.Request().Context(), reqTx.TxHash) - if existingTx != nil { - if existingTx.Status != types.StatusSigningFailed && - existingTx.Status != types.StatusRejected { - return c.NoContent(http.StatusConflict) - } - - if err := s.db.UpdateTransactionStatus(c.Request().Context(), existingTx.ID, types.StatusPending, reqTx.Metadata); err != nil { - s.logger.Errorf("fail to update transaction status: %v", err) - return c.NoContent(http.StatusInternalServerError) - } - return c.NoContent(http.StatusOK) - } - - if _, err := s.db.CreateTransactionHistory(c.Request().Context(), reqTx); err != nil { - s.logger.Errorf("fail to create transaction, err: %v", err) - return c.NoContent(http.StatusInternalServerError) - } - return c.NoContent(http.StatusOK) -} - -func (s *Server) UpdateTransaction(c echo.Context) error { - var reqTx types.TransactionHistory - if err := c.Bind(&reqTx); err != nil { - return c.NoContent(http.StatusBadRequest) - } - - existingTx, _ := s.db.GetTransactionByHash(c.Request().Context(), reqTx.TxHash) - if existingTx == nil { - return c.NoContent(http.StatusNotFound) - } - - if err := s.db.UpdateTransactionStatus(c.Request().Context(), existingTx.ID, reqTx.Status, reqTx.Metadata); err != nil { - s.logger.Errorf("fail to update transaction status, err: %v", err) - return c.NoContent(http.StatusInternalServerError) - } - return c.NoContent(http.StatusOK) -} diff --git a/internal/types/transaction.go b/internal/types/transaction.go deleted file mode 100644 index 0db054e..0000000 --- a/internal/types/transaction.go +++ /dev/null @@ -1,40 +0,0 @@ -package types - -import ( - "time" - - "github.com/google/uuid" -) - -type TransactionStatus string - -const ( - StatusSigningInProgress TransactionStatus = "SIGNING_IN_PROGRESS" - StatusSigningFailed TransactionStatus = "SIGNING_FAILED" - StatusSigned TransactionStatus = "SIGNED" - StatusBroadcast TransactionStatus = "BROADCAST" - StatusPending TransactionStatus = "PENDING" - StatusMined TransactionStatus = "MINED" - StatusRejected TransactionStatus = "REJECTED" -) - -type TransactionHistory struct { - ID uuid.UUID `json:"id"` - PolicyID uuid.UUID `json:"policy_id"` - TxBody string `json:"tx_body"` - TxHash string `json:"tx_hash"` - Status TransactionStatus `json:"status"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - Metadata map[string]interface{} `json:"metadata"` - ErrorMessage *string `json:"error_message,omitempty"` -} - -type SignedTransaction struct { - PolicyID string - TxHash string - RawTx string - Signature string - Metadata map[string]any - BroadcastAt *time.Time -} diff --git a/service/policy.go b/service/policy.go index 7094b3d..e81c92a 100644 --- a/service/policy.go +++ b/service/policy.go @@ -10,7 +10,6 @@ import ( vtypes "github.com/vultisig/verifier/types" "github.com/vultisig/plugin/internal/scheduler" - "github.com/vultisig/plugin/internal/types" "github.com/vultisig/plugin/storage" ) @@ -20,7 +19,6 @@ type Policy interface { DeletePolicy(ctx context.Context, policyID uuid.UUID, signature string) error GetPluginPolicies(ctx context.Context, pluginID vtypes.PluginID, publicKey string) ([]vtypes.PluginPolicy, error) GetPluginPolicy(ctx context.Context, policyID uuid.UUID) (vtypes.PluginPolicy, error) - GetPluginPolicyTransactionHistory(ctx context.Context, policyID string) ([]types.TransactionHistory, error) } var _ Policy = (*PolicyService)(nil) @@ -142,18 +140,3 @@ func (s *PolicyService) GetPluginPolicy(ctx context.Context, policyID uuid.UUID) } return policy, nil } - -func (s *PolicyService) GetPluginPolicyTransactionHistory(ctx context.Context, policyID string) ([]types.TransactionHistory, error) { - // Convert string to UUID - policyUUID, err := uuid.Parse(policyID) - if err != nil { - return []types.TransactionHistory{}, fmt.Errorf("invalid policy_id: %s", policyID) - } - - history, err := s.db.GetTransactionHistory(ctx, policyUUID, "SWAP", 30, 0) // take the last 30 records and skip the first 0 - if err != nil { - return []types.TransactionHistory{}, fmt.Errorf("failed to get policy history: %w", err) - } - - return history, nil -} diff --git a/storage/db.go b/storage/db.go index 5b52de7..168f307 100644 --- a/storage/db.go +++ b/storage/db.go @@ -29,13 +29,5 @@ type DatabaseStorage interface { UpdateTriggerStatus(ctx context.Context, policyID uuid.UUID, status types.TimeTriggerStatus) error GetTriggerStatus(ctx context.Context, policyID uuid.UUID) (types.TimeTriggerStatus, error) - CountTransactions(ctx context.Context, policyID uuid.UUID, status types.TransactionStatus, txType string) (int64, error) - CreateTransactionHistoryTx(ctx context.Context, dbTx pgx.Tx, tx types.TransactionHistory) (uuid.UUID, error) - UpdateTransactionStatusTx(ctx context.Context, dbTx pgx.Tx, txID uuid.UUID, status types.TransactionStatus, metadata map[string]interface{}) error - CreateTransactionHistory(ctx context.Context, tx types.TransactionHistory) (uuid.UUID, error) - UpdateTransactionStatus(ctx context.Context, txID uuid.UUID, status types.TransactionStatus, metadata map[string]interface{}) error - GetTransactionHistory(ctx context.Context, policyID uuid.UUID, transactionType string, take int, skip int) ([]types.TransactionHistory, error) - GetTransactionByHash(ctx context.Context, txHash string) (*types.TransactionHistory, error) - Pool() *pgxpool.Pool } diff --git a/storage/postgres/db.go b/storage/postgres/db.go index 3abd6ce..bda15a7 100644 --- a/storage/postgres/db.go +++ b/storage/postgres/db.go @@ -2,15 +2,11 @@ package postgres import ( "context" - "errors" "fmt" - "github.com/google/uuid" - "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "github.com/sirupsen/logrus" - "github.com/vultisig/plugin/internal/types" "github.com/vultisig/plugin/storage" ) @@ -80,174 +76,6 @@ func (p *PostgresBackend) Migrate(opts *MigrationOptions) error { return nil } -func (p *PostgresBackend) CreateTransactionHistoryTx(ctx context.Context, dbTx pgx.Tx, tx types.TransactionHistory) (uuid.UUID, error) { - query := ` - INSERT INTO transaction_history ( - policy_id, tx_body, tx_hash, status, metadata - ) VALUES ($1, $2, $3, $4, $5) - ON CONFLICT (tx_hash) DO UPDATE SET - policy_id = EXCLUDED.policy_id, - tx_body = EXCLUDED.tx_body, - status = 'PENDING', - metadata = EXCLUDED.metadata - RETURNING id - ` - var txID uuid.UUID - err := dbTx.QueryRow(ctx, query, - tx.PolicyID, - tx.TxBody, - tx.TxHash, - tx.Status, - tx.Metadata, - ).Scan(&txID) - - if err != nil { - return uuid.Nil, fmt.Errorf("failed to create transaction history: %w", err) - } - - return txID, nil -} - -func (p *PostgresBackend) UpdateTransactionStatusTx(ctx context.Context, dbTx pgx.Tx, txID uuid.UUID, status types.TransactionStatus, metadata map[string]interface{}) error { - query := ` - UPDATE transaction_history - SET status = $1, metadata = metadata || $2::jsonb, updated_at = NOW() - WHERE id = $3 - ` - - _, err := dbTx.Exec(ctx, query, status, metadata, txID) - return err -} - -func (p *PostgresBackend) CreateTransactionHistory(ctx context.Context, tx types.TransactionHistory) (uuid.UUID, error) { - query := ` - INSERT INTO transaction_history ( - policy_id, tx_body, tx_hash, status, metadata - ) VALUES ($1, $2, $3, $4, $5) - RETURNING id - ` - var txID uuid.UUID - err := p.pool.QueryRow(ctx, query, - tx.PolicyID, - tx.TxBody, - tx.TxHash, - tx.Status, - tx.Metadata, - ).Scan(&txID) - - if err != nil { - return uuid.Nil, fmt.Errorf("failed to create transaction history: %w", err) - } - - return txID, nil -} - -func (p *PostgresBackend) UpdateTransactionStatus(ctx context.Context, txID uuid.UUID, status types.TransactionStatus, metadata map[string]interface{}) error { - query := ` - UPDATE transaction_history - SET status = $1, metadata = metadata || $2::jsonb, updated_at = NOW() - WHERE id = $3 - ` - - _, err := p.pool.Exec(ctx, query, status, metadata, txID) - return err - -} - -func (p *PostgresBackend) GetTransactionHistory(ctx context.Context, policyID uuid.UUID, transactionType string, take int, skip int) ([]types.TransactionHistory, error) { - query := ` - SELECT id, policy_id, tx_body, tx_hash, status, created_at, updated_at, metadata, error_message - FROM transaction_history - WHERE policy_id = $1 - AND metadata->>'transaction_type' = $2 - ORDER BY created_at DESC - LIMIT $3 OFFSET $4 - ` - - rows, err := p.pool.Query(ctx, query, policyID, transactionType, take, skip) - if err != nil { - return nil, err - } - defer rows.Close() - - var history []types.TransactionHistory - for rows.Next() { - var tx types.TransactionHistory - err := rows.Scan( - &tx.ID, - &tx.PolicyID, - &tx.TxBody, - &tx.TxHash, - &tx.Status, - &tx.CreatedAt, - &tx.UpdatedAt, - &tx.Metadata, - &tx.ErrorMessage, - ) - if err != nil { - return nil, err - } - history = append(history, tx) - } - - return history, nil -} - -func (p *PostgresBackend) GetTransactionByHash(ctx context.Context, txHash string) (*types.TransactionHistory, error) { - query := ` - SELECT - id, - policy_id, - tx_body, - tx_hash, - status, - created_at, - updated_at, - metadata, - error_message - FROM transaction_history - WHERE tx_hash = $1 - ` - - var tx types.TransactionHistory - err := p.pool.QueryRow(ctx, query, txHash).Scan( - &tx.ID, - &tx.PolicyID, - &tx.TxBody, - &tx.TxHash, - &tx.Status, - &tx.CreatedAt, - &tx.UpdatedAt, - &tx.Metadata, - &tx.ErrorMessage, - ) - - if err != nil { - if errors.Is(err, pgx.ErrNoRows) { - return nil, fmt.Errorf("transaction with Tx Hash %s not found", txHash) - } - return nil, fmt.Errorf("failed to get transaction: %w", err) - } - - return &tx, nil -} - -func (p *PostgresBackend) CountTransactions(ctx context.Context, policyID uuid.UUID, status types.TransactionStatus, txType string) (int64, error) { - var count int64 - query := ` - SELECT COUNT(*) - FROM transaction_history - WHERE policy_id = $1 - AND status = $2 - AND metadata->>'transaction_type' = $3 - ` - err := p.pool.QueryRow(ctx, query, policyID, status, txType).Scan(&count) - if err != nil { - return 0, fmt.Errorf("failed to count transactions: %w", err) - } - return count, nil -} - func (p *PostgresBackend) Pool() *pgxpool.Pool { return p.pool } diff --git a/storage/postgres/migrations/plugin/20250102180600_add_transaction_history.sql b/storage/postgres/migrations/plugin/20250102180600_add_transaction_history.sql deleted file mode 100644 index 79bec9c..0000000 --- a/storage/postgres/migrations/plugin/20250102180600_add_transaction_history.sql +++ /dev/null @@ -1,34 +0,0 @@ --- +goose Up --- +goose StatementBegin -CREATE TYPE transaction_status AS ENUM ( - 'PENDING', - 'SIGNING_FAILED', - 'SIGNED', - 'BROADCAST', - 'MINED', - 'REJECTED' -); -CREATE TABLE transaction_history ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - policy_id UUID NOT NULL REFERENCES plugin_policies(id), - tx_body TEXT NOT NULL, - tx_hash TEXT NOT NULL, - status transaction_status NOT NULL, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - metadata JSONB, - error_message TEXT, - CONSTRAINT fk_policy FOREIGN KEY (policy_id) REFERENCES plugin_policies(id) -); -CREATE INDEX idx_transaction_history_policy_id ON transaction_history(policy_id); -CREATE INDEX idx_transaction_history_status ON transaction_history(status); -CREATE INDEX idx_transaction_history_tx_hash ON transaction_history(tx_hash); -ALTER TABLE transaction_history - ADD CONSTRAINT unique_tx_hash UNIQUE (tx_hash); - --- +goose StatementEnd --- +goose Down --- +goose StatementBegin -DROP TABLE IF EXISTS transaction_history; -DROP TYPE IF EXISTS transaction_status; --- +goose StatementEnd \ No newline at end of file diff --git a/storage/postgres/schema/schema.sql b/storage/postgres/schema/schema.sql index 61f2d2e..4842d73 100644 --- a/storage/postgres/schema/schema.sql +++ b/storage/postgres/schema/schema.sql @@ -5,15 +5,6 @@ CREATE TYPE "plugin_id" AS ENUM ( 'vultisig-fees-feee' ); -CREATE TYPE "transaction_status" AS ENUM ( - 'PENDING', - 'SIGNING_FAILED', - 'SIGNED', - 'BROADCAST', - 'MINED', - 'REJECTED' -); - CREATE TYPE "trigger_status" AS ENUM ( 'PENDING', 'RUNNING' @@ -67,18 +58,6 @@ CREATE SEQUENCE "time_triggers_id_seq" ALTER SEQUENCE "time_triggers_id_seq" OWNED BY "public"."time_triggers"."id"; -CREATE TABLE "transaction_history" ( - "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL, - "policy_id" "uuid" NOT NULL, - "tx_body" "text" NOT NULL, - "tx_hash" "text" NOT NULL, - "status" "transaction_status" NOT NULL, - "created_at" timestamp with time zone DEFAULT "now"(), - "updated_at" timestamp with time zone DEFAULT "now"(), - "metadata" "jsonb", - "error_message" "text" -); - CREATE TABLE "tx_indexer" ( "id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL, "plugin_id" character varying(255) NOT NULL, @@ -105,15 +84,9 @@ ALTER TABLE ONLY "plugin_policies" ALTER TABLE ONLY "time_triggers" ADD CONSTRAINT "time_triggers_pkey" PRIMARY KEY ("id"); -ALTER TABLE ONLY "transaction_history" - ADD CONSTRAINT "transaction_history_pkey" PRIMARY KEY ("id"); - ALTER TABLE ONLY "tx_indexer" ADD CONSTRAINT "tx_indexer_pkey" PRIMARY KEY ("id"); -ALTER TABLE ONLY "transaction_history" - ADD CONSTRAINT "unique_tx_hash" UNIQUE ("tx_hash"); - CREATE INDEX "idx_plugin_policies_active" ON "plugin_policies" USING "btree" ("active"); CREATE INDEX "idx_plugin_policies_plugin_id" ON "plugin_policies" USING "btree" ("plugin_id"); @@ -124,22 +97,10 @@ CREATE INDEX "idx_time_triggers_policy_id" ON "time_triggers" USING "btree" ("po CREATE INDEX "idx_time_triggers_start_time" ON "time_triggers" USING "btree" ("start_time"); -CREATE INDEX "idx_transaction_history_policy_id" ON "transaction_history" USING "btree" ("policy_id"); - -CREATE INDEX "idx_transaction_history_status" ON "transaction_history" USING "btree" ("status"); - -CREATE INDEX "idx_transaction_history_tx_hash" ON "transaction_history" USING "btree" ("tx_hash"); - CREATE INDEX "idx_tx_indexer_key" ON "tx_indexer" USING "btree" ("chain_id", "plugin_id", "policy_id", "token_id", "to_public_key", "created_at"); CREATE INDEX "idx_tx_indexer_status_onchain_lost" ON "tx_indexer" USING "btree" ("status_onchain", "lost"); -ALTER TABLE ONLY "transaction_history" - ADD CONSTRAINT "fk_policy" FOREIGN KEY ("policy_id") REFERENCES "plugin_policies"("id"); - ALTER TABLE ONLY "time_triggers" ADD CONSTRAINT "time_triggers_policy_id_fkey" FOREIGN KEY ("policy_id") REFERENCES "plugin_policies"("id"); -ALTER TABLE ONLY "transaction_history" - ADD CONSTRAINT "transaction_history_policy_id_fkey" FOREIGN KEY ("policy_id") REFERENCES "plugin_policies"("id"); - From 962ddbef7a4bc6cd3725bb29a2e46cbd58cf61c7 Mon Sep 17 00:00:00 2001 From: webpiratt <213060745+webpiratt@users.noreply.github.com> Date: Tue, 1 Jul 2025 20:28:34 +0300 Subject: [PATCH 2/3] remove legacy tx history --- plugin/dca/dca.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/plugin/dca/dca.go b/plugin/dca/dca.go index 7a6da3b..b2d2ab0 100644 --- a/plugin/dca/dca.go +++ b/plugin/dca/dca.go @@ -28,7 +28,6 @@ import ( "github.com/vultisig/plugin/common" "github.com/vultisig/plugin/internal/sigutil" - "github.com/vultisig/plugin/internal/types" "github.com/vultisig/plugin/pkg/uniswap" "github.com/vultisig/plugin/storage" ) @@ -732,11 +731,8 @@ func (p *DCAPlugin) logTokenBalances(client *uniswap.Client, signerAddress *gcom } func (p *DCAPlugin) getCompletedSwapTransactionsCount(ctx context.Context, policyID uuid.UUID) (int64, error) { - count, err := p.db.CountTransactions(ctx, policyID, types.StatusMined, "SWAP") - if err != nil { - return 0, err - } - return count, nil + // TODO implement in scope of DCA plugin implementation + return 0, nil } func (p *DCAPlugin) calculateSwapAmountPerOrder(totalAmount, totalOrders *big.Int, completedSwaps int64) *big.Int { From bf639192f8980b7338661ba9c560adf13bd5f5cb Mon Sep 17 00:00:00 2001 From: webpiratt <213060745+webpiratt@users.noreply.github.com> Date: Tue, 1 Jul 2025 21:12:15 +0300 Subject: [PATCH 3/3] remove legacy tx history --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 2857dbe..d814fb5 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/vultisig/commondata v0.0.0-20250430024109-a2492623ef05 github.com/vultisig/mobile-tss-lib v0.0.0-20250316003201-2e7e570a4a74 github.com/vultisig/recipes v0.0.0-20250627044941-5f6e07d5d22f - github.com/vultisig/verifier v0.0.0-20250627125920-a555ee8da0cb + github.com/vultisig/verifier v0.0.0-20250701180729-848563b4ed33 github.com/vultisig/vultiserver v0.0.0-20250515110921-82d56d3d9cc9 ) diff --git a/go.sum b/go.sum index 689add6..e879a58 100644 --- a/go.sum +++ b/go.sum @@ -769,6 +769,8 @@ github.com/vultisig/verifier v0.0.0-20250626093402-fa1ecf8bd816 h1:hCTbtaqIKBsnR github.com/vultisig/verifier v0.0.0-20250626093402-fa1ecf8bd816/go.mod h1:dLmQBnF5F0auFkGtCMHOCqkUwdTRL6fWm3H4yfHfsVU= github.com/vultisig/verifier v0.0.0-20250627125920-a555ee8da0cb h1:x2h4ud358pS5jQ5ZEVAu6Jazc2OzDrLa1E8rtdFUEFg= github.com/vultisig/verifier v0.0.0-20250627125920-a555ee8da0cb/go.mod h1:dLmQBnF5F0auFkGtCMHOCqkUwdTRL6fWm3H4yfHfsVU= +github.com/vultisig/verifier v0.0.0-20250701180729-848563b4ed33 h1:PUeuOyOphzJq/NhCOwMJjqm8YC2U5v55jQtg7Fuf5t4= +github.com/vultisig/verifier v0.0.0-20250701180729-848563b4ed33/go.mod h1:dLmQBnF5F0auFkGtCMHOCqkUwdTRL6fWm3H4yfHfsVU= github.com/vultisig/vultiserver v0.0.0-20250515110921-82d56d3d9cc9 h1:pZhGN8q8+gPB1JJjVDC1hDg8qn6Tbj0XBJymgTQ8qQg= github.com/vultisig/vultiserver v0.0.0-20250515110921-82d56d3d9cc9/go.mod h1:HwP2IgW6Mcu/gX8paFuKvfibrGE9UmPgkOFTub6dskM= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=