Skip to content

Stellar Key Custody & Transaction Signing Service with KMS Abstraction, Sequence Management & Fee-Bump Retries #40

Closed

Description

@meshackyaro

Description

This issue aims to address the implementation of Stellar Key Custody & Transaction Signing Service with KMS Abstraction, Sequence Management & Fee-Bump Retries.

The core objective is to: Build the signing layer the backend needs to submit Soroban transactions safely — pluggable key custody (env/local for dev, KMS/HSM for production), serialized sequence-number allocation with channel accounts, and fee-bump-based resubmission for transactions that stall in the mempool.

By completing this feature, we will ensure that the GuildWorkman protocol maintains its high standards for security, usability, and decentralized logic. This issue requires careful attention to the Backend architecture and adherence to the existing project conventions.

When picking up this issue, please ensure you document any new dependencies or architectural decisions made during development.

Component

Backend (Spring Boot / Java 17)

Difficulty

⚫ Very Hard

Current state

The backend has no Stellar/Soroban signing capability at all, and no key material handling worth the name — utils/JwtUtils.java signs with a literal HMAC256("secret"), which is a fair indication of the current bar. Every on-chain feature on the roadmap (escrow orchestration, settlement, loyalty minting) is blocked on a service that can hold a key, allocate a sequence number without racing itself, and get a transaction to final status.

Sequence-number handling is the sharp edge: a single source account serializes all submissions and one stuck transaction blocks the queue, while naive parallel submission produces tx_bad_seq storms. Channel accounts and a proper allocation strategy are the point of this issue, not an optional extra.

Tasks

  • Review the existing Spring Boot structure under backend-api/src/main/java
  • Implement the service and REST endpoints for: Stellar Key Custody & Transaction Signing Service with KMS Abstraction, Sequence Management & Fee-Bump Retries
  • Define a SigningProvider abstraction with at least a local/dev implementation and one externalized-KMS implementation, selected by profile — no secret key may ever be logged, serialized into a response, or committed
  • Implement sequence-number allocation that is safe under concurrent submission, using a channel-account pool with database-backed leasing
  • Implement submission with polling to final status, plus fee-bump resubmission for transactions that stall, with a bounded fee ceiling
  • Classify and handle Soroban/Horizon failure modes distinctly: tx_bad_seq, tx_insufficient_fee, tx_too_late, and simulation failures each need their own recovery path
  • Persist every submission attempt with its hash and terminal status so a restart can resume rather than double-submit
  • Add or adjust JPA entities, repositories, and schema migrations as needed
  • Write unit and integration tests (Spring Boot Test; MockWebServer for external RPC calls), including a concurrency test that proves N parallel submissions produce N distinct sequence numbers
  • Add caching for Maven dependencies in CI
  • Run ./mvnw verify and ./mvnw test to validate build and coverage

Acceptance Criteria

  • Feature accurately implements the objective: Build the signing layer the backend needs to submit Soroban transactions safely — pluggable key custody (env/local for dev, KMS/HSM for production), serialized sequence-number allocation with channel accounts, and fee-bump-based resubmission for transactions that stall in the mempool.
  • Secret key material never appears in logs, responses, exception messages, or the repository
  • Concurrent submissions never collide on a sequence number, demonstrated by a test
  • A stalled transaction is fee-bumped and reaches a terminal state rather than hanging forever
  • A restart mid-submission does not double-submit an already-broadcast transaction
  • Any PR that introduces failing tests or compilation errors is automatically blocked
  • Endpoints/services are covered by tests including failure and concurrency paths
  • Public API is documented (OpenAPI) and errors follow a consistent response contract
  • Code is properly reviewed and approved by codeowners

Estimated Time

4-6 days

