Conditional-upon-Transfer-Decryption for DvP
Abstract
The interfaces in this proposal model a functional transaction scheme to establish a secure delivery-versus-payment across two blockchains, where a) no intermediary is required and b) one of the two chains can securely interact with a stateless “decryption oracle”. Here, delivery-versus-payment refers to the exchange of, e.g., an asset against a payment; however, the concept is generic to make a transfer of one token on one chain (e.g., the payment) conditional to the successful transfer of another token on another chain (e.g., the asset).
The scheme is realized by two smart contracts, one on each chain.
One smart contract implements the ILockingContract
interface on one chain (e.g. the “asset chain”), and another smart contract implements the IDecryptionContract
interface on the other chain (e.g., the “payment chain”).
The smart contract implementing ILockingContract
locks a token (e.g., the asset) on its chain until a key is presented to encrypt to one of two given values.
The smart contract implementing IDecryptionContract
, decrypts one of two keys (via the decryption oracle) conditional to the success or failure of the token transfer (e.g., the payment). A stateless decryption oracle is attached to the chain running IDecryptionContract
for the decryption.
Motivation
Within the domain of financial transactions and distributed ledger technology (DLT), the Hash-Linked Contract (HLC) concept has been recognized as valuable and has been thoroughly investigated. The concept may help to solve the challenge of delivery-versus-payment (DvP), especially in cases where the asset chain and payment system (which may be a chain, too) are separated. A prominent application of smart contracts realizing a secure DvP is that of buying an asset, where the asset is managed on one chain (the asset chain), but the payments are executed on another chain (the payment chain). Proposed solutions are based on an API-based interaction mechanism which bridges the communication between a so-called asset chain and a corresponding payment system or requires complex and problematic time locks.1
Here, we propose a protocol that facilitates secure delivery-versus-payment with less overhead, especially with a stateless oracle.2
Specification
Methods
Smart Contract on the chain that performs the locking (e.g. the asset chain)
The following methods specify the functionality of the smart contract implementing
the locking. For further information, please also look at the interface
documentation ILockingContract.sol
.
Initiation of Transfer: inceptTransfer
function inceptTransfer(uint256 id, int amount, address from, string keyHashedSeller, string memory keyEncryptedSeller) external;
Called from the buyer of the token to initiate token transfer. Emits a TransferIncepted
event.
The parameter id
is an identifier of the trade. The parameter from
is the address of the seller (the address of the buyer is msg.sender
).
The parameter keyHashedSeller
is a hash of the key that can be used by the seller to (re-)claim the token.
The parameter keyEncryptedSeller
is an encryption of the key that can be used by the buyer to claim the token.
It is possible to implement the protocol in a way where the hashing method agrees with the encryption method. See below on “encryption”.
Initiation of Transfer: confirmTransfer
function confirmTransfer(uint256 id, int amount, address to, string keyHashedBuyer, string memory keyEncryptedBuyer) external;
Called from the seller of the token to confirm token transfer. Emits a TransferConfirmed
event.
The parameter id
is an identifier of the trade. The parameter to
is the address of the buyer (the address of the seller is msg.sender
).
The parameter keyHashedBuyer
is a hash of the key that can be used by the buyer to (re-)claim the token.
The parameter keyEncryptedBuyer
is an encryption of the key that can be used by the buyer to (re-)claim the token.
It is possibly to implement the protocol in a way where the hashing method agrees with the encryption method. See below on “encryption”.
If the trade specification, that is, the quadruple (id
, amount
, from
, to
), in a call to confirmTransfer
matches that of a previous call to inceptTransfer
, and the balance is sufficient, the corresponding amount
of tokens is locked (transferred from from
to the smart contract) and TransferConfirmed
is emitted.
Transfer: transferWithKey
function transferWithKey(uint256 id, string memory key) external;
Called from either the buyer or the seller of the token
of the trade with id id
.
If the method is called from the buyer (to
) and the hashing of key
matches keyHashedBuyer
,
then the locked tokens are transferred to the buyer (to
). This emits TokenClaimed
.
If the method is called from the seller (from
) and the hashing of key
matches keyHashedSeller
,
then the locked tokens are transferred (back) to the seller (to
). This emits TokenReclaimed
.
Summary
The interface ILockingContract
:
interface ILockingContract {
event TransferIncepted(uint256 id, int amount, address from, address to, string keyHashedSeller, string keyEncryptedSeller);
event TransferConfirmed(uint256 id, int amount, address from, address to, string keyHashedBuyer, string keyEncryptedBuyer);
event TokenClaimed(uint256 id, string key);
event TokenReclaimed(uint256 id, string key);
function inceptTransfer(uint256 id, int amount, address from, string memory keyHashedSeller, string memory keyEncryptedSeller) external;
function confirmTransfer(uint256 id, int amount, address to, string memory keyHashedBuyer, string memory keyEncryptedBuyer) external;
function transferWithKey(uint256 id, string memory key) external;
}
Smart Contract on the other chain that performs the conditional decryption (e.g. the payment chain)
The following methods specify the functionality of the smart contract implementing
the conditional decryption. For further information, please also look at the interface
documentation IDecryptionContract.sol
.
Initiation of Transfer: inceptTransfer
function inceptTransfer(uint256 id, int amount, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
Called from the receiver of the amount to initiate payment transfer. Emits a TransferIncepted
.
The parameter id
is an identifier of the trade. The parameter from
is the address of the sender of the payment (the address of the receiver is msg.sender
).
The parameter keyEncryptedSuccess
is an encryption of a key and will be decrypted if the transfer is successful in a call to transferAndDecrypt
.
The parameter keyEncryptedFailure
is an encryption of a key and will be decrypted if the transfer fails in a call to transferAndDecrypt
or if cancelAndDecrypt
is successful.
Transfer: transferAndDecrypt
function transferAndDecrypt(uint256 id, int amount, address to, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
Called from the sender of the amount to initiate completion of the payment transfer. Emits a TransferKeyRequested
with keys depending on completion success.
The parameter id
is an identifier of the trade. The parameter to
is the address of the receiver of the payment (the sender of the payment (from) is implicitly the msg.sender
).
The parameter keyEncryptedSuccess
is an encryption of the key and will be decrypted if the transfer is successful.
The parameter keyEncryptedFailure
is an encryption of the key and will be decrypted if the transfer fails.
The method will not decrypt any key and not perform a transfer of a payment if the values (id
, amount
, from
to
, keyEncryptedSuccess
, keyEncryptedFailure
)
do not match a previous call to inceptTransfer
.
Cancelation of Transfer: cancelAndDecrypt
function cancelAndDecrypt(uint256 id, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
Called from the receiver of the amount to cancel payment transfer (cancels the incept transfer).
The method must be called from the caller of a previous call to inceptTransfer
with the exact same arguments and cancels this specific transfer.
If these preconditions are met and a valid call to transferAndDecrypt
has not been issued before,
i.e. if keyEncryptedSuccess
has not been issued in a TransferKeyRequested
event,
then this method emits a TransferKeyRequested
with the key keyEncryptedFailure
.
Release of ILockingContract Access Key: releaseKey
function releaseKey(uint256 id, string memory key) external;
Called from the (possibly external) decryption oracle.
Emits the event TransferKeyReleased
with the value of key
if the call was eligible.
Summary
The interface IDecryptionContract
:
interface IDecryptionContract {
event TransferIncepted(uint256 id, int amount, address from, address to, string keyEncryptedSuccess, string keyEncryptedFailure);
event TransferKeyRequested(address sender, uint256 id, string encryptedKey);
event TransferKeyReleased(address sender, uint256 id, bool success, string key);
function inceptTransfer(uint256 id, int amount, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
function transferAndDecrypt(uint256 id, int amount, address to, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
function cancelAndDecrypt(uint256 id, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
function releaseKey(uint256 id, string memory key) external;
}
Encryption and Decryption
The linkage of the two smart contracts relies on use of a key
, encryptedKey
and hashedKey
.
The implementation is free to support several encryption methods for
as long as the decryption oracle supports it.
The encryption is performed with the public key of the decryption oracle. Either the encryption oracle offers a method performing encryption, in which case the encryption method isn’t even required to be known, or both parties know the public key of the decryption oracle and can perform the generation of the key and its encryption.
It is implicitly assumed that the two parties may check that
the strings keyEncryptedBuyer
and keyEncryptedSeller
are
in a valid format.
To avoid on-chain encryption in the ILockingContract
, it is possible to use a
simpler hashing algorithm on the ILockingContract
. In that case, the decryption oracle has
to provide a method that allows to obtain the hash H(K) (keyHashed
) for an
encrypted key E(K) (keyEncrypted
) without exposing the key K (``key`), cf. 2.
Sequence diagram of delivery versus payment
The interplay of the two smart contracts is summarized in the following sequence diagram:
Rationale
The protocol tries to be parsimonious. The transfer
is associated with a (preferably unique) id
possibly
generated by some additional interaction of the trading
parties.
The key
and the encryptedKey
arguments are strings to
allow the flexible use of different encryption schemes.
The decryption/encryption scheme should be inferable from the contents
of the encryptedKey
.
Ensuring Secure Key Decryption - Key Format
It has to be ensured that the decryption oracle decrypts a key only for the eligible contract.
It seems as if this would require us to introduce a concept of eligibility to the description oracle, which would imply a kind of state.
A fully stateless decryption can be realized by introducing a document format for the key and a corresponding eligibility verification protocol. We propose the following elements:
- The (unencrypted) key documents contain the address of the payment contract implementing
IDecryptionContract
. - The decryption oracle offers a stateless function
verify
that receives an encrypted key and returns the callback address (that will be used for thereleaseKey
call) that is stored inside the decrypted key without returning the decrypted key. - When an encrypted key is presented to the decryption oracle, the oracle decrypts the document and passes the decrypted key to
releaseKey
of the callback contract address found within the document decrypted key.
We propose the following XML schema for the document of the decrypted key:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://finnmath.net/erc/ILockingContract" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="releaseKey">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="contract" type="xs:string" use="required" />
<xs:attribute name="transaction" type="xs:unsignedShort" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:schema>
A corresponding XML sample is shown below.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<releaseKey contract="eip155:1:0x1234567890abcdef1234567890abcdef12345678" transaction="3141" xmlns="http://finnmath.net/erc/ILockingContract">
<!-- random data -->
zZsnePj9ZLPkelpSKUUcg93VGNOPC2oBwX1oCcVwa+U=
</releaseKey>
Security Considerations
The decryption oracle does not need to be a single trusted entity. Instead, a threshold decryption scheme can be employed, where multiple oracles perform partial decryption, requiring a quorum of them to reconstruct the secret key. This enhances security by mitigating the risk associated with a single point of failure or trust.
In such cases, each participating decryption oracle will observe the decryption request from an emitted TransferKeyRequested
event, and subsequently call the releaseKey
method with a partial decryption result. The following sequence diagram illustrates this.
See 2 for details.
Copyright
Copyright and related rights waived via CC0.
{
"type": "article",
"id": 1,
"author": [
{
"family": "La Rocca",
"given": "Rosario"
},
{
"family": "Mancini",
"given": "Riccardo"
},
{
"family": "Benedetti",
"given": "Marco"
},
{
"family": "Caruso",
"given": "Matteo"
},
{
"family": "Cossu",
"given": "Stefano"
},
{
"family": "Galano",
"given": "Giuseppe"
},
{
"family": "Mancini",
"given": "Simone"
},
{
"family": "Marcelli",
"given": "Gabriele"
},
{
"family": "Martella",
"given": "Piero"
},
{
"family": "Nardelli",
"given": "Matteo"
},
{
"family": "Oliviero",
"given": "Ciro"
}
],
"DOI": "10.2139/ssrn.4386904",
"title": "Integrating DLTs with Market Infrastructures: Analysis and Proof-of-Concept for Secure DvP between TIPS and DLT Platforms",
"original-date": {
"date-parts": [
[2022, 7, 19]
]
},
"URL": "http://dx.doi.org/10.2139/ssrn.4386904"
}
{
"type": "article",
"id": 2,
"author": [
{
"family": "Fries",
"given": "Christian"
},
{
"family": "Kohl-Landgraf",
"given": "Peter"
}
],
"DOI": "10.2139/ssrn.4628811",
"title": "A Proposal for a Lean and Functional Delivery versus Payment across two Blockchains",
"original-date": {
"date-parts": [
[2023, 11, 9]
]
},
"URL": "http://dx.doi.org/10.2139/ssrn.4628811"
}