# Address Generation Guide

## Table of Contents
- [Address Types Overview](#address-types-overview)
- [P2OP Addresses](#p2op-addresses)
- [Classical Addresses](#classical-addresses)
- [Address Class Usage](#address-class-usage)
- [Network Support](#network-support)
- [Address Comparison](#address-comparison)

## Address Types Overview

OPNet supports multiple address types for different use cases:

| Address Type | Format | Use Case | Quantum Support |
|-------------|--------|----------|----------------|
| **P2OP** | bc1s... (v16) | OPNet contract addresses | ✅ Quantum (contracts only) |
| **P2MR** | bc1z... (v2) | Quantum-safe user wallets (BIP 360) | ✅ Quantum |
| **P2QRH** | TBD | Quantum-resistant hash-based addresses | ✅ Quantum (NOT IMPLEMENTED, separate BIP) |
| **P2TR** | bc1p... (v1) | Taproot, privacy, efficiency | ❌ Classical |
| **P2WPKH** | bc1q... (v0) | SegWit, standard Bitcoin | ❌ Classical |
| **P2PKH** | 1... | Legacy Bitcoin | ❌ Classical |
| **P2SH** | 3... | Script hash, multi-sig | ❌ Classical |
| **P2WDA** | bc1q... (P2WSH) | Witness data authentication | ❌ Classical |

## P2OP Addresses

### What is P2OP?

**P2OP (Pay-to-OPNet)** is an address format for OPNet contract addresses:

- Uses **witness version 16** (OP_16)
- Encoded in **Bech32m format**
- Encodes the **quantum address** (SHA256 hash of ML-DSA public key) from `address.toHex()`
- Used exclusively for contract addresses on OPNet
- **Supports quantum** for contracts only

The quantum address (`address.toHex()`) is the user's universal public key - a 32-byte hash that can be encoded in various formats like P2OP.

> **Note:** For quantum-safe user wallet outputs, use **P2MR** (Pay-to-Merkle-Root, BIP 360) via the `useP2MR` flag on transaction builders. P2MR eliminates the quantum-vulnerable key-path spend by committing directly to a Merkle root. P2OP is used exclusively for contract addresses. **P2QRH** is a separate, unrelated BIP proposal that is not yet implemented.

## Classical Addresses

### P2TR (Taproot)

```typescript
const wallet = mnemonic.derive(0);

// Mainnet Taproot
const p2trMainnet = wallet.p2tr;
console.log('P2TR Mainnet:', p2trMainnet);
// Output: bc1p...

// Testnet Taproot
const p2trTestnet = wallet.address.p2tr(networks.testnet);
console.log('P2TR Testnet:', p2trTestnet);
// Output: tb1p...

// Regtest Taproot
const p2trRegtest = wallet.address.p2tr(networks.regtest);
console.log('P2TR Regtest:', p2trRegtest);
// Output: bcrt1p...
```

### P2WPKH (SegWit)

```typescript
// Mainnet SegWit
const p2wpkhMainnet = wallet.p2wpkh;
console.log('P2WPKH Mainnet:', p2wpkhMainnet);
// Output: bc1q...

// Testnet SegWit
const p2wpkhTestnet = wallet.address.p2wpkh(networks.testnet);
console.log('P2WPKH Testnet:', p2wpkhTestnet);
// Output: tb1q...
```

### P2PKH (Legacy)

```typescript
// Mainnet Legacy
const p2pkhMainnet = wallet.p2pkh;
console.log('P2PKH Mainnet:', p2pkhMainnet);
// Output: 1...

// Testnet Legacy
const p2pkhTestnet = wallet.address.p2pkh(networks.testnet);
console.log('P2PKH Testnet:', p2pkhTestnet);
// Output: m... or n...
```

### P2SH-P2WPKH (Wrapped SegWit)

```typescript
// Mainnet Wrapped SegWit
const p2shMainnet = wallet.address.p2shp2wpkh(networks.bitcoin);
console.log('P2SH-P2WPKH Mainnet:', p2shMainnet);
// Output: 3...

// Testnet Wrapped SegWit
const p2shTestnet = wallet.address.p2shp2wpkh(networks.testnet);
console.log('P2SH-P2WPKH Testnet:', p2shTestnet);
// Output: 2...
```

### P2WDA (Witness Data Authentication)

```typescript
// P2WDA with authenticated data fields
const p2wdaAddress = wallet.address.p2wda(networks.bitcoin);
console.log('P2WDA:', p2wdaAddress);
// Output: P2WSH address (bc1q...) with special witness script
```

## Address Class Usage

### Creating Addresses Directly

```typescript
import { Address } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';

import { fromHex } from '@btc-vision/bitcoin';

// From ML-DSA public key hash and classical public key
const mldsaHash = new Uint8Array(32).fill(0x01);  // SHA256 of ML-DSA public key
const classicalKey = fromHex('02...');  // 33-byte compressed key

const address = new Address(mldsaHash, classicalKey);

// Generate addresses
const p2op = address.p2op(networks.bitcoin);
const p2tr = address.p2tr(networks.bitcoin);
```

### From String

```typescript
// Create address from hex strings
const address = Address.fromString(
    '0xabcdef1234567890...',  // ML-DSA public key hash (32 bytes hex)
    '0x02...'                  // Classical public key (33 bytes hex)
);
```

### Dead Address

```typescript
// Special "dead" address (all zeros)
const deadAddress = Address.dead();
console.log('Dead address:', deadAddress.toHex());
// Output: 0x0000000000000000000000000000000000000000000000000000000000000000
```

### Address Properties

```typescript
const address = wallet.address;

// Quantum address (SHA256 hash of ML-DSA public key) - Universal public key
console.log('Quantum address:', address.toHex());
console.log('Quantum address bytes:', address.toBuffer());

// Classical public key
console.log('Classical key (hex):', address.tweakedToHex());
console.log('Classical key (bytes):', address.tweakedPublicKeyToBuffer());

// Original keys
console.log('Full ML-DSA public key:', address.mldsaPublicKey);  // 1312-2592 bytes
console.log('Original classical key:', address.originalPublicKey);
```

## Network Support

### Mainnet

```typescript
import { networks } from '@btc-vision/bitcoin';

const wallet = mnemonic.derive(0);

// All mainnet addresses
console.log('P2OP:', wallet.address.p2op(networks.bitcoin));      // bc1s...
console.log('P2TR:', wallet.address.p2tr(networks.bitcoin));      // bc1p...
console.log('P2WPKH:', wallet.address.p2wpkh(networks.bitcoin));  // bc1q...
console.log('P2PKH:', wallet.address.p2pkh(networks.bitcoin));    // 1...
```

### Testnet

```typescript
// Testnet with different prefixes
const mnemonic = Mnemonic.generate(
    undefined,                            // Default strength (24 words)
    '',                                   // No passphrase
    networks.testnet,                     // Testnet network
    MLDSASecurityLevel.LEVEL2            // Security level
);

const wallet = mnemonic.derive(0);

console.log('P2OP:', wallet.address.p2op(networks.testnet));      // tb1s...
console.log('P2TR:', wallet.address.p2tr(networks.testnet));      // tb1p...
console.log('P2WPKH:', wallet.address.p2wpkh(networks.testnet));  // tb1q...
console.log('P2PKH:', wallet.address.p2pkh(networks.testnet));    // m... or n...
```

### Regtest

```typescript
// Regtest for local development
const regtestMnemonic = Mnemonic.generate(
    undefined,                            // Default strength (24 words)
    '',                                   // No passphrase
    networks.regtest,                     // Regtest network
    MLDSASecurityLevel.LEVEL2            // Security level
);

const wallet = regtestMnemonic.derive(0);

console.log('P2OP:', wallet.address.p2op(networks.regtest));      // bcrt1s...
console.log('P2TR:', wallet.address.p2tr(networks.regtest));      // bcrt1p...
```

## Address Comparison

### Equality

```typescript
const wallet1 = mnemonic.derive(0);
const wallet2 = mnemonic.derive(0);
const wallet3 = mnemonic.derive(1);

const addr1 = wallet1.address;
const addr2 = wallet2.address;
const addr3 = wallet3.address;

// Same derivation index = same address
console.log(addr1.equals(addr2));  // true

// Different index = different address
console.log(addr1.equals(addr3));  // false
```

### Ordering

```typescript
const addresses = [
    mnemonic.derive(5).address,
    mnemonic.derive(2).address,
    mnemonic.derive(8).address,
    mnemonic.derive(1).address,
];

// Less than comparison
console.log(addresses[0].lessThan(addresses[1]));

// Greater than comparison
console.log(addresses[0].greaterThan(addresses[1]));

// Sort addresses
addresses.sort((a, b) => {
    if (a.lessThan(b)) return -1;
    if (a.greaterThan(b)) return 1;
    return 0;
});
```

## P2MR Addresses (BIP 360)

P2MR (Pay-to-Merkle-Root) is a quantum-safe SegWit version 2 output type. Unlike P2TR, P2MR commits directly to a Merkle root without an internal public key, eliminating the quantum-vulnerable key-path spend.

### P2MR in Transactions

All transaction builders support P2MR via the `useP2MR` flag:

```typescript
// Deploy a contract using P2MR
const result = await factory.signDeployment({
    // ... other params
    useP2MR: true,   // Use P2MR instead of P2TR
});
// Script address starts with bc1z... instead of bc1p...
```

### P2MR Multi-Signature

```typescript
import { P2MR_MS } from '@btc-vision/transaction';

const multisigAddress = P2MR_MS.generateMultiSigAddress(
    [pubkey1, pubkey2, pubkey3],
    2,                       // 2-of-3
    networks.bitcoin,
);
console.log('P2MR Multisig:', multisigAddress);
// Output: bc1z...
```

### P2MR CSV Time-Locked

```typescript
const csvP2MR = wallet.address.toCSVP2MR(144, networks.bitcoin);
console.log('P2MR CSV (144 blocks):', csvP2MR);
// Output: bc1z...
```

## Time-Locked Addresses (CSV)

### CheckSequenceVerify Addresses

```typescript
// Create time-locked address (100 blocks)
const duration = 100;
const csvAddress = wallet.address.toCSV(duration, networks.bitcoin);

console.log('CSV Address (100 blocks):', csvAddress);

// Different durations
const addr1Day = wallet.address.toCSV(144, networks.bitcoin);    // ~1 day
const addr1Week = wallet.address.toCSV(1008, networks.bitcoin);  // ~1 week
const addr1Month = wallet.address.toCSV(4320, networks.bitcoin); // ~1 month

// Valid range: 1 to 65535 blocks
const minLock = wallet.address.toCSV(1, networks.bitcoin);
const maxLock = wallet.address.toCSV(65535, networks.bitcoin);
```

### P2MR CSV Time-Locked

```typescript
// Create a P2MR time-locked address (quantum-safe CSV)
const csvP2MR = wallet.address.toCSVP2MR(144, networks.bitcoin);
console.log('P2MR CSV (1 day):', csvP2MR);
// Output: bc1z... (no key-path, quantum-safe)
```

## Complete Example

```typescript
import { Mnemonic, MLDSASecurityLevel } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';

// Generate wallet with ML-DSA support
const mnemonic = Mnemonic.generate(
    undefined,                            // Default strength (24 words)
    '',                                   // No passphrase
    networks.bitcoin,                     // Mainnet
    MLDSASecurityLevel.LEVEL2            // Security level
);

const wallet = mnemonic.derive(0);
const address = wallet.address;

console.log('=== Universal Public Key (Quantum Address) ===');
console.log('Quantum Address:', address.toHex());  // SHA256 hash of ML-DSA public key
console.log('ML-DSA Key Size:', address.mldsaPublicKey?.length, 'bytes');

console.log('\n=== P2OP Address (Contract Address) ===');
console.log('P2OP:', address.p2op(networks.bitcoin));  // Encoded form of quantum address

console.log('\n=== Classical Addresses ===');
console.log('P2TR (Taproot):', address.p2tr(networks.bitcoin));
console.log('P2WPKH (SegWit):', address.p2wpkh(networks.bitcoin));
console.log('P2PKH (Legacy):', address.p2pkh(networks.bitcoin));
console.log('P2SH-P2WPKH:', address.p2shp2wpkh(networks.bitcoin));

console.log('\n=== Testnet Addresses ===');
console.log('P2OP:', address.p2op(networks.testnet));
console.log('P2TR:', address.p2tr(networks.testnet));

console.log('\n=== Time-Locked Address ===');
console.log('CSV (100 blocks):', address.toCSV(100, networks.bitcoin));
```

## Next Steps

- [Message Signing](./04-message-signing.md) - Sign messages with ML-DSA and Schnorr
- [Address Verification](./05-address-verification.md) - Validate addresses and keys
