Skip to content
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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

christophersanborn
Copy link
Member

@christophersanborn christophersanborn commented Oct 17, 2018

Initial draft of BSIP 53, following discussion in #91 .

Hours estimated for this initial draft: 55, as per issue comment here.

@christophersanborn
Copy link
Member Author

Not sure if PR should include edits to table in README.md, so these are segregated into separate commits.

@pmconrad
Copy link
Contributor

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.

@ryanRfox
Copy link
Contributor

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?

@christophersanborn
Copy link
Member Author

christophersanborn commented Nov 15, 2018

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.
Copy link
Contributor

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.
Copy link
Contributor

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.
Copy link
Contributor

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.
Copy link
Contributor

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.
Copy link
Contributor

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.
Copy link
Contributor

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"

Suggested change
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)**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
**Stealth Memo structure: (Stealth I)**
**Stealth Memo structure: (Existing: Stealth I)**

or

Suggested change
**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.
Copy link
Contributor

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

Suggested change
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
Copy link
Contributor

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.
Copy link
Contributor

@MichelSantos MichelSantos Dec 12, 2018

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."

Suggested change
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`
Copy link
Contributor

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.)"

@christophersanborn
Copy link
Member Author

@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.
Copy link
Contributor

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)&nbsp;&rarr;&nbsp;secret <br> Shared(A,b) &rarr; 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>&nbsp; _secret = SHA512(P<sub>X</sub>)_; &nbsp; &nbsp; _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)&nbsp;&rarr;&nbsp;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>&nbsp; _child = BigInteger(SHA256(Compressed(B)_ &vert;&vert; _index))_<br><br>_Compressed(B)_ refers to the SEC1 "compressed" representation of public key _B_. The &vert;&vert; symbol refers to concatenation.
Copy link
Contributor

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)&nbsp;&rarr;&nbsp;secret <br> Shared(A,b) &rarr; 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>&nbsp; _secret = SHA512(P<sub>X</sub>)_; &nbsp; &nbsp; _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)&nbsp;&rarr;&nbsp;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>&nbsp; _child = BigInteger(SHA256(Compressed(B)_ &vert;&vert; _index))_<br><br>_Compressed(B)_ refers to the SEC1 "compressed" representation of public key _B_. The &vert;&vert; symbol refers to concatenation.

**Sending:**
Copy link
Contributor

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)
Copy link
Contributor

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:
Copy link
Contributor

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.

Copy link
Contributor

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`:** &nbsp; _(EC curve point, 33 bytes)_<br> **`to`:** &nbsp; Use the AuthKey here! _(EC curve point, 33 bytes)_<br> **`encrypted_memo`:** &nbsp; 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.)_
Copy link
Contributor

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`.
Copy link
Contributor

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)**. &nbsp; _(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>
Copy link
Contributor

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)**. &nbsp; _(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. &nbsp; _(Integer, 32 bytes)_
**`blinding_factor`:** | Blinding factor. &nbsp; _(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. &nbsp; _(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._
Copy link
Contributor

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.)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe emphasize the sentence

Suggested change
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".
Copy link
Contributor

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.
Copy link
Contributor

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.
Copy link
Contributor

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.
Copy link
Contributor

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.)_
Copy link
Contributor

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.
Copy link
Contributor

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.
Copy link
Contributor

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent point to emphasize

Suggested change
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.
Copy link
Contributor

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. &nbsp; _(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. &nbsp; _(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.)_
Copy link
Contributor

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)**. &nbsp; _(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. &nbsp; _(Integer, 32 bytes)_
Copy link
Contributor

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
Copy link
Contributor

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)

@pmconrad pmconrad mentioned this pull request Jan 22, 2019
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants