Skip to content

Add ignore_missing_asset_packets to SubmitTx#952

Open
sekulicd wants to merge 5 commits intoarkade-os:masterfrom
sekulicd:2026-03-02-ignore-missing-asset-packets
Open

Add ignore_missing_asset_packets to SubmitTx#952
sekulicd wants to merge 5 commits intoarkade-os:masterfrom
sekulicd:2026-03-02-ignore-missing-asset-packets

Conversation

@sekulicd
Copy link
Collaborator

@sekulicd sekulicd commented Mar 3, 2026

This closes #942

@altafan @Kukks please review.

Summary by CodeRabbit

  • New Features

    • Added an optional flag on transaction submission to skip validation for missing asset packets (OP_RETURN) while retaining other asset checks.
  • Behavior Changes

    • With the flag enabled, submissions missing asset packets succeed; resulting outputs have no asset metadata.
  • Tests

    • Added unit and end-to-end tests covering flag-enabled and flag-disabled scenarios, including handling of malformed asset packets.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2026

Walkthrough

Adds an optional boolean flag to SubmitTx/SubmitOffchainTx that, when true, causes missing OP_RETURN asset packets to be silently ignored during asset validation; the flag is added to API specs, threaded through service and validator layers, and covered by unit and e2e tests.

Changes

Cohort / File(s) Summary
API Specs
api-spec/openapi/swagger/ark/v1/service.openapi.json, api-spec/protobuf/ark/v1/service.proto
Added ignoreMissingAssetPackets / ignore_missing_asset_packets boolean field to SubmitTxRequest/SubmitTx request definition.
Asset validation
internal/core/application/asset_validation.go, internal/core/application/asset_validation_test.go
Extended validateAssetTransaction signature to accept the flag; when true, suppresses ASSET_VALIDATION_FAILED errors containing "asset packet not found"; added unit tests covering flag=true/false and malformed-packet behavior.
Service surface
internal/core/application/types.go, internal/core/application/service.go
Updated SubmitOffchainTx signature to include the flag and threaded it through validation calls; RegisterIntent validation explicitly passes false.
Handler & tests
internal/interface/grpc/handlers/arkservice.go, internal/test/e2e/e2e_test.go
gRPC handler forwards IgnoreMissingAssetPackets to service; added e2e test exercising SubmitTx with flag=false (expect failure) and flag=true (expect success).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Handler as gRPC Handler
    participant Service as Application Service
    participant Validator as Asset Validator

    Client->>Handler: SubmitTx(tx, ignoreMissingAssetPackets)
    Handler->>Service: SubmitOffchainTx(checkpoints, signedArkTx, ignoreMissingAssetPackets)
    Service->>Validator: validateAssetTransaction(tx, ext, inputAssets, ignoreMissingAssetPackets)

    alt Asset packet present
        Validator->>Validator: validate asset metadata
        Validator-->>Service: success
    else Asset packet missing & ignoreMissingAssetPackets=true
        Validator->>Validator: detect "asset packet not found" -> suppress
        Validator-->>Service: success (suppressed)
    else Asset packet missing & ignoreMissingAssetPackets=false
        Validator-->>Service: ASSET_VALIDATION_FAILED
    else Other validation error
        Validator-->>Service: ASSET_VALIDATION_FAILED
    end

    Service-->>Handler: AcceptedOffchainTx or error
    Handler-->>Client: SubmitTxResponse
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested reviewers

  • altafan
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add ignore_missing_asset_packets to SubmitTx' directly and clearly summarizes the main change: adding a new field to the SubmitTx functionality.
Linked Issues check ✅ Passed The PR addresses all four main objectives from issue #942: adds the field to proto [OpenAPI and Protobuf files], wires validation logic [asset_validation.go and service.go], includes tests [asset_validation_test.go and e2e_test.go], and updates documentation.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the ignore_missing_asset_packets feature across API specs, validation logic, and tests; no unrelated refactoring or scope creep detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 (1)
internal/core/application/asset_validation.go (1)

30-35: Avoid coupling suppression to raw error text.

