This document defines the Voucher Exchange Protocol designed to drive voucher-exchange schemes that allow participants to exchange vouchers of any kind defined by such a scheme. The protocol ensures that the total balance of vouchers in circulation is under control of the scheme. The protocol relies on a underlying consensus-system for storing an account and transfer state information, but does not store information on behalf of participants. Consequently, the scheme operator always knows the exact total amount of vouchers in circulation, but he does not know who is holding them.
The protocol relies on well-established cryptographic primitives, including cryptographic hash-functions, asymmetric key signatures and block encryption-algorithms, namely:
The protocol allows the operation of any number of deposit accounts without interaction with scheme operator. A limited set of bailment-accounts under control of the operator represent the physical funds behind vouchers issued. Each account is represented by an individual block-chain.
The protocol involves account-owners, validators, minters and a consensus-system not shown here.
The validator service is a stateless responder that serves to purpose of approving sufficient funds are available on an account requesting a transfer. Multiple validators can operate simultanously and multiple validation-signatures may be required by the scheme.
The minter service generates transfer-token for previously validated transfers. It ensures that only one token can be generated per transfer and it that each token can be consumed only once. The minter uses the consensus-system to store account and transfer state information.
The account owner maintains an account-book, consisting of blocks, chained together by the digest value of the predecessor block and by a set of signatures, including minter and validator signatures.
U5074-10 The account-block is the elementary unit building the account-book block chain. Each block contains one or more records. Each block, except the first block, refers to a predecessor by including the digest of the preceeding block.
The head-block must contain a single manifest-record and must be signed by a minter for account-registration. Subsequent blocks include transfer and receive records. Each block must be submitted to a validator for validation at least once.
| Element | Data Type | Tag | Description |
|---|---|---|---|
| Previous | binary(256) | R4568-09 | The block-key of the previous block. |
| Sequence | int(64) | R5064-19 | Zero-based block sequence number. |
| Records | constructed | U5083-03 | Records included in the block. |
| Signatures | constructed | Signatures associated with the block. |
The to-be-signed content includes the Previous, Sequence and Records elements.
U4570-01 The block-key is computed as the digest of the DER encoded block, including the Previous, Sequence and Records elements.
Records are the payload of account-book chain blocks. The voucher-exchange protocol is only concerned with the record-types describes below.
U5062-23 The manifest-record occurs in the first account block.
| Element | Data Type | Tag | Description |
|---|---|---|---|
| AccountPublicKey | PKCS#1 | U4565-02 | PKCS#1 encoded public-key or X.509 certificate. |
| AccountSelector | binary(1..32) | U5062-42 | A value assigned by the account-owner to discriminate different accounts using the same public-key credential. |
| ManifestItems | constructed | U4565-03 | Optional collection of manifest-items, such as the BailmentDeclaration. |
The same key-pair can be used for multiple accounts using a different account-selector for each account.
U5074-02 The transfer-record stores information about outgoing voucher transactions.
| Element | Data Type | Tag | Description |
|---|---|---|---|
| Vouchers | amount+ | R5074-01 | Transfer amounts, ordered by unit. |
The receive-record captures incoming voucher transactions.
| Element | Data Type | Tag | Description |
|---|---|---|---|
| Vouchers | amount+ | R5074-01 | Received amounts, ordered by unit. |
U4565-04 In this context, a signature applies to a block in the account-book by including the corresponding block-key into computation, along with other, signature-type specific elements.
| Kind | Tag | Elements | Description |
|---|---|---|---|
| account | AccountSelector | The account-owner signature is required on every block. | |
| validator | U5063-33 | DigestOfBalance | Required on a transfer-block. |
| registration | Required on the first block. | ||
| minter-coin | U5065-09 | Asserts the generation of a coin on behalf of the signed transfer block, required on transfer-block. | |
| minter-transit | Assert the melting of a coin on behalf of a receive-block. |
The signature-record is used to represent a signature:
| Element | Data Type | Tag | Description |
|---|---|---|---|
| Kind | signature-kind | U4565-04 | Identifies the kind of signature. |
| SignerPublicKeyIdentifier | binary | R5075-06 | Reference to the signing key (SKI, CFS-KEYID?). |
| SignatureAlgorithm | object-identifier | Identifies the signature computation algorithm (e.g. RSA-SHA256) | |
| Timestamp | datetime | Signature timestamp | |
| AccountSelector | binary | U5062-42 | Required in account-signatures |
| DigestOfVouchers | binary | Required in validator and minter-transition signatures | |
| VerifyData | binary | Signature verification data |
U5064-16 The encoded data to-be-signed depends on the kind of signature.
R5074-04 The signature is computed on the SHA-256 digest of to-be-signed.
The signature verify-data is computed using RSA-SHA256 using PKCS#1 padding including the block-key and possibly other elements, depending on the signature-type, as described below.
TBSData ::= SEQUENCE
{
kind INTEGER,
blockKey OCTET STRING,
-- optional elements --
accountSelector [0] IMPLICIT OCTET STRING,
digestOfVouchers [1] IMPLICIT OCTET STRING,
-- trailer --
timestamp GeneralizedTime,
signerKeyIdentifier OCTET STRING,
}
U5074-08 The validation procedure ensures that sufficient funds exist to perform the requested transfer.
The input to the validator includes at least one block containing a transfer-record. The block must be preceeded by any receive-blocks incorporated into the account-book after the first-block or the last transfer-block.
The previous-block-key of the first block supplied to the validation procedure must refer to the first-block or the last-transfer-block.
| Element | Data Type | Tag | Description |
|---|---|---|---|
| AccountPublicKey | Public-key or certificate of requestor. | ||
| Blocks | block+ | Blocks to be included in validation, where the last one is the transfer-block to be validated. | |
| Balance | amount+ | Previously validated account balance. | |
| Signatures | signature* | Signatures associated with the block preceeding the first given block. |
As the result of a successful validation, the validator creates a validator-signature and returns it the requestor.
The signature computiation must include the block-key of the new transfer-block, the last-transfer-block-key and the digest-of-balance-element.
The minter performs two complementary tasks: the mint-procedure creates a new coin associated with a previously validated transfer-block, while the melt-procedure consumes a previously created coin into the receive-block of the receiving account.
The minter interacts with the consensus-system to store account-registration and coin-transaction information.
Minter transactions are repeatable. The requestor shall repeat the request with the same parameters in case of a network problem.
U5083-02 The minter join-procedure serves the purpose of establishing account-registration for a new account.
The account-owner invokes this procedure once with the block-key of the first block including the manifest-record.
R5063-30 The minter writes the account-registration attachment to the consensus-system.
U5076-10 The minter writes the account-state attachment to the consensus-system.
U5065-11 The minter computes the registration-signature and conveyes it with the response.
The mint-procedure produces, upon presentation of a validated account-book transfer-block, a coin suited to represent the transfer encoded in that block, without including any of its content.
The coin is protected by the sender-coin-secret which is not revealed to the minter. Instead the sender-coin-token derived from last-block-key, sender-coin-secret and transfer-amounts is passed to the mint-procedure.
The input to the mint-procedure includes the transfer-block-key, the sender-coin-token, digest-of-balance, account and validator signatures. The account public-key and selector shall be supplied along with the account-signature.
| Element | Data Type | Tag | Description |
|---|---|---|---|
| DigestOfBalance | binary(256) | Digest of balance element asserted by validators | |
| Vouchers | amount+ | U5075-01 | Amount to be transferred by the coin |
| NextBlockKey | binary(256) | Block-key of previously validated new transfer-block to be minted | |
| Signatures | Account and validator signatures |
Before issueing a coin, the minter must ensure the following:
The minter creates a new coin by generating a random minter-coin-secret. He derives the minter-coin-token from the secret.
R5075-03 The minter computes the coin-consensus-key from the sender-coin-token and the minter-coin-token and the coin-verification-value from ???.
The minter registers the coin at the consensus-system by storing coin-verification-value as an attachment of coin-consensus-key.
U5076-10 The minter updates account-state in the consensus-system to refer to the transfer-block just minted.
| Element | Data Type | Tag | Description |
|---|---|---|---|
| MinterCoinToken | |||
| Signatures | signature | minter-coin |
The minter responds with the minter-coin-token and a minter-coin signature.
R5075-05 The minter must be able to generate a suitable response upon replay of a previously successful request.
The melt-procedure consumes a coin previously generated by the mint-procedure.
The request presents the recipient-coin-token derived from (sender-coin-secret, minter-coin-token, ...)
| Element | Data Type | Tag | Description |
|---|---|---|---|
| RecipientCoinToken | |||
| DigestOfAmount | |||
| Next | binary(256) | Block-key of new receive-block |
The minter computes coin-consensus-key from ...
The minter reads the coin-verification-value from the consensus-system.
The minter checks the verification-value.
The minter replaces the coin-verification-value with the coin-consumed-value in the consensus-system.
| Element | Data Type | Tag | Description |
|---|---|---|---|
| Signatures | minter-transit |
R5062-27 The minter operates on possibly distributed consensus database that can associate a value with a fixed length key conforming to ACID properties.
The minter stores the following associations in the consensus-system:
| Attachment Type | Tag | Lifetime | Description |
|---|---|---|---|
| account-registration | U4571-42 | account | Written once during the JOIN operation. |
| account-state | U5076-10 | account | The most recently minted account block. |
| coin-in-flight | U5076-12 | transaction + redo interval | written during MINT operation |
| coin-receipt | U5076-12 | redo interval | written during the MELT operation |
U5063-02 A voucher-exchange scheme is represented by a scheme-manifest and one or more service-dictionary documents referenced by the manifest.
The scheme provides a conclusive and accurate list of validator and minter signatures key including their validity intervals.
R5078-05 The scheme-authority acts on behalf of the scheme-operator and issues service membership certificates.
U5061-30 A voucher-account is a list of blocks chained together as described above. The account-owner is responsible for storing the account-book. Account-credential private-key access is required to operated the account.
R5075-09 The account-identifier is the digest derived from the scheme-uri, the public-key identifier and the account-selector.
U5064-02 The account-validation procedure ensures that the account block-chain is correct and each block is equipped with the necessary signatures. The account-balance is computed in the process.
The balance of a normal account is not allowed to go below zero with any transaction.
R5082-28 In contrast to a normal account, a bailment-account is not allowed to exceed a balance of zero.
The negative balance of a bailment account shall correspond to the balance of the associated physical account.
Transfers outgoing from bailment-accounts correspond to incomes on the physical account.
Receives incoming to a bailment-account correspond to a withdrawal of physical funds.
This section describes the coin based exchange procedure in detail.
The sender shall prepare and validate a new transfer-block.
R5065-12 The sender shall allocate a coin-secret and derive the transfer-protection-key from it.
U5075-01 The sender shall compute the sender-coin-token from the sender-coin-secret, the next block-key and the transfer-amount.
U5089-01 The sender shall compose a coin-payload including the transfer-amount.
R5089-02 The sender shall encrypt transfer-data using the transfer-protection-key to generate the protected-coin-payload data element.
The sender shall persist request data, before sending the request to the minter; the request MUST be repeated in case of network failure.
The sender shall select a minter randomly and send the mint-request including the transfer-block-key, the protected-coin-payload, account and validator signatures.
As result of a successful MINT operation, the sender receives a minter-token from the minter.
The minter shall generate a random minter-token for the new coin. It shall associate the protected transfer-data with it in the consensus-system.
The minter shall update the account-state to reflect the transfer. It shall store transfer-data with the account-state.
The minter shall create a minter-coin signature.
The minter shall return the minter-coin signature and the coin-consensus-key to the sender.
After receiving the mint-response, the sender shall extract the minter-token and minter-coin signature and persist the block into the account-book.
U5077-04 The sender computes the coin-transfer-token from the coin-secret and the minter-token.
Depending on the use-case, there are two possible flows for transferring the coin-token:
The sender of a coin may choose to use a browser-uri or an application-uri:
U5093-02 The URI format is suitable where short representation is needed, such as QR code.
The URI shall be HTTPS and point to the scheme host for client fallback scenarios, such as app-installation, such as:
https://vxcoin.net/coins?c=300E0404F2E9D0040406DBED240344CC
U5076-15 Specific elements used in the account block-chain and signatures need to be represented in a canonical way. This section provides the ASN.1 definitions for those structures.
U5074-10 The implementation must be capable of serializing the account-book given the format herein for the purpose of block-key computation. It does not need to employ the format for its internal purposes.
R5075-09 The account-identifier is computed as the digest of the following structure:
AccountIdentifierToBeDigested ::= {
schemeURI UTF8String,
keyIdentifier OCTET STRING,
selector OCTET STRING
}
The amount-element contains one or more simple-amount-elements, ordered by voucher-unit for canonical representation.
Amount ::= SET OF SimpleAmount
U5064-03 The amount-element describes a voucher amount as a rational number, represented by the tuple (Unit, Nominator, Denominator).
Amount ::= SEQUENCE {
unit UTF8String,
nominator INTEGER,
denominator INTEGER }
R5088-07 The voucher-unit must be one allowed by the scheme-manifest.
R5082-28 The bailment-declaration MUST be present in the manifest-record of bailment-accounts.
BailmentDeclaration ::= SEQUENCE {
accountNumber UTF8String,
accountOwner UTF8String,
institute [0] UTF8String }
U5074-10 ASN.1 representation of account block.
Block ::= SEQUENCE {
sequence INTEGER,
previousBlockKey OCTET STRING OPTIONAL,
records SEQUENCE OF EncodedRecord,
signatures [0] EXPLICIT OPTIONAL SEQUENCE OF Signature
attributes [1] EXPLICIT OPTIONAL SEQUENCE OF BlockAttribute }
U5077-02 Information stored in the consensus system on behalf of a coin.
CoinPayload ::= SEQUENCE
{
references [0] EXPLICIT SET OF ReferenceElement OPTIONAL,
vouchers [1] EXPLICIT Amount,
}
U5077-04 The encoded coin-transfer element must be transmitted from sender to receiver directly.
CoinTransferToken ::= SEQUENCE {
version INTEGER DEFAULT(0),
sendersecret OCTET STRING,
mintertoken OCTET STRING }
CredentialData ::= SEQUENCE {
keyIdentifier [0] IMPLICT OCTET STRING OPTIONAL,
encodedX509Certificate [1] IMPLICIT OCTET STRING OPTIONAL }
U5062-23 Manifest Record ASN.1 Syntax.
ManifestRecord ::= SEQUENCE
{
publicKey CredentialData,
selector OCTET STRING,
manifestItems [0] OPTIONAL SEQUENCE OF CHOICE {
bailment BailmentDeclaration
}
}
For bailment-accounts, manifest-items shall contain exactly one bailment-declaration.
A record wrapper is used to keep the protocol open for custom content.
EncodedRecord ::= SEQUENCE
{
type RecordType,
content COICE {
rawcontent OCTET STRING,
manifest ManifestRecord,
receive ReceiveRecord,
transfer TransferRecord }
}
RecordType ::= CHOICE {
numtype BasicRecordType,
oidtype OBJECT IDENTIFIER }
U5089-07 Reference information to be included into a record.
ReferenceElement ::= SEQUENCE {
typeID ReferenceTypeID,
content ReferenceContent OPTIONAL }
The type of reference can be given by an URI or an object-identifier:
ReferenceTypeID ::= CHOICE {
uri IA5String,
oid OBJECT IDENTIFIER }
The content can be a string or binary content.
ReferenceContent ::= CHOICE {
text UTF8String,
binary OCTET STRING }
The following are TypeID currently in use:
| TypeID | Description |
|---|---|
| urn:vxcoin.net:reftext | Reference Text |
| urn:vxcoin.net:refuri | Reference URI |
Represents an incoming transaction.
ReceiveRecord ::= SEQUENCE {
references [0] EXPLICIT SET OF ReferenceElement OPTIONAL,
vouchers Amount
}
U4565-04 The signature element is DER encoded according to the following syntax:
Signature ::= SEQUENCE {
kind INTEGER,
timestamp GeneralizedTime,
signerKey CredentialData,
accountSelector [0] IMPLICIT OCTET STRING OPTIONAL,
verifyData OCTET STRING }
U4596-01 Full transfer information message.
TransferMessage ::= SEQUENCE {
coin OCTET STRING,
references [0] SET OF ReferenceElement OPTIONAL,
vouchers [1] Amount OPTIONAL,
senderBlockKey [2] OCTET STRING OPTIONAL }
Represents an outgoing transaction.
TransferRecord ::= SEQUENCE {
references [0] EXPLICIT SET OF ReferenceElement OPTIONAL,
vouchers Amount
}
The validator sees the content of account-blocks.
The minter sees only the block-key and trusts the validator-signature for the block-content.
Detailed computations of various data elements used in the protocol.