Skip to content
This repository was archived by the owner on Feb 8, 2026. It is now read-only.

verifier<>plugin keysign#127

Merged
webpiratt merged 16 commits into
mainfrom
payroll-2
Jul 19, 2025
Merged

verifier<>plugin keysign#127
webpiratt merged 16 commits into
mainfrom
payroll-2

Conversation

@webpiratt

@webpiratt webpiratt commented Jul 11, 2025

Copy link
Copy Markdown
Contributor

Ref: #124 , vultisig/verifier#266

Summary by CodeRabbit

  • New Features

    • Added support for verifier service configuration, including URL, token, and party prefixes, in payroll and fee plugins.
    • Introduced a generic HTTP utility for flexible API calls.
    • Added a new signing coordinator to manage multi-party threshold signature sessions.
    • Added new emitters for plugin and verifier signing requests.
  • Bug Fixes

    • Improved handling of multiple recipients per rule in payroll transaction proposals.
  • Refactor

    • Updated configuration file structure for payroll plugin to support nested RPC and verifier settings.
    • Changed plugin and API constructors to accept verifier tokens.
    • Removed legacy constants, unused signing endpoints, and deprecated payroll plugin config.
    • Refactored payroll plugin to use external signer and Ethereum RPC client.
    • Simplified signing flow by removing asynchronous task queue for payroll signing.
    • Removed plugin-specific signing endpoint and related server routes.
    • Improved error messages and logging in scheduler and payroll components.
    • Removed payroll.yml configuration file and related Dockerfile references.
    • Updated payroll worker to prevent scaling due to scheduler constraints.
  • Style

    • Reformatted function calls and configuration structures for clarity.
  • Documentation

    • Updated configuration examples to reflect new structure.

@coderabbitai

coderabbitai Bot commented Jul 11, 2025

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@webpiratt has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 5 minutes and 17 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 6125bcc and 0150cf4.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (3)
  • .run/[git] tx_indexer worker.run.xml (1 hunks)
  • go.mod (1 hunks)
  • plugin/payroll/transaction.go (12 hunks)
## Walkthrough

This update removes the `SignPluginMessages` API endpoint and its handler, restructures plugin and worker configuration to include a verifier service with URL and token, and updates plugin logic to interact with the verifier for signing operations. Several function signatures and struct fields are adjusted to accommodate these changes, and configuration formats are updated accordingly.

## Changes

| File(s)                                  | Change Summary                                                                                          |
|-----------------------------------------|-------------------------------------------------------------------------------------------------------|
| api/plugin.go, api/server.go             | Removed `SignPluginMessages` method and its route; cleaned up related imports.                         |
| cmd/fees/server/main.go, cmd/fees/worker/main.go | Reformatted `fees.NewFeePlugin` invocation for readability; no logic changes.                          |
| cmd/payroll/server/main.go, cmd/payroll/worker/main.go | Changed `payroll.NewPayrollPlugin` to `payroll.NewPlugin` with updated arguments and added signer; removed unused inspector. |
| cmd/payroll/worker/config.go             | Added `Rpc` and `Verifier` fields to `PayrollWorkerConfig`; introduced new `Rpc`, `rpcItem`, and updated `verifier` structs. |
| common/util.go                          | Removed temporary plugin/verifier party ID constants.                                                 |
| etc/vultisig/payroll.yml, plugin/payroll/config.go, plugin/payroll/constants.go | Removed payroll config file, constants, and plugin config; restructured config with nested RPC and verifier sections. |
| internal/libhttp/libhttp.go              | Added generic `Call` function for flexible HTTP requests and typed responses.                         |
| internal/verifierapi/fees.go, internal/verifierapi/verifierapi.go | Changed `VerifierApi` methods to pointer receivers; renamed URL field to lowercase; updated constructor and methods. |
| internal/keysign/api_emitter.go          | Added `apiEmitter` struct and `NewVerifierEmitter` to emit signing requests via HTTP API with auth token. |
| internal/keysign/plugin_emitter.go       | Added `PluginEmitter` struct to enqueue signing tasks asynchronously via asynq client.                |
| internal/keysign/signer.go                | Introduced `Signer` type coordinating multi-party signing sessions with emitters and relay client.    |
| plugin/dca/dca.go                        | Removed use of static party IDs in `PluginKeysignRequest` construction.                               |
| plugin/fees/fees.go                      | Reformatted `verifierApi` instantiation call; no logic change.                                       |
| plugin/payroll/payroll.go                | Renamed `PayrollPlugin` to `Plugin`; removed config and inspector fields; added `signer` field; updated constructor to accept `signer` and `ethRpc`. |
| plugin/payroll/transaction.go            | Refactored signing flow to use `signer.Sign` directly; updated to support multiple recipients per rule; changed helper function signature. |
| payroll.worker.example.json              | Updated config example by adding `verifier` and `rpc` sections; removed `base_file_path`.             |
| Dockerfile.Payroll.server, Dockerfile.Payroll.worker | Removed copying of `payroll.yml` config file.                                                        |
| .run/[git] payroll server.run.xml, .run/[git] payroll worker.run.xml | Updated `DATABASE_DSN` environment variable to use `vultisig-payroll` database.                       |
| test/e2e/keygen_test.go, test/keys/iPad/.gitignore, test/keys/iPhone/.gitignore, test/test-2of2-vault-backups/* | Removed test files and ignore rules related to keygen and vault backups.                             |
| internal/scheduler/scheduler.go          | Improved error messages for scheduler initialization and trigger creation; reordered imports.         |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Plugin
    participant VerifierApi
    participant VerifierService

    Plugin->>VerifierApi: Sign(ctx, PluginKeysignRequest)
    VerifierApi->>VerifierService: POST /plugin-signer/sign (with Bearer token)
    VerifierService-->>VerifierApi: Task ID or error
    VerifierApi-->>Plugin: Task ID or error

Possibly related PRs

Suggested reviewers

  • johnnyluo
  • RaghavSood

Poem

In the warren of code, a tunnel’s now closed,
The plugin’s old signer, retired and reposed.
A new verifier hops in, with token in paw,
Configs reshaped, much to rabbits’ awe.
With parties and rules, the flow’s now refined—
Hopping forward, leaving old routes behind!
🐇✨


<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=vultisig/plugin&utm_content=127):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (6)
internal/libhttp/libhttp.go (3)

20-23: Handle nil/empty body gracefully.

The function always marshals the body to JSON, which could cause issues if the body is nil or shouldn't be JSON. Consider handling empty bodies separately.

-	b, err := json.Marshal(body)
-	if err != nil {
-		return *new(T), fmt.Errorf("json.Marshal: %w", err)
-	}
+	var b []byte
+	if body != nil {
+		var err error
+		b, err = json.Marshal(body)
+		if err != nil {
+			return *new(T), fmt.Errorf("json.Marshal: %w", err)
+		}
+	}

43-46: Consider using a configurable HTTP client.

Using http.DefaultClient doesn't allow for timeout configuration or other customizations. Consider accepting an HTTP client as a parameter or using a client with reasonable defaults.

-	res, err := http.DefaultClient.Do(req)
+	client := &http.Client{
+		Timeout: 30 * time.Second,
+	}
+	res, err := client.Do(req)

59-63: Improve string type detection.

The current approach to detect string response types using type assertion is somewhat indirect. Consider using type switches or reflection for cleaner type detection.

-	_, isString := any(new(T)).(string)
-	if isString {
-		// for string response type no need to unmarshal JSON
-		return any(string(bodyBytes)).(T), nil
-	}
+	var zero T
+	if _, ok := any(zero).(string); ok {
+		// for string response type no need to unmarshal JSON
+		return any(string(bodyBytes)).(T), nil
+	}
etc/vultisig/payroll.yml (1)

6-8: Verify verifier token for production deployment.

The verifier configuration looks correct for local development. Ensure that production deployments use secure, environment-specific tokens rather than the "localhost-apikey" placeholder.

plugin/payroll/transaction.go (1)

91-96: The verifier Sign response is not utilized.

The call to p.verifier.Sign(ctx, req) returns a response that could contain important information (like a task ID), but it's currently discarded. Consider using the response for tracking or logging purposes.

Consider utilizing the response:

-	_, e = p.verifier.Sign(ctx, req)
+	taskID, e := p.verifier.Sign(ctx, req)
 	if e != nil {
 		p.logger.WithError(e).Error("failed to make Sign request with verifier")
 		return fmt.Errorf("p.verifier.Sign: %w", e)
 	}
+	p.logger.WithField("verifier_task_id", taskID).Info("verifier sign request submitted")
internal/verifierapi/verifierapi.go (1)

57-75: Well-implemented Sign method with proper error handling.

The Sign method correctly implements authenticated HTTP requests with proper error handling and logging. The use of libhttp.Call provides consistent HTTP client behavior.

Consider making the endpoint path configurable:

func (v *VerifierApi) Sign(ctx context.Context, req types.PluginKeysignRequest) (string, error) {
-	endpoint := v.url + "/plugin-signer/sign"
+	endpoint := v.url + "/plugin-signer/sign" // TODO: make endpoint path configurable
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9812451 and f49bba4.

📒 Files selected for processing (17)
  • api/plugin.go (0 hunks)
  • api/server.go (0 hunks)
  • cmd/fees/server/main.go (1 hunks)
  • cmd/fees/worker/main.go (1 hunks)
  • cmd/payroll/server/main.go (1 hunks)
  • cmd/payroll/worker/config.go (2 hunks)
  • cmd/payroll/worker/main.go (1 hunks)
  • common/util.go (0 hunks)
  • etc/vultisig/payroll.yml (1 hunks)
  • internal/libhttp/libhttp.go (1 hunks)
  • internal/verifierapi/fees.go (3 hunks)
  • internal/verifierapi/verifierapi.go (2 hunks)
  • plugin/dca/dca.go (1 hunks)
  • plugin/fees/fees.go (2 hunks)
  • plugin/payroll/config.go (1 hunks)
  • plugin/payroll/payroll.go (4 hunks)
  • plugin/payroll/transaction.go (3 hunks)
💤 Files with no reviewable changes (3)
  • api/server.go
  • common/util.go
  • api/plugin.go
🧰 Additional context used
🧠 Learnings (14)
📓 Common learnings
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:178-183
Timestamp: 2025-06-18T18:28:19.759Z
Learning: In the payroll plugin, the Hash field in PluginKeysignRequest is intentionally set to the unsigned transaction hex (same as Message field) because computing a hash with empty V,R,S signature fields doesn't make sense, and it's documented as "not on-chain hash without signature". This is a deliberate placeholder approach.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
cmd/payroll/server/main.go (5)
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:510-514
Timestamp: 2025-06-18T18:20:59.510Z
Learning: The erc20ABI constant is defined in plugin/payroll/constants.go within the payroll package, making it accessible to other files in the same package like transaction.go.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config from the external package "github.com/vultisig/verifier/vault_config" in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). The vault_config.Config struct contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). It contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
cmd/payroll/worker/main.go (6)
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:510-514
Timestamp: 2025-06-18T18:20:59.510Z
Learning: The erc20ABI constant is defined in plugin/payroll/constants.go within the payroll package, making it accessible to other files in the same package like transaction.go.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.
Learnt from: RaghavSood
PR: vultisig/plugin#75
File: storage/postgres/db_plugin.go:25-40
Timestamp: 2025-05-30T02:44:31.711Z
Learning: The embed.FS directive `//go:embed migrations/plugin/*.sql` in storage/postgres/db_plugin.go correctly embeds plugin migration files that exist in the storage/postgres/migrations/plugin/ directory. The path "migrations/plugin" passed to goose.Up() references the embedded filesystem structure, not the physical file system path.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config from the external package "github.com/vultisig/verifier/vault_config" in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). The vault_config.Config struct contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). It contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
cmd/fees/server/main.go (9)
Learnt from: webpiratt
PR: vultisig/plugin#126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.005Z
Learning: The constant `vtypes.PluginVultisigFees_feee` in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/transaction.go:186-197
Timestamp: 2025-07-09T22:22:36.651Z
Learning: In plugin/payroll/transaction.go, the getTokenID function is designed to return evm.ZeroAddress.Hex() when no "token" parameter constraint is found, rather than returning an error. This is expected behavior according to the team's design intent, even though the token parameter is marked as required in the recipe specification.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config from the external package "github.com/vultisig/verifier/vault_config" in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). The vault_config.Config struct contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). It contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
cmd/payroll/worker/config.go (5)
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config from the external package "github.com/vultisig/verifier/vault_config" in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). The vault_config.Config struct contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). It contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:510-514
Timestamp: 2025-06-18T18:20:59.510Z
Learning: The erc20ABI constant is defined in plugin/payroll/constants.go within the payroll package, making it accessible to other files in the same package like transaction.go.
etc/vultisig/payroll.yml (4)
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config from the external package "github.com/vultisig/verifier/vault_config" in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). The vault_config.Config struct contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:510-514
Timestamp: 2025-06-18T18:20:59.510Z
Learning: The erc20ABI constant is defined in plugin/payroll/constants.go within the payroll package, making it accessible to other files in the same package like transaction.go.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). It contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
plugin/dca/dca.go (4)
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
Learnt from: webpiratt
PR: vultisig/plugin#105
File: plugin/dca/dca.go:734-736
Timestamp: 2025-07-01T17:35:35.277Z
Learning: The DCA plugin in the vultisig/plugin codebase is currently not fully implemented. Methods like getCompletedSwapTransactionsCount() return placeholder values (e.g., 0) with TODO comments, which is expected behavior during the development phase. The plugin implementation is intentionally incomplete while other parts of the system are being refactored.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: Dockerfile.Payroll.server:14-19
Timestamp: 2025-07-02T04:55:36.331Z
Learning: In the vultisig/plugin repository, the team maintains both the main repository and the go-wrappers dependency repository, so they are comfortable downloading from the master branch rather than pinning to specific commits.
internal/verifierapi/fees.go (4)
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
Learnt from: webpiratt
PR: vultisig/plugin#126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.005Z
Learning: The constant `vtypes.PluginVultisigFees_feee` in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.
cmd/fees/worker/main.go (10)
Learnt from: webpiratt
PR: vultisig/plugin#126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.005Z
Learning: The constant `vtypes.PluginVultisigFees_feee` in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:43-44
Timestamp: 2025-06-18T18:22:06.358Z
Learning: In the vultisig/plugin codebase, the hardcoded ethereumEvmChainID = big.NewInt(1) in plugin/payroll/transaction.go is intentional for the current implementation phase. The team is implementing ETH first, with plans to add other EVM chains later. The functions/methods are already designed to work with all EVM chains.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config from the external package "github.com/vultisig/verifier/vault_config" in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). The vault_config.Config struct contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). It contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
Learnt from: RaghavSood
PR: vultisig/plugin#75
File: storage/postgres/db_plugin.go:25-40
Timestamp: 2025-05-30T02:44:31.711Z
Learning: The embed.FS directive `//go:embed migrations/plugin/*.sql` in storage/postgres/db_plugin.go correctly embeds plugin migration files that exist in the storage/postgres/migrations/plugin/ directory. The path "migrations/plugin" passed to goose.Up() references the embedded filesystem structure, not the physical file system path.
plugin/payroll/payroll.go (7)
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:510-514
Timestamp: 2025-06-18T18:20:59.510Z
Learning: The erc20ABI constant is defined in plugin/payroll/constants.go within the payroll package, making it accessible to other files in the same package like transaction.go.
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:43-44
Timestamp: 2025-06-18T18:22:06.358Z
Learning: In the vultisig/plugin codebase, the hardcoded ethereumEvmChainID = big.NewInt(1) in plugin/payroll/transaction.go is intentional for the current implementation phase. The team is implementing ETH first, with plans to add other EVM chains later. The functions/methods are already designed to work with all EVM chains.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: Dockerfile.Payroll.server:14-19
Timestamp: 2025-07-02T04:55:36.331Z
Learning: In the vultisig/plugin repository, the team maintains both the main repository and the go-wrappers dependency repository, so they are comfortable downloading from the master branch rather than pinning to specific commits.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config from the external package "github.com/vultisig/verifier/vault_config" in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). The vault_config.Config struct contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
plugin/payroll/transaction.go (5)
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/transaction.go:186-197
Timestamp: 2025-07-09T22:22:36.651Z
Learning: In plugin/payroll/transaction.go, the getTokenID function is designed to return evm.ZeroAddress.Hex() when no "token" parameter constraint is found, rather than returning an error. This is expected behavior according to the team's design intent, even though the token parameter is marked as required in the recipe specification.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.
plugin/payroll/config.go (8)
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:510-514
Timestamp: 2025-06-18T18:20:59.510Z
Learning: The erc20ABI constant is defined in plugin/payroll/constants.go within the payroll package, making it accessible to other files in the same package like transaction.go.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config from the external package "github.com/vultisig/verifier/vault_config" in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). The vault_config.Config struct contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). It contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:43-44
Timestamp: 2025-06-18T18:22:06.358Z
Learning: In the vultisig/plugin codebase, the hardcoded ethereumEvmChainID = big.NewInt(1) in plugin/payroll/transaction.go is intentional for the current implementation phase. The team is implementing ETH first, with plans to add other EVM chains later. The functions/methods are already designed to work with all EVM chains.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.
plugin/fees/fees.go (6)
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
Learnt from: webpiratt
PR: vultisig/plugin#126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.005Z
Learning: The constant `vtypes.PluginVultisigFees_feee` in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config from the external package "github.com/vultisig/verifier/vault_config" in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). The vault_config.Config struct contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
internal/verifierapi/verifierapi.go (1)
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
🧬 Code Graph Analysis (6)
cmd/payroll/worker/main.go (1)
plugin/payroll/payroll.go (1)
  • NewPayrollPlugin (33-76)
internal/verifierapi/fees.go (1)
internal/verifierapi/verifierapi.go (1)
  • VerifierApi (28-32)
plugin/payroll/payroll.go (1)
internal/verifierapi/verifierapi.go (2)
  • VerifierApi (28-32)
  • NewVerifierApi (34-40)
plugin/payroll/transaction.go (1)
internal/types/keysign.go (1)
  • PluginKeysignRequest (7-12)
plugin/fees/fees.go (1)
internal/verifierapi/verifierapi.go (1)
  • NewVerifierApi (34-40)
internal/verifierapi/verifierapi.go (2)
internal/types/keysign.go (1)
  • PluginKeysignRequest (7-12)
internal/libhttp/libhttp.go (1)
  • Call (13-72)
🔇 Additional comments (21)
plugin/dca/dca.go (1)

344-346: LGTM: Party IDs removal aligns with refactor objectives.

The change from hardcoded party identifiers to an empty slice is consistent with the broader refactor that removes temporary placeholder party IDs and moves signing responsibility to the verifier API. The PluginID and PolicyID fields are properly set using the policy data.

cmd/payroll/worker/main.go (1)

84-92: LGTM: Improved code formatting.

The multi-line formatting with trailing comma improves readability and makes future modifications easier. This follows Go formatting best practices.

cmd/payroll/server/main.go (1)

74-82: LGTM: Consistent formatting improvement.

The multi-line formatting matches the style used in the worker file and improves code readability. The trailing comma facilitates future modifications.

etc/vultisig/payroll.yml (1)

3-5: LGTM: Improved configuration structure.

The nested RPC configuration is more organized and extensible than the flat structure. This aligns with the broader refactor to support multiple chains and structured configuration.

cmd/payroll/worker/config.go (2)

16-16: Configuration integration looks good.

The addition of the Verifier field to the PayrollWorkerConfig struct follows the established pattern and supports the new verifier service integration.


29-32: Well-structured verifier configuration.

The verifier struct is properly defined with appropriate field tags for configuration mapping and JSON serialization.

cmd/fees/worker/main.go (1)

95-107: Multi-line formatting improves readability.

The refactoring to multi-line format makes the function call more readable and maintainable.

cmd/fees/server/main.go (1)

81-93: Consistent formatting with worker implementation.

The multi-line formatting is consistent with the worker implementation and improves code readability. The empty token placeholder follows the same pattern as the worker.

internal/verifierapi/fees.go (3)

30-30: Improved receiver type consistency.

Changing from value receiver to pointer receiver is a good practice for the VerifierApi struct, which contains multiple fields including url, token, and logger. This avoids unnecessary copying and maintains consistency with other methods in the package.


62-62: Consistent pointer receiver pattern.

The pointer receiver change maintains consistency across all VerifierApi methods.


93-93: Completes the receiver type standardization.

All three methods now use pointer receivers, ensuring consistent behavior across the VerifierApi interface.

plugin/payroll/payroll.go (4)

9-9: Proper import addition for verifier integration.

The import of verifierapi package is correctly added to support the new verifier functionality.


22-22: Verifier field properly added to plugin struct.

The verifier field is appropriately added to the PayrollPlugin struct with the correct type *verifierapi.VerifierApi.


50-50: Configuration structure update handled correctly.

The change from cfg.RpcURL to cfg.Rpc.Ethereum.URL indicates a restructuring to nested configuration, which improves organization and supports future multi-chain expansion.


62-66: Verifier initialization follows best practices.

The verifier is properly initialized using verifierapi.NewVerifierApi with the configuration values and a scoped logger. This follows the constructor pattern defined in the verifierapi package.

plugin/payroll/transaction.go (1)

238-337: Excellent refactoring to support multiple recipients per rule.

The refactoring to handle multiple recipients per rule is well-implemented with proper concurrency control using errgroup. The goroutine-based approach ensures each recipient is processed independently while maintaining thread safety with the mutex.

plugin/fees/fees.go (2)

57-57: LGTM: Clean integration of verifier token parameter.

The addition of the verifierToken parameter to the constructor is properly integrated and enables authenticated communication with the verifier service.


85-89: LGTM: Proper verifier API initialization with token.

The verifier API initialization correctly passes the token parameter, enabling authenticated requests to the verifier service.

internal/verifierapi/verifierapi.go (3)

29-30: LGTM: Proper encapsulation with token field addition.

The addition of the token field and making the url field lowercase improves encapsulation and enables authenticated requests to the verifier service.


34-40: LGTM: Constructor properly updated for token support.

The constructor correctly accepts and initializes the token parameter, enabling authenticated verifier API interactions.


42-55: LGTM: Receiver consistency improved.

Changing the receiver from value to pointer improves consistency and allows for potential future modifications to the struct state.

Comment thread cmd/fees/worker/main.go Outdated
Comment thread plugin/payroll/config.go Outdated
Comment thread plugin/payroll/transaction.go
Comment thread plugin/payroll/transaction.go Outdated
RaghavSood
RaghavSood previously approved these changes Jul 11, 2025
@webpiratt webpiratt closed this Jul 11, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (4)
cmd/payroll/worker/config.go (3)

16-17: Inconsistent field naming convention.

The field Rpc is capitalized while verifier is not. For consistency with Go conventions and the rest of the struct fields, consider using either RPC and Verifier or rpc and verifier.

Apply this diff for consistency:

-	Rpc                Rpc                       `mapstructure:"Rpc" json:"Rpc,omitempty"`
-	Verifier           verifier                  `mapstructure:"verifier" json:"verifier,omitempty"`
+	RPC                RPC                       `mapstructure:"rpc" json:"rpc,omitempty"`
+	Verifier           Verifier                  `mapstructure:"verifier" json:"verifier,omitempty"`

29-35: Type names should follow Go naming conventions for acronyms.

According to Go conventions, acronyms in type names should be capitalized. Consider renaming Rpc to RPC and rpcItem to RPCItem.

Apply this diff to follow Go naming conventions:

-type Rpc struct {
-	Ethereum rpcItem `mapstructure:"ethereum" json:"ethereum,omitempty"`
+type RPC struct {
+	Ethereum RPCItem `mapstructure:"ethereum" json:"ethereum,omitempty"`
 }

-type rpcItem struct {
+type RPCItem struct {
 	URL string `mapstructure:"url" json:"url,omitempty"`
 }

37-41: Type name should be capitalized.

The type verifier should be Verifier to follow Go naming conventions for exported types.

Apply this diff:

-type verifier struct {
+type Verifier struct {
 	URL         string `mapstructure:"url"`
 	Token       string `mapstructure:"token"`
 	PartyPrefix string `mapstructure:"party_prefix"`
 }
internal/keysign/api_emitter.go (1)

38-44: Consider logging API response for debugging.

The response from the API call is ignored. While this works for the happy path, the response might contain useful error details or request IDs that could help with debugging failures.

Consider logging the response:

 func (e *apiEmitter[T]) Sign(ctx context.Context, req types.PluginKeysignRequest) error {
-	_, err := libhttp.Call[T](ctx, e.method, e.endpoint, e.headers, req, nil)
+	resp, err := libhttp.Call[T](ctx, e.method, e.endpoint, e.headers, req, nil)
 	if err != nil {
 		return fmt.Errorf("libhttp.Call: %w", err)
 	}
+	// Log response if needed for debugging
+	// logrus.WithField("response", resp).Debug("API emitter response")
 	return nil
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f49bba4 and 5c4cda4.

📒 Files selected for processing (13)
  • cmd/payroll/server/main.go (1 hunks)
  • cmd/payroll/worker/config.go (2 hunks)
  • cmd/payroll/worker/main.go (2 hunks)
  • etc/vultisig/payroll.yml (0 hunks)
  • internal/keysign/api_emitter.go (1 hunks)
  • internal/keysign/plugin_emitter.go (1 hunks)
  • internal/keysign/signer.go (1 hunks)
  • internal/verifierapi/verifierapi.go (1 hunks)
  • payroll.worker.example.json (1 hunks)
  • plugin/payroll/config.go (0 hunks)
  • plugin/payroll/constants.go (0 hunks)
  • plugin/payroll/payroll.go (2 hunks)
  • plugin/payroll/transaction.go (4 hunks)
💤 Files with no reviewable changes (3)
  • etc/vultisig/payroll.yml
  • plugin/payroll/constants.go
  • plugin/payroll/config.go
✅ Files skipped from review due to trivial changes (1)
  • payroll.worker.example.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • internal/verifierapi/verifierapi.go
  • cmd/payroll/server/main.go
  • plugin/payroll/transaction.go
  • plugin/payroll/payroll.go
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:178-183
Timestamp: 2025-06-18T18:28:19.759Z
Learning: In the payroll plugin, the Hash field in PluginKeysignRequest is intentionally set to the unsigned transaction hex (same as Message field) because computing a hash with empty V,R,S signature fields doesn't make sense, and it's documented as "not on-chain hash without signature". This is a deliberate placeholder approach.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
cmd/payroll/worker/main.go (10)
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:43-44
Timestamp: 2025-06-18T18:22:06.358Z
Learning: In the vultisig/plugin codebase, the hardcoded ethereumEvmChainID = big.NewInt(1) in plugin/payroll/transaction.go is intentional for the current implementation phase. The team is implementing ETH first, with plans to add other EVM chains later. The functions/methods are already designed to work with all EVM chains.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:510-514
Timestamp: 2025-06-18T18:20:59.510Z
Learning: The erc20ABI constant is defined in plugin/payroll/constants.go within the payroll package, making it accessible to other files in the same package like transaction.go.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/transaction.go:186-197
Timestamp: 2025-07-09T22:22:36.651Z
Learning: In plugin/payroll/transaction.go, the getTokenID function is designed to return evm.ZeroAddress.Hex() when no "token" parameter constraint is found, rather than returning an error. This is expected behavior according to the team's design intent, even though the token parameter is marked as required in the recipe specification.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:178-183
Timestamp: 2025-06-18T18:28:19.759Z
Learning: In the payroll plugin, the Hash field in PluginKeysignRequest is intentionally set to the unsigned transaction hex (same as Message field) because computing a hash with empty V,R,S signature fields doesn't make sense, and it's documented as "not on-chain hash without signature". This is a deliberate placeholder approach.
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: Dockerfile.Payroll.server:14-19
Timestamp: 2025-07-02T04:55:36.331Z
Learning: In the vultisig/plugin repository, the team maintains both the main repository and the go-wrappers dependency repository, so they are comfortable downloading from the master branch rather than pinning to specific commits.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config from the external package "github.com/vultisig/verifier/vault_config" in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). The vault_config.Config struct contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). It contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
cmd/payroll/worker/config.go (5)
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config from the external package "github.com/vultisig/verifier/vault_config" in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). The vault_config.Config struct contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:510-514
Timestamp: 2025-06-18T18:20:59.510Z
Learning: The erc20ABI constant is defined in plugin/payroll/constants.go within the payroll package, making it accessible to other files in the same package like transaction.go.
Learnt from: johnnyluo
PR: vultisig/plugin#108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). It contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
internal/keysign/api_emitter.go (1)
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
internal/keysign/plugin_emitter.go (1)
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
🧬 Code Graph Analysis (3)
cmd/payroll/worker/main.go (6)
cmd/payroll/worker/config.go (1)
  • Rpc (29-31)
plugin/payroll/payroll.go (1)
  • NewPayrollPlugin (31-63)
internal/keysign/signer.go (2)
  • NewSigner (30-47)
  • Emitter (19-21)
internal/keysign/api_emitter.go (1)
  • NewVerifierEmitter (12-21)
internal/keysign/plugin_emitter.go (1)
  • NewPluginEmitter (19-25)
internal/tasks/tasks.go (2)
  • TypeKeySignDKLS (13-13)
  • QUEUE_NAME (9-9)
internal/keysign/api_emitter.go (3)
internal/keysign/signer.go (1)
  • Emitter (19-21)
internal/types/keysign.go (1)
  • PluginKeysignRequest (7-12)
internal/libhttp/libhttp.go (1)
  • Call (13-72)
internal/keysign/plugin_emitter.go (1)
internal/types/keysign.go (1)
  • PluginKeysignRequest (7-12)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (5)
cmd/payroll/worker/main.go (3)

8-11: LGTM! Clean import organization.

The new imports for Ethereum client and keysign package are properly organized and necessary for the refactored signing architecture.


88-91: Ethereum RPC client initialization looks good.

Proper error handling and clear error message for RPC client creation failure.


93-112: Complex but correct PayrollPlugin initialization with new Signer architecture.

The initialization properly sets up the keysign.Signer with both verifier and plugin emitters, enabling the dual signing path architecture. All parameters are correctly sourced from the configuration.

internal/keysign/signer.go (2)

99-119: Review error handling in signature collection loop.

The continue statement on line 108 continues the inner loop but doesn't affect the outer polling loop. If CheckKeysignComplete consistently fails for one message, the method will keep polling indefinitely without returning the partial results or aggregating errors.

Consider whether partial failures should be handled differently:

 			sigs := make(map[string]tss.KeysignResponse, len(messageIDs))
+			var errors []error
 			for _, messageID := range messageIDs {
 				sig, completeErr := s.relay.CheckKeysignComplete(sessionID, messageID)
 				if completeErr != nil {
 					s.logger.WithFields(logrus.Fields{
 						"sessionID": sessionID,
 						"messageID": messageID,
 						"partyIDs":  partyIDs,
 					}).WithError(completeErr).Info("continue polling: CheckKeysignComplete")
-					continue
+					errors = append(errors, completeErr)
+					break // Break inner loop to retry in outer loop
 				}
 				if sig == nil {
 					return nil, fmt.Errorf(
 						"unexpected empty sig: messageID: %s, sessionID: %s",
 						messageID,
 						sessionID,
 					)
 				}
 				sigs[messageID] = *sig
 			}
+			if len(errors) > 0 {
+				continue // Retry in outer loop
+			}
 			return sigs, nil

49-75: Well-designed signing coordination implementation.

The Sign method properly orchestrates the multi-party signing process by:

  1. Emitting requests to all configured emitters
  2. Waiting for parties to join with proper prefix filtering
  3. Collecting results with context-aware polling
    Excellent use of context for cancellation support.

Comment thread internal/keysign/plugin_emitter.go
Comment thread internal/keysign/plugin_emitter.go
Comment thread internal/keysign/api_emitter.go
Comment thread internal/keysign/signer.go
@webpiratt
webpiratt marked this pull request as draft July 12, 2025 23:29
Comment thread internal/libhttp/libhttp.go Outdated
@webpiratt webpiratt changed the title payroll: process keysign verifier<>plugin keysign Jul 19, 2025
webpiratt and others added 5 commits July 19, 2025 14:10
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@webpiratt
webpiratt marked this pull request as ready for review July 19, 2025 11:49

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
internal/keysign/signer.go (1)

182-187: Fix grammar in error message.

There's a grammatical error in the error message.

Apply this diff:

 				return nil, fmt.Errorf(
 					"too many parties joined: [%s], expected prefixes: [%s],"+
-						" it may be caused by a bug in calling code",
+						" it may be caused by a bug in the calling code",
 					strings.Join(partiesIDs, ","),
 					strings.Join(partiesPrefixes, ","),
 				)
🧹 Nitpick comments (1)
plugin/payroll/transaction.go (1)

88-97: Simplify single signature extraction

The current approach uses a loop to extract a single signature from the map. Consider a more direct approach.

 	if len(sigs) != 1 {
 		p.logger.
 			WithField("sigs_count", len(sigs)).
 			Error("expected only 1 message+sig per request for evm")
 		return fmt.Errorf("failed to sign transaction: invalid signature count: %d", len(sigs))
 	}
-	var sig tss.KeysignResponse
-	for _, s := range sigs {
-		sig = s
-	}
+	// Extract the single signature from the map
+	var sig tss.KeysignResponse
+	for _, s := range sigs {
+		sig = s
+		break
+	}

Or even better, since we know there's exactly one message:

+	// Get the signature for the single message
+	sig, ok := sigs[req.Messages[0].Hash]
+	if !ok {
+		return fmt.Errorf("signature not found for message hash")
+	}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5c4cda4 and 6125bcc.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (26)
  • .run/[git] payroll server.run.xml (2 hunks)
  • .run/[git] payroll worker.run.xml (2 hunks)
  • Dockerfile.Payroll.server (1 hunks)
  • Dockerfile.Payroll.worker (1 hunks)
  • cmd/fees/server/main.go (1 hunks)
  • cmd/fees/worker/main.go (1 hunks)
  • cmd/payroll/server/main.go (1 hunks)
  • cmd/payroll/worker/main.go (2 hunks)
  • go.mod (1 hunks)
  • internal/keysign/api_emitter.go (1 hunks)
  • internal/keysign/plugin_emitter.go (1 hunks)
  • internal/keysign/signer.go (1 hunks)
  • internal/libhttp/libhttp.go (1 hunks)
  • internal/scheduler/scheduler.go (5 hunks)
  • internal/verifierapi/verifierapi.go (1 hunks)
  • payroll.worker.example.json (1 hunks)
  • plugin/fees/fees.go (1 hunks)
  • plugin/payroll/payroll.go (2 hunks)
  • plugin/payroll/policy.go (2 hunks)
  • plugin/payroll/transaction.go (12 hunks)
  • test/e2e/keygen_test.go (0 hunks)
  • test/keys/iPad/.gitignore (0 hunks)
  • test/keys/iPhone/.gitignore (0 hunks)
  • test/test-2of2-vault-backups/Fast Vault #2-0985-part1of2-Vultiserver.vult (0 hunks)
  • test/test-2of2-vault-backups/Fast Vault #2-0985-part2of2.vult (0 hunks)
  • test/test-2of2-vault-backups/Vault Info.txt (0 hunks)
💤 Files with no reviewable changes (6)
  • test/test-2of2-vault-backups/Vault Info.txt
  • test/keys/iPad/.gitignore
  • test/test-2of2-vault-backups/Fast Vault #2-0985-part2of2.vult
  • test/keys/iPhone/.gitignore
  • test/test-2of2-vault-backups/Fast Vault #2-0985-part1of2-Vultiserver.vult
  • test/e2e/keygen_test.go
✅ Files skipped from review due to trivial changes (7)
  • Dockerfile.Payroll.worker
  • Dockerfile.Payroll.server
  • .run/[git] payroll server.run.xml
  • .run/[git] payroll worker.run.xml
  • plugin/payroll/policy.go
  • internal/scheduler/scheduler.go
  • go.mod
🚧 Files skipped from review as they are similar to previous changes (11)
  • cmd/fees/server/main.go
  • cmd/payroll/server/main.go
  • payroll.worker.example.json
  • plugin/fees/fees.go
  • cmd/fees/worker/main.go
  • internal/verifierapi/verifierapi.go
  • cmd/payroll/worker/main.go
  • internal/libhttp/libhttp.go
  • internal/keysign/api_emitter.go
  • internal/keysign/plugin_emitter.go
  • plugin/payroll/payroll.go
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:178-183
Timestamp: 2025-06-18T18:28:19.759Z
Learning: In the payroll plugin, the Hash field in PluginKeysignRequest is intentionally set to the unsigned transaction hex (same as Message field) because computing a hash with empty V,R,S signature fields doesn't make sense, and it's documented as "not on-chain hash without signature". This is a deliberate placeholder approach.
Learnt from: webpiratt
PR: vultisig/plugin#127
File: internal/keysign/api_emitter.go:12-21
Timestamp: 2025-07-19T11:09:26.168Z
Learning: In the vultisig/plugin codebase, URL formatting and validation for endpoints like the verifier emitter is handled at the configuration level, so additional URL validation in individual functions is not needed.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
internal/keysign/signer.go (1)
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
plugin/payroll/transaction.go (8)
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:510-514
Timestamp: 2025-06-18T18:20:59.510Z
Learning: The erc20ABI constant is defined in plugin/payroll/constants.go within the payroll package, making it accessible to other files in the same package like transaction.go.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:43-44
Timestamp: 2025-06-18T18:22:06.358Z
Learning: In the vultisig/plugin codebase, the hardcoded ethereumEvmChainID = big.NewInt(1) in plugin/payroll/transaction.go is intentional for the current implementation phase. The team is implementing ETH first, with plans to add other EVM chains later. The functions/methods are already designed to work with all EVM chains.
Learnt from: webpiratt
PR: vultisig/plugin#125
File: plugin/payroll/transaction.go:186-197
Timestamp: 2025-07-09T22:22:36.651Z
Learning: In plugin/payroll/transaction.go, the getTokenID function is designed to return evm.ZeroAddress.Hex() when no "token" parameter constraint is found, rather than returning an error. This is expected behavior according to the team's design intent, even though the token parameter is marked as required in the recipe specification.
Learnt from: RaghavSood
PR: vultisig/plugin#36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path `github.com/vultisig/verifier/plugin` refers to an external dependency that provides the plugin interface, and should not be changed to `github.com/vultisig/plugin/plugin` as these are distinct packages with different purposes.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.
Learnt from: webpiratt
PR: vultisig/plugin#96
File: plugin/payroll/transaction.go:178-183
Timestamp: 2025-06-18T18:28:19.759Z
Learning: In the payroll plugin, the Hash field in PluginKeysignRequest is intentionally set to the unsigned transaction hex (same as Message field) because computing a hash with empty V,R,S signature fields doesn't make sense, and it's documented as "not on-chain hash without signature". This is a deliberate placeholder approach.

Comment thread internal/keysign/signer.go
@webpiratt
webpiratt requested a review from evgensheff July 19, 2025 12:01
@webpiratt
webpiratt enabled auto-merge July 19, 2025 12:28

@RaghavSood RaghavSood left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One nit, non-blocking

I believe a good portion of this should be split up and probably go into verifier or vultisig-go, but that is not a blocker for getting this in and keeping things moving first

Amazing effort, thank you @webpiratt


type PayrollWorkerConfig struct {
Redis storage.RedisConfig `mapstructure:"redis" json:"redis,omitempty"`
Rpc Rpc `mapstructure:"Rpc" json:"Rpc,omitempty"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Rpc Rpc `mapstructure:"Rpc" json:"Rpc,omitempty"`
Rpc Rpc `mapstructure:"rpc" json:"rpc,omitempty"`

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, PR already auto-merged, I'll put this typo fix in next PR, seems viper loads it as case-insensitive - I didn't notice because config loaded fine

@webpiratt
webpiratt merged commit 40433dc into main Jul 19, 2025
3 checks passed
@webpiratt
webpiratt deleted the payroll-2 branch July 19, 2025 20:02
This was referenced Jul 22, 2025
This was referenced Jul 30, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants