An interactive explainer

v0.0.2, August 2026

The Anatomy of SATP

My experience has told me that explaining SATP in technical terms is very challenging. Hopefully, this interactive walkthrough will make it easier to understand the protocol and its implementation in Hyperledger Cacti.

Two blockchains do not talk by default. They share no canonical state, validators, blocks, clocks or notion of shared finality. Yet modern business requires assets to move across network boundaries. The Secure Asset Transfer Protocol (SATP) addresses this challenge by moving the problem off the ledgers and into a peer-to-peer protocol.[4] Each network boundary is gated by a gateway: software that acts as the agent for that network. User applications talk to their own gateway, gateways talk to each other, and mediate the cross-boundary transfer. The properties and assumptions of this protocol are described in the SATP papers[2] and core draft. [4]

This page follows Cacti's current v03 message schemas and protocol map. Stages 1–3 correspond to the SATP Core draft; Stage 0 is implemented in Cacti and specified separately, so expect changes to happen.

SATP Core draft v03 and SATP Core draft v15 (latest). SATP Core GitHub repo.

Chapter 1

Why secure interoperability is hard

And what can SATP help solve

Consider an asset on a source ledger. Inside one ledger, moving such asset is simple: a blockchain transaction is incorporated by a consensus protocol, which decides the order and validity of transactions. Across two ledgers there is no shared view. Each chain will happily accept a write without knowing anything about the other, which is how the same representation of value can end up existing twice (double spend), or vanishing entirely (lost in the transfer).[1][3]

SATP does not try to make two chains agree. It defines a protocol between two gateways, each of which is the only authorised agent for its own network, and it fixes the order of that conversation to constrain every intermediate state. The source value is locked before its destination representation is minted; only then is the source copy burned. Each party signs what it saw, and each signed message commits to the previous one, so nobody can later claim a different agreement was made.[4]. The general flow idea is the following:

  1. a user U asks via its application for an asset transfer
  2. a client application CI asks for a transfer
  3. its gateway takes the client role G1
  4. G1 establishes a connection with the server gateway G2
  5. the two gateways negotiate and agree on the transfer terms (stage 0)
  6. the gateways execute SATP:
    • stage 1: a specific transfer request is created and signed by the client, and agreed by the server
    • stage 2: the asset is locked on the source ledger
    • stage 3: the asset is minted on the target ledger, and burned on the source ledger
  7. the transfer is finalised

If a gateway crashes mid-transfer, the session is not lost: the protocol's recorded state is what recovery works from, which is the subject of a separate draft.[6].

Hyperledger Cacti implements SATP in Typescript and Rust. I will talk about the Typescript implementation as I'm more familiarized with it than the Rust one. The implementation I will discuss is cactus-plugin-satp-hermes.

The diagram below represents a transfer request from the client application through the business logic orchestrator (API1) and Cacti API server into the SATP gateway. Each gateway contains multiple components, including storage, the protocol core, ledger connectors, proof generation, adapter hooks and primitives to communicate with the counterparty gateway. Each gateway sends and receives a sequence of messages that, together, are the SATP protocol.

This browser cannot display the architecture diagram. Open the SATP architecture PDF.

SATP architecture. PDF

Chapter 2

How two gateways agree on the terms of a transfer

The basics of gateway to gateway communication.

Before Stage 1, Cacti's Stage 0 discovers the peer gateway and opens the session. Stage 1 then establishes the transfer terms: asset, amount, networks, owners and protocol parameters. It uses four messages: a proposal, a receipt, a commence request and an acknowledgement. After them, both gateways hold signed evidence of exactly the same terms, and only then may an asset be locked.

Down below we are able to inspect the messages more closely. In particular, SATP defines a common message body, a common way to represent session state (session data), and a way to show errors.

The schema overview needs JavaScript. SATP defines a common message envelope, shared error codes and a persistent gateway session record.

Pick a message and open its fields. Every field carries a plain-language note saying what it is and why it exists; the highlighted rows are the hash and signature fields that chain the messages together. Switch to the raw view to see the same object as it appears on the wire, in the shape the Cacti v02 proto defines.

Chapter 3 places these four messages inside the complete 36-step flow, including Stage 0 setup, Stage 2 locking and Stage 3 commitment.

The message explorer needs JavaScript. The message shapes are defined in proto/cacti/satp/v02/service/stage_1.proto in the Cacti repository.

Chapter 3

The shape of SATP

We use an interactive diagram with four parties - two gateways and two networks - to illustrate the asset movement flow.

The end to end asset movement starts before SATP does. Alice, a human operator, requests her application (originator operating on network 1) to move the asset to a destinatary (network 2); the application then activates a transfer in its own gateway. Those two hand-offs are the dashed arrows on the left of the diagram: they are ordinary API calls, not protocol messages, and everything after them is SATP.

Scroll the steps below and watch three things: which lane the message is on, which gateway is checking rather than sending, and what the two ledger bands at the bottom say. Stage 0 covers discovery and session setup and is being specified in the IETF draft and so, it is very likely to change in the close future draft-avrilionis-satp-setup-stage; Stages 1–3 come from SATP Core.[4]

The invariant to watch for is in the last stage: the asset is minted on the destination while it is still locked at the source, and only then is the source copy burned and the destination copy assigned to Bob. The two representations may briefly coexist, but never as independently spendable value.

The animated flow needs JavaScript. The step table below lists the same steps in the same order.

SATP protocol step table

The SATP protocol steps as a reference table. Hover a step name or a wire message to read what it does.

The step table needs JavaScript. Without it, read core/satp-protocol-map.ts in the Cacti repository directly.

Chapter 4

API1: turning user intent into SATP flows

How does the application connect with SATP via the API1, and how one local transfer request becomes session state, setup messages and a signed proposal between gateways.

Everything in the previous chapters happens between gateways. Before that conversation can start, Alice's application must describe the outcome it wants: which asset leaves which network, who owns it now, where it should arrive and who will own it there. API1 is that local boundary.

API1 does not ask the application to construct protocol messages. The gateway validates the business request, creates private session state, chooses the destination gateway and then expresses the intent as a SATP protocol instance.

Below, we show the API1 specification:

BLO / API Type 1 · v0.0.2

The complete client-facing surface

API1 covers more than starting a transfer. It exposes discovery, session control, gateway setup, oracle tasks and external approvals.

OpenAPI source

Live rendering of the bundled Cacti API1 OpenAPI document.Open the full reference.

Application walkthrough

Follow one POST /transact request

Now zoom in on the operation that turns application intent into a SATP session.

Illustrative: sample values below match the Cacti API shapes; they were not produced by a running gateway.

  1. POST …/transact receives contextID, sourceAsset and receiverAsset.
  2. executeTransact() validates required fields and expands them into private SessionData.
  3. SATPManager.transfer() selects the destination channel and sends Stage 0 NewSessionRequest.
  4. After Stage 0, TransferProposalRequest carries the signed Stage 1 agreement proposal.

The response contains a generated sessionID and its current statusResponse. In the linked implementation, the endpoint awaits manager.transfer(session) before returning.

Chapter 5

Using SATP in the enterprise setting with Adapters

How external applications inspect, approve or reject work at exact points inside SATP execution.

Adapters enable real world applications to leverage SATP: either by performing compliance/business logic checks, integrating SATP on business flows, or simply to increase auditability.

These adapters are not ledger connectors. They are adapter-layer hooks bound to a stage, protocol step and execution point. Here, one hook client is connected to each gateway while an INIT_PROPOSAL crosses between them.

Gateway 1 uses outbound webhooks: HTTP success lets SATP continue; HTTP failure aborts the operation. Gateway 2 combines an outbound notification with an inbound decision: its hook client posts continue: true or continue: false while proposal validation is paused.

Illustrative adaptation: this applies the Cacti demo's Stage 0 adapter pattern to a Stage 1 transfer proposal.

GatewayOperationHookHuman action
Gateway 1transferProposalRequestbeforeReturn HTTP success or error
Gateway 1Create and send INIT_PROPOSALafterAcknowledge webhook
Gateway 2checkTransferProposalRequestMessagebeforeApprove or reject
Gateway 2Create INIT_RECEIPTtransferProposalResponse afterAcknowledge webhook

Current handler has no checkTransferProposalRequestMessage/after callback. Its post-processing hook is transferProposalResponse/after.

Chapter 6

Tying it all together: the CBDC demo

Planned end-to-end walkthrough: two CBDC applications, two gateways, two ledgers and one asset transfer.

This chapter is still being worked on. Until then, explore the CBDC demo in Cacti demos.

References

Further reading

The protocol drafts and the research this explainer draws on. Source code: github.com/hyperledger-cacti.

  1. Belchior, R.; Vasconcelos, A.; Guerreiro, S.; Correia, M. A Survey on Blockchain Interoperability: Past, Present, and Future Trends. ACM Computing Surveys 54(8):168, 2021. 10.1145/3471140
  2. Belchior, R.; Vasconcelos, A.; Correia, M.; Hardjono, T. HERMES: Fault-tolerant middleware for blockchain interoperability. Future Generation Computer Systems 129:236–251, 2022. 10.1016/j.future.2021.11.004
  3. Belchior, R.; Süßenguth, J.; Feng, Q.; Hardjono, T.; Vasconcelos, A.; Correia, M. A Brief History of Blockchain Interoperability. Communications of the ACM 67(10):62–69, 2024. 10.1145/3648607
  4. Hargreaves, M.; Hardjono, T.; Belchior, R.; Ramakrishna, V.; Chiriac, A. Secure Asset Transfer Protocol (SATP). IETF Internet-Draft draft-ietf-satp-core 16, 2023 (work in progress). datatracker.ietf.org/doc/draft-ietf-satp-core
  5. Ramakrishna, V.; Hardjono, T.; Liu, C. Secure Asset Transfer (SAT) Use Cases. IETF Internet Draft draft-ietf-satp-usecases, 2026 (work in progress). datatracker.ietf.org/doc/draft-ietf-satp-usecases
  6. Belchior, R.; Correia, M.; Hardjono, T. Secure Asset Transfer Protocol (SATP) Gateway Crash Recovery Mechanism. IETF Internet-Draft draft-belchior-satp-gateway-recovery, 2021 (work in progress). datatracker.ietf.org/doc/draft-belchior-satp-gateway-recovery
  7. Belchior, R. SATP Hermes in Hyperledger Cacti — project explanation (video). Hyperledger, talk recording. youtube.com/watch?v=pN1m0vgV7bY
  8. Hyperledger Cacti Contributors. Hyperledger Cacti workshop (video). Hyperledger, workshop recording. youtube.com/watch?v=Bcqd475U0WA