Skip to content

feat: accept all intent message types in SubmitIntent#101

Open
Dunsin-cyber wants to merge 4 commits into
arkade-os:masterfrom
Dunsin-cyber:feat/submit-intent-all-message-types
Open

feat: accept all intent message types in SubmitIntent#101
Dunsin-cyber wants to merge 4 commits into
arkade-os:masterfrom
Dunsin-cyber:feat/submit-intent-all-message-types

Conversation

@Dunsin-cyber

Copy link
Copy Markdown

fixes #34

SubmitIntent only decoded the register intent message, so contract vtxos could register but never authenticate any other intent based arkd operation. this generalizes the path to accept all six arkd intent message types, keeping the existing register flow identical and wire compatible while adding tests for decoding and validation.

@arkanaai arkanaai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review — feat: accept all intent message types in SubmitIntent

Verdict: APPROVE

Clean, well-structured PR. The change generalizes SubmitIntent from RegisterMessage-only to all six arkd intent message types. This is a necessary evolution — contract VTXOs need to authenticate delete, get-pending-tx, estimate-fee, get-intent, and get-data operations, not just registration.

What I verified

1. Type safety & interface correctness

  • Confirmed all six arkd types (RegisterMessage, EstimateIntentFeeMessage, DeleteMessage, GetPendingTxMessage, GetIntentMessage, GetDataMessage) implement Encode() (string, error) and Decode(string) error in the upstream arkd/pkg/ark-lib/intent package. The IntentMessage interface (service.go:28-31) is correctly satisfied by all six.

2. Wire compatibility preserved

  • The proto (service.proto) changes are comment-only — no wire format change. The Intent message still carries proof and message as strings. Existing clients sending register messages continue to work identically.
  • The public client package (pkg/client/transport_client.go) uses raw string fields — completely unaffected.

3. Validation logic is correct

  • validateMessage() (intent.go:80-99) correctly handles the asymmetry: RegisterMessage and EstimateIntentFeeMessage carry both ValidAt+ExpireAt; the other four only carry ExpireAt. The type switch extracts the right fields for each.
  • The default branch properly rejects unknown types.
  • Zero-value timestamps are treated as "no bound" — consistent with the original behavior.

4. Parser logic is sound

  • parseIntent() (parser.go:17-66) does a two-phase decode: peek at BaseMessage.Type via json.Unmarshal, then dispatch to the concrete struct's Decode(). This is the standard pattern in arkd and avoids any type confusion.
  • Error messages include the message type for debuggability (fmt.Errorf("invalid %s message: %w", base.Type, err)).

5. No cross-repo breakage

  • SubmitFinalization (finalization.go) only uses Intent.Proof.Packet — never touches Intent.Message at all. The type change from intent.RegisterMessage to IntentMessage is invisible to finalization.
  • Integration tests (test/*.go) use the client package (pkg/client) which operates on raw strings — they compile and behave identically.
  • TypeScript SDK already supports DeleteMessage and GetPendingTxMessage — this aligns the emulator with what the SDK already sends.

6. Test coverage is adequate

  • intent_test.go: covers all six types valid, zero timestamps, expired, not-valid-yet, and unsupported type. Good.
  • parser_test.go: covers all six types, missing proof, missing message, invalid proof, unsupported type. Good.
  • The unknownMessage test stub in intent_test.go:58-61 correctly exercises the default branch.

Minor observations (non-blocking)

  1. parser.go:37json.Unmarshal([]byte(message), &base): The message string is already JSON (produced by Encode()), so the cast to []byte is fine, but worth noting this assumes Encode() always returns valid JSON. This is guaranteed by the arkd implementation but isn't validated here. Not a real risk — just a trust boundary note.

  2. Time-of-check / time-of-use on expiry: validateMessage() checks ExpireAt at parse time, but the intent proof may be used slightly later. The original code had the same gap. Not introduced by this PR.

No protocol-critical concerns. The VTXO signing path (SubmitIntent body, lines 20-75) is completely unchanged — only the validation preamble was generalized. Forfeit and commitment signing in SubmitFinalization are untouched.

🤖 Reviewed by Arkana

@Dunsin-cyber Dunsin-cyber marked this pull request as ready for review June 17, 2026 13:21
@Dunsin-cyber

Copy link
Copy Markdown
Author
  • for the TOCTOU, arkd re-validates it before use on the server so it's not a problem

please review @louisinger

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SubmitIntent should support any type of message

1 participant