From be6bc78d7e99e38d3abb27e8aa19f22d8446784d Mon Sep 17 00:00:00 2001 From: Oleg Andreev Date: Wed, 24 Apr 2019 21:49:26 -0700 Subject: [PATCH 1/7] wip --- zkvm/docs/import-spec.md | 51 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 zkvm/docs/import-spec.md diff --git a/zkvm/docs/import-spec.md b/zkvm/docs/import-spec.md new file mode 100644 index 000000000..f33d1c8e0 --- /dev/null +++ b/zkvm/docs/import-spec.md @@ -0,0 +1,51 @@ +# Importing assets from Stellar to ZkVM + +This protocol defines the process of importing of assets originally issued on the Stellar into ZkVM and exporting them back to the Stellar network. + +The protocol uses _trusted custodian_ secured with multi-signatures and stateless validation (only the blockchain state is used). + +## Importing assets + +TBD: + +## Exporting assets + +TBD: + +## Asset to flavor mapping + +To map the stellar asset, we will use `metadata` argument that represents an XDR-encoded `Asset` structure +as specified in the `Stellar-ledger-entries.x` XDR file: + +``` +namespace stellar { + typedef PublicKey AccountID; + ... + typedef opaque AssetCode4[4]; + typedef opaque AssetCode12[12]; + + enum AssetType { + ASSET_TYPE_NATIVE = 0, + ASSET_TYPE_CREDIT_ALPHANUM4 = 1, + ASSET_TYPE_CREDIT_ALPHANUM12 = 2 + }; + + union Asset switch (AssetType type) { + case ASSET_TYPE_NATIVE: void; + case ASSET_TYPE_CREDIT_ALPHANUM4: + struct { + AssetCode4 assetCode; + AccountID issuer; + } alphaNum4; + case ASSET_TYPE_CREDIT_ALPHANUM12: + struct { + AssetCode12 assetCode; + AccountID issuer; + } alphaNum12; + }; +} +``` + +The resulting _flavor scalar_ is therefore formed as any other flavor, as a combination of the ZkVM issuer (custodian) key and the metadata identifying the Stellar asset. + +See also [ZkVM `issue` documentation](zkvm-spec.md#issue). From 209bba96bf8db0c90ef7810f73e03050a6d04dad Mon Sep 17 00:00:00 2001 From: Oleg Andreev Date: Thu, 25 Apr 2019 17:10:16 -0700 Subject: [PATCH 2/7] WIP --- zkvm/docs/import-spec.md | 54 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/zkvm/docs/import-spec.md b/zkvm/docs/import-spec.md index f33d1c8e0..290649873 100644 --- a/zkvm/docs/import-spec.md +++ b/zkvm/docs/import-spec.md @@ -4,11 +4,59 @@ This protocol defines the process of importing of assets originally issued on th The protocol uses _trusted custodian_ secured with multi-signatures and stateless validation (only the blockchain state is used). -## Importing assets +## Definitions + +Some funds exist on a _main chain_. + +These may be _pegged in_. +This means the funds are immobilized and may not be used in any way on the main chain until they are _pegged out_. + +Once funds are _pegged in_, they are _imported_ to the sidechain. +Importing means issuing new value on the sidechain that corresponds 1:1 with the pegged-in funds. + +Imported funds may subsequently be _exported_. Exported funds are permanently retired from the sidechain. + +Once funds have been exported from the sidechain, +the corresponding funds on the main chain may be _pegged out_, +or released from immobilization. + +TBD: define user, custodian-node, custodian-signer. + +## Peg in + +This is a multi-step process that requires actions from +both the user and the custodian who secures the peg. + +#### Preparation step + +The user prepares an empty output on the ZkVM chain that would uniquely identify the import of assets from the Stellar chain. + +The output specifies the stellar asset, quantity and the destination predicate where the user wishes to receive the asset. + +TBD: specify the contract + +This step requires no cooperation from the custodian. + +TBD: this can be extended to support multiple assets imported under one predicate for certain multi-asset contracts. + +#### Deposit step + +The user makes a Stellar transaction paying the specified quantity of the Stellar asset +with a "memo" field containing the ZkVM output ID. + + +#### Peg-in step + +The custodian-node notices the incoming payment and finds the identified output ID. + +Custodian-node forms a transaction that + +TBD: should we automagically make tx on ZkVM, or simply return signed blob to the user to perform tx themselves? +The latter is working better with utxo proofs, and makes less moves on the network, but requires extra actions from the user. +However, user needs to create a token anyway, so these operations can all be turned around quickly within one session (also unconfirmed txs can be chained). -TBD: -## Exporting assets +## Peg out TBD: From 5eec5511092cf69409f2ea9abb7fb23ad6f89ebb Mon Sep 17 00:00:00 2001 From: Oleg Andreev Date: Fri, 26 Apr 2019 16:59:09 -0700 Subject: [PATCH 3/7] wip on the spec --- zkvm/docs/import-spec.md | 105 ++++++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 17 deletions(-) diff --git a/zkvm/docs/import-spec.md b/zkvm/docs/import-spec.md index 290649873..66e7ebada 100644 --- a/zkvm/docs/import-spec.md +++ b/zkvm/docs/import-spec.md @@ -2,34 +2,95 @@ This protocol defines the process of importing of assets originally issued on the Stellar into ZkVM and exporting them back to the Stellar network. -The protocol uses _trusted custodian_ secured with multi-signatures and stateless validation (only the blockchain state is used). +The assets may change hands and another user may export the asset back, than the user who imported them in the first place. + +The protocol uses _trusted custodian_ secured with multi-signatures and stateless validation (participants rely on validity of the blockchain state instead of the private state of the custodian, plus their honest ). + +* [Definitions](#definitions) +* [Peg-in specification](#peg-in-specification) +* [Peg-out specification](#peg-out-specification) +* [Flavor ID mapping](#flavor-id-mapping) ## Definitions -Some funds exist on a _main chain_. +### Main chain + +The Stellar chain where the assets are originally issued. + +### Side chain + +The ZkVM chain where the [original asset](#original-asset) is represented by the [mapped asset](#mapped-asset) issued by [custodian](#custodian). + +### Original asset + +An asset originally issued on the [main chain](#main-chain). + +### Mapped asset + +An asset issued on the [side chain](#side-chain) with an intent to represent a corresponding [original asset](#original-asset) implementing a [peg](#peg). + +### User + +A party that controls an [original asset](#original-asset) and wishes to [peg](#peg) it to the [side chain](#side-chain) in order to perform trades using it there. + +### Custodian + +A party that is trusted to hold 1:1 balance between the [deposited](#deposit) assets on the [main chain](#main-chain) +and the [imported](#import) assets on the [side chain](#side-chain). + +### Custodian-signer + +A component of the [custodian](#custodian) that performs a signing protocol for [import](#import) or [withdrawal](#withdrawal). + +### Custodian-node + +A component of the [custodian](#custodian) that performs service functions such as +locating [deposits](#deposit) and [exports](#export), building transactions and +routing data to the [custodian-signer](#custodian-signer). -These may be _pegged in_. -This means the funds are immobilized and may not be used in any way on the main chain until they are _pegged out_. +### Peg -Once funds are _pegged in_, they are _imported_ to the sidechain. -Importing means issuing new value on the sidechain that corresponds 1:1 with the pegged-in funds. +The property of an [original asset](#original-asset) to be immobilized on the [main chain](#main-chain) (with the support of [custodian](#custodian)), +while being represented with a [mapped asset](#mapped-asset) on the [side chain](#side-chain). -Imported funds may subsequently be _exported_. Exported funds are permanently retired from the sidechain. +Assets can be [pegged in](#peg-in) an [pegged out](#peg-out). -Once funds have been exported from the sidechain, -the corresponding funds on the main chain may be _pegged out_, -or released from immobilization. +### Peg in -TBD: define user, custodian-node, custodian-signer. +A combination of [deposit](#deposit) and [import](#import) actions resulting in a [peg](#peg). -## Peg in +### Peg out + +A combination of [export](#export) and [withdrawal](#withdrawal) actions that undo the [peg](#peg) for a given asset. + +### Deposit + +Transfer of an [original asset](#original-asset) by [user](#user) to the [custodian](#custodian) on the [main chain](#main-chain), +which is followed by an [import](#import) action. + +### Withdrawal + +Transfer of an [original asset](#original-asset) from the [custodian](#custodian) to a [user](#user) on the [main chain](#main-chain), +following an [export](#export) action. + +### Import + +Issuance of the [mapped asset](#mapped-asset) by the [custodian](#custodian) followed by the [deposit](#deposit). + +### Export + +Retirement of the [mapped asset](#mapped-asset) by the [user](#user) in order to perform [withdrawal](#withdrawal). + + +## Peg in specification This is a multi-step process that requires actions from both the user and the custodian who secures the peg. #### Preparation step -The user prepares an empty output on the ZkVM chain that would uniquely identify the import of assets from the Stellar chain. +The user prepares an input on the ZkVM chain, the [contract ID](zkvm-spec.md#contract-id) of which +will be a unique anchor for the [issuance contract](zkvm-spec.md#issue) for the imported funds. The output specifies the stellar asset, quantity and the destination predicate where the user wishes to receive the asset. @@ -56,13 +117,23 @@ The latter is working better with utxo proofs, and makes less moves on the netwo However, user needs to create a token anyway, so these operations can all be turned around quickly within one session (also unconfirmed txs can be chained). -## Peg out -TBD: -## Asset to flavor mapping +## Peg out specification + +TBD: + +Sketch: + +Prepare a unique account (starting seq num is the ledger's seqno), and pre-determined transaction that merges it back in, +perform export/retire, ask signer to sign that tx that pays to a destination address and also merges that account. + +The signer has to check that tx they are signing has that one merge operation which guarantees replay prevention (simply sequence number won't do as it can be updated with other requests). It should be possible to batch concurrent withdrawals in one tx, that has multiple pairs of (pay-out, unique-acc-merge) operations corresponding to the respective exports in zkvm. + + +## Flavor ID mapping -To map the stellar asset, we will use `metadata` argument that represents an XDR-encoded `Asset` structure +To map the Stellar asset into ZkVM flavor, we will use `metadata` argument that represents an XDR-encoded `Asset` structure as specified in the `Stellar-ledger-entries.x` XDR file: ``` From 544e50554e0790f37249e789c24009c0b004117b Mon Sep 17 00:00:00 2001 From: Oleg Andreev Date: Fri, 26 Apr 2019 17:10:50 -0700 Subject: [PATCH 4/7] wip --- zkvm/docs/import-spec.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/zkvm/docs/import-spec.md b/zkvm/docs/import-spec.md index 66e7ebada..13db8aec3 100644 --- a/zkvm/docs/import-spec.md +++ b/zkvm/docs/import-spec.md @@ -82,6 +82,9 @@ Issuance of the [mapped asset](#mapped-asset) by the [custodian](#custodian) fol Retirement of the [mapped asset](#mapped-asset) by the [user](#user) in order to perform [withdrawal](#withdrawal). + + + ## Peg in specification This is a multi-step process that requires actions from @@ -92,25 +95,28 @@ both the user and the custodian who secures the peg. The user prepares an input on the ZkVM chain, the [contract ID](zkvm-spec.md#contract-id) of which will be a unique anchor for the [issuance contract](zkvm-spec.md#issue) for the imported funds. -The output specifies the stellar asset, quantity and the destination predicate where the user wishes to receive the asset. - -TBD: specify the contract - This step requires no cooperation from the custodian. TBD: this can be extended to support multiple assets imported under one predicate for certain multi-asset contracts. #### Deposit step -The user makes a Stellar transaction paying the specified quantity of the Stellar asset -with a "memo" field containing the ZkVM output ID. +TBD: user makes a payment with a well-formed memo field to the custodian's address. + +#### Import step + +TBD. + +Custodian-signer receives two pieces of data: + +1. A proof of a stellar deposit: a transaction, a proof of publication in the chain, and externalized SCP message trusted by the custodian. +2. Components of the issuance to be signed on the ZkVM: check the anchor ID specified in the memo field, compose metadata based on [flavor id mapping rule](#flavor-id-mapping), form qty commitment. +Signs the program from the memo field, and the computed contract ID for a given asset, and returns the signature. -#### Peg-in step +User receives the signature, uses it in their zkvm transaction, and satisfies the signed program with the user's signature. The asset is moved/split how the user wishes. -The custodian-node notices the incoming payment and finds the identified output ID. -Custodian-node forms a transaction that TBD: should we automagically make tx on ZkVM, or simply return signed blob to the user to perform tx themselves? The latter is working better with utxo proofs, and makes less moves on the network, but requires extra actions from the user. From 10136448a4edda7b8ca22e7b7d2a6df229acd8cc Mon Sep 17 00:00:00 2001 From: Oleg Andreev Date: Tue, 30 Apr 2019 13:30:52 -0700 Subject: [PATCH 5/7] wip --- zkvm/docs/import-spec.md | 77 ++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/zkvm/docs/import-spec.md b/zkvm/docs/import-spec.md index 13db8aec3..e0b298796 100644 --- a/zkvm/docs/import-spec.md +++ b/zkvm/docs/import-spec.md @@ -83,6 +83,9 @@ Retirement of the [mapped asset](#mapped-asset) by the [user](#user) in order to +## Setup + +Custodian is initialized with a multi-signature account that [pegs](#peg) all the received funds. ## Peg in specification @@ -92,38 +95,84 @@ both the user and the custodian who secures the peg. #### Preparation step -The user prepares an input on the ZkVM chain, the [contract ID](zkvm-spec.md#contract-id) of which +The user prepares an unspent output on the ZkVM chain, the [contract ID](zkvm-spec.md#contract-id) of which will be a unique anchor for the [issuance contract](zkvm-spec.md#issue) for the imported funds. +This output can be specifically created for the purpose of this protocol, +or simply locked within the user’s wallet to not be accidentally spent by other transaction. + +User also prepares a program to be signed by the [custodian](#custodian) which allows user to authorize spending of the [mapped asset](#mapped-asset). -This step requires no cooperation from the custodian. +The program can be anything. The simplest option is to lock the [mapped asset](#mapped-asset) by the user’s public key, +then the user can author any transaction spending this asset themselves. -TBD: this can be extended to support multiple assets imported under one predicate for certain multi-asset contracts. +``` +push: contract:1 +``` #### Deposit step -TBD: user makes a payment with a well-formed memo field to the custodian's address. +User forms a transaction paying to the custodian’s account N units of asset A, with a memo string of type `MEMO_HASH` the identifies the [import](#import) on the ZkVM chain. -#### Import step +The memo is a 32-byte hash computed as follows: + +``` +T = Transcript::new("ZkVM.import") +T.commit("program", program) // user’s authorization program to be signed by the custodian +T.commit("anchor", anchor) // contract ID to be used as an anchor in the issuance contract +memo = T.challenge_bytes() +``` -TBD. +User signs and publishes the [deposit](#deposit) transaction. -Custodian-signer receives two pieces of data: +#### Signing step -1. A proof of a stellar deposit: a transaction, a proof of publication in the chain, and externalized SCP message trusted by the custodian. -2. Components of the issuance to be signed on the ZkVM: check the anchor ID specified in the memo field, compose metadata based on [flavor id mapping rule](#flavor-id-mapping), form qty commitment. +Once the [deposit](#deposit) transaction is published, user and [custodian-signer](#custodian-signer) perform the following stateless protocol: -Signs the program from the memo field, and the computed contract ID for a given asset, and returns the signature. +First, user sends a reference to the deposit transaction, `program` and `anchor`. -User receives the signature, uses it in their zkvm transaction, and satisfies the signed program with the user's signature. The asset is moved/split how the user wishes. +In response, custodian-signer: +1. Takes the first payment, ignores the rest and reads `Asset` structure and the paid quantity. +2. Verifies that the `MEMO_HASH` matches the `program` and `anchor` specified by the user (see above). +3. Computes an unblinded `qty` commitment based on the quantity. +4. Forms a metadata string for the `issue` instruction as XDR encoding of the `Asset` structure. See [Flavor ID mapping](#flavor-id-mapping). +5. Computes the ZkVM [flavor ID](zkvm-spec.md#issue) using its ZkVM issuance predicate and the metadata string. This defines the flavor ID for the [mapped asset](#mapped-asset). +6. Creates a contract with the `anchor`, issuance predicate and the Value object with unblinded quantity and flavor commitments. +7. Computes the [contract ID](zkvm-spec.md#contract-id) of the resulting contract. +8. Signs user’s `program` and the issuance contract ID for the [`delegate`](zkvm-spec.md#delegate) instruction. +9. Returns the signature to the user. +Note: this protocol can be safely replayed arbitrary number of times because both the Stellar payment +is tied to the same unique anchor (embedded in a `MEMO_HASH`) as the ZkVM signature for the delegate instruction +(which covers the issuance contract that uses the anchor). -TBD: should we automagically make tx on ZkVM, or simply return signed blob to the user to perform tx themselves? -The latter is working better with utxo proofs, and makes less moves on the network, but requires extra actions from the user. -However, user needs to create a token anyway, so these operations can all be turned around quickly within one session (also unconfirmed txs can be chained). +Future work: + +1. this can be extended to support multiple assets imported under one predicate for certain multi-asset contracts. +2. multiple payments to the custodian can also be supported and not be ignored. + +#### Import step + +User forms a transaction that spends the previously allocated unspent output, followed by the following issuance snippet: + +``` + input + issue + delegate +... +``` +where: +* `utxo` is the serialized UTXO that the user is spending, and which contract ID is used as an anchor in the issuance contract. +* `Q` is an unblinded quantity commitment. +* `F` is an unblinded flavor commitment. +* `XDR(Asset)` is metadata string — XDR-serialized `Asset` structure describing the [original asset](#original-asset) type. +* `issuance_predicate` is the custodian’s issuance predicate for which the `signature` is provided. +* `user_prog` is the user-provided authorization program embedded into `MEMO_HASH` on the [main chain](#main-chain). +* `signature` is the custodian-signer’s signature corresponding to the `issuance_predicate`. +TBD: a sketch of what user needs to do to allow non-interactive issuance. ## Peg out specification From f7aabf9766e77cc4f2c5a7edfc24fe3001ce6a3c Mon Sep 17 00:00:00 2001 From: Oleg Andreev Date: Tue, 30 Apr 2019 16:24:52 -0700 Subject: [PATCH 6/7] peg-out spec and tweaks --- zkvm/docs/import-spec.md | 169 ++++++++++++++++++++++++++++----------- 1 file changed, 124 insertions(+), 45 deletions(-) diff --git a/zkvm/docs/import-spec.md b/zkvm/docs/import-spec.md index e0b298796..4df0c65ee 100644 --- a/zkvm/docs/import-spec.md +++ b/zkvm/docs/import-spec.md @@ -4,13 +4,15 @@ This protocol defines the process of importing of assets originally issued on th The assets may change hands and another user may export the asset back, than the user who imported them in the first place. -The protocol uses _trusted custodian_ secured with multi-signatures and stateless validation (participants rely on validity of the blockchain state instead of the private state of the custodian, plus their honest ). +The protocol uses _trusted custodian_ secured with multi-signatures and stateless validation (everyone relies only on validity of the blockchain state and honest execution of the stateless signers). * [Definitions](#definitions) +* [Setup](#setup) * [Peg-in specification](#peg-in-specification) * [Peg-out specification](#peg-out-specification) * [Flavor ID mapping](#flavor-id-mapping) + ## Definitions ### Main chain @@ -38,16 +40,6 @@ A party that controls an [original asset](#original-asset) and wishes to [peg](# A party that is trusted to hold 1:1 balance between the [deposited](#deposit) assets on the [main chain](#main-chain) and the [imported](#import) assets on the [side chain](#side-chain). -### Custodian-signer - -A component of the [custodian](#custodian) that performs a signing protocol for [import](#import) or [withdrawal](#withdrawal). - -### Custodian-node - -A component of the [custodian](#custodian) that performs service functions such as -locating [deposits](#deposit) and [exports](#export), building transactions and -routing data to the [custodian-signer](#custodian-signer). - ### Peg The property of an [original asset](#original-asset) to be immobilized on the [main chain](#main-chain) (with the support of [custodian](#custodian)), @@ -85,7 +77,15 @@ Retirement of the [mapped asset](#mapped-asset) by the [user](#user) in order to ## Setup -Custodian is initialized with a multi-signature account that [pegs](#peg) all the received funds. +[Custodian](#custodian) is initialized with: + +1. A multi-signature account on [main chain](#main-chain) that [pegs](#peg) all the received [original assets](#original-asset). +2. A multi-signature predicate on [side chain](#side-chain) that issues the [mapped assets](#mapped-asset). +3. A quorum slice configuration for each chain (main + side) which will be used to verify publication of the transaction. + +[Users](#user) are assumed to know about the above configuration (e.g. it is built into the wallets), +and can derive all subsequent data such as [flavor IDs](#flavor-id-mapping). + ## Peg in specification @@ -95,14 +95,13 @@ both the user and the custodian who secures the peg. #### Preparation step -The user prepares an unspent output on the ZkVM chain, the [contract ID](zkvm-spec.md#contract-id) of which +[User](#user) prepares an unspent output on the ZkVM chain, the [contract ID](zkvm-spec.md#contract-id) of which will be a unique anchor for the [issuance contract](zkvm-spec.md#issue) for the imported funds. This output can be specifically created for the purpose of this protocol, or simply locked within the user’s wallet to not be accidentally spent by other transaction. -User also prepares a program to be signed by the [custodian](#custodian) which allows user to authorize spending of the [mapped asset](#mapped-asset). - -The program can be anything. The simplest option is to lock the [mapped asset](#mapped-asset) by the user’s public key, +User also prepares a `program` to be signed by the [custodian](#custodian) which allows user to authorize spending of the [mapped asset](#mapped-asset). +The `program` can be anything. The simplest option is to lock the [mapped asset](#mapped-asset) by the user’s public key, then the user can author any transaction spending this asset themselves. ``` @@ -119,46 +118,55 @@ The memo is a 32-byte hash computed as follows: T = Transcript::new("ZkVM.import") T.commit("program", program) // user’s authorization program to be signed by the custodian T.commit("anchor", anchor) // contract ID to be used as an anchor in the issuance contract -memo = T.challenge_bytes() +memo = T.challenge_bytes("memo") ``` User signs and publishes the [deposit](#deposit) transaction. #### Signing step -Once the [deposit](#deposit) transaction is published, user and [custodian-signer](#custodian-signer) perform the following stateless protocol: +Once the [deposit](#deposit) transaction is published, user and [custodian](#custodian) perform the following stateless protocol: -First, user sends a reference to the deposit transaction, `program` and `anchor`. +First, user sends a reference to the [deposit](#deposit) transaction, `program` and `anchor`. -In response, custodian-signer: +In response, custodian: -1. Takes the first payment, ignores the rest and reads `Asset` structure and the paid quantity. -2. Verifies that the `MEMO_HASH` matches the `program` and `anchor` specified by the user (see above). -3. Computes an unblinded `qty` commitment based on the quantity. -4. Forms a metadata string for the `issue` instruction as XDR encoding of the `Asset` structure. See [Flavor ID mapping](#flavor-id-mapping). -5. Computes the ZkVM [flavor ID](zkvm-spec.md#issue) using its ZkVM issuance predicate and the metadata string. This defines the flavor ID for the [mapped asset](#mapped-asset). -6. Creates a contract with the `anchor`, issuance predicate and the Value object with unblinded quantity and flavor commitments. -7. Computes the [contract ID](zkvm-spec.md#contract-id) of the resulting contract. -8. Signs user’s `program` and the issuance contract ID for the [`delegate`](zkvm-spec.md#delegate) instruction. -9. Returns the signature to the user. +1. [Custodian](#custodian) verifies that the deposit transaction is published (via hash-links to a ledger that’s signed by an externalized SCP message with quorum slice trusted by the custodian). +2. Takes the first payment, ignores the rest and reads `Asset` structure and the paid quantity. +3. Verifies that the `MEMO_HASH` matches the `program` and `anchor` specified by the user (see above). +4. Computes an unblinded `qty` commitment based on the quantity. +5. Forms a metadata string for the `issue` instruction as XDR encoding of the `Asset` structure. See [Flavor ID mapping](#flavor-id-mapping). +6. Computes the ZkVM [flavor ID](zkvm-spec.md#issue) using its ZkVM issuance predicate and the metadata string. This defines the flavor ID for the [mapped asset](#mapped-asset). +7. Creates a contract with the `anchor`, issuance predicate and the Value object with unblinded quantity and flavor commitments. +8. Computes the [contract ID](zkvm-spec.md#contract-id) of the resulting contract. +9. Signs user’s `program` and the issuance contract ID for the [`delegate`](zkvm-spec.md#delegate) instruction, producing `signature`. +10. Returns the `signature` to the user. -Note: this protocol can be safely replayed arbitrary number of times because both the Stellar payment -is tied to the same unique anchor (embedded in a `MEMO_HASH`) as the ZkVM signature for the delegate instruction -(which covers the issuance contract that uses the anchor). +Note: this protocol can be safely replayed arbitrary number of times because both the Stellar deposit and ZkVM issuance +are tied to the same unique anchor (embedded in a `MEMO_HASH`) — the ZkVM signature for the `delegate` instruction covers the issuance contract, which in turn contains the anchor. -Future work: +Future work: 1. this can be extended to support multiple assets imported under one predicate for certain multi-asset contracts. -2. multiple payments to the custodian can also be supported and not be ignored. +2. multiple payments to the custodian in the same transaction can also be supported instead of being ignored. #### Import step User forms a transaction that spends the previously allocated unspent output, followed by the following issuance snippet: ``` - input - issue - delegate +push: +input + +push: +push: +push: +push: +issue + +push: +push: +delegate ... ``` @@ -170,20 +178,82 @@ where: * `XDR(Asset)` is metadata string — XDR-serialized `Asset` structure describing the [original asset](#original-asset) type. * `issuance_predicate` is the custodian’s issuance predicate for which the `signature` is provided. * `user_prog` is the user-provided authorization program embedded into `MEMO_HASH` on the [main chain](#main-chain). -* `signature` is the custodian-signer’s signature corresponding to the `issuance_predicate`. +* `signature` is the custodian’s signature corresponding to the `issuance_predicate`. + + + -TBD: a sketch of what user needs to do to allow non-interactive issuance. ## Peg out specification -TBD: -Sketch: +#### Preparation step + +1. [User](#user) creates a new temporary account `T` that will be used as a uniqueness anchor when performing [withdrawal](#withdrawal). The account must be funded with 2 XLM to satisify minimum account balance and cost of `SetOptions` operation. The remaining balance will be returned to the user’s account. +2. When the temporary account `T` is created, its sequence number is known and can be used in the following step. +3. User forms a withdrawal transaction with the account `T` being the source account with incremented sequence number. Another operation is withdrawal of required quantity of the [original asset](#original-asset) from the custodian’s account. That operation does not consume the sequence number of the custodian, allowing publication of the withdrawal transactions in any order. +4. User computes the withdrawal transaction ID. +5. User signs the withdrawal transaction ID with the T’s key. + +#### Export step + +User builds an [export transaction](#export) that retires the [mapped asset](#mapped-asset) value with _unblinded commitments_. + +User also provides an annotation that links that transaction to an exact state of the temporary account on the [main chain](#main-chain). +The annotation must be done as an immediate `log` instruction that follows the `retire` instruction. +The corresponding entries in the transaction log will be checked to be adjacent to avoid ambiguity and prevent double-withdrawal attacks. + +``` + retire + log +``` + +The annotation `memo` is computed as follows: + +``` +T = Transcript::new("ZkVM.export") +T.commit("anchor_acc", temp_account_id) +T.commit("anchor_seq", temp_account_new_sequence_number) +T.commit("qty", L64E(qty)) +T.commit("asset", XDR(Asset)) +memo = T.challenge_bytes("memo") +``` + +The annotation is linked to a unique anchor (account ID + sequence number), and also describes the quantity and the type of the [original asset](#original-asset). + +The export transaction is published on the [side chain](#side-chain). + +#### Signing step + +User sends to custodian: -Prepare a unique account (starting seq num is the ledger's seqno), and pre-determined transaction that merges it back in, -perform export/retire, ask signer to sign that tx that pays to a destination address and also merges that account. +1. the proof of publication of the export transaction to the [custodian](#custodian), +2. data embedded into the `memo` hash (account id, sequence number, asset structure and quantity), +3. an index of the [retire entry](zkvm-spec.md#retire-entry) in the transaction log, +4. withdrawal transaction formed previously. -The signer has to check that tx they are signing has that one merge operation which guarantees replay prevention (simply sequence number won't do as it can be updated with other requests). It should be possible to batch concurrent withdrawals in one tx, that has multiple pairs of (pay-out, unique-acc-merge) operations corresponding to the respective exports in zkvm. +Custodian: + +1. Checks that the export transaction is actually published (by following merkle path to a block signed via externalized SCP message with pre-arranged quorum slice configuration). +2. Computes the memo hash with the raw data: account ID and sequence number, plaintext quantity and Asset structure. +3. Verifies that this memo hash is embedded in the [log entry](zkvm-spec.md#log-entry) immediately after the [retire entry](zkvm-spec.md#retire-entry) in question. +4. Verifies that the retired quantity is an unblinded commitment to the specified quantity: `Q == qty·B`. +5. Verifies that the retired flavor is an unblinded commitment to the [mapped flavor](#flavor-id-mapping): `F == flv·B`. +6. Verifies that the source of the withdrawal transaction is the specified temporary account. +7. Verifies that the sequence number of the withdrawal transaction is equal to the earlier specified sequence number. +8. Verifies that the first operation is an [Account Merge](https://www.stellar.org/developers/guides/concepts/list-of-operations.html#account-merge). +9. Verifies that the second operation is a payment of exactly `qty` units of the Stellar asset specified above. +10. Verifies that there are no other operations in the transaction. +11. Signs the withdrawal transaction and returns the signature to the user. + +Note: this protocol can be safely replayed arbitrary number of times because both the ZkVM retirement and Stellar withdrawal +are tied to the same unique anchor (pair of account ID and sequence number). + + +#### Withdrawal step + +User adds the custodian’s signature to the transaction, alongside with theirs +(to authorize merge of the temporary account), and publishes it on the [main chain](#main-chain). ## Flavor ID mapping @@ -220,6 +290,15 @@ namespace stellar { } ``` +The XDR-encoded metadata is used to compute the issued flavor per [`issue`](zkvm-spec.md#issue) specification +using the custodian’s issuance predicate: + +``` +T = Transcript("ZkVM.issue") +T.commit("predicate", issuance_predicate) +T.commit("metadata", XDR(Asset)) +flavor = T.challenge_scalar("flavor") +``` + The resulting _flavor scalar_ is therefore formed as any other flavor, as a combination of the ZkVM issuer (custodian) key and the metadata identifying the Stellar asset. -See also [ZkVM `issue` documentation](zkvm-spec.md#issue). From 322898ac2e07e28627b393bee5a40a7dba183a59 Mon Sep 17 00:00:00 2001 From: Oleg Andreev Date: Tue, 30 Apr 2019 16:38:41 -0700 Subject: [PATCH 7/7] fix --- zkvm/docs/import-spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zkvm/docs/import-spec.md b/zkvm/docs/import-spec.md index 4df0c65ee..3829821d4 100644 --- a/zkvm/docs/import-spec.md +++ b/zkvm/docs/import-spec.md @@ -236,7 +236,7 @@ Custodian: 1. Checks that the export transaction is actually published (by following merkle path to a block signed via externalized SCP message with pre-arranged quorum slice configuration). 2. Computes the memo hash with the raw data: account ID and sequence number, plaintext quantity and Asset structure. -3. Verifies that this memo hash is embedded in the [log entry](zkvm-spec.md#log-entry) immediately after the [retire entry](zkvm-spec.md#retire-entry) in question. +3. Verifies that this memo hash is embedded in the [log entry](zkvm-spec.md#data-entry) immediately after the [retire entry](zkvm-spec.md#retire-entry) in question. 4. Verifies that the retired quantity is an unblinded commitment to the specified quantity: `Q == qty·B`. 5. Verifies that the retired flavor is an unblinded commitment to the [mapped flavor](#flavor-id-mapping): `F == flv·B`. 6. Verifies that the source of the withdrawal transaction is the specified temporary account.