Skip to content

Expose pkg/emulator signing library with injectable finalizer#102

Open
Kukks wants to merge 7 commits into
masterfrom
arkade-library-export
Open

Expose pkg/emulator signing library with injectable finalizer#102
Kukks wants to merge 7 commits into
masterfrom
arkade-library-export

Conversation

@Kukks

@Kukks Kukks commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Turns the emulator's signing service into a reusable Go library so other services (e.g. arkd-signer) can perform signing-only ArkadeScript signing by importing it, instead of running a separate emulator process. The standalone emulator keeps working unchanged.

Changes

  • Promote internal/applicationpkg/emulator (new module, package emulator). Pure mechanical move — exports Service, New, and the request/response types.

  • Injectable finalization. New Finalizer interface (the arkd round-trip subset used by SubmitTx):

    • SubmitTx(ctx, arkTx string, checkpoints []string) (txid, finalArkTx string, arkdCheckpoints []string, error)
    • FinalizeTx(ctx, txid string, checkpoints []string) error

    New now takes arkdPubKey *btcec.PublicKey and finalizer Finalizer (instead of arkdURL). SubmitTx finalizes only when finalizer != nil; with nil it returns the signed ark tx + checkpoints (signing-only). The go-sdk client structurally satisfies Finalizer, so the standalone passes it directly.

  • Public gRPC handler pkg/emulator/grpchandler (the EmulatorService impl), so consumers can register it on their own server. Health handler/interceptors stay internal.

  • Standalone rewired: internal/config builds the go-sdk client, fetches arkdPubKey via GetInfo at startup, and passes the client as the finalizer. Behavior unchanged.

Compatibility

  • No emulatorv1 wire-protocol changes.
  • Standalone emulator behaves exactly as before (finalizer wired).

Testing

  • pkg/emulator unit tests pass (incl. a new nil-finalizer signing-only test).
  • Standalone root module builds.
  • Integration suite unchanged (requires Nigiri).

Kukks added 7 commits June 19, 2026 22:36
The Docker build COPYs each module's go.mod/go.sum for layer caching and
runs go mod download per module; pkg/emulator was missing, failing the root
go mod download (Build and Scan + integration). The Makefile unit target
lists each separate module explicitly; pkg/emulator (a new module) was not
included, so its tests never ran.

@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.

🔍 Arkana Code Review — arkade-os/emulator#102

Scope: Promotes internal/applicationpkg/emulator, introduces injectable Finalizer interface, exposes public gRPC handler. Protocol-critical: touches signing paths and finalization logic.


✅ What looks good

  1. Finalizer interface (pkg/emulator/service.go:18-21): Minimal, clean, 2-method interface. Structurally satisfied by go-sdk's grpc client — zero coupling. Good API design.

  2. Signing-only path (pkg/emulator/tx.go:120): !isFinalizer || s.finalizer == nil is correct. When finalizer is nil, the service returns the signed ark tx + checkpoints without attempting arkd round-trip. The guard is correctly placed after all signing and checkpoint signature verification.

  3. Close() nil-safety (pkg/emulator/service.go:104-108): Type-asserting a nil interface value returns (nil, false) in Go — this is safe. No panic risk when finalizer is nil.

  4. Config refactor (internal/config/config.go:183-204): The arkd pubkey fetch + parse logic moved cleanly from New() to AppService(). Same validation, same error handling. The standalone emulator behavior is preserved.

  5. No wire-protocol changes: emulatorv1 proto is untouched. Existing clients are unaffected.

  6. Test coverage: TestSubmitTxSigningOnly properly exercises the nil-finalizer signing-only path with a fully-formed VTXO spend — verifies the emulator signs both ark tx and checkpoint without attempting finalization.

  7. New() constructor (pkg/emulator/service.go:73): Correctly validates arkdPubKey != nil (required for finalizer role determination even in signing-only mode, since finalizerAccumulator needs it). finalizer is allowed to be nil — intentional.

  8. No cross-repo breakage: No external consumers of internal/application or pkg/emulator exist yet. No downstream SDKs affected.


⚠️ Issues

1. Dead code: internal/interface/grpc/handlers/emulator_handler.go should be removed

Severity: Medium (maintenance hazard)

internal/interface/grpc/service.go:143 now uses grpchandler.New() from pkg/emulator/grpchandler, not handlers.New() from the internal package. The internal emulator_handler.go is ~300 lines of dead code that duplicates the public handler line-for-line. Only NewHealthHandler() from health_handler.go is still used from the handlers package.

Keeping both will cause silent drift — someone fixes a bug in one handler, the other stays broken. Recommend deleting internal/interface/grpc/handlers/emulator_handler.go in this PR.

Files: internal/interface/grpc/handlers/emulator_handler.go (entire file), internal/interface/grpc/service.go:14 (unused import of handlers for emulator funcs)


📝 Minor / Non-blocking

  1. pkg/emulator/service.go:73 — unused ctx parameter: New takes _ context.Context but never uses it (the arkd GetInfo call moved to config). Consider removing it to signal that construction is synchronous, or keep it if you anticipate future use. Non-blocking.

  2. pkg/emulator/grpchandler/handler.go:500New return type: Returns emulatorv1.EmulatorServiceServer (interface) vs the internal handler returning *handler (concrete). The public version is better — just noting the inconsistency with the dead internal handler reinforces point ⚠️1 above.


🔐 Protocol-Critical Flag

This PR modifies signing paths (SubmitTx, SubmitFinalization), key handling, and finalization logic. While the changes are mechanically sound and the behavioral modification (signing-only mode) is well-guarded, this requires human review before merge per protocol-critical policy.

Specific areas for human verification:

  • pkg/emulator/tx.go:120 — the || s.finalizer == nil guard: confirm that signing-only consumers (e.g., arkd-signer) will never need to trigger finalization through this path
  • pkg/emulator/finalization.go — unchanged but now public: confirm the forfeit signing and commitment signing logic is safe to expose as a library

Summary: Clean refactor, good interface design, solid test. One dead code issue to fix. Flagging for human review due to protocol-critical scope.

@Kukks Kukks requested a review from louisinger June 22, 2026 20:17
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.

1 participant