RLN-IP 0004
RLN-IP: 4
Title: RLN Protobuf Message Definitions
Author: Anthony Culligan <anthony.culligan@setl.io>
Comments-Summary: No comments yet.
Comments-URI: https://github.com/
Status: Active
Type: Process
Created: 2023-11-02
License: CC-BY-SA-4.0: [Creative Commons Attribution-ShareAlike]
Abstract
The following specifies the protobuf definitions for messages which form the set required to communication between RLN Domains to settle inter domain transactions
Messages
Envelope
A universal wrapper for the possible messages. Simplifies message decoding.
message Envelope {
string version = 1
[
(validate.rules).string.min_len = 1
];
optional EntityLocation recipient = 2;
oneof contents {
// Initial Transfer Request to the network
ProposeTransferSet propose_transfer_set = 10;
// Request to Participants for Settlement Steps
RequestSteps request_steps = 13;
// Response from Participant of Settlement Steps
PossibleSteps possible_steps = 14;
// Transfer request message after enrichment with full settlement path.
Manifest manifest = 16;
// Vote (Approval) message from Participant
Vote vote = 17;
// Finalised Transfer message to Participants
Finalised finalised = 18;
}
}
Initiating Proposal
Wrapper for a set of transfers to be processed atomically.
message ProposeTransferSet {
/**
* The correlation ID that uniquely identifies this group of transfers.
* The correlation ID is provided by the client and applies to all messages across a Transfer Set settlement.
*/
string correlation_id = 2
[
(validate.rules).string.min_len = 1
];
/**
* The ID of the proposing party.
*/
Participant proposer = 3
[
(validate.rules).message.required = true
];
/** The transfers that constitute this group. */
repeated ProposeTransfer transfers = 4
[
(validate.rules).repeated.min_items = 1
];
}
A transfer of a single asset type from one party to another. One, of potentially many, transfers in a transfer set.
message ProposeTransfer {
/**
* The type of this transfer. The type must be understood by all parties to
* the transfer. A party that does not recognise a proposal type is expected
* to vote to reject it.
*
* REQUIRED.
*/
string type = 1
[
(validate.rules).string.min_len = 1
];
/**
* The correlation ID that uniquely identifies this group of transfers.
* The correlation ID is provided by the client and applies to all messages across a Transfer Set settlement.
*/
string correlation_id = 2
[
(validate.rules).string.min_len = 1
];
/**
* The source of the transfer.
*/
Party from = 3;
/**
* The destination of the transfer.
*/
Party to = 4;
/**
* Details of this transaction. For example, the amount to be transferred,
* or a list of identifiers of non-fungible tokens.
*/
Payload payload = 5;
/** The message that led to this transfer. e.g. SWIFT Message or internal settlement instruction. */
SourceMessage source_message = 6;
/**
* The possible initial steps to route this proposed transfer.
*/
optional PossibleSteps possible_steps = 7;
/**
* ID to uniquely identify this Transfer within the TransferSet.
* Where there is only a single Transfer in the TransferSet, this ID may not be required.
*/
optional string transfer_id = 8;
}
Settlement Query
Request for possible settlement destinations for a given transfer.
message RequestSteps {
/**
* The correlation ID that uniquely identifies this specific transfer.
*/
string correlation_id = 1
[
(validate.rules).string.min_len = 1
];
/**
* A unique ID for this specific request. This is used to match the "Possible Steps"
* response to a specific Scheduler request.
*/
string request_id = 2
[
(validate.rules).string.min_len = 1
];
/**
* The type of the transfer, as specified in the Propose Transfer message.
*/
string type = 3
[
(validate.rules).string.min_len = 1
];
/**
* If true, the participant is being invited as an observer.
*/
bool is_observer = 4;
/**
* If true, the routing is being built in the reverse direction from the
* destination towards the source.
*/
bool is_reverse = 5;
/**
* The ID of the original source party.
*/
optional Participant from_participant = 6;
/**
* The ID of the original destination party.
*/
optional Participant to_participant = 7;
Payload proposed_payload = 8;
optional SourceMessage source_message = 9;
/**
* The path that leads to the participant that is being asked to provide
* the next link.
*
*/
repeated Link path_links = 10;
/**
* Observers to this path.
*/
repeated Participant observers = 11;
AccountAction account_action = 12;
}
Settlement Query Response
Response of settlement counterparties.
message PossibleSteps {
/** Possible reasons for giving this response to route a transfer. */
enum ResponseCode {
/** No code specified. This indicates the response is malformed. */
UNSPECIFIED = 0;
/** No error. Everything is OK. */
OK = 1;
/** The transfer type was not recognised. */
UNKNOWN_TYPE = 2;
/** The transfer requires a step context, but none was provided. */
MISSING_STEP_CONTEXT = 3;
/** The transfer required a transfer context, but none was provided. */
MISSING_TRANSFER_CONTEXT = 4;
/** The step context was mis-specified. */
BAD_STEP_CONTEXT = 5;
/** The transfer context was mis-specified. */
BAD_TRANSFER_CONTEXT = 6;
/**
* The request was understood but the participant cannot not route it.
*
* The ledger swarm will attempt to route by another path.
*/
CANNOT_ROUTE = 7;
/**
* The request was understood but the participant refuses to route it.
*
* The ledger swarm will attempt to route by another path.
*/
REFUSED = 8;
/**
* The request was understood but the participant either refuses to or
* cannot route it. Furthermore, the participant wants to add observers
* to the transfer, giving them the opportunity to vote to reject it.
*
* The response may specify steps provided they only list observers.
*
* The network will add the specified observers and attempt to route
* by another path.
*/
OBSERVE_ONLY = 9;
/**
* The participant cannot suggest further steps to the path, but is
* willing to act as a connecting point for the path as constructed so
* far.
*
* For example, a top-level entity might refuse to further expand a
* forward path as that would lead to specifying all entities in the
* domain. Instead the reverse path must be expanded until it arrives at
* the same top-level entity.
*
* Alternatively, a gateway into a private domain would not list the
* members of the private domain. If expanding the other end of the path
* leads to the same gateway it can route it, but it will not reveal the
* members of the private domain.
*/
CANNOT_SUGGEST = 10;
}
/**
* The correlation ID that uniquely identifies this specific transfer.
*/
string correlation_id = 1
[
(validate.rules).string.min_len = 1
];
/**
* A unique ID from the request to which this is a response. This is used to
* match this "Possible Steps" response to a specific Scheduler request.
*
* Note: this is a required field in response to a "Request Steps", but not
* required if part of a "Propose Transfer".
*/
string request_id = 2;
ResponseCode status = 3
[
(validate.rules).enum.defined_only = true
];
/**
Participant sending the response
*/
Participant participant = 4;
/**
* An optional message associated with this response.
*/
optional Message settlement_message = 5;
/**
* The steps that could be used to resolve a transfer. The most preferred
* step is the first one listed, with each subsequent step being less
* desirable than its predecessors.
*/
repeated ObservedLink steps = 6;
/**
* How many seconds can this response be re-used for? If this value is
* non-zero then the participant is happy for these possible steps to be
* re-used as a response for any identical "Request Steps" message.
*
* A non-zero value does not guarantee re-use. A zero value does guarantee
* that this response will not be re-used.
*/
uint32 valid_for_seconds = 7;
/**
* Observer participants.
*
* Observers will not be asked to vote on a transfer and will be informed as to
* whether it is accepted or rejected.
* <p>Observers on an ObservedLink would apply in addition to these observers.</p>
* <p>Observers on an ObservedLink will only apply if that link was on the final settlement path.</p>
*/
repeated Participant observers = 8;
}
Request for Authorisation
Details of a proposed set of transfers, with settlement details, requiring approval.
/**
* Manifest : Send a proposed (scheduled) Transferset to the Participants for approval.
*/
message Manifest {
/**
* The correlation ID that uniquely identifies this group of transfers.
* The correlation ID is provided by the client and applies to all messages across a Transfer Set settlement.
*/
string correlation_id = 1
[
(validate.rules).string.min_len = 1
];
/**
* A unique ID for this specific manifest.
* Used by the assembler to match Manifests to Votes.
*/
string request_id = 2;
/** The transfers that constitute this group. */
repeated Transfer transfers = 3
[
(validate.rules).repeated.min_items = 1
];
}
Authorisation
Approval, or rejection, of a set of Transfers.
/**
* A vote for or against a set of proposed transfers.
*/
message Vote {
/**`
* The correlation ID that uniquely identifies this group of transfers.
* The correlation ID is provided by the client and applies to all messages across a Transfer Set settlement.
*/
string correlation_id = 1
[
(validate.rules).string.min_len = 1
];
/**
* A unique ID for this Vote.
* Must be taken from the specific manifest received. Used by the assembler to match Votes to Manifests.
*/
string request_id = 2
[
(validate.rules).string.min_len = 1
];
/**
* The party that is approving or rejecting.
*/
Participant participant = 3;
/**
* If true, the transfer is approved.
*/
bool is_approved = 4;
/**
* An optional message associated with the vote. This may provide a reason
* for the rejection.
*/
optional Message message = 5;
/**
* The signature of the vote.
* The Swarm ID should be signed if approved.
* The enclosing message is signed, which should be sufficient for Rejection.
*/
optional Signature signature = 6;
/**
* The status of the vote.
* The Participant can indicate if this vote is a repeat, or if the transfer has already been finalised.
*/
Status status = 7;
}
Settlement Finality
Notification of commitment to a previously approved set of Transfers.
/**
* Announcement of the finalisation of a transfer after sufficient votes are
* gathered by the network.
*/
message Finalised {
enum Status {
APPROVED = 0;
REJECTED = 1;
}
/**
* The correlation ID that uniquely identifies this group of transfers.
* The correlation ID is provided by the client and applies to all messages across a Transfer Set settlement.
*/
string correlation_id = 1
[
(validate.rules).string.min_len = 1
];
string request_id = 2;
/** Was the transfer approved, rejected or something? */
Status status = 3;
int64 timestamp = 4;
/**
* A message which may provide some additional information about the final
* decision.
*/
optional Message message = 5;
/**
* The signatures of the participants who have approved the finalisation.
*/
repeated Signature signatures = 6;
}
Supporting message classes
Participant
message Participant {
/**
* The ID of the party, as it is known to the network.
*/
string id = 1
[
(validate.rules).string.min_len = 1
];
string domain = 2;
}
Party
message Party {
/**
* The ID of the party, as it is known to the network.
*
* REQUIRED.
*/
Participant participant = 1
[
(validate.rules).message.required = true
];
/**
* The account via which the specific transaction is routed.
* For example, it could specify a bank account or blockchain address.
*
* REQUIRED.
*/
Account account = 2
[
(validate.rules).message.required = true
];
}
Account
message Account {
oneof specification {
option (validate.required) = true;
/** A generic account. */
GenericAccount account = 1;
/** A block chain address. */
BlockChainAddress address = 2;
/** An account with a linked client account. */
NostroVostro nostro_vostro = 3;
}
}
AccountAction
GenericAccount
message GenericAccount {
/**
* The ID of the agency that holds this account.
*/
string agent_id = 1
[
(validate.rules).string.min_len = 1
];
/**
* The ID of the account.
*/
string account_id = 2
[
(validate.rules).string.min_len = 1
];
}
BlockChainAddress
message BlockChainAddress {
/**
* The ID of the agency that manages this address.
*/
string agent_id = 1;
/**
* An identifier for the block chain where the address's transactions are
* recorded.
*/
string chain_id = 2;
/**
* The address's identifier.
*/
string address = 3
[
(validate.rules).string.min_len = 1
];
}
NostroVostro
message NostroVostro {
/** The nostro (mine) account. */
GenericAccount nostro = 1;
/** The vostro (yours) account. */
GenericAccount vostro = 2;
}
Payload
message Payload {
oneof specification {
/** A quantity of a named asset. */
NamedAssetAmount asset_amount = 1;
/** A quantity of cash. */
CashAmount cash_amount = 2;
/** A list of non-fungible tokens. */
NftList nft_list = 3;
/** A quantity of fungible tokens. */
TokenAmount tokenAmount = 4;
}
}
NamedAssetAmount
message NamedAssetAmount {
string asset_id = 1
[
(validate.rules).string.min_len = 1
];
Amount amount = 2
[
(validate.rules).message.required = true
];
string asset_id_type = 3;
}
CashAmount
message CashAmount {
/** The currency code. The code is required. If no currency applies, the
* 'XXX' or 999 code should be used.
*/
CurrencyCode currency = 1;
/** The amount of cash. */
Amount amount = 2
[
(validate.rules).message.required = true
];
}
NftList
message NftList {
/**
* An identifier for the block chain where the NFTs are recorded.
*/
string chain_id = 1;
/**
* The ID of the class of NFTs.
*/
string token_id = 2;
/** The IDs of the NFTs being transferred. */
repeated string nft_id = 3
[
(validate.rules).repeated.items.string.min_len = 1
];
}
TokenAmount
message TokenAmount {
/**
* An identifier for the block chain where the NFTs are recorded.
* The chain ID is expected but not required, as the chain may be
* implicit from the token ID, or the token could be represented on
* multiple chains.
*/
string chain_id = 1;
/** The ID of the token. This field is required. */
string token_id = 2
[
(validate.rules).string.min_len = 1
];
/** The amount of fungible tokens. This field is required. */
Amount amount = 3
[
(validate.rules).message.required = true
];
}
Amount
message Amount {
oneof representation {
option (validate.required) = true;
/** The amount as a 64-bit unsigned integer. */
uint64 value = 1;
/**
* The amount as a byte array containing the binary
* big-endian representation.
*/
bytes bits = 2;
};
/** Number of decimal places in the amount. */
uint32 scale = 3;
}
SourceMessage
message SourceMessage {
/** The type of the message. For example, a PACS.008. */
string type = 1;
/** The actual message. */
oneof storage {
/* The original triggering message is included in this message. */
string raw_message = 2;
/* The URI from which the original message can be retrieved. */
string archive_uri = 3;
}
}
Link
message Link {
/** The Party ( Participant + Account ) that will handle the next step. */
Party party = 1
[
(validate.rules).message.required = true
];
/**
* An optional message associated with this link.
* <p>Settlement Message on Link would override Settlement Message on a PossibleSteps Message.</p>
*/
optional Message settlement_message = 2;
AccountAction account_action = 3;
}
ObservedLink
message ObservedLink {
/** The link to the next participant in the settlement path. */
optional Link next = 1;
/**
* Additional observer participants.
*
* Observers will not be asked to vote on a transfer and will be informed as to
* whether it is accepted or rejected.
*/
repeated Participant observers = 2;
}
Message
message Message {
/**
* The message code that identifies the message type and indicates which
* template should be used to generate a user interface message from
* the parameters.
*/
string code = 1
[
(validate.rules).string.min_len = 1
];
/**
* The parameters associated with the message.
*/
google.protobuf.Struct parameters = 2;
}
Transfer
message Transfer {
/**
* The type of this transfer. The type must be understood by all parties to
* the transfer. A party that does not recognise a proposal type is expected
* to vote to reject it.
*
* Some transfer types may have only a "from" or a "to". For example, a
* "token mint" operation might only have a "to" party.
*
* REQUIRED.
*/
string type = 1
[
(validate.rules).string.min_len = 1
];
/**
* The correlation ID that uniquely identifies this group of transfers.
* The correlation ID is provided by the client and applies to all messages across a Transfer Set settlement.
*/
string correlation_id = 2
[
(validate.rules).string.min_len = 1
];
/**
* The source of the transfer.
*/
Party from = 3;
/**
* The destination of the transfer.
*/
Party to = 4;
/**
* Details of this transaction. For example, the amount to be transferred,
* or a list of identifiers of non-fungible tokens.
*
* REQUIRED
*/
Payload payload = 5
[
(validate.rules).message.required = true
];
/**
* The observers to this transfer.
*/
repeated Participant observers = 6;
/**
* The settlement route to this transfer.
*/
repeated Link path_links = 7
[
(validate.rules).repeated.min_items = 1
];
}
Signature
message Signature {
/** Signature algorithms accepted by the Ledger Swarm. */
enum Algorithm {
SHA256_WITH_RSA = 0;
SHA384_WITH_RSA = 1;
SHA512_WITH_RSA = 2;
SHA512_256_WITH_RSA = 3;
SHA3_256_WITH_RSA = 4;
SHA3_384_WITH_RSA = 5;
SHA3_512_WITH_RSA = 6;
SHA256_WITH_DSA = 7;
SHA384_WITH_DSA = 8;
SHA512_WITH_DSA = 9;
SHA3_256_WITH_DSA = 10;
SHA3_384_WITH_DSA = 11;
SHA3_512_WITH_DSA = 12;
SHA256_WITH_ECDSA = 13;
SHA384_WITH_ECDSA = 14;
SHA512_WITH_ECDSA = 15;
SHA3_256_WITH_ECDSA = 16;
SHA3_384_WITH_ECDSA = 17;
SHA3_512_WITH_ECDSA = 18;
ED_25519 = 19;
ED_448 = 20;
}
/** Payload to Sign. */
string payload = 1
[
(validate.rules).string.min_len = 1
];
/** Signature - Expected to be B64 Encoded. */
string signature = 2
[
(validate.rules).string.min_len = 1
];
/** PEM encoded X.590 Certificate chain for the signer. */
string certificate = 3
[
(validate.rules).string.min_len = 1
];
/** Algorithm used generate payload. */
Algorithm algorithm = 4
[
(validate.rules).enum.defined_only = true
];
}