Introduction
The FinP2P network enables secure, decentralized financial transactions across disparate ledgers. Central to this is the
Execution Plan (EP), a mechanism for orchestrating multi-step operations. This document details additional capabilities
in the EP trust model for allowing ledger adapters to provide proofs of execution of EP instructions.
Ledger Operation Proofs
Ledger operations produce a Receipt, which serves as a guarantee from the underlying platform of a transaction that
occurred in its ledger. This receipt is provided by an adapter to the router to record transactions, either as part of
the EP instruction completion proposal phase or individually to record transactions that were triggered externally to
FinP2P and affect the investors' accounts.
To further enhance this guarantee, an additional proof can be attached to the Receipt. By supplying the proof as part of
the Receipt, the organization adds another layer of trust and a guarantee that a transaction was recorded in the ledger.
This can increase the trust of other parties that may not have direct access to the ledger.
Organizations can provide segregated private keys for ledger proofs. The information about the key used for verification
is provided by the FinP2P asset policy, which provides general information about the tokenization platform capabilities
and is published as metadata on specific asset profiles. These keys can be further pinned by other parties to reduce the
need to trust external configuration dependencies.
Overview of Proof Types
- Receipt Signature Based:
- Ledgers may apply a digital signing algorithm encoding the Receipt transaction information into a digest, which
will be signed by a private key owned exclusively by the organization controlling the ledger or tokenization
platform. The additional signature-based proof adds another layer of reliability for the guarantee provided by the
organization that the Receipt transaction was indeed recorded in its ledger, and the data was not tampered with. - The proof is a digital signature applied to the Receipt data and signed by a private key owned by the controlling
organization of the tokenization platform, the structure of the message to be signed can follow the below EIP712
structure of Hashlist structure. - The key may differ from the Organization's Router private key, which is associated with the public key identity of
the organization in the FinP2P network (AKA FinID).
- Ledgers may apply a digital signing algorithm encoding the Receipt transaction information into a digest, which
Other proof types to be added soon:
- Zero Knowledge:
- For ledgers and tokenization platforms that support Zero Knowledge Proofs (ZKP), the ledger may provide a ZKP for
the existence of the transaction within a blockchain block and that the network has reached consensus about the
block.
- For ledgers and tokenization platforms that support Zero Knowledge Proofs (ZKP), the ledger may provide a ZKP for
- Ledger Specific Proofs:
- Ledgers may supply proof of a transaction being recorded on a ledger by providing ledger-specific cryptographic
proofs of this action. This may require additional key pre-setup to ensure other parties can validate the proof.
- Ledgers may supply proof of a transaction being recorded on a ledger by providing ledger-specific cryptographic
Receipt Signature Based proof
EIP712 Proof Structure
Type Definitions
The following table describes the EIP-712 type definitions:
Order | Type Name | Field Name | Field Type | Description |
---|---|---|---|---|
1 | EIP712Domain | name | string | Name of the signing domain |
2 | version | string | Version of the signing domain | |
3 | chainId | uint256 | Chain ID where the contract is deployed | |
4 | verifyingContract | string | Address of the verifying contract | |
5 | Source | accountType | string | Type of the account |
6 | Source | finId | string | FinID of the account |
7 | Destination | accountType | string | Type of the account |
8 | Destination | finId | string | FinID of the account |
9 | TradeDetails | executionContext | ExecutionContext | Execution plan context |
10 | ExecutionContext | executionPlanId | string | Execution plan ID |
11 | ExecutionContext | instructionSequenceNumber | string | Instruction sequence number |
12 | TransactionDetails | operationId | string | Operation ID of the transaction |
13 | TransactionDetails | transactionId | string | Transaction ID on the ledger |
14 | Asset | assetId | string | ID of the asset |
15 | Asset | assetType | string | Type of the asset |
16 | Receipt | id | string | ID of the receipt |
17 | Receipt | operationType | string | The operation type (e.g., hold, release) |
18 | Receipt | source | Source | the source account |
19 | Receipt | destination | Destination | the destination account |
20 | Receipt | asset | Asset | the asset |
21 | Receipt | tradeDetails | TradeDetails | the trade details relating to the EP |
22 | Receipt | transactionDetails | TransactionDetails | the transaction details |
Message Fields
The following table describes the fields included in the EIP-712 message:
Field Name | Field Type | Description |
---|---|---|
id | string | ID of the receipt |
operationType | string | The operation type (e.g., hold, release) |
sourceAccountType | string | Type of the source account |
sourceFinId | string | Financial ID of the source account |
destinationAccountType | string | Type of the destination account |
destinationFinId | string | Financial ID of the destination account |
assetId | string | ID of the asset |
assetType | string | Type of the asset |
executionPlanId | string | Execution plan ID |
instructionSequenceNumber | string | Instruction sequence number |
operationId | string | Operation ID of the transaction |
transactionId | string | Transaction ID |
JSON Samples:
EIP712 Template
{
"domain": {
"chainId": 1,
"name": "FinP2P",
"verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
"version": "1"
},
"message": {
"id": "receipt123456",
"operationType": "hold",
"source": {
"accountType": "sourceAccountType",
"finId": "sourceFinId"
},
"destination": {
"accountType": "destinationAccountType",
"finId": "destinationFinId"
},
"asset": {
"assetId": "asset123",
"assetType": "finp2p"
},
"tradeDetails": {
"executionContext": {
"executionPlanId": "ep123",
"instructionSequenceNumber": "1"
}
},
"transactionDetails": {
"operationId": "op123",
"transactionId": "tx123"
}
},
"primaryType": "Receipt",
"types": {
"EIP712Domain": [
{
"name": "name",
"type": "string"
},
{
"name": "version",
"type": "string"
},
{
"name": "chainId",
"type": "uint256"
},
{
"name": "verifyingContract",
"type": "address"
}
],
"Source": [
{
"name": "accountType",
"type": "string"
},
{
"name": "finId",
"type": "string"
}
],
"Destination": [
{
"name": "accountType",
"type": "string"
},
{
"name": "finId",
"type": "string"
}
],
"TransactionDetails": [
{
"name": "operationId",
"type": "string"
},
{
"name": "transactionId",
"type": "string"
}
],
"Asset": [
{
"name": "assetId",
"type": "string"
},
{
"name": "assetType",
"type": "string"
}
],
"ExecutionContext": [
{
"name": "executionPlanId",
"type": "string"
},
{
"name": "instructionSequenceNumber",
"type": "string"
}
],
"TradeDetails": [
{
"name": "executionContext",
"type": "ExecutionContext"
}
],
"Receipt": [
{
"name": "id",
"type": "string"
},
{
"name": "operationType",
"type": "string"
},
{
"name": "source",
"type": "Source"
},
{
"name": "destination",
"type": "Destination"
},
{
"name": "asset",
"type": "Asset"
},
{
"name": "tradeDetails",
"type": "TradeDetails"
},
{
"name": "transactionDetails",
"type": "TransactionDetails"
}
]
}
}
Ledger adapter API template type
{
"signature": {
"hashFunc": "keccak_256",
"signature": "56f471d1010b3cad0e1461886c2bb9c85bdb0bcc288f857bf8e877f147a3a2e97d21053fcaff61593df9cac2701c889e0e43e7872d38d8696739e3fbf6479eb2",
"template": {
"domain": {
"chainId": 1,
"name": "FinP2P",
"verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
"version": "1"
},
"hash": "b55a46f6fa8188ab834de7bd4c9105b5ede3c7accc9eb320c423fce8e2d7e255",
"message": {
"id": "receipt123456",
"operationType": "hold",
"source": {
"accountType": "sourceAccountType",
"finId": "sourceFinId"
},
"destination": {
"accountType": "destinationAccountType",
"finId": "destinationFinId"
},
"asset": {
"assetId": "asset123",
"assetType": "finp2p"
},
"tradeDetails": {
"executionContext": {
"executionPlanId": "ep123",
"instructionSequenceNumber": "1"
}
},
"transactionDetails": {
"operationId": "op123",
"transactionId": "tx123"
}
},
"primaryType": "Receipt",
"type": "EIP712",
"types": {
"definitions": [
{
"fields": [
{
"name": "name",
"type": "string"
},
{
"name": "version",
"type": "string"
},
{
"name": "chainId",
"type": "uint256"
},
{
"name": "verifyingContract",
"type": "address"
}
],
"name": "EIP712Domain"
},
{
"fields": [
{
"name": "accountType",
"type": "string"
},
{
"name": "finId",
"type": "string"
}
],
"name": "Source"
},
{
"fields": [
{
"name": "accountType",
"type": "string"
},
{
"name": "finId",
"type": "string"
}
],
"name": "Destination"
},
{
"fields": [
{
"name": "operationId",
"type": "string"
},
{
"name": "transactionId",
"type": "string"
}
],
"name": "TransactionDetails"
},
{
"fields": [
{
"name": "assetId",
"type": "string"
},
{
"name": "assetType",
"type": "string"
}
],
"name": "Asset"
},
{
"fields": [
{
"name": "executionPlanId",
"type": "string"
},
{
"name": "instructionSequenceNumber",
"type": "string"
}
],
"name": "ExecutionContext"
},
{
"fields": [
{
"name": "executionContext",
"type": "ExecutionContext"
}
],
"name": "TradeDetails"
},
{
"fields": [
{
"name": "id",
"type": "string"
},
{
"name": "operationType",
"type": "string"
},
{
"name": "source",
"type": "Source"
},
{
"name": "destination",
"type": "Destination"
},
{
"name": "asset",
"type": "Asset"
},
{
"name": "tradeDetails",
"type": "TradeDetails"
},
{
"name": "transactionDetails",
"type": "TransactionDetails"
}
],
"name": "Receipt"
}
]
}
}
},
"type": "signatureProofPolicy"
}
Hashlist Proof Structure
The signature template for the Receipt proof in Hashlist format, The Hashlist signature format involves creating an
array of hashes, where each hash represents a group of values.
The list of fields as defined in Message Fields is hashed in order to create a Hash Group (HG). The
HG is then hashed to create a Hashlist. The Hashlist is then signed by the sender's private key.
HG = hash('SHA3-256', [fields by order]);
hashList = hash('SHA3-256', [HG]);
Signature = sign(sender private secp256k1 key, hashList)