-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BSIP 53: Detection of inbound Stealth transactions #116
base: master
Are you sure you want to change the base?
Conversation
Not sure if PR should include edits to table in README.md, so these are segregated into separate commits. |
It should, normally, although that often leads to conflicts. |
Not the best place for this discussion, but: I have a task on my list to update the README.md file with the known BSIP identifiers, status and links. The thought is that the repo Maintainer will own that file and then the Authors can focus on their drafts within the PR. The README will link to the PR discussion until the BSIP draft is merged. Thoughts? |
Would love to see this merged soon as an “initial draft.” Obviously, further refinements and additions will still need to follow in response to community feedback, thus while this PR may close, I presume that issue #91 will stay open as the discussion hub for this BSIP. But hopefully this initial draft can merge and be considered a “milestone”? One item I’ll be working on very soon is doing some performance benchmarks to assess wallet efficiency in scanning network activity for owned transaction outputs. The basis of the scanning algorithm is recently implemented in a Kotlin library in the @Agorise repo here: https://github.com/Agorise/bitshares-stealth-k. Kotlin compiles to the Java Virtual Machine and this library is targeted towards smartphones. I’ll be running the benchmarks on a 2014 MacBook Pro and on a Raspberry Pi to gauge how quickly a “day’s” worth of activity can be scanned on various hardware. I will make a table of results and post in issue #91 and eventually merge into the BSIP doc as part of the edits and revisions phase. I estimate a few hours of work to run and tabulate these benchmarks. I may follow that up with some investigations of strategies for increasing scanning performance. Tagging: @ryanRfox |
A confidential transaction (cTX) does not identify the recipient. As such, there is no direct way for a wallet to use only its Stealth address to query the p2p network for inbound transactions. In the current "phase one" implementation of Stealth ([BSIP-0008](bsip-0008.md)), inbound discovery is a manual process requiring the sender to communicate "transaction receipts" to the intended recipients of each transaction output in order to alert each recipient of their incoming balance. Transaction receipts are encrypted data structures that embed the Pedersen commitment of the transaction output and the value and blinding factor that the recipient needs to "open" the commitment. Additionally, the receipt records the one-time public key which the recipient must use to derive the private key offset needed to spend the incoming coin, via a shared-secret procedure between the one-time key and the recipient's address key. The need to communicate transaction receipts is burdensome and introduces substantial risk of lost funds due to failure to communicate or retain receipts. | ||
|
||
_Keys involved in a cTX output (cTXO):_ | ||
* **One-Time Key (OTK)** — The sender generates this key (public and private) from randomness and uses it to generate a shared-secret between the OTK and the recipient's Address ViewKey. The OTK PubKey will be clear-text encoded in the Tx receipt, and optionally also recorded in the transaction output to enable automated discovery. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe swap the order of OTK description with ViewKey and AuthKey description because OTK references ViewKey
|
||
_Keys involved in a cTX output (cTXO):_ | ||
* **One-Time Key (OTK)** — The sender generates this key (public and private) from randomness and uses it to generate a shared-secret between the OTK and the recipient's Address ViewKey. The OTK PubKey will be clear-text encoded in the Tx receipt, and optionally also recorded in the transaction output to enable automated discovery. | ||
* **Address Keys (ViewKey and SpendKey)** — These are public keys encoded in the recipient's stealth address. The goal of a stealth address scheme is to _not_ identify these public keys in any transaction output. A long-form address encodes _two_ public keys, referred to as ViewKey and SpendKey. The SpendKey serves as a base point from which individual Tx output AuthKeys are computed as an offset, and the ViewKey is used with the OTK to compute that offset. A short-form address encodes only a single public key, which serves as both the ViewKey and SpendKey. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will a sender learn about a recipient's ViewKey and SpendKey?
_Keys involved in a cTX output (cTXO):_ | ||
* **One-Time Key (OTK)** — The sender generates this key (public and private) from randomness and uses it to generate a shared-secret between the OTK and the recipient's Address ViewKey. The OTK PubKey will be clear-text encoded in the Tx receipt, and optionally also recorded in the transaction output to enable automated discovery. | ||
* **Address Keys (ViewKey and SpendKey)** — These are public keys encoded in the recipient's stealth address. The goal of a stealth address scheme is to _not_ identify these public keys in any transaction output. A long-form address encodes _two_ public keys, referred to as ViewKey and SpendKey. The SpendKey serves as a base point from which individual Tx output AuthKeys are computed as an offset, and the ViewKey is used with the OTK to compute that offset. A short-form address encodes only a single public key, which serves as both the ViewKey and SpendKey. | ||
* **Tx Output Authorization Key (AuthKey)** — This public key will be recorded in the confidential transaction output (cTXO) as the key which is authorized to spend the commitment. This key is offset from the address SpendKey by a secret offset that only the sender and recipient can calculate (from the shared secret between OTK and ViewKey). The sender can only know the offset, but not the full secret key to the AuthKey. The recipient, knowing the private key behind the SpendKey, can compute the private key to AuthKey and therefore can spend the commitment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe change "This public key" to "This short-form public key"
* **Address Keys (ViewKey and SpendKey)** — These are public keys encoded in the recipient's stealth address. The goal of a stealth address scheme is to _not_ identify these public keys in any transaction output. A long-form address encodes _two_ public keys, referred to as ViewKey and SpendKey. The SpendKey serves as a base point from which individual Tx output AuthKeys are computed as an offset, and the ViewKey is used with the OTK to compute that offset. A short-form address encodes only a single public key, which serves as both the ViewKey and SpendKey. | ||
* **Tx Output Authorization Key (AuthKey)** — This public key will be recorded in the confidential transaction output (cTXO) as the key which is authorized to spend the commitment. This key is offset from the address SpendKey by a secret offset that only the sender and recipient can calculate (from the shared secret between OTK and ViewKey). The sender can only know the offset, but not the full secret key to the AuthKey. The recipient, knowing the private key behind the SpendKey, can compute the private key to AuthKey and therefore can spend the commitment. | ||
|
||
Automated discovery could be enabled if the receipt were embedded within the transaction data structure and if an aspect of that data structure supported a challenge condition which the recipient could recognize. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe elaborate on the purpose of a challenge condition
|
||
Automated discovery could be enabled if the receipt were embedded within the transaction data structure and if an aspect of that data structure supported a challenge condition which the recipient could recognize. | ||
|
||
Current network rules allow for a receipt to be embedded in each Tx output via a `stealth_memo` field which is formatted in a similar way as the encrypted memos that may accompany regular (non-Stealth) transfer operations. These memos are composed of a header specifying the OTK PubKey and the "message PubKey" for which the recipient holds the corresponding private key, followed by cipher text which is AES encrypted with a shared-secret key between the OTK and the message PubKey. For this `stealth_memo` field, the current behavior of the CLI reference wallet is to use the recipient's Address PubKey as the message PubKey. Although this is a reasonable choice for encrypting message text generally, it has the severe downside of identifying the recipient's Address PubKey in the memo header, and therefore breaks anonymity and negates the unlinkability provided by using a stealth address scheme. For this reason, the CLI reference wallet currently does _NOT_ actually embed the memo in the Tx ouput but instead Base58 encodes it and prints it to the screen, calling it a "transaction receipt." The sender must manually, and secretly, transmit this to the recipient via a side channel. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"For this reason," sentence is a great explanation
|
||
Automated discovery could be enabled if the receipt were embedded within the transaction data structure and if an aspect of that data structure supported a challenge condition which the recipient could recognize. | ||
|
||
Current network rules allow for a receipt to be embedded in each Tx output via a `stealth_memo` field which is formatted in a similar way as the encrypted memos that may accompany regular (non-Stealth) transfer operations. These memos are composed of a header specifying the OTK PubKey and the "message PubKey" for which the recipient holds the corresponding private key, followed by cipher text which is AES encrypted with a shared-secret key between the OTK and the message PubKey. For this `stealth_memo` field, the current behavior of the CLI reference wallet is to use the recipient's Address PubKey as the message PubKey. Although this is a reasonable choice for encrypting message text generally, it has the severe downside of identifying the recipient's Address PubKey in the memo header, and therefore breaks anonymity and negates the unlinkability provided by using a stealth address scheme. For this reason, the CLI reference wallet currently does _NOT_ actually embed the memo in the Tx ouput but instead Base58 encodes it and prints it to the screen, calling it a "transaction receipt." The sender must manually, and secretly, transmit this to the recipient via a side channel. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This first reference to "message Pubkey" can be used to define "MPK"
Current network rules allow for a receipt to be embedded in each Tx output via a `stealth_memo` field which is formatted in a similar way as the encrypted memos that may accompany regular (non-Stealth) transfer operations. These memos are composed of a header specifying the OTK PubKey and the "message PubKey" for which the recipient holds the corresponding private key, followed by cipher text which is AES encrypted with a shared-secret key between the OTK and the message PubKey. For this `stealth_memo` field, the current behavior of the CLI reference wallet is to use the recipient's Address PubKey as the message PubKey. Although this is a reasonable choice for encrypting message text generally, it has the severe downside of identifying the recipient's Address PubKey in the memo header, and therefore breaks anonymity and negates the unlinkability provided by using a stealth address scheme. For this reason, the CLI reference wallet currently does _NOT_ actually embed the memo in the Tx ouput but instead Base58 encodes it and prints it to the screen, calling it a "transaction receipt." The sender must manually, and secretly, transmit this to the recipient via a side channel. | |
Current network rules allow for a receipt to be embedded in each Tx output via a `stealth_memo` field which is formatted in a similar way as the encrypted memos that may accompany regular (non-Stealth) transfer operations. These memos are composed of a header specifying the OTK PubKey and the "message PubKey" (MPK) for which the recipient holds the corresponding private key, followed by cipher text which is AES encrypted with a shared-secret key between the OTK and the message PubKey. For this `stealth_memo` field, the current behavior of the CLI reference wallet is to use the recipient's Address PubKey as the message PubKey. Although this is a reasonable choice for encrypting message text generally, it has the severe downside of identifying the recipient's Address PubKey in the memo header, and therefore breaks anonymity and negates the unlinkability provided by using a stealth address scheme. For this reason, the CLI reference wallet currently does _NOT_ actually embed the memo in the Tx ouput but instead Base58 encodes it and prints it to the screen, calling it a "transaction receipt." The sender must manually, and secretly, transmit this to the recipient via a side channel. |
|
||
Current network rules allow for a receipt to be embedded in each Tx output via a `stealth_memo` field which is formatted in a similar way as the encrypted memos that may accompany regular (non-Stealth) transfer operations. These memos are composed of a header specifying the OTK PubKey and the "message PubKey" for which the recipient holds the corresponding private key, followed by cipher text which is AES encrypted with a shared-secret key between the OTK and the message PubKey. For this `stealth_memo` field, the current behavior of the CLI reference wallet is to use the recipient's Address PubKey as the message PubKey. Although this is a reasonable choice for encrypting message text generally, it has the severe downside of identifying the recipient's Address PubKey in the memo header, and therefore breaks anonymity and negates the unlinkability provided by using a stealth address scheme. For this reason, the CLI reference wallet currently does _NOT_ actually embed the memo in the Tx ouput but instead Base58 encodes it and prints it to the screen, calling it a "transaction receipt." The sender must manually, and secretly, transmit this to the recipient via a side channel. | ||
|
||
**Stealth Memo structure: (Stealth I)** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
**Stealth Memo structure: (Stealth I)** | |
**Stealth Memo structure: (Existing: Stealth I)** |
or
**Stealth Memo structure: (Stealth I)** | |
**Existing Stealth Memo structure: (Stealth I)** |
|
||
_Proposed Stealth II behavior is to embed the AuthKey in the second slot, while still encrypting the message data with a shared key between the OTK and the Address key (specifically, the ViewKey so that watch-only wallets can read the commitment data)._ | ||
|
||
To support this strategy, a wallet will need to inspect all cTX activity on the network and test the challenge conditions on each transaction. This could be achieved if API nodes are extended to provide an API call to retrieve `stealth_memo` fields from all cTXOs appearing in a specified block range. The wallet could simply download the memos, test the challenge on each one, and identify and decrypt the ones that are destined to the wallet. No need would remain to manually transmit transaction receipts. The receipts would be embedded, compactly and unlinkably, in the Tx outputs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe emphasize the first sentence
To support this strategy, a wallet will need to inspect all cTX activity on the network and test the challenge conditions on each transaction. This could be achieved if API nodes are extended to provide an API call to retrieve `stealth_memo` fields from all cTXOs appearing in a specified block range. The wallet could simply download the memos, test the challenge on each one, and identify and decrypt the ones that are destined to the wallet. No need would remain to manually transmit transaction receipts. The receipts would be embedded, compactly and unlinkably, in the Tx outputs. | |
_To support this strategy, a wallet will need to inspect all cTX activity on the network and test the challenge conditions on each transaction._ This could be achieved if API nodes are extended to provide an API call to retrieve `stealth_memo` fields from all cTXOs appearing in a specified block range. The wallet could simply download the memos, test the challenge on each one, and identify and decrypt the ones that are destined to the wallet. No need would remain to manually transmit transaction receipts. The receipts would be embedded, compactly and unlinkably, in the Tx outputs. |
|
||
And in the second subsection, [_API requirements..._](#api-requirements-to-allow-detection-of-inbound-commitments), we propose a new API call for querying nodes for transaction outputs to be scanned for recognizable markers. This is an added feature for API nodes and does not involve any consensus changes. | ||
|
||
### Wallet procedure for recognizing own commitments |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section seems to cover more than recognizing own commitments. Maybe rename this section to "Wallet procedures", or create an explicit sub-section that covers the creation of transaction outputs.
1. Wallet has access to a set of private keys corresponding to stealth addresses which may own commitments on the blockchain. These private keys are needed to "recognize" incoming transactions. If the wallet is a watch-only wallet for a particular address, then it is assumed to have the private and public ViewKey, but only the public SpendKey. | ||
2. Wallet can query an API node for commitments occurring between specified block heights, to obtain sets of embedded receipts to scan for owned commitments. ([See below](#api-requirements-to-allow-detection-of-inbound-commitments) for this process.) | ||
|
||
We detail procedures for stealth address formats which encode either a single public key, or two distinct public keys in which one key is the ViewKey and the other the SpendKey. The single-key format is already in use on the BitShares network and is borrowed from the original Confidential Transactions specification. The dual-key format allows for additional wallet features and is borrowed from CryptoNote-based coins such as Monero. No changes to the network nodes are required for wallets to support dual-key address formats. In fact, the single-key format can be thought of as a special case of the dual-key format in which the same key is used as the ViewKey and the SpendKey. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First use of Confidential Transactions can be used to define "CT".
I also suggest emphasizing "No changes to the network nodes are required for wallets to support dual-key address formats."
We detail procedures for stealth address formats which encode either a single public key, or two distinct public keys in which one key is the ViewKey and the other the SpendKey. The single-key format is already in use on the BitShares network and is borrowed from the original Confidential Transactions specification. The dual-key format allows for additional wallet features and is borrowed from CryptoNote-based coins such as Monero. No changes to the network nodes are required for wallets to support dual-key address formats. In fact, the single-key format can be thought of as a special case of the dual-key format in which the same key is used as the ViewKey and the SpendKey. | |
We detail procedures for stealth address formats which encode either a single public key, or two distinct public keys in which one key is the ViewKey and the other the SpendKey. The single-key format is already in use on the BitShares network and is borrowed from the original Confidential Transactions (CT) specification. The dual-key format allows for additional wallet features and is borrowed from CryptoNote-based coins such as Monero. _No changes to the network nodes are required for wallets to support dual-key address formats._ In fact, the single-key format can be thought of as a special case of the dual-key format in which the same key is used as the ViewKey and the SpendKey. |
:------:|-------- | ||
**CT-style:** | Single public key and checksum. Public key _A_ serves both viewing and spending roles.<br><br> Format: `BTSaaaaaaaaaaaaaaaaaaaacccc` | ||
**CryptoNote-style:** | Two public keys plus a checksum. Public key _A_ serves the viewing role and public key _B_ serves the spending role.<br><br> Format: `BTSaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbcccc` | ||
**Invoice Nonce:** | This one encodes a single PubKey serving both the viewing and spending role, but also includes a 64-bit "nonce" or "tag" that the spending wallet is to include in the encrypted memo part of the cTXO, allowing the receiver to interpret payment as being applied to a specific invoice. <br><br> Format: `BTSaaaaaaaaaaaaaaaaaaaannnnnnnncccc` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Invoice Nonce" was not yet introduced. I suggest to either preface it, or reference the later description with "(See address-per-invoice below.)"
@MichelSantos — Thanks for the many great suggestions! I will take them all into consideration. |
|
||
We assume that the stealth address encodes public keys corresponding to two purposes: discovery, and expenditure. When an address encodes only one public key, that key is used for both purposes. We refer to the key for discovery as the "view" key, and denote the private, public pair as _(v, ViewKey)_. For spending, we denote the key pair as _(s, SpendKey)_. | ||
|
||
The AuthKey for a cTXO is an EC point summation of the address's SpendKey and an EC point "offset," which, for present purposes we will denote by the private, public pair _(o, Offset)_, with _Offset = o*G_, where _G_ is the generator point for the curve. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"EC" is probably "elliptic curve" but is not defined anywhere
Algorithm | Description / Specification | ||
:---:|:--------------------------- | ||
_Shared(a,B) → secret <br> Shared(A,b) → secret_ | This yields a "shared secret" between public keys _A_ and _B_ computable only by parties possessing at least one of the private keys _a_ and _b_.<br><br> _secret = SHA512(P<sub>X</sub>)_; _P = aB = Ab_<br><br>For BitShares Stealth, the secret is a byte buffer (64 bytes) computed from the SHA512 hash of the encoded _X_ coordinate (32 bytes) of EC point _P_. (c.f. [EC Diffie-Hellman](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie–Hellman).) | ||
_ChildOffset(B,index) → offset_ | This yields an integer-valued private key _offset_ that generates the keypair _(offset, Offset = offset*G)_. The offset is considered to be a "child" of key _B_, and the parameter _index_ is a byte buffer.<br><br> _child = BigInteger(SHA256(Compressed(B)_ || _index))_<br><br>_Compressed(B)_ refers to the SEC1 "compressed" representation of public key _B_. The || symbol refers to concatenation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the explicit connection between "offset" and "child"? Is "child" an output value that is another name for the "child" output value?
_Shared(a,B) → secret <br> Shared(A,b) → secret_ | This yields a "shared secret" between public keys _A_ and _B_ computable only by parties possessing at least one of the private keys _a_ and _b_.<br><br> _secret = SHA512(P<sub>X</sub>)_; _P = aB = Ab_<br><br>For BitShares Stealth, the secret is a byte buffer (64 bytes) computed from the SHA512 hash of the encoded _X_ coordinate (32 bytes) of EC point _P_. (c.f. [EC Diffie-Hellman](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie–Hellman).) | ||
_ChildOffset(B,index) → offset_ | This yields an integer-valued private key _offset_ that generates the keypair _(offset, Offset = offset*G)_. The offset is considered to be a "child" of key _B_, and the parameter _index_ is a byte buffer.<br><br> _child = BigInteger(SHA256(Compressed(B)_ || _index))_<br><br>_Compressed(B)_ refers to the SEC1 "compressed" representation of public key _B_. The || symbol refers to concatenation. | ||
|
||
**Sending:** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the "Sending" and "Receiving" sections specific to the "Procedure for single-key stealth addresses (CT-style)" or common to "CT-style", "CryptoNote-style", and "Invoice Nonce" address formats? The reason for the question is because the current formatting suggests that it is specific to "CT-style" only.
|
||
The dual-key format separates the duties of spending a commitment from those of reading the commitment, such that a person in possession of only the "viewing key" (the private key corresponding to the additional pubkey in the address) can discover, interpret, and tally incoming transactions, but _cannot_ spend them. The "spending key" (private key corresponding to the primary pubkey in the address) is needed to authorize the spending of a commitment. The dual-key address format and signing procedures are described in detail in [[vS13]](#references) and reviewed below. | ||
|
||
#### Procedure for single-key stealth addresses (CT-style) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is there no section for CryptoNote-style and "Invoice Nonce" address formats?
|
||
**Receiving:** | ||
|
||
The receiver, having acquired a list of cTXO metadata that includes _OTK_ and _AuthKey_, goes through the following process to test for ownership: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This process seems to require the receiver to be explicitly looking for a transaction from a specific sender.
If this is true, it might be worthwhile to mention in the text. I think that the implications are: unexpected transfers will not be detected, and sender addresses will always be known to a receiver.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my understanding, the receiver would scan all cTX outputs that arrive on the chain.
**`owner`:** | BitShares owner structure specifying weighted list of keys or accounts that may spend this commitment. (Typically lists just one public key, the "AuthKey" for the cTXO.) | ||
**`stealth_memo`:** | Also known as the "transaction receipt" when transmitted off-chain.<br><br> **`one_time_key`:** _(EC curve point, 33 bytes)_<br> **`to`:** Use the AuthKey here! _(EC curve point, 33 bytes)_<br> **`encrypted_memo`:** Data that recipient needs to "open" the commitment.<br><br> _The stealth memo is optional as far as the network is concerned, but essential if you want the recipient to be able to detect the incoming transaction without sending a "receipt."_ | ||
|
||
_(An example transaction showing all these fields can be seen in [block 22157273](https://cryptofresh.com/tx/8182e9d78cbce7df281bc252a9e6d87566ca0622). In this Tx, the stealth_memo '`to`' field unwisely names the recipient's address key, rather than the cTXO Auth key, and thus breaks unlinkability.)_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very helpful
|
||
_(An example transaction showing all these fields can be seen in [block 22157273](https://cryptofresh.com/tx/8182e9d78cbce7df281bc252a9e6d87566ca0622). In this Tx, the stealth_memo '`to`' field unwisely names the recipient's address key, rather than the cTXO Auth key, and thus breaks unlinkability.)_ | ||
|
||
Since the `stealth_memo` field can be used to record both the OTK and the AuthKey, all the wallet needs to do to scan for incoming transactions is to download batches of stealth memos and, for each one, test whether the combination of the OTK and the wallet's Address key yields the AuthKey. If it does, then derive the AES decryption key from _Shared(OTK,ViewKey)_ and use that to read the additional data in `encrypted_memo`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe emphasize this paragraph
|
||
_Field_ | _Purpose_ | ||
-------:|:------- | ||
**`from_key`:** | Original use:<br><br><ul>Identifies address key of sender **(optional)**. _(EC curve point, 33 bytes)_</ul>Alternate possible uses:<br><br> <ul><li>Instead of ID'ing the 'from' address, could use this field to embed an _invoice nonce_ to allow receiver to correlate payment to an invoice.</li></ul> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent contrast of "Original use" and "Alternate possible uses"
**`from_key`:** | Original use:<br><br><ul>Identifies address key of sender **(optional)**. _(EC curve point, 33 bytes)_</ul>Alternate possible uses:<br><br> <ul><li>Instead of ID'ing the 'from' address, could use this field to embed an _invoice nonce_ to allow receiver to correlate payment to an invoice.</li></ul> | ||
**`amount`:** | Value of commitment. _(Integer, 32 bytes)_ | ||
**`blinding_factor`:** | Blinding factor. _(Integer, 32 bytes)_<br><br>_Note: Except when a blind_sum is needed, the blinding factor is deterministic from a hash of the shared secret, meaning this field can potentially be repurposed or omitted. To guarantee that the blinding factor can always be deterministic, transactions can be padded with a commitment to zero to absorb the blind_sum._ | ||
**`commitment`:** | The Pedersen commitment. _(EC curve point, 33 bytes)_<br><br> _Note: This field is redundant, since the commitment is determined by_ C = amnt * H + blind * G, _and could potentially be omitted._ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is "H"?
|
||
### API Requirements to Allow Detection of Inbound Commitments | ||
|
||
To monitor for incoming transactions to a particular wallet, a wallet need only download sets of `stealth_memo` structures to test for recognition. The full cTXO (including Pedersen commitment, owner structure, range proof, etc.) need not be downloaded. Because the encrypted data inside the memo indicates the Pedersen commitment, the wallet will know which cTXO it has recognized. (Witness nodes index cTXO's by Pedersen commitment.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe emphasize the sentence
To monitor for incoming transactions to a particular wallet, a wallet need only download sets of `stealth_memo` structures to test for recognition. The full cTXO (including Pedersen commitment, owner structure, range proof, etc.) need not be downloaded. Because the encrypted data inside the memo indicates the Pedersen commitment, the wallet will know which cTXO it has recognized. (Witness nodes index cTXO's by Pedersen commitment.) | |
To monitor for incoming transactions to a particular wallet, a wallet need only download sets of `stealth_memo` structures to test for recognition. _The full cTXO (including Pedersen commitment, owner structure, range proof, etc.) need not be downloaded._ Because the encrypted data inside the memo indicates the Pedersen commitment, the wallet will know which cTXO it has recognized. (Witness nodes index cTXO's by Pedersen commitment.) |
|
||
(Discuss here a proposed API call for retrieving stealth_memos by block height range) | ||
|
||
To know whether a cTXO is still unspent (e.g. by another instance of the wallet), a wallet could attempt to retrieve the corresponding commitment object from an API node. An empty result indicates the commitment has been spent. However, this procedure indicates our interest in a specific set of commitments, and the network traffic generated runs the risk of revealing that those commitments are "linked". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent point
|
||
To know whether a cTXO is still unspent (e.g. by another instance of the wallet), a wallet could attempt to retrieve the corresponding commitment object from an API node. An empty result indicates the commitment has been spent. However, this procedure indicates our interest in a specific set of commitments, and the network traffic generated runs the risk of revealing that those commitments are "linked". | ||
|
||
To prevent this, we propose instead that, in like manner to the downloading of bulk `stealth_memo` structures, that an API call for downloading bulk lists of consumed commitments be implemented, with the download again being over specified block height ranges. A wallet then needs only to test that its own commitments are not on the list of spent commitments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand this. It seems like it would not tell you anything new. Would this tell the wallet which commitments were consumed during those block ranges? Maybe my understanding is deficient: what does it mean to "consume" a commitment?
|
||
In the event that ring signatures are implemented for transaction inputs (see [BSIP-0052](bsip-0052.md)), then instead of downloading a list of consumed commitments, we would instead download a list of used key images, which would serve the same purpose. | ||
|
||
Because a wallet downloads `stealth_memo` structures in bulk over block height ranges, the wallet never reveals to the network its interest in any specific cTXOs. Thus network interaction for monitoring purposes does not undermine privacy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent
|
||
Utilization of the dual-key address format has numerous interesting use cases, including: | ||
|
||
* The ability to maintain **watch-only wallets**. By entrusting only the View Key to a view-only node, it is possible for this node to monitor for activity to an address without granting spending access to the same node. This allows for such things as: opt-in transparency; cash register monitoring; organizational internal auditing, etc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a valuable feature
|
||
* The ability to maintain **watch-only wallets**. By entrusting only the View Key to a view-only node, it is possible for this node to monitor for activity to an address without granting spending access to the same node. This allows for such things as: opt-in transparency; cash register monitoring; organizational internal auditing, etc. | ||
|
||
* The ability to use **address-per-invoice** without introducing substantial additional scanning overhead. To use this, one keeps the same viewing PubKey and iterates the Spending PubKey part of the address, generating a distinct address per invoice. When scanning the blockchain, the _Child Offset_ is a function of the shared-secret between OTK and ViewKey, such that _AuthKey = SpendKey + Offset_. To obtain the public SpendKey, a watching wallet can subtract the Offset from the AuthKey to obtain the SpendKey, and simply compare against a list of per-invoice SpendKeys that were used to generate addresses. Adding additional SpendKeys to scan for does not incur any additional EC group operations, merely additional byte-wise comparisons, which are trivial. _(Note that while the invoice addresses generated in this manner are distinct, they are not unlinkably distinct, since they share the viewing component. If a business wants individual invoices to be mutually unlinkable, then this scheme will not be sufficient. However, this is a consideration for a business's off-chain security practices, as the addresses themselves never appear on-chain or in a transaction. An alternate solution which allows even the ViewKey to vary, while still allowing for efficient scanning, is presented in [MRL-0006](https://lab.getmonero.org/pubs/MRL-0006.pdf), however this introduces a change in how the deterministic offsets are generated, which would need to be signaled by a flag in the address format and supported by wallets.)_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"However, this is a consideration for a business's off-chain security practices, as the addresses themselves never appear on-chain or in a transaction."
How might invoice addresses be shared? Paper receipt? QR code?
|
||
#### Additional address formats | ||
|
||
The two stealth address formats described above provide for single key and dual key addresses, where the latter allows for separation of transaction monitoring from the ability to spend, allowing for view-only wallets. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears that three stealth addresses were described above, not two
|
||
There may be use cases for additional address formats allowing for more complex situations. | ||
|
||
One would be a multi-sig situation in which the address format encodes multiple spending keys and a weighting requirement. Although, this would make the resulting address very lengthy, it would also add an interesting use-case. And, since BitShares authority structures already allow for a vector of authorizing keys and weights, it should be possible to implement the feature on the wallet side, without needing any changes to consensus or API. This idea is not explored further here but merely suggested for future exploration if there is a desire for the feature. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"One would be a multi-sig situation in which the address format encodes multiple spending keys and a weighting requirement."
Very interesting. How might serialization need to be altered to handle this optional usage?
|
||
## Summary for Shareholders | ||
|
||
Although the goal of this BSIP is to support the long-range vision of [Stealth Phase II](bsip-0050.md), the implementation of this BSIP would provide value _right now_, as it would enable the utilization of even the Phase I _Confidential Transactions_ operations without the reliance on burdensome transaction receipts, which are the primary end-user stumbling block to routine Stealth use. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent point to emphasize
Although the goal of this BSIP is to support the long-range vision of [Stealth Phase II](bsip-0050.md), the implementation of this BSIP would provide value _right now_, as it would enable the utilization of even the Phase I _Confidential Transactions_ operations without the reliance on burdensome transaction receipts, which are the primary end-user stumbling block to routine Stealth use. | |
Although the goal of this BSIP is to support the long-range vision of [Stealth Phase II](bsip-0050.md), **the implementation of this BSIP would provide value _right now_, as it would enable the utilization of even the Phase I _Confidential Transactions_ operations without the reliance on burdensome transaction receipts, which are the primary end-user stumbling block to routine Stealth use.** |
|
||
We have detailed in this document procedures for producing recipient-recognizable transaction outputs from stealth addresses. Specifically, we have detailed the procedure for _two_ distinct stealth address formats: a single-key address format which is identical to that which is already in use, and a new dual-key address format which separates the duties of monitoring from spending, and thus allows for watch-only Stealth wallets. Support for the dual-key address format would require no network or consensus changes. It requires only wallet support. | ||
|
||
Most of the work needed to implement this BSIP is in the wallet, namely the correct production of recognizable cTXOs and the process of scanning for owned cTXOs. The only network-level change is the addition of two API calls: one to return batches of `stealth_memo` fields included in a block range, and one to return batches of consumed commitments (in the case of CT transactions) or used key-images (in the case of RingCT transactions). These API calls would need to be available on wallet-serving API nodes, but would not be needed on block-producing witness nodes. There are no consensus changes proposed in this document. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent summary of work to be done
**`commitment`:** | The Pedersen commitment. _(EC curve point, 33 bytes)_<br><br> _Note: This field is redundant, since the commitment is determined by_ C = amnt * H + blind * G, _and could potentially be omitted._ | ||
**`check`:** | Checksum to confirm correct decryption. _(4 bytes)_ | ||
|
||
_(TODO: How is this serialized? Do omitted fields "take up space"? Can fields be chosen a la carte? How hard will it be to extend this memo format, for, say, multiple assets in the case of CA? See fc::raw::pack.)_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An optional<T>
is serialized as a 0-integer if the value is absent, or as a 1-integer followed by the contained value otherwise. It is possible, but tricky, to extend this format, by allowing values other than 0 or 1 for the leading integer.
asset
is serialized as two varints, one for the asset ID and one for the amount.
Fixed-size byte sequences (i.e. public keys, hash values, commitments etc.) are serialized as-is.
_Field_ | _Purpose_ | ||
-------:|:------- | ||
**`from_key`:** | Original use:<br><br><ul>Identifies address key of sender **(optional)**. _(EC curve point, 33 bytes)_</ul>Alternate possible uses:<br><br> <ul><li>Instead of ID'ing the 'from' address, could use this field to embed an _invoice nonce_ to allow receiver to correlate payment to an invoice.</li></ul> | ||
**`amount`:** | Value of commitment. _(Integer, 32 bytes)_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
amount
is of type asset
, which is represented as two variable-length integers (for asset ID and amount).
Title: Blockchain scanning for inbound Stealth transactions | ||
Authors: Christopher J. Sanborn | ||
Status: Draft | ||
Type: Protocol |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think type "Informational" would be the correct choice here. While the proposal does describe a kind of client-interoperability protocol, the proposed changes are not mandatory for clients nor enforced in any way by the blockchain backend. Perhaps augmenting the type for clarification would be acceptable, although BSIP-0001 does not explicitly allow this.
Type: Informational (Client Protocol)
Initial draft of BSIP 53, following discussion in #91 .
Hours estimated for this initial draft: 55, as per issue comment here.