From d516d541df6972a5cd7a4bdf6fcd24e477017d8b Mon Sep 17 00:00:00 2001 From: Garry Sharp <> Date: Thu, 12 Jun 2025 21:57:00 +0400 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=9A=9A=20Latest=20type=20imports,=20f?= =?UTF-8?q?ixed=20names=20and=20policy=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 4 ++-- go.sum | 6 ++++++ plugin/dca/dca.go | 14 +++++++------- plugin/payroll/policy.go | 4 ++-- plugin/payroll/transaction.go | 6 +++--- scripts/dev/create_dca_policy/main.go | 2 +- scripts/dev/create_payroll_policy/main.go | 2 +- storage/postgres/time_trigger_test.go | 2 +- 8 files changed, 23 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 172d282..8036299 100644 --- a/go.mod +++ b/go.mod @@ -19,8 +19,8 @@ require ( github.com/spf13/viper v1.20.1 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-20250606100120-0ee16a73412d - github.com/vultisig/verifier v0.0.0-20250611063307-6e5e760de529 + github.com/vultisig/recipes v0.0.0-20250609134859-0655e0445c1b + github.com/vultisig/verifier v0.0.0-20250612165949-9db8a6828606 github.com/vultisig/vultiserver v0.0.0-20250515110921-82d56d3d9cc9 ) diff --git a/go.sum b/go.sum index e679b9e..bb3cbf3 100644 --- a/go.sum +++ b/go.sum @@ -747,8 +747,14 @@ github.com/vultisig/mobile-tss-lib v0.0.0-20250316003201-2e7e570a4a74 h1:goqwk4n github.com/vultisig/mobile-tss-lib v0.0.0-20250316003201-2e7e570a4a74/go.mod h1:nOykk4nOy1L3yXtLSlYvVsgizBnCQ3tR2N5uwGPdvaM= github.com/vultisig/recipes v0.0.0-20250606100120-0ee16a73412d h1:BVc4OL0BNY/cCmptU3EeqAoxcX8vS13Pr13gWpd5Xi0= github.com/vultisig/recipes v0.0.0-20250606100120-0ee16a73412d/go.mod h1:JT1FTsiJ8tY5W065vSsrxvrCSl1amp5o6SsBc1VVcCQ= +github.com/vultisig/recipes v0.0.0-20250609134859-0655e0445c1b h1:rXhRaf40re1FdUYlYbCTEIO6JqIx8FfLlksksu8LiGE= +github.com/vultisig/recipes v0.0.0-20250609134859-0655e0445c1b/go.mod h1:JT1FTsiJ8tY5W065vSsrxvrCSl1amp5o6SsBc1VVcCQ= github.com/vultisig/verifier v0.0.0-20250611063307-6e5e760de529 h1:owEyLmbtlN1yL0xG7EhzXgvXbBZYHSHITh4P8lvPhyQ= github.com/vultisig/verifier v0.0.0-20250611063307-6e5e760de529/go.mod h1:YpvZN2mbn6Z/34FDfnMS/TdE+B5Y8jghu5FvqOfRmB0= +github.com/vultisig/verifier v0.0.0-20250611171202-489e61b0205b h1:cY905EbOnT20AduKeHbQFQyT6D5EA/OpQNhTOzHBsI8= +github.com/vultisig/verifier v0.0.0-20250611171202-489e61b0205b/go.mod h1:YpvZN2mbn6Z/34FDfnMS/TdE+B5Y8jghu5FvqOfRmB0= +github.com/vultisig/verifier v0.0.0-20250612165949-9db8a6828606 h1:DGia8ZQM3izAm+Oo/LM+5yWzENc9MIWtEfFCsCZOgO0= +github.com/vultisig/verifier v0.0.0-20250612165949-9db8a6828606/go.mod h1:35VQIKhChb6/H+3J/XkbGhPkVF6lyLuxsUG/WXHS4+A= 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= diff --git a/plugin/dca/dca.go b/plugin/dca/dca.go index 54cd8fd..5bfa997 100644 --- a/plugin/dca/dca.go +++ b/plugin/dca/dca.go @@ -94,7 +94,7 @@ func (p *DCAPlugin) SigningComplete( ctx context.Context, signature tss.KeysignResponse, signRequest vtypes.PluginKeysignRequest, - policy vtypes.PluginPolicyCreateUpdate, + policy vtypes.PluginPolicy, ) error { var dcaPolicy DCAPolicy // TODO: convert recipe to DCAPolicy @@ -135,7 +135,7 @@ func (p *DCAPlugin) SigningComplete( return nil } -func (p *DCAPlugin) ValidatePluginPolicy(policyDoc vtypes.PluginPolicyCreateUpdate) error { +func (p *DCAPlugin) ValidatePluginPolicy(policyDoc vtypes.PluginPolicy) error { if policyDoc.PluginID != vtypes.PluginVultisigDCA_0000 { return fmt.Errorf("policy does not match plugin type, expected: %s, got: %s", pluginType, policyDoc.PluginID) } @@ -144,7 +144,7 @@ func (p *DCAPlugin) ValidatePluginPolicy(policyDoc vtypes.PluginPolicyCreateUpda return fmt.Errorf("policy does not match plugin version, expected: %s, got: %s", pluginVersion, policyDoc.PluginVersion) } - if policyDoc.PolicyVersion != policyVersion { + if fmt.Sprintf("%d", policyDoc.PolicyVersion) != policyVersion { //TODO policy version will essentially be a nonce that is incremented by 1, not, like plugin versions that will follow traditional engineering versioning e.g. v2.12.3. For now we can compare string types return fmt.Errorf("policy does not match policy version, expected: %s, got: %s", policyVersion, policyDoc.PolicyVersion) } @@ -270,7 +270,7 @@ func validateInterval(intervalStr string, frequency string) error { return nil } -func (p *DCAPlugin) ProposeTransactions(policy vtypes.PluginPolicyCreateUpdate) ([]vtypes.PluginKeysignRequest, error) { +func (p *DCAPlugin) ProposeTransactions(policy vtypes.PluginPolicy) ([]vtypes.PluginKeysignRequest, error) { p.logger.Info("DCA: PROPOSE TRANSACTIONS") var txs []vtypes.PluginKeysignRequest @@ -301,7 +301,7 @@ func (p *DCAPlugin) ProposeTransactions(policy vtypes.PluginPolicyCreateUpdate) } if completedSwaps >= totalOrders.Int64() { - if err := p.completePolicy(context.Background(), policy.ToPluginPolicy()); err != nil { + if err := p.completePolicy(context.Background(), policy); err != nil { return txs, fmt.Errorf("fail to complete policy: %w", err) } return txs, ErrCompletedPolicy @@ -358,7 +358,7 @@ func (p *DCAPlugin) ProposeTransactions(policy vtypes.PluginPolicyCreateUpdate) return txs, nil } -func (p *DCAPlugin) ValidateProposedTransactions(policy vtypes.PluginPolicyCreateUpdate, txs []vtypes.PluginKeysignRequest) error { +func (p *DCAPlugin) ValidateProposedTransactions(policy vtypes.PluginPolicy, txs []vtypes.PluginKeysignRequest) error { p.logger.Info("DCA: VALIDATE TRANSACTION PROPOSAL") if len(txs) == 0 { @@ -407,7 +407,7 @@ func (p *DCAPlugin) ValidateProposedTransactions(policy vtypes.PluginPolicyCreat } // TODO: Change this to make the policy to status COMPLETED if: completed swaps == total orders. if completedSwaps >= totalOrders.Int64() { - if err := p.completePolicy(context.Background(), policy.ToPluginPolicy()); err != nil { + if err := p.completePolicy(context.Background(), policy); err != nil { return fmt.Errorf("fail to complete policy: %w", err) } p.logger.Info("DCA: COMPLETED SWAPS: ", totalOrders.Int64()) diff --git a/plugin/payroll/policy.go b/plugin/payroll/policy.go index 70bc2c9..fca7b3b 100644 --- a/plugin/payroll/policy.go +++ b/plugin/payroll/policy.go @@ -37,7 +37,7 @@ type Schedule struct { EndTime string `json:"end_time,omitempty"` } -func (p *PayrollPlugin) ValidateProposedTransactions(policy vtypes.PluginPolicyCreateUpdate, txs []vtypes.PluginKeysignRequest) error { +func (p *PayrollPlugin) ValidateProposedTransactions(policy vtypes.PluginPolicy, txs []vtypes.PluginKeysignRequest) error { err := p.ValidatePluginPolicy(policy) if err != nil { return fmt.Errorf("failed to validate plugin policy: %v", err) @@ -196,7 +196,7 @@ func (p *PayrollPlugin) checkRule(rule *rtypes.Rule) error { } return nil } -func (p *PayrollPlugin) ValidatePluginPolicy(policyDoc vtypes.PluginPolicyCreateUpdate) error { +func (p *PayrollPlugin) ValidatePluginPolicy(policyDoc vtypes.PluginPolicy) error { if policyDoc.PluginID != vtypes.PluginVultisigPayroll_0000 { return fmt.Errorf("policy does not match plugin type, expected: %s, got: %s", vtypes.PluginVultisigPayroll_0000, policyDoc.PluginID) } diff --git a/plugin/payroll/transaction.go b/plugin/payroll/transaction.go index 615063d..e87225c 100644 --- a/plugin/payroll/transaction.go +++ b/plugin/payroll/transaction.go @@ -52,7 +52,7 @@ func (p *PayrollPlugin) HandleSchedulerTrigger(ctx context.Context, t *asynq.Tas _ = pluginPolicy return nil } -func (p *PayrollPlugin) ProposeTransactions(policy vtypes.PluginPolicyCreateUpdate) ([]vtypes.PluginKeysignRequest, error) { +func (p *PayrollPlugin) ProposeTransactions(policy vtypes.PluginPolicy) ([]vtypes.PluginKeysignRequest, error) { var txs []vtypes.PluginKeysignRequest err := p.ValidatePluginPolicy(policy) if err != nil { @@ -232,8 +232,8 @@ func (p *PayrollPlugin) generatePayrollTransaction(amountString, recipientString return txHash, rawTx, nil } -func (p *PayrollPlugin) SigningComplete(ctx context.Context, signature tss.KeysignResponse, signRequest vtypes.PluginKeysignRequest, policy vtypes.PluginPolicyCreateUpdate) error { - R, S, V, originalTx, chainID, _, err := p.convertData(signature, signRequest, policy.ToPluginPolicy()) +func (p *PayrollPlugin) SigningComplete(ctx context.Context, signature tss.KeysignResponse, signRequest vtypes.PluginKeysignRequest, policy vtypes.PluginPolicy) error { + R, S, V, originalTx, chainID, _, err := p.convertData(signature, signRequest, policy) if err != nil { return fmt.Errorf("failed to convert R and S: %v", err) } diff --git a/scripts/dev/create_dca_policy/main.go b/scripts/dev/create_dca_policy/main.go index febf47e..dc912c1 100644 --- a/scripts/dev/create_dca_policy/main.go +++ b/scripts/dev/create_dca_policy/main.go @@ -75,7 +75,7 @@ func main() { PublicKey: key, PluginID: vtypes.PluginVultisigDCA_0000, PluginVersion: "1.0.0", - PolicyVersion: "1.0.0", + PolicyVersion: 1, Active: true, Signature: "0x0000000000000000000000000000000000000000000000000000000000000000", } diff --git a/scripts/dev/create_payroll_policy/main.go b/scripts/dev/create_payroll_policy/main.go index 8e24fa7..d5af2a5 100644 --- a/scripts/dev/create_payroll_policy/main.go +++ b/scripts/dev/create_payroll_policy/main.go @@ -99,7 +99,7 @@ func main() { PublicKey: key, PluginID: vtypes.PluginVultisigPayroll_0000, PluginVersion: "1.0.0", - PolicyVersion: "1.0.0", + PolicyVersion: 1, Active: true, Signature: "0x0000000000000000000000000000000000000000000000000000000000000000", } diff --git a/storage/postgres/time_trigger_test.go b/storage/postgres/time_trigger_test.go index ad4e63b..2059a00 100644 --- a/storage/postgres/time_trigger_test.go +++ b/storage/postgres/time_trigger_test.go @@ -43,7 +43,7 @@ func TestTimeTrigger(t *testing.T) { PublicKey: "4a7b9c2f8e1d3a5b6c4f9e2d7a1b3c5f8d4e6a2b9c1f7e3d5a6b4c2f8e1d3a5b", PluginID: "vultisig-payroll-0000", PluginVersion: "1", - PolicyVersion: "1", + PolicyVersion: 1, Signature: "whatever", Recipe: "k3uaL47TpWtsT54tfhO7K6Gbyxf4H71jWma0zC2e3kQ=", Active: true, From 8e3ace9fa7797c2e098139aea914a93713b6e9cd Mon Sep 17 00:00:00 2001 From: Garry Sharp <> Date: Thu, 12 Jun 2025 22:05:35 +0400 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=9A=9A=20Updated=20more=20refs=20re?= =?UTF-8?q?=20PluginPolictCreateUpdate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/plugin.go | 16 ++++----- plugin/fees/config.go | 63 +++++++++++++++++++++++++++++++++++ plugin/fees/constraints.go | 12 +++++++ plugin/fees/fees.go | 68 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 plugin/fees/config.go create mode 100644 plugin/fees/constraints.go create mode 100644 plugin/fees/fees.go diff --git a/api/plugin.go b/api/plugin.go index a767383..54aed0e 100644 --- a/api/plugin.go +++ b/api/plugin.go @@ -60,7 +60,7 @@ func (s *Server) SignPluginMessages(c echo.Context) error { return fmt.Errorf("policy plugin ID mismatch") } - if err := s.plugin.ValidateProposedTransactions(policy.ToPluginPolicyCreateUpdate(), []vtypes.PluginKeysignRequest{req}); err != nil { + if err := s.plugin.ValidateProposedTransactions(policy, []vtypes.PluginKeysignRequest{req}); err != nil { return fmt.Errorf("failed to validate transaction proposal: %w", err) } @@ -192,7 +192,7 @@ func (s *Server) GetAllPluginPolicies(c echo.Context) error { } func (s *Server) CreatePluginPolicy(c echo.Context) error { - var policy vtypes.PluginPolicyCreateUpdate + var policy vtypes.PluginPolicy if err := c.Bind(&policy); err != nil { return fmt.Errorf("fail to parse request, err: %w", err) } @@ -208,12 +208,12 @@ func (s *Server) CreatePluginPolicy(c echo.Context) error { policy.ID = uuid.New() } - if !s.verifyPolicySignature(policy.ToPluginPolicy()) { + if !s.verifyPolicySignature(policy) { s.logger.Error("invalid policy signature") return c.JSON(http.StatusForbidden, NewErrorResponse("Invalid policy signature")) } - newPolicy, err := s.policyService.CreatePolicy(c.Request().Context(), policy.ToPluginPolicy()) + newPolicy, err := s.policyService.CreatePolicy(c.Request().Context(), policy) if err != nil { s.logger.WithError(err).Error("Failed to create plugin policy") return c.JSON(http.StatusInternalServerError, NewErrorResponse("failed to create policy")) @@ -223,7 +223,7 @@ func (s *Server) CreatePluginPolicy(c echo.Context) error { } func (s *Server) UpdatePluginPolicyById(c echo.Context) error { - var policy vtypes.PluginPolicyCreateUpdate + var policy vtypes.PluginPolicy if err := c.Bind(&policy); err != nil { return fmt.Errorf("fail to parse request, err: %w", err) } @@ -236,12 +236,12 @@ func (s *Server) UpdatePluginPolicyById(c echo.Context) error { return c.JSON(http.StatusBadRequest, NewErrorResponse("failed to validate policy")) } - if !s.verifyPolicySignature(policy.ToPluginPolicy()) { + if !s.verifyPolicySignature(policy) { s.logger.Error("invalid policy signature") return c.JSON(http.StatusForbidden, NewErrorResponse("Invalid policy signature")) } - updatedPolicy, err := s.policyService.UpdatePolicy(c.Request().Context(), policy.ToPluginPolicy()) + updatedPolicy, err := s.policyService.UpdatePolicy(c.Request().Context(), policy) if err != nil { s.logger.WithError(err).Error("Failed to update plugin policy") return c.JSON(http.StatusInternalServerError, NewErrorResponse("failed to update policy")) @@ -394,7 +394,7 @@ func policyToMessageHex(policy vtypes.PluginPolicy) ([]byte, error) { fields := []string{ policy.Recipe, policy.PublicKey, - policy.PolicyVersion, + fmt.Sprintf("%d", policy.PolicyVersion), policy.PluginVersion} for _, item := range fields { if strings.Contains(item, delimiter) { diff --git a/plugin/fees/config.go b/plugin/fees/config.go new file mode 100644 index 0000000..e374f80 --- /dev/null +++ b/plugin/fees/config.go @@ -0,0 +1,63 @@ +package fees + +import ( + "errors" + "fmt" + "strings" + + "github.com/spf13/viper" +) + +type PluginConfig struct { + Type string `mapstructure:"type"` + Version string `mapstructure:"version"` + RpcURL string `mapstructure:"rpc_url"` // URL for the RPC endpoint to interact with the ethereum/evm blockchain + USDCAddress string `mapstructure:"usdc_address"` // If a non-ethereum chain is used, this is the address of the USDC token contract on that chain + Gas struct { + LimitMultiplier int `mapstructure:"limit_multiplier"` + PriceMultiplier int `mapstructure:"price_multiplier"` + } `mapstructure:"gas"` + Monitoring struct { + TimeoutMinutes int `mapstructure:"timeout_minutes"` + CheckIntervalSeconds int `mapstructure:"check_interval_seconds"` + } `mapstructure:"monitoring"` +} + +func loadPluginConfig(basePath string) (*PluginConfig, error) { + v := viper.New() + v.SetConfigName("fees") + + // Add config paths in order of precedence + if basePath != "" { + v.AddConfigPath(basePath) + } + v.AddConfigPath(".") + v.AddConfigPath("/etc/vultisig") + + // Enable environment variable overrides + v.AutomaticEnv() + v.SetEnvPrefix("FEES") + v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) + + if err := v.ReadInConfig(); err != nil { + return nil, fmt.Errorf("failed to read config: %w", err) + } + + var config PluginConfig + if err := v.Unmarshal(&config); err != nil { + return nil, fmt.Errorf("failed to unmarshal config: %w", err) + } + + // Validate configuration + if config.Type != PLUGIN_TYPE { + return nil, fmt.Errorf("invalid plugin type: %s", config.Type) + } + if config.RpcURL == "" { + return nil, errors.New("rpc_url is required") + } + if config.Gas.LimitMultiplier <= 0 { + return nil, errors.New("gas limit multiplier must be positive") + } + + return &config, nil +} diff --git a/plugin/fees/constraints.go b/plugin/fees/constraints.go new file mode 100644 index 0000000..f8aa3e5 --- /dev/null +++ b/plugin/fees/constraints.go @@ -0,0 +1,12 @@ +package fees + +const PLUGIN_TYPE = "fees" +const erc20ABI = `[{ + "name": "transfer", + "type": "function", + "inputs": [ + {"name": "recipient", "type": "address"}, + {"name": "amount", "type": "uint256"} + ], + "outputs": [{"name": "", "type": "bool"}] +}]` diff --git a/plugin/fees/fees.go b/plugin/fees/fees.go new file mode 100644 index 0000000..b996742 --- /dev/null +++ b/plugin/fees/fees.go @@ -0,0 +1,68 @@ +package fees + +import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum/ethclient" + "github.com/sirupsen/logrus" + "github.com/vultisig/mobile-tss-lib/tss" + "github.com/vultisig/verifier/plugin" + "github.com/vultisig/verifier/types" + + "github.com/vultisig/plugin/storage" + rtypes "github.com/vultisig/recipes/types" +) + +var _ plugin.Plugin = (*FeePlugin)(nil) + +type FeePlugin struct { + db storage.DatabaseStorage + rpcClient *ethclient.Client + logger logrus.FieldLogger + config *PluginConfig +} + +func NewFeePlugin(db storage.DatabaseStorage, baseConfigPath string) (*FeePlugin, error) { + if db == nil { + return nil, fmt.Errorf("database storage cannot be nil") + } + cfg, err := loadPluginConfig(baseConfigPath) + if err != nil { + return nil, fmt.Errorf("failed to load plugin config: %w", err) + } + + rpcClient, err := ethclient.Dial(cfg.RpcURL) + if err != nil { + return nil, err + } + + return &FeePlugin{ + db: db, + rpcClient: rpcClient, + logger: logrus.WithField("plugin", "payroll"), + config: cfg, + }, nil +} + +func (fp *FeePlugin) GetRecipeSpecification() rtypes.RecipeSchema { + fp.logger.Debug("Getting recipe specification") + //TODO garry + return rtypes.RecipeSchema{ + PluginId: "vultisig-fees-0000", + Version: 1, + } +} + +func (fp *FeePlugin) ValidatePluginPolicy(policyDoc types.PluginPolicy) error { + return nil +} +func (fp *FeePlugin) ProposeTransactions(policy types.PluginPolicy) ([]types.PluginKeysignRequest, error) { + return []types.PluginKeysignRequest{}, nil +} +func (fp *FeePlugin) ValidateProposedTransactions(policy types.PluginPolicy, txs []types.PluginKeysignRequest) error { + return nil +} +func (fp *FeePlugin) SigningComplete(ctx context.Context, signature tss.KeysignResponse, signRequest types.PluginKeysignRequest, policy types.PluginPolicy) error { + return nil +} From 9638cb23aaec25020fbded30a114a82c0f742419 Mon Sep 17 00:00:00 2001 From: Garry Sharp <> Date: Thu, 12 Jun 2025 23:12:22 +0400 Subject: [PATCH 3/4] Tidied go.mod --- go.sum | 6 ------ 1 file changed, 6 deletions(-) diff --git a/go.sum b/go.sum index bb3cbf3..b0cfb47 100644 --- a/go.sum +++ b/go.sum @@ -745,14 +745,8 @@ github.com/vultisig/go-wrappers v0.0.0-20250403041248-86911e8aa33f h1:124Xlloih1 github.com/vultisig/go-wrappers v0.0.0-20250403041248-86911e8aa33f/go.mod h1:UfGCxUQW08kiwxyNBiHwXe+ePPuBmHVVS+BS51aU/Jg= github.com/vultisig/mobile-tss-lib v0.0.0-20250316003201-2e7e570a4a74 h1:goqwk4nQ/NEVIb3OPP9SUx7/u9ZfsUIcd5fIN/e4DVU= github.com/vultisig/mobile-tss-lib v0.0.0-20250316003201-2e7e570a4a74/go.mod h1:nOykk4nOy1L3yXtLSlYvVsgizBnCQ3tR2N5uwGPdvaM= -github.com/vultisig/recipes v0.0.0-20250606100120-0ee16a73412d h1:BVc4OL0BNY/cCmptU3EeqAoxcX8vS13Pr13gWpd5Xi0= -github.com/vultisig/recipes v0.0.0-20250606100120-0ee16a73412d/go.mod h1:JT1FTsiJ8tY5W065vSsrxvrCSl1amp5o6SsBc1VVcCQ= github.com/vultisig/recipes v0.0.0-20250609134859-0655e0445c1b h1:rXhRaf40re1FdUYlYbCTEIO6JqIx8FfLlksksu8LiGE= github.com/vultisig/recipes v0.0.0-20250609134859-0655e0445c1b/go.mod h1:JT1FTsiJ8tY5W065vSsrxvrCSl1amp5o6SsBc1VVcCQ= -github.com/vultisig/verifier v0.0.0-20250611063307-6e5e760de529 h1:owEyLmbtlN1yL0xG7EhzXgvXbBZYHSHITh4P8lvPhyQ= -github.com/vultisig/verifier v0.0.0-20250611063307-6e5e760de529/go.mod h1:YpvZN2mbn6Z/34FDfnMS/TdE+B5Y8jghu5FvqOfRmB0= -github.com/vultisig/verifier v0.0.0-20250611171202-489e61b0205b h1:cY905EbOnT20AduKeHbQFQyT6D5EA/OpQNhTOzHBsI8= -github.com/vultisig/verifier v0.0.0-20250611171202-489e61b0205b/go.mod h1:YpvZN2mbn6Z/34FDfnMS/TdE+B5Y8jghu5FvqOfRmB0= github.com/vultisig/verifier v0.0.0-20250612165949-9db8a6828606 h1:DGia8ZQM3izAm+Oo/LM+5yWzENc9MIWtEfFCsCZOgO0= github.com/vultisig/verifier v0.0.0-20250612165949-9db8a6828606/go.mod h1:35VQIKhChb6/H+3J/XkbGhPkVF6lyLuxsUG/WXHS4+A= github.com/vultisig/vultiserver v0.0.0-20250515110921-82d56d3d9cc9 h1:pZhGN8q8+gPB1JJjVDC1hDg8qn6Tbj0XBJymgTQ8qQg= From c4575e21f047e1abd6dba5fcce566149cc665651 Mon Sep 17 00:00:00 2001 From: Garry Sharp <> Date: Fri, 13 Jun 2025 02:05:44 +0400 Subject: [PATCH 4/4] fmt.Errorf small fix in error message. --- plugin/dca/dca.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/dca/dca.go b/plugin/dca/dca.go index 5bfa997..7a6da3b 100644 --- a/plugin/dca/dca.go +++ b/plugin/dca/dca.go @@ -145,7 +145,7 @@ func (p *DCAPlugin) ValidatePluginPolicy(policyDoc vtypes.PluginPolicy) error { } if fmt.Sprintf("%d", policyDoc.PolicyVersion) != policyVersion { //TODO policy version will essentially be a nonce that is incremented by 1, not, like plugin versions that will follow traditional engineering versioning e.g. v2.12.3. For now we can compare string types - return fmt.Errorf("policy does not match policy version, expected: %s, got: %s", policyVersion, policyDoc.PolicyVersion) + return fmt.Errorf("policy does not match policy version, expected: %s, got: %d", policyVersion, policyDoc.PolicyVersion) } if policyDoc.PublicKey == "" {