This branch currently relies on strings.Contains(err.Error(), "asset packet not found"), which is fragile to upstream message changes and can accidentally broaden/narrow suppression behavior. Prefer a structured discriminator (typed error, metadata key, or dedicated predicate from the asset validation layer).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/core/application/asset_validation.go` around lines 30 - 35, The
suppression branch currently matches on raw error text; replace that fragile
check with a structured predicate or typed error from the asset validation layer
(e.g. add and use an exported function like
assetvalidation.IsAssetPacketNotFound(err) or an exported sentinel/type such as
assetvalidation.ErrAssetPacketNotFound). Update the condition in the
ignoreMissingAssetPackets block to call that predicate (instead of
strings.Contains(err.Error(), "...")) while keeping the other checks
(err.CodeName() == "ASSET_VALIDATION_FAILED"); ensure the asset validation
package exports the predicate/type and import it where needed so the suppression
relies on a stable API rather than raw message text.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/core/application/asset_validation_test.go`:
- Line 93: The test currently ignores the error from hex.DecodeString when
creating malformedScript; change the call to capture and assert the error is nil
(e.g., check err and fail the test with t.Fatalf/t.Fatal or use require.NoError)
so a bad fixture hex string fails the test with a clear message; update the
hex.DecodeString invocation that assigns malformedScript to also capture err and
assert success before using malformedScript.

In `@internal/core/application/asset_validation.go`:
- Around line 40-42: Update the misleading comment for getAssetsFromTx: remove
the reference to an “early return above” and instead state succinctly that
getAssetsFromTx may return nil when no asset packet is present (for example,
when ignoreMissingAssetPackets is set), and that the subsequent loop that
consumes the result handles a nil map gracefully by not iterating. Refer to
getAssetsFromTx and the consumer loop so future readers understand the
nil-return behavior without implying unreachable control flow.

In `@internal/test/e2e/e2e_test.go`:
- Around line 5124-5126: The helper setupArkSDKwithPublicKey creates an SDK
client instance (returned as alice) but only the transport is closed; add an
explicit cleanup calling alice.Stop() (e.g., in the same t.Cleanup block where
grpcTransport.Close() is called) to ensure the SDK client is torn down between
subtests; update the test where alice, aliceWallet, _, grpcTransport :=
setupArkSDKwithPublicKey(t) is used to call t.Cleanup(func() { alice.Stop();
grpcTransport.Close() }) so alice.Stop() runs after the test.

---

Nitpick comments:
In `@internal/core/application/asset_validation.go`:
- Around line 30-35: The suppression branch currently matches on raw error text;
replace that fragile check with a structured predicate or typed error from the
asset validation layer (e.g. add and use an exported function like
assetvalidation.IsAssetPacketNotFound(err) or an exported sentinel/type such as
assetvalidation.ErrAssetPacketNotFound). Update the condition in the
ignoreMissingAssetPackets block to call that predicate (instead of
strings.Contains(err.Error(), "...")) while keeping the other checks
(err.CodeName() == "ASSET_VALIDATION_FAILED"); ensure the asset validation
package exports the predicate/type and import it where needed so the suppression
relies on a stable API rather than raw message text.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8615412 and 9bd8beb.

⛔ Files ignored due to path filters (2)
  • api-spec/protobuf/gen/ark/v1/indexer.pb.rgw.go is excluded by !**/gen/**
  • api-spec/protobuf/gen/ark/v1/service.pb.go is excluded by !**/*.pb.go, !**/gen/**
📒 Files selected for processing (8)
  • api-spec/openapi/swagger/ark/v1/service.openapi.json
  • api-spec/protobuf/ark/v1/service.proto
  • internal/core/application/asset_validation.go
  • internal/core/application/asset_validation_test.go
  • internal/core/application/service.go
  • internal/core/application/types.go
  • internal/interface/grpc/handlers/arkservice.go
  • internal/test/e2e/e2e_test.go

// pkg/ark-lib/asset/testdata/packet_fixtures.json.
// Decodes to: OP_RETURN <ARK 0x00 <1 group with out-of-bounds control
// asset group index>>.
malformedScript, _ := hex.DecodeString("6a0f41524b000102020100000101e80301")
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Don’t ignore fixture decode errors in tests.

If this hex string is accidentally edited into invalid data, the test may fail for the wrong reason. Assert decode success explicitly.

Suggested test hardening
-	malformedScript, _ := hex.DecodeString("6a0f41524b000102020100000101e80301")
+	malformedScript, err := hex.DecodeString("6a0f41524b000102020100000101e80301")
+	require.NoError(t, err)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
malformedScript, _ := hex.DecodeString("6a0f41524b000102020100000101e80301")
malformedScript, err := hex.DecodeString("6a0f41524b000102020100000101e80301")
require.NoError(t, err)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/core/application/asset_validation_test.go` at line 93, The test
currently ignores the error from hex.DecodeString when creating malformedScript;
change the call to capture and assert the error is nil (e.g., check err and fail
the test with t.Fatalf/t.Fatal or use require.NoError) so a bad fixture hex
string fails the test with a clear message; update the hex.DecodeString
invocation that assigns malformedScript to also capture err and assert success
before using malformedScript.

Comment on lines +5124 to +5126
alice, aliceWallet, _, grpcTransport := setupArkSDKwithPublicKey(t)
t.Cleanup(func() { grpcTransport.Close() })

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add explicit SDK client teardown in the helper.

Line 5124 creates an SDK client, but only the transport is closed. Add alice.Stop() cleanup to prevent resource leakage between subtests.

💡 Proposed fix
-		alice, aliceWallet, _, grpcTransport := setupArkSDKwithPublicKey(t)
-		t.Cleanup(func() { grpcTransport.Close() })
+		alice, aliceWallet, _, grpcTransport := setupArkSDKwithPublicKey(t)
+		t.Cleanup(func() { alice.Stop() })
+		t.Cleanup(func() { grpcTransport.Close() })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
alice, aliceWallet, _, grpcTransport := setupArkSDKwithPublicKey(t)
t.Cleanup(func() { grpcTransport.Close() })
alice, aliceWallet, _, grpcTransport := setupArkSDKwithPublicKey(t)
t.Cleanup(func() { alice.Stop() })
t.Cleanup(func() { grpcTransport.Close() })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/test/e2e/e2e_test.go` around lines 5124 - 5126, The helper
setupArkSDKwithPublicKey creates an SDK client instance (returned as alice) but
only the transport is closed; add an explicit cleanup calling alice.Stop()
(e.g., in the same t.Cleanup block where grpcTransport.Close() is called) to
ensure the SDK client is torn down between subtests; update the test where
alice, aliceWallet, _, grpcTransport := setupArkSDKwithPublicKey(t) is used to
call t.Cleanup(func() { alice.Stop(); grpcTransport.Close() }) so alice.Stop()
runs after the test.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/core/application/service.go`:
- Line 1965: The call to s.validateAssetTransaction is written as a long
one-liner and fails the golines formatter; reformat the call to wrap arguments
over multiple lines for readability and linelength compliance by placing the
arguments (ctx, proof.UnsignedTx, ext, assetInputs, false) each on their own
line (or break across two lines) and put the closing parenthesis on its own line
so the call to s.validateAssetTransaction(ctx, proof.UnsignedTx, ext,
assetInputs, false) retains the same behavior but satisfies formatting checks.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9bd8beb and 6b6ef5c.

📒 Files selected for processing (2)
  • internal/core/application/asset_validation.go
  • internal/core/application/service.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/core/application/asset_validation.go


// validate assets
if err := s.validateAssetTransaction(ctx, proof.UnsignedTx, ext, assetInputs); err != nil {
if err := s.validateAssetTransaction(ctx, proof.UnsignedTx, ext, assetInputs, false); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Line 1965: Reformat this call to fix the current golines CI failure.

Functionally this is correct (false keeps intent registration strict), but the one-liner is failing formatting checks.

Proposed formatting fix
-	if err := s.validateAssetTransaction(ctx, proof.UnsignedTx, ext, assetInputs, false); err != nil {
+	if err := s.validateAssetTransaction(
+		ctx, proof.UnsignedTx, ext, assetInputs, false,
+	); err != nil {
 		return "", err
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if err := s.validateAssetTransaction(ctx, proof.UnsignedTx, ext, assetInputs, false); err != nil {
if err := s.validateAssetTransaction(
ctx, proof.UnsignedTx, ext, assetInputs, false,
); err != nil {
return "", err
}
🧰 Tools
🪛 GitHub Actions: ci_unit

[error] 1965-1965: File is not properly formatted (golines)

🪛 GitHub Check: unit tests

[failure] 1965-1965:
File is not properly formatted (golines)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/core/application/service.go` at line 1965, The call to
s.validateAssetTransaction is written as a long one-liner and fails the golines
formatter; reformat the call to wrap arguments over multiple lines for
readability and linelength compliance by placing the arguments (ctx,
proof.UnsignedTx, ext, assetInputs, false) each on their own line (or break
across two lines) and put the closing parenthesis on its own line so the call to
s.validateAssetTransaction(ctx, proof.UnsignedTx, ext, assetInputs, false)
retains the same behavior but satisfies formatting checks.

sekulicd and others added 3 commits March 3, 2026 19:10
After merging master, validateAssetTransaction gained an
extension.Extension parameter (from PR arkade-os#946). Update all 3 test
calls to pass extension.Extension{} and redesign the
"other asset error" test to work with the extension-based
architecture instead of the old OP_RETURN parsing approach.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
internal/core/application/asset_validation_test.go (1)

76-111: Consider deduplicating the repeated dummy P2TR script fixture.

The same long byte slice appears twice; extracting it into a small helper/const would reduce noise and avoid accidental drift between fixtures.

Also applies to: 151-157

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/core/application/asset_validation_test.go` around lines 76 - 111,
Extract the repeated long PkScript byte slice into a single shared constant or
small helper so both fixtures reuse it (e.g., define dummyP2TRScript =
[]byte{...} or func makeDummyP2TR() []byte) and replace the two inline
occurrences in the tests with that symbol; update references where the same
slice appears (the PkScript fields around the shown block and the other
occurrence at lines ~151-157) to use the new constant/helper to avoid
duplication and drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/core/application/asset_validation_test.go`:
- Around line 116-120: The test helper txWithInvalidAssetPacket and its comment
indicate the case should trigger ASSET_OUTPUT_INVALID when the extension
references a non-existent vout, but the assertions currently check for an
input-asset mismatch message; update the test to assert the ASSET_OUTPUT_INVALID
condition instead: locate the test that calls validateAssetTransaction (and uses
ignoreMissingAssetPackets) and change the expectation to look for the
ASSET_OUTPUT_INVALID error (or the specific ErrAssetOutputInvalid sentinel/type
or its canonical message) rather than "not present in the packet", or
alternatively adjust the helper/comment if you intended to test the
input-asset-mismatch branch; ensure the assertion references
txWithInvalidAssetPacket and validateAssetTransaction so the fixture, comment,
and assertion are consistent.

---

Nitpick comments:
In `@internal/core/application/asset_validation_test.go`:
- Around line 76-111: Extract the repeated long PkScript byte slice into a
single shared constant or small helper so both fixtures reuse it (e.g., define
dummyP2TRScript = []byte{...} or func makeDummyP2TR() []byte) and replace the
two inline occurrences in the tests with that symbol; update references where
the same slice appears (the PkScript fields around the shown block and the other
occurrence at lines ~151-157) to use the new constant/helper to avoid
duplication and drift.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4f179dff-eb99-45f9-a9df-537e96f198f0

📥 Commits

Reviewing files that changed from the base of the PR and between 83af7d3 and 6cda500.

📒 Files selected for processing (1)
  • internal/core/application/asset_validation_test.go

Comment on lines +116 to +120
// txWithInvalidAssetPacket builds a wire.MsgTx together with an
// extension.Extension whose asset packet references an output index (vout=99)
// that does not exist in the transaction. This triggers an
// ASSET_OUTPUT_INVALID error during validateAssetTransaction, which must NOT
// be suppressed by the ignoreMissingAssetPackets flag.
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Test intent and assertions are currently misaligned.

The helper comment says this path should trigger ASSET_OUTPUT_INVALID, but the assertion checks for "not present in the packet" (input-asset mismatch). Please align either the fixture intent/comments or the assertions so the test states exactly what branch it validates.

Suggested alignment (comment + stronger assertion)
-// extension.Extension whose asset packet references an output index (vout=99)
-// that does not exist in the transaction. This triggers an
-// ASSET_OUTPUT_INVALID error during validateAssetTransaction, which must NOT
-// be suppressed by the ignoreMissingAssetPackets flag.
+// extension.Extension carrying a syntactically valid packet used to trigger a
+// non-"asset packet not found" validation error, which must NOT be suppressed
+// by the ignoreMissingAssetPackets flag.
@@
 	require.NotContains(t, err.Error(), "asset packet not found",
 		"error should be a different asset validation error, not 'not found'")
+	require.Equal(t, "ASSET_INPUT_INVALID", err.CodeName(),
+		"error should come from non-missing-packet validation path")
 	require.Contains(t, err.Error(), "not present in the packet",
 		"error should indicate asset input mismatch with the packet")

Also applies to: 209-215

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/core/application/asset_validation_test.go` around lines 116 - 120,
The test helper txWithInvalidAssetPacket and its comment indicate the case
should trigger ASSET_OUTPUT_INVALID when the extension references a non-existent
vout, but the assertions currently check for an input-asset mismatch message;
update the test to assert the ASSET_OUTPUT_INVALID condition instead: locate the
test that calls validateAssetTransaction (and uses ignoreMissingAssetPackets)
and change the expectation to look for the ASSET_OUTPUT_INVALID error (or the
specific ErrAssetOutputInvalid sentinel/type or its canonical message) rather
than "not present in the packet", or alternatively adjust the helper/comment if
you intended to test the input-asset-mismatch branch; ensure the assertion
references txWithInvalidAssetPacket and validateAssetTransaction so the fixture,
comment, and assertion are consistent.

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.

Add ignore_missing_asset_packets field to SubmitTx

1 participant