Activity

  1. kris-nana commented on Aug 19, 2026

    @kris-nana
    Contributor

    Hi maintainer,

    I’d like to take on this issue. I’m particularly interested in it because it sits at the boundary between backend architecture, distributed concurrency, and secure transaction infrastructure. I’d approach the implementation with the goal of making the signing layer reliable enough to serve as the foundation for the protocol’s upcoming on-chain features, rather than treating it as simply an RPC wrapper.

    Proposed approach

    I’d start by reviewing the existing backend-api structure, persistence conventions, configuration, exception handling, and test setup before introducing new abstractions.

    The implementation would be organized around a few explicit responsibilities:

    • Signing abstraction: introduce a SigningProvider interface with a profile-selected local/dev implementation and an external KMS-backed implementation. Private keys would remain confined to the provider boundary and would never be logged, returned through APIs, persisted unnecessarily, or included in exception messages.
    • Sequence allocation: model channel accounts and sequence leases in the database, using transactional locking/atomic state transitions to ensure concurrent workers cannot obtain the same sequence. The allocator would be designed around short-lived leases so abandoned work can be recovered.
    • Submission state machine: persist transaction/submission attempts before and after broadcast, including transaction hash, channel account, allocated sequence, attempt number, and terminal status. This gives restart recovery a durable source of truth and prevents blindly rebroadcasting work that was already submitted.
    • Soroban submission lifecycle: separate simulation, signing, broadcast, polling, and recovery so each failure mode has an explicit path rather than a generic retry loop.
    • Fee-bump retries: when a transaction remains pending beyond the configured threshold, construct a fee-bumped replacement subject to a hard fee ceiling and persist each attempt independently.
    • Failure classification: handle tx_bad_seq, tx_insufficient_fee, tx_too_late, simulation failures, and other terminal errors distinctly, with recovery limited to cases where retrying is actually safe.
    • API contract: expose the necessary service endpoints with consistent error responses and OpenAPI documentation, while keeping signing/key-management internals out of the public API.

    Concurrency and recovery

    The sequence allocator is the part I would treat as the highest-risk area.

    I would add a concurrency-focused integration test that launches N parallel submissions against the same channel-account pool and verifies that all N allocations are distinct. I’d also test lease expiration/recovery and contention between workers, rather than relying only on a unit test around an increment operation.

    For restart safety, I’d make submission state durable enough to distinguish:

    1. allocation/signing in progress,
    2. signed and ready for broadcast,
    3. broadcast with a known hash,
    4. polling,
    5. fee-bump replacement,
    6. terminal success/failure.

    That allows recovery logic to inspect existing attempts before broadcasting again.

    Testing

    I’d cover the implementation with Spring Boot integration tests and MockWebServer-based RPC tests, including:

    • concurrent sequence allocation;
    • channel-account leasing and recovery;
    • successful simulation/signing/submission;
    • simulation failures;
    • tx_bad_seq;
    • tx_insufficient_fee;
    • tx_too_late;
    • stalled transactions followed by fee-bump submission;
    • fee ceiling enforcement;
    • restart/recovery without duplicate broadcast;
    • secret material redaction;
    • REST validation and consistent error responses.

    I’d also run both ./mvnw test and ./mvnw verify before considering the implementation complete, and ensure CI caches Maven dependencies and blocks merges on compilation/test failures.

    Security and architectural decisions

    I would document the KMS/provider boundary and explain why key material is intentionally never represented in persistence or API DTOs. The local provider would exist strictly for development/testing, while production configuration would select the externalized provider.

    I’d also document the sequence allocation model, lease semantics, retry/fee-bump policy, and any additional dependencies introduced. If the existing project conventions provide suitable patterns, I’d prefer extending them rather than introducing unnecessary infrastructure.

    The goal would be a small, explicit set of abstractions with strong invariants: keys stay outside application state, sequences are allocated exactly once, every broadcast is durable, retries are bounded, and every failure has a defined recovery path.

    I’m happy to break the work into reviewable commits—for example, persistence/schema + allocation, signing abstraction/providers, submission/retry state machine, API, and tests/CI—so the security- and concurrency-sensitive pieces can be reviewed independently.

    I’d also make sure the final PR includes the architectural/dependency documentation and leaves the project passing ./mvnw test and ./mvnw verify.

  2. Sparexonzy95 commented on Aug 19, 2026

    @Sparexonzy95

    I’m interested in taking this issue. I have experience with React and Stellar/Soroban integrations, and I’ve reviewed the requirements and existing transaction flow carefully. I’m confident I can implement the required signing, sequence management, retry, and testing logic and submit a clean PR within 2 days.

  3. Sparexonzy95 commented on Aug 19, 2026

    @Sparexonzy95

    I’m interested in taking this issue. I have experience working with Stellar/Soroban transaction flows and backend integrations, and I understand the key requirements around secure signing, concurrency-safe sequence management, persistent transaction recovery, and fee-bump retries. I’m confident I can implement this cleanly within the existing Spring Boot architecture, cover the critical failure and concurrency paths with tests, and submit a solid PR within 2-3 days.

  4. grantfox-oss commented on Aug 19, 2026

    @grantfox-oss

    🦊 GrantFox — @kris-nana has been assigned to this issue as part of the Third Campaign campaign!

    Next steps:

    1. Open a Pull Request referencing this issue (e.g., Closes #40)
    2. Your PR will be reviewed by the workman-labs maintainers

    Good luck! Track your progress on GrantFox.

  5. grantfox-oss commented on Aug 22, 2026

    @grantfox-oss

    🎉 This issue has been marked as completed on GrantFox as part of the Third Campaign campaign!

    @kris-nana's PR #48 was approved and merged by @meshackyaro.

    🏆 @kris-nana: You earned 35 FoxPoints for this contribution! Your current tier: Explorer (306 total points). Track your full progress on GrantFox.

    👏 Great work, @kris-nana! Keep contributing to workman-labs.

  6. added a commit that references this issue on Aug 22, 2026
    87726bc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26Third CampaignCampaign: Third CampaignbackendBackend API (Spring Boot) workdifficulty: very hard⚫ Very HardenhancementNew feature or requesthelp wantedExtra attention is neededpriority: high🔴 High priority — core / blocking

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions