BSIP: 1203 (unassigned)
Title: Blockchain scanning for inbound Stealth transactions
Authors: Christopher J. Sanborn
Status: Draft
Type: Protocol
Created: 2018-01-29
Discussion: https://github.com/bitshares/bsips/issues/91
## Abstract
The existing Stealth implementation ([BSIP-0008](bsip-0008.md)) requires the sender to manually communicate *transaction receipts* to the recipients of each transaction to alert them to the presence of an inbound balance transfer, creating a danger of lost funds due to miscommunicated or lost receipts. This BSIP explores options for automated discovery of inbound transactions while still preserving fundamental privacy features of unlinkability and anonymity.
## Motivation
"Stealth addresses" are a method of providing _unlinkability_ to blockchain transactions. Unlinkability is a major component of the Privacy Triad: _unlinkability_, _confidentiality_, and _untraceability_. Using a stealth address, a sending wallet is able to compute a child public key that derives from a public key encoded in the address, but which cannot be correlated, or "linked", to the address public key, unless you are either the sender or the receiver. This child key becomes the authorization key for transaction outputs (TXOs) intended for the receiver. As such, third party observers cannot link TXOs to addresses, nor even link together independent TXOs which are destined to the same address.
Although this is a great benefit to privacy, it complicates the matter of detecting inbound transactions, since a wallet cannot simply scan for transactions which explicitly identify the destination address.
Existing [Stealth Phase I](bsip-0008.md) functionality already includes the use of stealth addresses, but does not include a solution for detection of inbound transactions. As a result of which, user adoption of the Stealth feature has been very minimal. We propose below a solution to inbound transaction detection as well as some additional enhancements to the stealth addressing scheme, including a proposed new address format that allows for watch-only wallets.
## Rationale
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.
* **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.
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)**
|
-----: | :---
**One-time PubKey:** | Chosen from randomness by sender **_(33 bytes)_**
**Message PubKey:** | Public key controlled by recipient. **_(33 bytes)_**
**Cipher Text:** | AES encrypted message, using _key ← Shared(OTK,MPK)_
_Current Stealth I behavior is to use the Address PubKey as the message PubKey, which reveals intended recipient!!_
A very simple solution would be to change the behavior of embedding the Address PubKey in the message PubKey field, and to instead record the Tx output AuthKey in this slot. Because the recipient is also able to derive this AuthKey through knowledge of her own address private keys (in combination with the OTK recorded in the header), the recipient would simply need to test the OTK against each of their own Address Keys to see if the resulting AuthKey matches the one in the header. If it does, then the output is recognized as destined to the recipient, even though the recipient's Address PubKeys are not identified in the memo header. The computational cost of this is one Diffie Hellman round, a hash operation, and a child key derivation. It should be noted that the AES encryption key should still be computed from the shared secret between the OTK and the address ViewKey, however, as this will allow view-only wallets which cannot compute the private key behind the AuthKey to decrypt the memo and tally the incoming transaction.
**Stealth Memo structure: (Proposed: Stealth II)**
|
-----: | :---
**One-time PubKey:** | Chosen from randomness by sender **_(33 bytes)_**
**cTXO AuthKey:** | Child public key of the stealth address and the OTK. **_(33 bytes)_**
**Cipher Text:** | AES encrypted message, using _key ← Shared(OTK,ViewKey)_
_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.
## Specifications
We specify two protocols. In the first subsection, [_Wallet procedure..._](#wallet-procedure-for-recognizing-own-commitments), we specify the recognition protocol by detailing wallet behaviors for:
* Creating transaction outputs that can be recognized by their recipients, and,
* Recognizing transaction outputs that are destined to the wallet.
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
Assumptions:
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.
**Address Formats:**
| Format:
:------:|--------
**CT-style:** | Single public key and checksum. Public key _A_ serves both viewing and spending roles.
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.
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.
Format: `BTSaaaaaaaaaaaaaaaaaaaannnnnnnncccc`
_(In the address formats above we consider the part following the "BTS" identifier to be Base58 encodings of the concatenated byte buffer representations of public keys and checksum bytes. C.f. [Base58Check](https://en.bitcoin.it/wiki/Base58Check_encoding) encoding.)_
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)
Recognizability depends on there being a deterministic relationship between the AuthKey that authorizes expenditure of a particular cTXO, the one-time key (OTK) that the sender generated randomly for the cTXO, and the recipient's Address key (or keys).
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.
_AuthKey = SpendKey + Offset_
Anonymity is preserved so long as only the sender and the receiver are able to compute _o_ and _Offset_. The algorithm for computing _Offset_ is a deterministic function of the OTK and ViewKey only, (and not the SpendKey). This allows the the recipient to recover the SpendKey by simple subtraction of _Offset_ from the AuthKey. The recipient's wallet then compares the computed SpendKey against the address SpendKey. The wallet may even compare against a whole list of SpendKeys that the wallet may have used to generate an address family with a common ViewKey, allowing for differentiable invoices, without sacrificing efficiency of scanning. (See _[address-per-invoice](#utility-of-dual-key-addresses)_ below.)
Algorithm | Description / Specification
:---:|:---------------------------
_Shared(a,B) → secret
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_.
_secret = SHA512(PX)_; _P = aB = Ab_
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.
_child = BigInteger(SHA256(Compressed(B)_ || _index))_
_Compressed(B)_ refers to the SEC1 "compressed" representation of public key _B_. The || symbol refers to concatenation.
**Sending:**
The sender's procedure for computing the offset and generating the AuthKey for the cTXO is detailed as follows: