# CON-003: DIG_MAINNET and DIG_TESTNET

> **Authoritative requirement:** [CON-003](../NORMATIVE.md#CON-003)
> **Verification:** [VERIFICATION.md](../VERIFICATION.md)
> **Tracking:** [TRACKING.yaml](../TRACKING.yaml)
> **Spec reference:** [SPEC.md](../../../../resources/SPEC.md) — Section 4.3

---

## Summary

The `dig-constants` crate exports two const `NetworkConstants` instances — `DIG_MAINNET` and `DIG_TESTNET` — that represent the canonical network configurations for the DIG L2. These are the only two valid network configurations, and all DIG crates should reference one of these constants rather than constructing `NetworkConstants` from scratch.

Each instance has a distinct genesis challenge that uniquely identifies the network. The genesis challenges are currently set to placeholder zeros because the DIG mainnet has not yet launched and the final values have not been determined. When mainnet launch occurs, the genesis challenges will be updated to their final values and the `dig-constants` crate will be released with the production constants. Until then, the placeholder values are sufficient for development and testing.

The two-network model matches Chia L1's approach of having separate `MAINNET` and `TESTNET` configurations. The testnet instance uses a different genesis challenge to ensure that transactions signed for one network cannot be replayed on the other (domain separation via AGG_SIG additional data, see CON-005). All other parameters (cost limits, fork heights, etc.) are identical between mainnet and testnet to ensure that applications can be tested on testnet with confidence that behavior will be identical on mainnet.

---

## Specification

### Const Declarations

```rust
use hex_literal::hex;

/// DIG L2 mainnet network constants.
/// Genesis challenge: placeholder zeros until mainnet launch.
pub const DIG_MAINNET: NetworkConstants = NetworkConstants::new(
    ConsensusConstants {
        genesis_challenge: Bytes32::new(hex!(
            "0000000000000000000000000000000000000000000000000000000000000000"
        )),
        // ... other fields (see CON-004, CON-005, CON-006)
        ..DIG_BASE_CONSTANTS
    }
);

/// DIG L2 testnet network constants.
/// Genesis challenge: distinct from mainnet for domain separation.
pub const DIG_TESTNET: NetworkConstants = NetworkConstants::new(
    ConsensusConstants {
        genesis_challenge: Bytes32::new(hex!(
            "0000000000000000000000000000000000000000000000000000000000000001"
        )),
        // ... other fields (same as mainnet except genesis_challenge)
        ..DIG_BASE_CONSTANTS
    }
);
```

### Distinct Genesis Challenges

```rust
#[test]
fn mainnet_and_testnet_differ() {
    // Genesis challenges MUST be distinct for domain separation
    assert_ne!(
        DIG_MAINNET.genesis_challenge(),
        DIG_TESTNET.genesis_challenge(),
    );
}
```

### Placeholder Values

The current genesis challenge values are placeholders:

| Network | Genesis Challenge | Status |
|---------|------------------|--------|
| DIG_MAINNET | `0x0000...0000` (32 zero bytes) | Placeholder — will be updated at launch |
| DIG_TESTNET | `0x0000...0001` (31 zero bytes + 0x01) | Placeholder — will be updated at launch |

When mainnet launches:
1. The genesis challenge for DIG_MAINNET will be set to the hash of the genesis block
2. The genesis challenge for DIG_TESTNET will be set to a distinct value
3. The `dig-constants` crate version will be bumped
4. All AGG_SIG additional data (CON-005) will be recomputed from the new genesis challenges

### Shared Base Constants

```rust
/// Base constants shared between mainnet and testnet.
/// Only genesis_challenge (and derived AGG_SIG data) differs.
const DIG_BASE_CONSTANTS: ConsensusConstants = ConsensusConstants {
    // Cost limits
    max_block_cost_clvm: 11_000_000_000,  // Same as Chia L1
    cost_per_byte: 12_000,                 // Same as Chia L1
    max_coin_amount: u64::MAX,             // No artificial limit

    // Fork heights (CON-004)
    hard_fork_height: 0,
    hard_fork2_height: 0,

    // PoS/VDF neutral values (CON-006)
    // ... (see CON-006 for details)

    // These will be overridden per network:
    genesis_challenge: Bytes32::new([0u8; 32]),
    agg_sig_me_additional_data: Bytes32::new([0u8; 32]),
    // ... other AGG_SIG data (CON-005)
};
```

### Usage Patterns

```rust
// In production code:
use dig_constants::DIG_MAINNET;

let context = ValidationContext {
    constants: DIG_MAINNET,
    // ...
};

// In tests:
use dig_constants::DIG_TESTNET;

let context = ValidationContext {
    constants: DIG_TESTNET,
    // ...
};

// Network-aware code:
fn get_constants(is_testnet: bool) -> NetworkConstants {
    if is_testnet { DIG_TESTNET } else { DIG_MAINNET }
}
```

---

## Acceptance Criteria

- [ ] `DIG_MAINNET` and `DIG_TESTNET` are `const NetworkConstants` values exported from `dig-constants`.
- [ ] The two instances have distinct genesis challenges.
- [ ] Both instances use placeholder zero-based genesis challenges until mainnet launch.
- [ ] All parameters other than genesis challenge (and derived AGG_SIG data) are identical between the two instances.
- [ ] Both instances are usable in `const` contexts (compile-time evaluation).

---

## Implementation Notes

- **Primary file:** `dig-constants/src/constants.rs` or `dig-constants/src/lib.rs`.
- **Placeholder lifecycle:** The placeholder genesis challenges will be replaced before mainnet launch. Code that computes derived values (like AGG_SIG additional data) from the genesis challenge must be ready to handle the change. No code should hardcode the placeholder values outside of `dig-constants`.
- **hex-literal dependency:** The `hex!()` macro from `hex-literal` is used for readable hex byte arrays in const contexts. This is preferred over manual `[0x00, 0x00, ...]` arrays.
- **No runtime construction:** Callers should use `DIG_MAINNET` or `DIG_TESTNET` rather than constructing `NetworkConstants` themselves. The `NetworkConstants::new()` constructor is `pub` for flexibility, but the canonical instances should be preferred.
- **Testing with custom constants:** For unit tests that need non-standard parameters (e.g., lower cost limits), it is acceptable to construct a custom `NetworkConstants`. This does not violate the two-network model — custom instances are for testing only.
- **Semver implications:** Changing the genesis challenges is a breaking change for any code that depends on the specific challenge values. The `dig-constants` crate should follow semver and bump the major version when genesis challenges are finalized.

---

## Verification

### Test Plan

| Test | Type | Description | Expected Result |
|------|------|-------------|-----------------|
| Distinct challenges | Unit test | DIG_MAINNET.genesis_challenge() != DIG_TESTNET.genesis_challenge() | True |
| Mainnet is const | Compile test | `const _: NetworkConstants = DIG_MAINNET;` | Compiles |
| Testnet is const | Compile test | `const _: NetworkConstants = DIG_TESTNET;` | Compiles |
| Shared cost limits | Unit test | DIG_MAINNET.max_block_cost_clvm() == DIG_TESTNET.max_block_cost_clvm() | Equal |
| Shared cost_per_byte | Unit test | DIG_MAINNET.cost_per_byte() == DIG_TESTNET.cost_per_byte() | Equal |
| Placeholder values | Unit test | Both genesis challenges are zero-based | Currently true (will change at launch) |

---

## Source Citations

- **SPEC.md Section 4.3**: "Two const NetworkConstants with distinct genesis challenges. Placeholder zeros until mainnet launch."
- **SPEC.md Section 4.3**: "DIG_MAINNET and DIG_TESTNET."
- **Chia L1 reference:** Separate MAINNET and TESTNET configurations with distinct genesis challenges.

---

## References

- [CON-001](CON-001.md) — Separate dig-constants crate (where these are defined)
- [CON-002](CON-002.md) — NetworkConstants type (type of these instances)
- [CON-004](CON-004.md) — Fork heights at zero (shared parameter)
- [CON-005](CON-005.md) — AGG_SIG additional data derivation (derived from genesis_challenge)
- [CON-006](CON-006.md) — Neutral PoS/VDF fields (shared parameter)
