# EIP-41 Stealth Address Standard
* Author: ross-weir
* Status: Proposed
* Created: 16-Dec-2022
* Last edited: 17-Dec-2022
* License: CC0
* Forking: not needed
## Motivation
This specification defines a standardized way of implementing and interacting with stealth addresses on the Ergo blockchain.
Stealth addresses enable recipients of a payment to remain anonymous when receiving funds thus providing financial privacy should an actor desire it.
## Scenario
An actor, `Receiver`, wishes to receive a stealth payment so they generate a public address and share it.
An actor, `Sender`, wishes to make a stealth payment to `Receiver` so they create a box protected by a "one-time-secret" generated from the `Receiver`s public address. Due to the method of generation this box will be spendable by `Receiver` and cannot be linked to the `Receiver`s public address they shared.
## Stealth address specification
The implementation suggested in this EIP was posted by `scalahub` in a thread on `ergoforum.org` [[1]](#1) and is outlined below.
**Script protecting stealth boxes:**
```scala
{
// ===== Contract Information ===== //
// Name: EIP-0041 Stealth address contract
// Version: 1.0.0
val gr = SELF.R4[GroupElement].get
val gy = SELF.R5[GroupElement].get
val ur = SELF.R6[GroupElement].get
val uy = SELF.R7[GroupElement].get
proveDHTuple(gr,gy,ur,uy)
}
```
**Script ErgoTree:**
```
1000cee4c6a70407e4c6a70507e4c6a70607e4c6a70707
```
**Generation of stealth box registers [[5]](#5):**
```typescript
const g = new EC("secp256k1").g; // group element generator
const u = receiverPublicKey;
const r = BigInt(rand(32));
const y = BigInt(rand(32));
const gr = g.mul(r); // gr = g^r = R4
const gy = g.mul(y); // gy = g^y = R5
const ur = u.mul(r); // ur = u^r = R6
const uy = u.mul(y); // uy = u^y = R7
```
**Box register declarations:**
- Register `R4`
- Type: `SConstant[SGroupElement]`
- Value: gr = g^r
- Register `R5`
- Type: `SConstant[SGroupElement]`
- Value: gy = g^y
- Register `R6`
- Type: `SConstant[SGroupElement]`
- Value: ur = u^r
- Register `R7`
- Type: `SConstant[SGroupElement]`
- Value: uy = u^y
> 📝 As discussed in the `ergoforum` discussion [[1]](#1) this register declaration is larger in size than that originally proposed by `kushti` but possesses the useful property that it could look like a legitimate use-case.
## Public key generation
Public keys used for `Receiver` stealth addresses should be generated following `EIP-3` [[6]](#6) so they are deterministic and payments made to `Receiver` can be retrieved after a fresh wallet restore.
## Scanning for spendable stealth boxes
All stealth boxes created following this standard will be located at the encoded address `2pxnLshTr2aL5t3QFd6ScSEHC5Jk6EpnMRzGb3`. In order to discover spendable stealth boxes a wallet would need to check the following for each box at this address:
```ts
const gr = stealthBox.R4;
const gy = stealthBox.R5;
const ur = stealthBox.R6;
const uy = stealthBox.R7;
const x = receiverSecretKey; // the secret key corresponding to the public key shared by `Receiver`
const isSpendable = ur.eq(gr.mul(x)) && uy.eq(gy.mul(x));
```
> ⚠️ All stealth boxes being located at `2pxnLshTr2aL5t3QFd6ScSEHC5Jk6EpnMRzGb3` is a potential scalability issue related to this EIP. Wallets/indexing services will need to ensure stealth box scanning implementations are efficient.
## Stealth address encoding
To provide users of Ergo a seamless experience when interacting with stealth addresses there needs to be a way for wallets/applications to detect a `Receiver` is requesting a stealth payment. If a `Receiver` shares a standard `P2PK` address, for example, there is currently no way for a wallet to know that the user wants to receive a stealth payment.
To address this issue we propose adding a new `AddressType`.
Currently Ergo uses:
```ts
enum AddressType {
P2PK = 1,
P2SH = 2,
P2S = 3
}
```
We propose adding a new address type of `AddressType.P2SA`:
```ts
enum AddressType {
P2PK = 1,
P2SH = 2,
P2S = 3,
P2SA = 4
}
```
This will allow `Sender`s wallet to detect that a `Receiver` is requesting a stealth payment like so:
```ts
const isStealthAddress = headByte & 0xf == AddressType.P2SA
```
And the `Sender`s wallet can construct the stealth transaction accordingly.
## References
- [1] [Stealth Address Contract (ergoforum)](https://www.ergoforum.org/t/stealth-address-contract/255)
- [2] [ErgoScript by example](https://github.com/ergoplatform/ergoscript-by-example/blob/main/stealthAddress.md)
- [3] [Stealth-doc (ERGOHACK III aragogi)](https://github.com/aragogi/Stealth-doc)
- [4] [Ethereum (EIP-5564)](https://eips.ethereum.org/EIPS/eip-5564#:~:text=A%20Stealth%20address%20is%20generated,compute%20the%20matching%20private%20key.)
- [5] [TypeScript stealth address example](https://github.com/ross-weir/ergo-stealth-address-example/blob/main/index.ts)
- [6] [Ergo (EIP-0003)](eip-0003.md)