mirror of
https://github.com/luxfi/precompile.git
synced 2026-09-24 00:26:21 +00:00
fix: restore docs/ site and package READMEs
docs/ is the Fumadocs site for precompile.lux.network — should not have been deleted. Package READMEs document input/output formats and gas costs referenced by the docs site.
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
# Blake3 Precompile
|
||||
|
||||
**Address**: `0x0000000000000000000000000000000000000504`
|
||||
|
||||
Blake3 hash function precompile for the Lux EVM.
|
||||
|
||||
## Overview
|
||||
|
||||
Blake3 is a cryptographic hash function that is:
|
||||
- **Fast**: 6-17x faster than SHA-3 and SHA-256
|
||||
- **Parallelizable**: Can utilize multiple cores
|
||||
- **Versatile**: Supports XOF (extendable output), KDF, and MAC
|
||||
- **Simple**: Single algorithm for all use cases
|
||||
|
||||
## Operations
|
||||
|
||||
| Operation | Selector | Gas Cost | Description |
|
||||
|-----------|----------|----------|-------------|
|
||||
| `hash256` | `0x01` | 100 + 3/word | Standard 32-byte hash |
|
||||
| `hash512` | `0x02` | 150 + 3/word | Extended 64-byte hash |
|
||||
| `hashXOF` | `0x03` | 200 + 3/in + 5/out | Arbitrary length output |
|
||||
| `hashWithDomain` | `0x04` | 150 + 3/word | Domain-separated hash |
|
||||
| `merkleRoot` | `0x10` | 500 + 100/leaf | Merkle tree root |
|
||||
| `deriveKey` | `0x20` | 300 + 3/word | Key derivation |
|
||||
|
||||
## Input Formats
|
||||
|
||||
### hash256 (0x01)
|
||||
```
|
||||
[1 byte: 0x01][data...]
|
||||
```
|
||||
Returns: 32 bytes
|
||||
|
||||
### hash512 (0x02)
|
||||
```
|
||||
[1 byte: 0x02][data...]
|
||||
```
|
||||
Returns: 64 bytes
|
||||
|
||||
### hashXOF (0x03)
|
||||
```
|
||||
[1 byte: 0x03][4 bytes: output_length][data...]
|
||||
```
|
||||
Returns: `output_length` bytes (max 1024)
|
||||
|
||||
### hashWithDomain (0x04)
|
||||
```
|
||||
[1 byte: 0x04][1 byte: domain_length][domain bytes][data...]
|
||||
```
|
||||
Returns: 32 bytes
|
||||
|
||||
### merkleRoot (0x10)
|
||||
```
|
||||
[1 byte: 0x10][4 bytes: num_leaves][32 bytes: leaf_0][32 bytes: leaf_1]...
|
||||
```
|
||||
Returns: 32 bytes (Merkle root)
|
||||
|
||||
### deriveKey (0x20)
|
||||
```
|
||||
[1 byte: 0x20][1 byte: context_length][context bytes][32 bytes: key_material]
|
||||
```
|
||||
Returns: 32 bytes (derived key)
|
||||
|
||||
## Solidity Usage
|
||||
|
||||
```solidity
|
||||
import {Blake3Lib} from "./IBlake3.sol";
|
||||
|
||||
contract MyContract {
|
||||
using Blake3Lib for bytes;
|
||||
|
||||
function hashData(bytes memory data) external view returns (bytes32) {
|
||||
return Blake3Lib.hash256(data);
|
||||
}
|
||||
|
||||
function buildMerkleRoot(bytes32[] memory leaves) external view returns (bytes32) {
|
||||
return Blake3Lib.merkleRoot(leaves);
|
||||
}
|
||||
|
||||
function deriveEncryptionKey(bytes32 masterKey) external view returns (bytes32) {
|
||||
return Blake3Lib.deriveKey("MyApp.encryption.v1", masterKey);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
|
||||
### 1. Fast Hashing
|
||||
Blake3 is ideal for high-throughput applications that need fast hashing:
|
||||
- Content addressing
|
||||
- Transaction hashing
|
||||
- State root computation
|
||||
|
||||
### 2. Merkle Trees
|
||||
Built-in Merkle tree root computation:
|
||||
- Rollup state commitments
|
||||
- Data availability proofs
|
||||
- Batch transaction verification
|
||||
|
||||
### 3. Key Derivation
|
||||
Domain-separated key derivation for:
|
||||
- Hierarchical key generation
|
||||
- Deterministic wallet derivation
|
||||
- Protocol-specific key isolation
|
||||
|
||||
### 4. Commitments
|
||||
Domain-separated hashing for:
|
||||
- Commit-reveal schemes
|
||||
- Privacy protocols
|
||||
- Zero-knowledge commitments
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Not Post-Quantum**: Blake3 uses classical construction. For quantum-resistant hashing, use Poseidon2 (0x0502) or SHAKE256.
|
||||
|
||||
2. **Domain Separation**: Always use domain-separated hashing for different purposes to prevent cross-protocol attacks.
|
||||
|
||||
3. **XOF Mode**: When using XOF, ensure output length matches security requirements (256 bits = 128-bit security).
|
||||
|
||||
## Performance
|
||||
|
||||
| Operation | Input Size | Gas Cost | Time (M1 Max) |
|
||||
|-----------|------------|----------|---------------|
|
||||
| hash256 | 1 KB | ~200 | ~1 μs |
|
||||
| hash256 | 1 MB | ~100K | ~1 ms |
|
||||
| merkleRoot | 256 leaves | ~26K | ~50 μs |
|
||||
| deriveKey | 32 bytes | ~300 | ~0.5 μs |
|
||||
|
||||
## Related Precompiles
|
||||
|
||||
| Address | Precompile | Use Case |
|
||||
|---------|------------|----------|
|
||||
| 0x0502 | Pedersen | ZK-friendly commitments |
|
||||
| 0x0503 | Poseidon2 | Post-quantum ZK hashing |
|
||||
| 0x0504 | Blake3 | Fast general-purpose hashing |
|
||||
| 0x031D | KZG4844 | Blob commitments (EIP-4844) |
|
||||
|
||||
## Standards
|
||||
|
||||
- [Blake3 Specification](https://github.com/BLAKE3-team/BLAKE3-specs)
|
||||
- [Blake3 Paper](https://github.com/BLAKE3-team/BLAKE3-specs/blob/master/blake3.pdf)
|
||||
@@ -0,0 +1,302 @@
|
||||
# CGGMP21 Threshold Signature Precompile
|
||||
|
||||
## Overview
|
||||
|
||||
The CGGMP21 (Canetti-Gennaro-Goldfeder-Makriyannis-Peled 2021) precompile enables threshold ECDSA signature verification. CGGMP21 is the state-of-the-art threshold signature protocol with identifiable aborts and efficient key refresh.
|
||||
|
||||
**Address**: `0x020000000000000000000000000000000000000D`
|
||||
|
||||
## Features
|
||||
|
||||
- **Threshold ECDSA**: Any t out of n parties can sign
|
||||
- **Identifiable Aborts**: Malicious parties can be detected
|
||||
- **Key Refresh**: Update shares without changing public key
|
||||
- **Standard ECDSA**: Compatible with Ethereum, Bitcoin, etc.
|
||||
- **MPC Custody**: Enterprise-grade multi-party custody
|
||||
|
||||
## Algorithm
|
||||
|
||||
CGGMP21 is a threshold signature scheme where:
|
||||
- **n** total parties hold shares of an ECDSA private key
|
||||
- Any **t** parties can collaborate to produce a valid signature
|
||||
- The signature is standard ECDSA (indistinguishable from single-party)
|
||||
- Malicious parties causing failures can be identified
|
||||
|
||||
### Key Properties
|
||||
|
||||
- **Identifiable Aborts**: Unlike GG20, can identify malicious parties
|
||||
- **Efficient Refresh**: Proactive security without downtime
|
||||
- **Non-Interactive DKG**: Efficient distributed key generation
|
||||
- **Presignature Support**: Precompute signatures for faster online phase
|
||||
|
||||
## Specifications
|
||||
|
||||
### Input Format
|
||||
|
||||
Total size: **170 bytes** (minimum)
|
||||
|
||||
| Offset | Size | Field | Description |
|
||||
|--------|------|-------|-------------|
|
||||
| 0-3 | 4 bytes | threshold | Minimum signers required (t) |
|
||||
| 4-7 | 4 bytes | totalSigners | Total number of parties (n) |
|
||||
| 8-72 | 65 bytes | publicKey | Aggregated ECDSA public key (uncompressed) |
|
||||
| 73-104 | 32 bytes | messageHash | Keccak256 hash of message |
|
||||
| 105-169 | 65 bytes | signature | ECDSA signature (r \|\| s \|\| v) |
|
||||
|
||||
### Output Format
|
||||
|
||||
**32 bytes**: Boolean result as uint256
|
||||
- `0x0000...0001` = Valid signature
|
||||
- `0x0000...0000` = Invalid signature
|
||||
|
||||
### Gas Costs
|
||||
|
||||
| Operation | Base Gas | Per-Signer Gas |
|
||||
|-----------|----------|----------------|
|
||||
| CGGMP21 Verify | 75,000 | 10,000 |
|
||||
|
||||
**Examples**:
|
||||
- 2-of-3 threshold: 75,000 + (3 × 10,000) = **105,000 gas**
|
||||
- 3-of-5 threshold: 75,000 + (5 × 10,000) = **125,000 gas**
|
||||
- 5-of-7 threshold: 75,000 + (7 × 10,000) = **145,000 gas**
|
||||
- 10-of-15 threshold: 75,000 + (15 × 10,000) = **225,000 gas**
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Solidity - Threshold Wallet
|
||||
|
||||
```solidity
|
||||
import "./ICGGMP21.sol";
|
||||
|
||||
contract MultiSigWallet is CGGMP21Verifier {
|
||||
bytes public thresholdPublicKey;
|
||||
uint32 public threshold;
|
||||
uint32 public totalSigners;
|
||||
|
||||
function executeWithThreshold(
|
||||
address to,
|
||||
uint256 value,
|
||||
bytes calldata data,
|
||||
bytes calldata signature
|
||||
) external {
|
||||
bytes32 txHash = keccak256(abi.encodePacked(to, value, data, nonce));
|
||||
|
||||
verifyCGGMP21Signature(
|
||||
threshold,
|
||||
totalSigners,
|
||||
thresholdPublicKey,
|
||||
txHash,
|
||||
signature
|
||||
);
|
||||
|
||||
// Execute transaction
|
||||
(bool success, ) = to.call{value: value}(data);
|
||||
require(success, "Execution failed");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### TypeScript (ethers.js)
|
||||
|
||||
```typescript
|
||||
const CGGMP21 = new ethers.Contract(
|
||||
'0x020000000000000000000000000000000000000D',
|
||||
[
|
||||
'function verify(uint32,uint32,bytes,bytes32,bytes) view returns(bool)'
|
||||
],
|
||||
provider
|
||||
);
|
||||
|
||||
// Verify 3-of-5 threshold ECDSA signature
|
||||
const isValid = await CGGMP21.verify(
|
||||
3, // threshold
|
||||
5, // totalSigners
|
||||
publicKey, // 65 bytes uncompressed
|
||||
messageHash, // 32 bytes
|
||||
signature // 65 bytes ECDSA
|
||||
);
|
||||
```
|
||||
|
||||
### Go - MPC Integration
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/luxfi/mpc/pkg/protocol/cggmp21"
|
||||
)
|
||||
|
||||
// Initialize CGGMP21 protocol
|
||||
protocol := cggmp21.NewProtocol()
|
||||
|
||||
// Distributed key generation (3-of-5)
|
||||
keygenParty, err := protocol.KeyGen("party1", partyIDs, 3)
|
||||
config := keygenParty.Result()
|
||||
|
||||
// Threshold signing
|
||||
signParty, err := protocol.Sign(config, signers, messageHash)
|
||||
signature := signParty.Result()
|
||||
|
||||
// Verify on-chain via precompile
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
|
||||
### 1. Multi-Party Custody
|
||||
|
||||
```solidity
|
||||
contract InstitutionalCustody is CGGMP21Verifier {
|
||||
// 5-of-7 threshold for institutional custody
|
||||
uint32 constant THRESHOLD = 5;
|
||||
uint32 constant TOTAL_SIGNERS = 7;
|
||||
|
||||
function transferAssets(
|
||||
address token,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata thresholdSig
|
||||
) external {
|
||||
bytes32 txHash = keccak256(abi.encodePacked(token, to, amount));
|
||||
|
||||
verifyCGGMP21Signature(
|
||||
THRESHOLD,
|
||||
TOTAL_SIGNERS,
|
||||
custodyPublicKey,
|
||||
txHash,
|
||||
thresholdSig
|
||||
);
|
||||
|
||||
IERC20(token).transfer(to, amount);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. DAO Treasury Management
|
||||
|
||||
```solidity
|
||||
contract DAOTreasury is CGGMP21Verifier {
|
||||
// 7-of-10 DAO council
|
||||
function executeDAODecision(
|
||||
bytes32 proposalId,
|
||||
bytes calldata executionData,
|
||||
bytes calldata councilSignature
|
||||
) external {
|
||||
verifyCGGMP21Signature(
|
||||
DAO_THRESHOLD,
|
||||
DAO_COUNCIL_SIZE,
|
||||
daoPublicKey,
|
||||
proposalId,
|
||||
councilSignature
|
||||
);
|
||||
|
||||
// Execute DAO decision
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Cross-Chain Bridge
|
||||
|
||||
```solidity
|
||||
contract ThresholdBridge is CGGMP21Verifier {
|
||||
// Validators sign cross-chain messages
|
||||
function relayMessage(
|
||||
uint256 sourceChain,
|
||||
bytes calldata message,
|
||||
bytes calldata validatorSig
|
||||
) external {
|
||||
bytes32 messageHash = keccak256(abi.encodePacked(
|
||||
sourceChain,
|
||||
block.chainid,
|
||||
message
|
||||
));
|
||||
|
||||
verifyCGGMP21Signature(
|
||||
VALIDATOR_THRESHOLD,
|
||||
TOTAL_VALIDATORS,
|
||||
validatorPublicKey,
|
||||
messageHash,
|
||||
validatorSig
|
||||
);
|
||||
|
||||
// Process cross-chain message
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Threshold Selection
|
||||
|
||||
- **2-of-3**: Small teams, personal wallets
|
||||
- **3-of-5**: Standard multi-sig, small DAOs
|
||||
- **5-of-7**: Medium security, trading firms
|
||||
- **7-of-10** or higher: High security, institutional custody
|
||||
|
||||
### Key Management
|
||||
|
||||
- **Key Refresh**: Periodically refresh shares for proactive security
|
||||
- **Backup Shares**: Securely backup threshold shares
|
||||
- **Identifiable Aborts**: Monitor and remove malicious parties
|
||||
- **Share Distribution**: Never store all shares in one location
|
||||
|
||||
### Message Hashing
|
||||
|
||||
Always hash messages with domain separation:
|
||||
|
||||
```solidity
|
||||
bytes32 domainHash = keccak256(abi.encodePacked(
|
||||
address(this),
|
||||
block.chainid,
|
||||
"CGGMP21-v1"
|
||||
));
|
||||
|
||||
bytes32 messageHash = keccak256(abi.encodePacked(
|
||||
domainHash,
|
||||
nonce,
|
||||
data
|
||||
));
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
Benchmarks on Apple M1 Max:
|
||||
|
||||
| Configuration | Gas Cost | Verify Time | Memory |
|
||||
|--------------|----------|-------------|--------|
|
||||
| 2-of-3 | 105,000 | ~65 μs | 12 KB |
|
||||
| 3-of-5 | 125,000 | ~80 μs | 14 KB |
|
||||
| 5-of-7 | 145,000 | ~95 μs | 16 KB |
|
||||
| 10-of-15 | 225,000 | ~140 μs | 22 KB |
|
||||
|
||||
## Comparison with Other Schemes
|
||||
|
||||
| Algorithm | Type | Signature Size | Gas Cost | Identifiable Aborts |
|
||||
|-----------|------|---------------|----------|-------------------|
|
||||
| CGGMP21 (this) | ECDSA | 65 bytes | 75k-225k | ✅ |
|
||||
| FROST | Schnorr | 64 bytes | 50k-125k | ❌ |
|
||||
| GG20 | ECDSA | 65 bytes | 75k-225k | ❌ |
|
||||
| BLS (Warp) | BLS12-381 | 96 bytes | 120k | ✅ |
|
||||
|
||||
## Integration with Lux MPC
|
||||
|
||||
This precompile integrates with `/Users/z/work/lux/mpc/pkg/protocol/cggmp21`:
|
||||
|
||||
```go
|
||||
import "github.com/luxfi/mpc/pkg/protocol/cggmp21"
|
||||
|
||||
// The MPC library provides:
|
||||
// - protocol.KeyGen() - Distributed key generation
|
||||
// - protocol.Sign() - Threshold signing
|
||||
// - protocol.Refresh() - Share refreshing
|
||||
// - protocol.PreSign() - Presignature generation
|
||||
```
|
||||
|
||||
## Standards Compliance
|
||||
|
||||
- **CGGMP21 Paper**: [ePrint 2021/060](https://eprint.iacr.org/2021/060)
|
||||
- **ECDSA**: secp256k1 curve (Bitcoin/Ethereum)
|
||||
- **EIP-191**: Signed data standard
|
||||
|
||||
## References
|
||||
|
||||
- [CGGMP21 Paper](https://eprint.iacr.org/2021/060.pdf)
|
||||
- [Lux MPC Library](https://github.com/luxfi/mpc)
|
||||
- [Threshold ECDSA Overview](https://www.fireblocks.com/what-is-mpc-wallet/)
|
||||
@@ -0,0 +1,337 @@
|
||||
# Corona Threshold Signature Precompile
|
||||
|
||||
Post-quantum threshold signature verification precompile for Lux EVM, implementing the LWE-based two-round threshold signature scheme from [Corona (ePrint 2024/1113)](https://eprint.iacr.org/2024/1113).
|
||||
|
||||
## Overview
|
||||
|
||||
The Corona Threshold precompile enables verification of lattice-based threshold signatures on-chain, providing post-quantum security for multi-party consensus protocols. This is a critical component of the Quasar quantum consensus mechanism.
|
||||
|
||||
**Precompile Address**: `0x020000000000000000000000000000000000000B`
|
||||
|
||||
## Features
|
||||
|
||||
- **Post-Quantum Security**: Based on Learning With Errors (LWE) lattice problem
|
||||
- **Threshold Signatures**: Supports t-of-n threshold schemes
|
||||
- **Two-Round Protocol**: Efficient distributed signing
|
||||
- **Quasar Integration**: Native support for quantum consensus validators
|
||||
- **Flexible Thresholds**: Configurable from 1-of-n to n-of-n
|
||||
|
||||
## Algorithm
|
||||
|
||||
Corona implements a threshold signature scheme based on:
|
||||
- **Lattice Cryptography**: LWE problem hardness
|
||||
- **Ring Learning With Errors**: Polynomial ring operations
|
||||
- **Threshold Secret Sharing**: Shamir's secret sharing over rings
|
||||
- **Two-Round Protocol**: Efficient distributed key generation and signing
|
||||
|
||||
### Parameters
|
||||
|
||||
From `corona/sign/config.go`:
|
||||
|
||||
| Parameter | Value | Description |
|
||||
|-----------|-------|-------------|
|
||||
| M | 8 | Matrix rows |
|
||||
| N | 7 | Matrix columns |
|
||||
| Dbar | 48 | Signature dimension |
|
||||
| Q | 0x1000000004A01 | Prime modulus (48-bit) |
|
||||
| LogN | 8 | Ring dimension log (256) |
|
||||
| SigmaE | 6.108 | Error distribution |
|
||||
| SigmaStar | 1.73e11 | Masking distribution |
|
||||
|
||||
### Security Level
|
||||
|
||||
- **Classical**: >128-bit security
|
||||
- **Quantum**: Resistant to Shor's algorithm
|
||||
- **Hardness**: Based on LWE with modulus Q and dimension 256
|
||||
|
||||
## Gas Costs
|
||||
|
||||
| Operation | Formula | Example |
|
||||
|-----------|---------|---------|
|
||||
| Base Cost | 150,000 | Fixed cost |
|
||||
| Per Party | 10,000 × n | Cost per party |
|
||||
| **2 parties** | 150,000 + 20,000 | **170,000 gas** |
|
||||
| **3 parties** | 150,000 + 30,000 | **180,000 gas** |
|
||||
| **5 parties** | 150,000 + 50,000 | **200,000 gas** |
|
||||
| **10 parties** | 150,000 + 100,000 | **250,000 gas** |
|
||||
|
||||
## Input Format
|
||||
|
||||
```
|
||||
Offset | Size | Field
|
||||
--------|------|------------------
|
||||
0-4 | 4 | threshold (uint32)
|
||||
4-8 | 4 | totalParties (uint32)
|
||||
8-40 | 32 | messageHash (bytes32)
|
||||
40-... | ~4KB | signature (variable)
|
||||
```
|
||||
|
||||
### Signature Components
|
||||
|
||||
The signature consists of serialized lattice elements:
|
||||
- **c**: Challenge polynomial (256 bytes)
|
||||
- **z**: Response vector (N × 256 bytes = 1,792 bytes)
|
||||
- **Delta**: Difference vector (M × 256 bytes = 2,048 bytes)
|
||||
- **A**: Public matrix (M × N × 256 bytes = 14,336 bytes)
|
||||
- **bTilde**: Rounded vector (M × 256 bytes = 2,048 bytes)
|
||||
|
||||
**Total**: ~20KB per signature
|
||||
|
||||
## Usage
|
||||
|
||||
### Solidity
|
||||
|
||||
```solidity
|
||||
import "./ICoronaThreshold.sol";
|
||||
|
||||
contract MyContract is CoronaThresholdVerifier {
|
||||
function verifyConsensus(
|
||||
bytes32 messageHash,
|
||||
bytes calldata signature
|
||||
) external view returns (bool) {
|
||||
// 2-of-3 threshold
|
||||
return verifyThresholdSignature(
|
||||
2, // threshold
|
||||
3, // total parties
|
||||
messageHash,
|
||||
signature
|
||||
);
|
||||
}
|
||||
|
||||
function processSignedData(
|
||||
bytes32 messageHash,
|
||||
bytes calldata signature
|
||||
) external {
|
||||
// Revert if invalid
|
||||
CoronaThresholdLib.verifyOrRevert(
|
||||
2, 3, messageHash, signature
|
||||
);
|
||||
|
||||
// Process data - signature is valid
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### TypeScript/ethers.js
|
||||
|
||||
```typescript
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
const CORONA_THRESHOLD = '0x020000000000000000000000000000000000000B';
|
||||
|
||||
const abi = [
|
||||
'function verifyThreshold(uint32,uint32,bytes32,bytes) view returns(bool)'
|
||||
];
|
||||
|
||||
const precompile = new ethers.Contract(CORONA_THRESHOLD, abi, provider);
|
||||
|
||||
// Verify 2-of-3 threshold signature
|
||||
const isValid = await precompile.verifyThreshold(
|
||||
2, // threshold
|
||||
3, // total parties
|
||||
messageHash, // bytes32
|
||||
signatureBytes // bytes
|
||||
);
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
```go
|
||||
import (
|
||||
"corona/sign"
|
||||
"github.com/luxfi/lattice/v6/ring"
|
||||
)
|
||||
|
||||
// Generate threshold signature (off-chain)
|
||||
threshold := 2
|
||||
totalParties := 3
|
||||
|
||||
// Initialize rings
|
||||
r, _ := ring.NewRing(1<<sign.LogN, []uint64{sign.Q})
|
||||
r_xi, _ := ring.NewRing(1<<sign.LogN, []uint64{sign.QXi})
|
||||
r_nu, _ := ring.NewRing(1<<sign.LogN, []uint64{sign.QNu})
|
||||
|
||||
// Run threshold signing protocol
|
||||
// ... (see corona/main.go for full example)
|
||||
|
||||
// Verify signature
|
||||
valid := sign.Verify(r, r_xi, r_nu, z, A, mu, bTilde, c, Delta)
|
||||
```
|
||||
|
||||
## Protocol Flow
|
||||
|
||||
### Setup Phase
|
||||
1. Trusted dealer generates keys using `sign.Gen()`
|
||||
2. Secret shares distributed to n parties
|
||||
3. Public parameters (A, b) published
|
||||
|
||||
### Signing Phase (Two Rounds)
|
||||
|
||||
**Round 1**: Each party generates masking polynomials
|
||||
```go
|
||||
D_i, MACs_i := party.SignRound1(A, sid, PRFKey, T)
|
||||
```
|
||||
|
||||
**Round 2 Preprocess**: Verify MACs and combine D matrices
|
||||
```go
|
||||
valid, DSum, hash := party.SignRound2Preprocess(A, b, D, MACs, sid, T)
|
||||
```
|
||||
|
||||
**Round 2**: Each party generates signature share
|
||||
```go
|
||||
z_i := party.SignRound2(A, bTilde, DSum, sid, mu, T, PRFKey, hash)
|
||||
```
|
||||
|
||||
**Finalize**: Combiner aggregates shares
|
||||
```go
|
||||
c, z_sum, Delta := party.SignFinalize(z, A, bTilde)
|
||||
```
|
||||
|
||||
### Verification
|
||||
```go
|
||||
valid := sign.Verify(r, r_xi, r_nu, z, A, mu, bTilde, c, Delta)
|
||||
```
|
||||
|
||||
## Quasar Consensus Integration
|
||||
|
||||
The Corona threshold precompile is designed for Quasar consensus:
|
||||
|
||||
```solidity
|
||||
contract QuasarConsensus {
|
||||
uint32 constant VALIDATORS = 5;
|
||||
uint32 constant THRESHOLD = 4; // 4-of-5 for finality
|
||||
|
||||
function finalizeBlock(
|
||||
bytes32 blockHash,
|
||||
bytes calldata validatorSignature
|
||||
) external {
|
||||
// Verify 4-of-5 validators signed
|
||||
CoronaThresholdLib.verifyOrRevert(
|
||||
THRESHOLD,
|
||||
VALIDATORS,
|
||||
blockHash,
|
||||
validatorSignature
|
||||
);
|
||||
|
||||
// Block is finalized with quantum-resistant proof
|
||||
emit BlockFinalized(blockHash);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Post-Quantum Security
|
||||
- **Quantum Attacks**: Resistant to Shor's algorithm
|
||||
- **Classical Attacks**: >128-bit security under LWE assumption
|
||||
- **Side Channels**: Constant-time operations in lattice library
|
||||
|
||||
### Threshold Properties
|
||||
- **Unforgeability**: Cannot forge signature without t parties
|
||||
- **Robustness**: Works with any subset of size t
|
||||
- **Non-interactivity**: After setup, signing is non-interactive per party
|
||||
|
||||
### Network Security
|
||||
- **MAC Protection**: Message authentication codes prevent tampering
|
||||
- **Replay Protection**: Session IDs prevent signature replay
|
||||
- **Rank Checks**: Full rank verification prevents malicious matrices
|
||||
|
||||
## Performance
|
||||
|
||||
### Benchmarks (Apple M1 Max)
|
||||
|
||||
| Operation | Time | Gas |
|
||||
|-----------|------|-----|
|
||||
| 2-of-3 verify | ~2.5ms | 170,000 |
|
||||
| 3-of-5 verify | ~3.8ms | 200,000 |
|
||||
| 5-of-7 verify | ~5.2ms | 220,000 |
|
||||
|
||||
### Comparison with Other Schemes
|
||||
|
||||
| Scheme | Signature Size | Verify Time | Quantum Secure |
|
||||
|--------|---------------|-------------|----------------|
|
||||
| ECDSA (secp256k1) | 65 bytes | ~88μs | ❌ |
|
||||
| BLS | 96 bytes | ~2.1ms | ❌ |
|
||||
| **Corona** | **~20KB** | **~3.8ms** | **✅** |
|
||||
| ML-DSA-65 | 3.3KB | ~108μs | ✅ |
|
||||
| SLH-DSA | 7.9KB | ~4.2ms | ✅ |
|
||||
|
||||
**Trade-offs**:
|
||||
- ✅ Post-quantum security
|
||||
- ✅ Threshold signatures
|
||||
- ✅ Two-round protocol
|
||||
- ⚠️ Large signature size (~20KB)
|
||||
- ⚠️ Higher verification time
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
# Run tests
|
||||
cd /Users/z/work/lux/standard/src/precompiles/corona-threshold
|
||||
go test -v
|
||||
|
||||
# Run benchmarks
|
||||
go test -bench=. -benchmem
|
||||
|
||||
# Test with specific threshold
|
||||
go test -run TestCoronaThresholdVerify_3of5
|
||||
```
|
||||
|
||||
### Test Coverage
|
||||
|
||||
- ✅ 2-of-3 threshold signature
|
||||
- ✅ 3-of-5 threshold signature
|
||||
- ✅ Full threshold (n-of-n)
|
||||
- ✅ Invalid signature rejection
|
||||
- ✅ Wrong message rejection
|
||||
- ✅ Threshold not met rejection
|
||||
- ✅ Input validation
|
||||
- ✅ Gas cost calculation
|
||||
|
||||
## Migration from Classical Signatures
|
||||
|
||||
### From ECDSA
|
||||
```solidity
|
||||
// Before (ECDSA)
|
||||
function verify(bytes32 hash, bytes memory sig) public view {
|
||||
address signer = ECDSA.recover(hash, sig);
|
||||
require(isAuthorized(signer), "Unauthorized");
|
||||
}
|
||||
|
||||
// After (Corona Threshold)
|
||||
function verify(bytes32 hash, bytes memory sig) public view {
|
||||
CoronaThresholdLib.verifyOrRevert(
|
||||
THRESHOLD,
|
||||
TOTAL_SIGNERS,
|
||||
hash,
|
||||
sig
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### From BLS
|
||||
```solidity
|
||||
// Before (BLS aggregate)
|
||||
function verify(bytes32 hash, bytes memory sig) public view {
|
||||
require(BLS.verify(aggregateKey, hash, sig), "Invalid");
|
||||
}
|
||||
|
||||
// After (Corona Threshold)
|
||||
function verify(bytes32 hash, bytes memory sig) public view {
|
||||
require(
|
||||
verifyThresholdSignature(THRESHOLD, N, hash, sig),
|
||||
"Invalid"
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [Corona Paper (ePrint 2024/1113)](https://eprint.iacr.org/2024/1113)
|
||||
- [Lattice Library](https://github.com/luxfi/lattice)
|
||||
- [Corona Implementation](/Users/z/work/lux/corona/)
|
||||
- [Quasar Consensus](/Users/z/work/lux/node/consensus/protocol/quasar/)
|
||||
|
||||
## License
|
||||
|
||||
Copyright (C) 2025, Lux Industries, Inc. All rights reserved.
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
# Dead Precompile (LP-0150)
|
||||
|
||||
**Address**: Multiple (0x0, 0xdead, 0xdEaD...)
|
||||
**Gas Cost**: 10,000 base
|
||||
**Status**: Implemented
|
||||
|
||||
## Overview
|
||||
|
||||
The Dead Precompile intercepts transfers to "dead" addresses (commonly used for token burns) and routes them to a 50/50 split between:
|
||||
|
||||
1. **Actual Burn (50%)** - Value is permanently destroyed (deflationary)
|
||||
2. **DAO Treasury (50%)** - Value goes to Protocol-Owned Liquidity (POL)
|
||||
|
||||
This creates sustainable protocol revenue from burn activities instead of purely destroying value.
|
||||
|
||||
## Registered Addresses
|
||||
|
||||
| Address | Description | ConfigKey |
|
||||
|---------|-------------|-----------|
|
||||
| `0x0000000000000000000000000000000000000000` | Zero address | `deadZeroConfig` |
|
||||
| `0x000000000000000000000000000000000000dEaD` | Common dead address | `deadConfig` |
|
||||
| `0xdEaD000000000000000000000000000000000000` | Full dead prefix | `deadFullConfig` |
|
||||
|
||||
## DAO Treasury
|
||||
|
||||
Funds are routed to: `0x9011E888251AB053B7bD1cdB598Db4f9DEd94714`
|
||||
|
||||
This address is on X-Chain and accumulates protocol-owned liquidity.
|
||||
|
||||
## Split Ratio
|
||||
|
||||
| Component | Percentage | BPS |
|
||||
|-----------|------------|-----|
|
||||
| Burn | 50% | 5000 |
|
||||
| Treasury | 50% | 5000 |
|
||||
|
||||
When values cannot be split evenly (odd wei amounts), the treasury receives the extra wei.
|
||||
|
||||
## Usage
|
||||
|
||||
### Direct Interaction
|
||||
|
||||
The precompile is automatically invoked when calling or transferring to any registered dead address:
|
||||
|
||||
```solidity
|
||||
// Solidity - transfer to dead address triggers precompile
|
||||
address payable dead = payable(0x000000000000000000000000000000000000dEaD);
|
||||
dead.transfer(1 ether);
|
||||
// Result: 0.5 ETH burned, 0.5 ETH to treasury
|
||||
```
|
||||
|
||||
### Programmatic Access
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/luxfi/precompile/dead"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func main() {
|
||||
value := big.NewInt(1e18) // 1 ETH
|
||||
|
||||
// Check if address is a dead address
|
||||
if dead.IsDeadAddress(addr) {
|
||||
burn, treasury := dead.CalculateSplit(value)
|
||||
// burn = 0.5 ETH
|
||||
// treasury = 0.5 ETH
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Mechanics
|
||||
|
||||
When a transaction targets a dead address:
|
||||
|
||||
1. EVM recognizes the address as a precompile
|
||||
2. `DeadPrecompile.Run()` is invoked
|
||||
3. The `value` (ETH sent) is split 50/50
|
||||
4. 50% is left at the dead address (effectively burned)
|
||||
5. 50% is transferred to DAO treasury
|
||||
6. Transaction stats are recorded via event
|
||||
|
||||
## Events
|
||||
|
||||
```solidity
|
||||
event DeadReceived(
|
||||
address indexed sender,
|
||||
address indexed deadAddress,
|
||||
uint256 totalValue,
|
||||
uint256 burnedAmount,
|
||||
uint256 treasuryAmount
|
||||
);
|
||||
```
|
||||
|
||||
## Gas Costs
|
||||
|
||||
| Operation | Gas |
|
||||
|-----------|-----|
|
||||
| Base cost | 10,000 |
|
||||
| With balance transfer | +21,000 (standard transfer) |
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Deterministic Split**: Split ratio is hardcoded (not configurable) to prevent manipulation
|
||||
2. **DAO Treasury**: Uses a fixed address, governance changes require contract upgrade
|
||||
3. **Reentrancy**: The precompile is stateless and doesn't call external contracts in a reentrant manner
|
||||
4. **Value Conservation**: Total value always equals burn + treasury (verified in tests)
|
||||
|
||||
## Files
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `contract.go` | Core precompile implementation |
|
||||
| `contract_test.go` | Unit tests |
|
||||
| `module.go` | Module registration |
|
||||
| `README.md` | This documentation |
|
||||
|
||||
## Related
|
||||
|
||||
- [LP-0150](https://github.com/luxfi/lps/blob/main/LPs/lp-0150-dead-precompile.md) - Full specification
|
||||
- [IDead.sol](https://github.com/luxfi/standard/blob/main/contracts/precompile/interfaces/IDead.sol) - Solidity interface
|
||||
@@ -0,0 +1,33 @@
|
||||
# dependencies
|
||||
node_modules
|
||||
.pnpm-debug.log*
|
||||
|
||||
# next.js
|
||||
.next/
|
||||
out/
|
||||
|
||||
# production
|
||||
build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
.env
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
# fumadocs generated
|
||||
.source/
|
||||
@@ -0,0 +1,49 @@
|
||||
import { source } from '@/lib/source';
|
||||
import { DocsPage, DocsBody } from 'fumadocs-ui/page';
|
||||
import { notFound } from 'next/navigation';
|
||||
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
||||
|
||||
export default async function Page({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ slug?: string[] }>;
|
||||
}) {
|
||||
const { slug } = await params;
|
||||
const page = source.getPage(slug);
|
||||
if (!page) notFound();
|
||||
|
||||
const MDX = page.data.body;
|
||||
|
||||
return (
|
||||
<DocsPage toc={page.data.toc}>
|
||||
<DocsBody>
|
||||
<h1>{page.data.title}</h1>
|
||||
<p className="text-fd-muted-foreground text-lg mb-8">
|
||||
{page.data.description}
|
||||
</p>
|
||||
<MDX components={{ ...defaultMdxComponents }} />
|
||||
</DocsBody>
|
||||
</DocsPage>
|
||||
);
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
return source.getPages().map((page) => ({
|
||||
slug: page.slugs,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ slug?: string[] }>;
|
||||
}) {
|
||||
const { slug } = await params;
|
||||
const page = source.getPage(slug);
|
||||
if (!page) notFound();
|
||||
|
||||
return {
|
||||
title: page.data.title,
|
||||
description: page.data.description,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
||||
import { source } from '@/lib/source';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<DocsLayout
|
||||
tree={source.pageTree}
|
||||
nav={{
|
||||
title: 'Lux Precompiles',
|
||||
}}
|
||||
links={[
|
||||
{
|
||||
text: 'Standard Contracts',
|
||||
url: 'https://standard.lux.network',
|
||||
external: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{children}
|
||||
</DocsLayout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
@import 'tailwindcss';
|
||||
@import 'fumadocs-ui/css/neutral.css';
|
||||
@import 'fumadocs-ui/css/preset.css';
|
||||
@plugin 'tailwindcss-animate';
|
||||
|
||||
@theme {
|
||||
--color-fd-primary: hsl(0, 0%, 100%);
|
||||
--color-fd-primary-foreground: hsl(0, 0%, 9%);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--color-fd-primary: hsl(0, 0%, 98%);
|
||||
--color-fd-primary-foreground: hsl(0, 0%, 9%);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import './globals.css';
|
||||
import { RootProvider } from 'fumadocs-ui/provider/next';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export const metadata = {
|
||||
title: 'Lux Precompiles',
|
||||
description: 'Native EVM precompile documentation for Lux Network',
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<body>
|
||||
<RootProvider>{children}</RootProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
import Link from 'next/link';
|
||||
|
||||
const features = [
|
||||
{
|
||||
title: 'Cryptography',
|
||||
description: 'ML-DSA, ML-KEM, SLH-DSA, FROST, Corona, CGGMP21',
|
||||
href: '/docs/crypto',
|
||||
icon: '🔐',
|
||||
},
|
||||
{
|
||||
title: 'DEX',
|
||||
description: 'PoolManager, SwapRouter, Hooks, FlashLoan',
|
||||
href: '/docs/dex',
|
||||
icon: '🔄',
|
||||
},
|
||||
{
|
||||
title: 'FHE',
|
||||
description: 'Fully Homomorphic Encryption for private computation',
|
||||
href: '/docs/fhe',
|
||||
icon: '🔒',
|
||||
},
|
||||
{
|
||||
title: 'Oracle',
|
||||
description: 'Native price feeds and GraphQL via G-Chain',
|
||||
href: '/docs/oracle',
|
||||
icon: '📊',
|
||||
},
|
||||
{
|
||||
title: 'AI Mining',
|
||||
description: 'GPU attestation, NVTrust, compute rewards',
|
||||
href: '/docs/ai',
|
||||
icon: '🤖',
|
||||
},
|
||||
{
|
||||
title: 'Threshold',
|
||||
description: 'FROST Schnorr, CGGMP21 ECDSA, Corona PQ',
|
||||
href: '/docs/threshold',
|
||||
icon: '🔑',
|
||||
},
|
||||
{
|
||||
title: 'Bridge',
|
||||
description: 'Warp messaging, cross-chain verification',
|
||||
href: '/docs/bridge',
|
||||
icon: '🌉',
|
||||
},
|
||||
{
|
||||
title: 'ZK Proofs',
|
||||
description: 'KZG, Groth16, PLONK verification',
|
||||
href: '/docs/zk',
|
||||
icon: '✨',
|
||||
},
|
||||
];
|
||||
|
||||
const standardLink = {
|
||||
title: 'Solidity Contracts',
|
||||
description: 'Pure Solidity implementations for maximum compatibility',
|
||||
href: 'https://standard.lux.network',
|
||||
external: true,
|
||||
};
|
||||
|
||||
const stats = [
|
||||
{ label: 'Precompiles', value: '40+' },
|
||||
{ label: 'Gas Savings', value: '10-100x' },
|
||||
{ label: 'Latency', value: '<3μs' },
|
||||
{ label: 'Throughput', value: '400K/s' },
|
||||
];
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<main className="min-h-screen">
|
||||
{/* Hero Section */}
|
||||
<section className="relative overflow-hidden bg-gradient-to-b from-fd-background to-fd-muted/30">
|
||||
<div className="absolute inset-0 bg-grid-white/[0.02] bg-[size:60px_60px]" />
|
||||
<div className="relative mx-auto max-w-7xl px-6 py-24 sm:py-32 lg:px-8">
|
||||
<div className="mx-auto max-w-2xl text-center">
|
||||
<div className="mb-8 flex justify-center">
|
||||
<div className="rounded-full bg-fd-primary/10 px-4 py-1.5 text-sm font-medium text-fd-primary ring-1 ring-inset ring-fd-primary/20">
|
||||
v0.4.0 — Native Performance
|
||||
</div>
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold tracking-tight sm:text-6xl bg-gradient-to-r from-fd-foreground to-fd-foreground/70 bg-clip-text text-transparent">
|
||||
Lux Precompiles
|
||||
</h1>
|
||||
<p className="mt-6 text-lg leading-8 text-fd-muted-foreground">
|
||||
Native EVM precompiles for high-performance cryptography,
|
||||
DEX operations, and blockchain primitives.
|
||||
10-100x faster than Solidity.
|
||||
</p>
|
||||
<div className="mt-10 flex items-center justify-center gap-x-4">
|
||||
<Link
|
||||
href="/docs"
|
||||
className="rounded-lg bg-fd-primary px-5 py-2.5 text-sm font-semibold text-fd-primary-foreground shadow-sm hover:bg-fd-primary/90 transition-colors"
|
||||
>
|
||||
Get Started
|
||||
</Link>
|
||||
<Link
|
||||
href="https://github.com/luxfi/precompile"
|
||||
className="rounded-lg px-5 py-2.5 text-sm font-semibold text-fd-foreground ring-1 ring-fd-border hover:bg-fd-muted transition-colors"
|
||||
>
|
||||
GitHub →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Stats Section */}
|
||||
<section className="border-y border-fd-border bg-fd-muted/30">
|
||||
<div className="mx-auto max-w-7xl px-6 py-12 lg:px-8">
|
||||
<dl className="grid grid-cols-2 gap-x-8 gap-y-8 text-center lg:grid-cols-4">
|
||||
{stats.map((stat) => (
|
||||
<div key={stat.label} className="mx-auto flex max-w-xs flex-col">
|
||||
<dt className="text-base leading-7 text-fd-muted-foreground">{stat.label}</dt>
|
||||
<dd className="order-first text-3xl font-semibold tracking-tight text-fd-foreground">{stat.value}</dd>
|
||||
</div>
|
||||
))}
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Features Grid */}
|
||||
<section className="mx-auto max-w-7xl px-6 py-24 lg:px-8">
|
||||
<div className="mx-auto max-w-2xl text-center">
|
||||
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl">
|
||||
Native Performance for Every Operation
|
||||
</h2>
|
||||
<p className="mt-4 text-lg text-fd-muted-foreground">
|
||||
Precompiles execute as native code, bypassing EVM overhead
|
||||
</p>
|
||||
</div>
|
||||
<div className="mx-auto mt-16 grid max-w-5xl grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{features.map((feature) => (
|
||||
<Link
|
||||
key={feature.title}
|
||||
href={feature.href}
|
||||
className="group relative rounded-xl border border-fd-border bg-fd-card p-6 hover:border-fd-primary/50 hover:bg-fd-muted/50 transition-all"
|
||||
>
|
||||
<div className="text-3xl mb-4">{feature.icon}</div>
|
||||
<h3 className="text-lg font-semibold text-fd-foreground group-hover:text-fd-primary transition-colors">
|
||||
{feature.title}
|
||||
</h3>
|
||||
<p className="mt-2 text-sm text-fd-muted-foreground">
|
||||
{feature.description}
|
||||
</p>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Standard Callout */}
|
||||
<section className="border-t border-fd-border">
|
||||
<div className="mx-auto max-w-7xl px-6 py-12 lg:px-8">
|
||||
<a
|
||||
href={standardLink.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group flex items-center justify-between rounded-xl border border-fd-border bg-gradient-to-r from-fd-muted/50 to-fd-card p-6 hover:border-fd-primary/50 transition-all"
|
||||
>
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xl">📜</span>
|
||||
<h3 className="text-lg font-semibold text-fd-foreground group-hover:text-fd-primary transition-colors">
|
||||
{standardLink.title}
|
||||
</h3>
|
||||
<span className="rounded-full bg-fd-primary/10 px-2.5 py-0.5 text-xs font-medium text-fd-primary">
|
||||
469 Contracts
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-2 text-sm text-fd-muted-foreground max-w-xl">
|
||||
Need portable Solidity? Lux Standard Library provides tokens, DeFi, governance, and more as pure Solidity.
|
||||
</p>
|
||||
</div>
|
||||
<span className="text-fd-muted-foreground group-hover:text-fd-primary transition-colors">→</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Address Map Section */}
|
||||
<section className="border-t border-fd-border bg-fd-muted/30">
|
||||
<div className="mx-auto max-w-7xl px-6 py-24 lg:px-8">
|
||||
<div className="mx-auto max-w-2xl">
|
||||
<h2 className="text-2xl font-bold tracking-tight mb-8">Address Map</h2>
|
||||
<div className="rounded-xl border border-fd-border bg-fd-card overflow-hidden">
|
||||
<div className="border-b border-fd-border px-4 py-2 bg-fd-muted/50">
|
||||
<span className="text-sm text-fd-muted-foreground">Precompile Ranges</span>
|
||||
</div>
|
||||
<pre className="p-4 text-sm overflow-x-auto">
|
||||
<code className="text-fd-foreground">{`0x0100-0x01FF Warp/Teleport Cross-chain messaging
|
||||
0x0300-0x03FF AI/ML Mining, NVTrust, Models
|
||||
0x0400-0x04FF DEX Uniswap v4-style AMM
|
||||
0x0500-0x05FF Graph/Query GraphQL, Subscriptions
|
||||
0x0600-0x06FF Post-Quantum ML-DSA, ML-KEM, SLH-DSA
|
||||
0x0700-0x07FF Privacy FHE, ECIES, Ring, HPKE
|
||||
0x0800-0x08FF Threshold FROST, CGGMP21, Corona
|
||||
0x0900-0x09FF ZK Proofs KZG, Groth16, PLONK`}</code>
|
||||
</pre>
|
||||
</div>
|
||||
<div className="mt-8 flex gap-4">
|
||||
<Link
|
||||
href="/docs"
|
||||
className="text-sm font-medium text-fd-primary hover:text-fd-primary/80"
|
||||
>
|
||||
View full address map →
|
||||
</Link>
|
||||
<Link
|
||||
href="/docs/usage"
|
||||
className="text-sm font-medium text-fd-muted-foreground hover:text-fd-foreground"
|
||||
>
|
||||
Usage examples
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Performance Section */}
|
||||
<section className="mx-auto max-w-7xl px-6 py-24 lg:px-8">
|
||||
<div className="mx-auto max-w-2xl text-center mb-16">
|
||||
<h2 className="text-3xl font-bold tracking-tight">Benchmarks (Apple M1 Max)</h2>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-5xl mx-auto">
|
||||
<div className="text-center">
|
||||
<div className="mx-auto w-12 h-12 rounded-full bg-fd-primary/10 flex items-center justify-center mb-4">
|
||||
<span className="text-2xl">🔄</span>
|
||||
</div>
|
||||
<h3 className="font-semibold mb-2">DEX Swap</h3>
|
||||
<p className="text-2xl font-bold text-fd-primary">2.26μs</p>
|
||||
<p className="text-sm text-fd-muted-foreground">443K ops/sec</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="mx-auto w-12 h-12 rounded-full bg-fd-primary/10 flex items-center justify-center mb-4">
|
||||
<span className="text-2xl">🔐</span>
|
||||
</div>
|
||||
<h3 className="font-semibold mb-2">ML-DSA Verify</h3>
|
||||
<p className="text-2xl font-bold text-fd-primary">50μs</p>
|
||||
<p className="text-sm text-fd-muted-foreground">Post-quantum secure</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="mx-auto w-12 h-12 rounded-full bg-fd-primary/10 flex items-center justify-center mb-4">
|
||||
<span className="text-2xl">🔑</span>
|
||||
</div>
|
||||
<h3 className="font-semibold mb-2">FROST Verify</h3>
|
||||
<p className="text-2xl font-bold text-fd-primary">45μs</p>
|
||||
<p className="text-sm text-fd-muted-foreground">Threshold Schnorr</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Footer */}
|
||||
<footer className="border-t border-fd-border">
|
||||
<div className="mx-auto max-w-7xl px-6 py-12 lg:px-8">
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-8 mb-8">
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold text-fd-foreground mb-4">Documentation</h4>
|
||||
<ul className="space-y-2">
|
||||
<li><Link href="https://docs.lux.network" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">Lux Docs</Link></li>
|
||||
<li><Link href="https://standard.lux.network" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">Standard Contracts</Link></li>
|
||||
<li><Link href="https://precompile.lux.network" className="text-sm text-fd-primary hover:text-fd-primary/80">Precompiles</Link></li>
|
||||
<li><Link href="https://lps.lux.network" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">LPs (Proposals)</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold text-fd-foreground mb-4">Network</h4>
|
||||
<ul className="space-y-2">
|
||||
<li><Link href="https://consensus.lux.network" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">Consensus</Link></li>
|
||||
<li><Link href="https://explorer.lux.network" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">Explorer</Link></li>
|
||||
<li><Link href="https://bridge.lux.network" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">Bridge</Link></li>
|
||||
<li><Link href="https://dex.lux.network" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">DEX</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold text-fd-foreground mb-4">Developers</h4>
|
||||
<ul className="space-y-2">
|
||||
<li><Link href="https://github.com/luxfi" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">GitHub</Link></li>
|
||||
<li><Link href="https://github.com/luxfi/precompile" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">Precompile Repo</Link></li>
|
||||
<li><Link href="https://github.com/luxfi/standard" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">Standard Repo</Link></li>
|
||||
<li><Link href="https://github.com/luxfi/node" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">Node Repo</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold text-fd-foreground mb-4">Community</h4>
|
||||
<ul className="space-y-2">
|
||||
<li><Link href="https://discord.gg/lux" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">Discord</Link></li>
|
||||
<li><Link href="https://twitter.com/luxnetwork" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">Twitter</Link></li>
|
||||
<li><Link href="https://t.me/luxnetwork" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">Telegram</Link></li>
|
||||
<li><Link href="https://lux.network" className="text-sm text-fd-muted-foreground hover:text-fd-foreground">Website</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-t border-fd-border pt-8 flex flex-col items-center justify-between gap-4 sm:flex-row">
|
||||
<p className="text-sm text-fd-muted-foreground">
|
||||
© 2025 Lux Industries. MIT License.
|
||||
</p>
|
||||
<p className="text-sm text-fd-muted-foreground">
|
||||
Built with Fumadocs
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
---
|
||||
title: AI Mining Precompiles
|
||||
description: GPU attestation and compute verification
|
||||
---
|
||||
|
||||
# AI Mining Precompiles
|
||||
|
||||
Native precompiles for AI compute attestation and mining operations.
|
||||
|
||||
## Address Range
|
||||
|
||||
AI precompiles occupy addresses `0x0300` through `0x0302`.
|
||||
|
||||
## Precompiles
|
||||
|
||||
| Address | Precompile | Gas | Description |
|
||||
|---------|------------|-----|-------------|
|
||||
| `0x0300` | AI_MINING | 100,000 | ML-DSA signature verification, rewards |
|
||||
| `0x0301` | NV_TRUST | 50,000 | GPU TEE attestation (NVTrust) |
|
||||
| `0x0302` | MODEL_REGISTRY | 25,000 | AI model registration/verification |
|
||||
|
||||
## Hardware Trust Tiers
|
||||
|
||||
| Level | Hardware | Multiplier | Description |
|
||||
|-------|----------|------------|-------------|
|
||||
| Sovereign (4) | Blackwell | 1.5x | Full TEE, highest trust |
|
||||
| Confidential (3) | H100/TDX/SEV | 1.0x | Hardware-backed confidential compute |
|
||||
| Private (2) | SGX/A100 | 0.5x | Trusted execution environment |
|
||||
| Public (1) | Consumer GPU | 0.25x | Stake-based soft attestation |
|
||||
|
||||
## Usage
|
||||
|
||||
```solidity
|
||||
import {IAIMining} from "@luxfi/precompile/ai/IAIMining.sol";
|
||||
import {INVTrust} from "@luxfi/precompile/ai/INVTrust.sol";
|
||||
|
||||
contract ComputeProvider {
|
||||
IAIMining constant MINING = IAIMining(0x0300);
|
||||
INVTrust constant NVTRUST = INVTrust(0x0301);
|
||||
|
||||
function startSession(bytes calldata teeQuote) external returns (bytes32 sessionId) {
|
||||
// Verify TEE quote from GPU
|
||||
require(NVTRUST.verifyQuote(teeQuote), "Invalid TEE quote");
|
||||
|
||||
// Start mining session
|
||||
sessionId = MINING.startSession(msg.sender, teeQuote);
|
||||
}
|
||||
|
||||
function heartbeat(bytes32 sessionId) external returns (uint256 reward) {
|
||||
// Submit proof of work and receive rewards
|
||||
return MINING.heartbeat(sessionId);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## NVTrust Verification
|
||||
|
||||
The NVTrust precompile verifies NVIDIA Confidential Computing attestations:
|
||||
|
||||
```solidity
|
||||
// Verify a TEE quote
|
||||
bool valid = NVTRUST.verifyQuote(teeQuote);
|
||||
|
||||
// Get hardware info from quote
|
||||
(
|
||||
uint8 trustLevel,
|
||||
bytes32 gpuId,
|
||||
uint256 computeUnits
|
||||
) = NVTRUST.parseQuote(teeQuote);
|
||||
```
|
||||
|
||||
## Model Registry
|
||||
|
||||
Register and verify AI models on-chain:
|
||||
|
||||
```solidity
|
||||
import {IModelRegistry} from "@luxfi/precompile/ai/IModelRegistry.sol";
|
||||
|
||||
IModelRegistry constant REGISTRY = IModelRegistry(0x0302);
|
||||
|
||||
// Register a model
|
||||
bytes32 modelId = REGISTRY.register(
|
||||
"llama-3-70b",
|
||||
modelHash,
|
||||
metadata
|
||||
);
|
||||
|
||||
// Verify model execution
|
||||
bool valid = REGISTRY.verifyExecution(modelId, inputHash, outputHash, proof);
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- **[Lux Standard Contracts](https://standard.lux.network/docs/ai)** - AI token and mining contracts
|
||||
- **[A-Chain Documentation](https://docs.lux.network)** - Attestation chain details
|
||||
- **[LP-2000](https://lps.lux.network)** - AI Mining specification
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
title: Cryptography Precompiles
|
||||
description: Post-quantum and threshold signature precompiles
|
||||
---
|
||||
|
||||
# Cryptography Precompiles
|
||||
|
||||
Native implementations of post-quantum cryptography and threshold signature schemes.
|
||||
|
||||
## Address Range
|
||||
|
||||
Cryptography precompiles occupy addresses `0x0200...0005` through `0x0200...000D`.
|
||||
|
||||
## Precompiles
|
||||
|
||||
### Post-Quantum Signatures
|
||||
|
||||
| Address | Precompile | Gas | Description |
|
||||
|---------|------------|-----|-------------|
|
||||
| `0x...0005` | PQCrypto | Variable | Multi-algorithm PQ operations |
|
||||
| `0x...0006` | ML-DSA | 100,000 | FIPS 204 post-quantum signatures |
|
||||
| `0x...0007` | SLH-DSA | 150,000 | Stateless hash-based signatures |
|
||||
| `0x...0009` | ML-KEM | 50,000 | FIPS 203 key encapsulation |
|
||||
| `0x...000A` | Quasar | Variable | Quantum consensus operations |
|
||||
|
||||
### Threshold Signatures
|
||||
|
||||
| Address | Precompile | Gas | Description |
|
||||
|---------|------------|-----|-------------|
|
||||
| `0x...000B` | Corona | 150,000 | Post-quantum threshold signatures |
|
||||
| `0x...000C` | FROST | 50,000 | Schnorr threshold signatures |
|
||||
| `0x...000D` | CGGMP21 | 75,000 | ECDSA threshold signatures |
|
||||
|
||||
### Cross-Chain
|
||||
|
||||
| Address | Precompile | Gas | Description |
|
||||
|---------|------------|-----|-------------|
|
||||
| `0x...0008` | Warp | 120,000 | Cross-chain BLS messaging |
|
||||
|
||||
## Usage
|
||||
|
||||
```solidity
|
||||
import {IMLDSA} from "@luxfi/precompile/mldsa/IMLDSA.sol";
|
||||
|
||||
contract QuantumSafeContract {
|
||||
IMLDSA constant MLDSA = IMLDSA(0x0200000000000000000000000000000000000006);
|
||||
|
||||
function verifySignature(
|
||||
bytes calldata publicKey,
|
||||
bytes calldata message,
|
||||
bytes calldata signature
|
||||
) external view returns (bool) {
|
||||
return MLDSA.verify(publicKey, message, signature);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Security Levels
|
||||
|
||||
| Algorithm | Classical Security | Quantum Security |
|
||||
|-----------|-------------------|------------------|
|
||||
| ML-DSA-44 | 128-bit | NIST Level 2 |
|
||||
| ML-DSA-65 | 192-bit | NIST Level 3 |
|
||||
| ML-DSA-87 | 256-bit | NIST Level 5 |
|
||||
| SLH-DSA | Variable | NIST Level 1-5 |
|
||||
| Corona | 128-bit | Quantum-resistant |
|
||||
|
||||
## Related
|
||||
|
||||
- **[Lux Standard Contracts](https://standard.lux.network/docs/lamport)** - Lamport signatures in pure Solidity
|
||||
- **[FROST LP-321](https://lps.lux.network)** - FROST threshold signature specification
|
||||
- **[CGGMP21 LP-322](https://lps.lux.network)** - CGGMP21 threshold ECDSA specification
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: DEX Precompiles
|
||||
description: Uniswap v4-style native DEX operations
|
||||
---
|
||||
|
||||
# DEX Precompiles
|
||||
|
||||
Native EVM precompiles implementing Uniswap v4-style decentralized exchange with singleton architecture.
|
||||
|
||||
## Address Range
|
||||
|
||||
DEX precompiles occupy addresses `0x0400` through `0x0403`.
|
||||
|
||||
## Core Precompiles
|
||||
|
||||
| Address | Precompile | Gas | Description |
|
||||
|---------|------------|-----|-------------|
|
||||
| `0x0400` | PoolManager | 2.26μs | Singleton pool management |
|
||||
| `0x0401` | SwapRouter | Variable | Optimized swap routing |
|
||||
| `0x0402` | HooksRegistry | Variable | Hook contract registry |
|
||||
| `0x0403` | FlashLoan | Variable | Flash loan facility |
|
||||
|
||||
## Extended Precompiles
|
||||
|
||||
| Address | Precompile | Gas | Description |
|
||||
|---------|------------|-----|-------------|
|
||||
| `0x0410` | LendingPool | 15,000 | Supply/borrow with collateral |
|
||||
| `0x0411` | InterestRate | 5,000 | Dynamic interest rate curves |
|
||||
| `0x0412` | Liquidator | 50,000 | Liquidation engine |
|
||||
| `0x0420` | PerpEngine | 25,000 | Perpetuals (up to 1111x leverage) |
|
||||
| `0x0421` | FundingRate | 10,000 | Funding rate calculation |
|
||||
| `0x0430` | LiquidVault | 20,000 | Self-repaying loans (90% LTV) |
|
||||
|
||||
## Performance Benchmarks (Apple M1 Max)
|
||||
|
||||
| Operation | Latency | Throughput |
|
||||
|-----------|---------|------------|
|
||||
| Swap | 2.26μs | 443K ops/sec |
|
||||
| ModifyLiquidity | 2.87μs | 348K ops/sec |
|
||||
| PoolKeyID | 439ns | 2.7M ops/sec |
|
||||
|
||||
## Usage
|
||||
|
||||
```solidity
|
||||
import {IPoolManager} from "@luxfi/precompile/dex/IPoolManager.sol";
|
||||
|
||||
contract SwapExample {
|
||||
IPoolManager constant POOL = IPoolManager(0x0400);
|
||||
|
||||
function swap(
|
||||
PoolKey calldata key,
|
||||
IPoolManager.SwapParams calldata params
|
||||
) external returns (BalanceDelta) {
|
||||
return POOL.swap(key, params, "");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
The DEX precompile implements:
|
||||
|
||||
- **Singleton Architecture** - All pools in single contract
|
||||
- **Flash Accounting** - Token transfers netted at transaction end
|
||||
- **Hooks System** - Modular contracts for custom pool logic
|
||||
- **Native LUX Support** - No wrapping required
|
||||
|
||||
## Related
|
||||
|
||||
- **[Lux Standard Contracts](https://standard.lux.network/docs/defi)** - Pure Solidity AMM implementations
|
||||
- **[PoolManager LP](https://lps.lux.network)** - Detailed pool manager specification
|
||||
@@ -0,0 +1,97 @@
|
||||
---
|
||||
title: FHE Precompiles
|
||||
description: Fully Homomorphic Encryption for private computation
|
||||
---
|
||||
|
||||
# FHE Precompiles
|
||||
|
||||
Native precompiles for Fully Homomorphic Encryption enabling private on-chain computation.
|
||||
|
||||
## Address Range
|
||||
|
||||
FHE precompiles occupy addresses `0x0200...0080` through `0x0200...0083`.
|
||||
|
||||
## Precompiles
|
||||
|
||||
| Address | Precompile | Description |
|
||||
|---------|------------|-------------|
|
||||
| `0x...0080` | FHE Ops | Encrypted arithmetic operations |
|
||||
| `0x...0081` | FHE Config | Configuration and parameters |
|
||||
| `0x...0082` | FHE Gateway | Decryption request gateway |
|
||||
| `0x...0083` | TaskManager | Async task management |
|
||||
|
||||
## Encrypted Types
|
||||
|
||||
```solidity
|
||||
type ebool is uint256; // Encrypted boolean
|
||||
type euint8 is uint256; // Encrypted 8-bit unsigned integer
|
||||
type euint16 is uint256; // Encrypted 16-bit unsigned integer
|
||||
type euint32 is uint256; // Encrypted 32-bit unsigned integer
|
||||
type euint64 is uint256; // Encrypted 64-bit unsigned integer
|
||||
type euint128 is uint256; // Encrypted 128-bit unsigned integer
|
||||
type euint256 is uint256; // Encrypted 256-bit unsigned integer
|
||||
type eaddress is uint256; // Encrypted address
|
||||
```
|
||||
|
||||
## Operations
|
||||
|
||||
### Arithmetic
|
||||
|
||||
```solidity
|
||||
FHE.add(euint64 lhs, euint64 rhs) → euint64
|
||||
FHE.sub(euint64 lhs, euint64 rhs) → euint64
|
||||
FHE.mul(euint64 lhs, euint64 rhs) → euint64
|
||||
FHE.div(euint64 lhs, euint64 rhs) → euint64
|
||||
```
|
||||
|
||||
### Comparison
|
||||
|
||||
```solidity
|
||||
FHE.lt(euint64 lhs, euint64 rhs) → ebool
|
||||
FHE.lte(euint64 lhs, euint64 rhs) → ebool
|
||||
FHE.gt(euint64 lhs, euint64 rhs) → ebool
|
||||
FHE.gte(euint64 lhs, euint64 rhs) → ebool
|
||||
FHE.eq(euint64 lhs, euint64 rhs) → ebool
|
||||
```
|
||||
|
||||
### Conditional
|
||||
|
||||
```solidity
|
||||
FHE.select(ebool condition, euint64 ifTrue, euint64 ifFalse) → euint64
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```solidity
|
||||
import {FHE, euint64} from "@luxfi/precompile/fhe/FHE.sol";
|
||||
|
||||
contract PrivateBalance {
|
||||
mapping(address => euint64) private balances;
|
||||
|
||||
function transfer(address to, euint64 amount) external {
|
||||
euint64 senderBalance = balances[msg.sender];
|
||||
euint64 receiverBalance = balances[to];
|
||||
|
||||
// All operations happen on encrypted values
|
||||
balances[msg.sender] = FHE.sub(senderBalance, amount);
|
||||
balances[to] = FHE.add(receiverBalance, amount);
|
||||
|
||||
// Allow recipient to decrypt their balance
|
||||
FHE.allow(balances[to], to);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## EVM Version
|
||||
|
||||
FHE contracts require **Cancun** EVM version for transient storage:
|
||||
|
||||
```toml
|
||||
# foundry.toml
|
||||
evm_version = "cancun"
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- **[Lux Standard Contracts](https://standard.lux.network/docs/fhe)** - ConfidentialERC20 and other FHE contracts
|
||||
- **[fhEVM Documentation](https://docs.zama.ai/fhevm)** - Underlying FHE technology
|
||||
@@ -0,0 +1,108 @@
|
||||
---
|
||||
title: Lux Precompiles
|
||||
description: High-performance native EVM precompiles for the Lux blockchain
|
||||
---
|
||||
|
||||
# Lux Precompiles
|
||||
|
||||
Native EVM precompiles providing high-performance cryptography, DEX operations, and blockchain primitives for the Lux Network.
|
||||
|
||||
## Overview
|
||||
|
||||
Precompiles are native code executed by the EVM at reserved addresses, offering 10-100x performance improvements over equivalent Solidity implementations.
|
||||
|
||||
| Category | Precompiles | Description |
|
||||
|----------|-------------|-------------|
|
||||
| [Cryptography](/docs/crypto) | ML-DSA, ML-KEM, SLH-DSA, FROST, Corona, CGGMP21 | Post-quantum and threshold signatures |
|
||||
| [DEX](/docs/dex) | PoolManager, Hooks, Lending, Perpetuals | Uniswap v4-style DEX operations |
|
||||
| [FHE](/docs/fhe) | Encrypted operations | Fully Homomorphic Encryption |
|
||||
| [Oracle](/docs/oracle) | Price feeds, GraphQL | Native oracle and query interface |
|
||||
| [AI](/docs/ai) | GPU attestation, mining | AI compute verification |
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# In your Solidity project
|
||||
forge install luxfi/precompile
|
||||
```
|
||||
|
||||
```toml
|
||||
# foundry.toml remapping
|
||||
@luxfi/precompile/=lib/precompile/
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```solidity
|
||||
import {IMLDSA} from "@luxfi/precompile/mldsa/IMLDSA.sol";
|
||||
import {IDEX} from "@luxfi/precompile/solidity/dex/IDEX.sol";
|
||||
import {IFHE} from "@luxfi/precompile/fhe/IFHE.sol";
|
||||
|
||||
contract MyContract {
|
||||
// Use precompiles for high-performance operations
|
||||
function verifySignature(bytes calldata sig, bytes32 msg) external view {
|
||||
IMLDSA(0x0200000000000000000000000000000000000006).verify(sig, msg);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Address Map
|
||||
|
||||
### Cryptography (0x0200...0005 - 0x0200...000D)
|
||||
|
||||
| Address | Precompile | Gas | Description |
|
||||
|---------|------------|-----|-------------|
|
||||
| `0x...0005` | PQCrypto | Variable | Multi-algorithm PQ operations |
|
||||
| `0x...0006` | ML-DSA | 100,000 | FIPS 204 post-quantum signatures |
|
||||
| `0x...0007` | SLH-DSA | 150,000 | Stateless hash-based signatures |
|
||||
| `0x...0008` | Warp | 120,000 | Cross-chain BLS messaging |
|
||||
| `0x...0009` | ML-KEM | 50,000 | FIPS 203 key encapsulation |
|
||||
| `0x...000A` | Quasar | Variable | Quantum consensus operations |
|
||||
| `0x...000B` | Corona | 150,000 | Post-quantum threshold signatures |
|
||||
| `0x...000C` | FROST | 50,000 | Schnorr threshold signatures |
|
||||
| `0x...000D` | CGGMP21 | 75,000 | ECDSA threshold signatures |
|
||||
|
||||
### DEX (0x0400 - 0x0403)
|
||||
|
||||
| Address | Precompile | Gas | Description |
|
||||
|---------|------------|-----|-------------|
|
||||
| `0x0400` | PoolManager | 2.26μs | Singleton pool management |
|
||||
| `0x0401` | SwapRouter | Variable | Optimized swap routing |
|
||||
| `0x0402` | HooksRegistry | Variable | Hook contract registry |
|
||||
| `0x0403` | FlashLoan | Variable | Flash loan facility |
|
||||
|
||||
### FHE (0x0200...0080 - 0x0200...0083)
|
||||
|
||||
| Address | Precompile | Description |
|
||||
|---------|------------|-------------|
|
||||
| `0x...0080` | FHE Ops | Encrypted arithmetic |
|
||||
| `0x...0081` | FHE Config | Configuration |
|
||||
| `0x...0082` | FHE Gateway | Decryption gateway |
|
||||
| `0x...0083` | Task Manager | Async task management |
|
||||
|
||||
### Oracle (0x0500)
|
||||
|
||||
| Address | Precompile | Description |
|
||||
|---------|------------|-------------|
|
||||
| `0x0500` | GraphQL | Native G-Chain queries |
|
||||
|
||||
### AI (0x0300)
|
||||
|
||||
| Address | Precompile | Description |
|
||||
|---------|------------|-------------|
|
||||
| `0x0300` | Attestation | GPU TEE verification |
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- **[Lux Standard Contracts](https://standard.lux.network)** - Pure Solidity implementations
|
||||
- **[Lux Node](https://docs.lux.network)** - Full node documentation
|
||||
- **[LPs (Lux Proposals)](https://lps.lux.network)** - Protocol specifications
|
||||
|
||||
## Performance Benchmarks (Apple M1 Max)
|
||||
|
||||
| Operation | Precompile | Pure Solidity | Speedup |
|
||||
|-----------|------------|---------------|---------|
|
||||
| DEX Swap | 2.26μs | ~200μs | 88x |
|
||||
| ML-DSA Verify | 50μs | N/A | - |
|
||||
| FROST Verify | 45μs | N/A | - |
|
||||
| FHE Add | 10μs | N/A | - |
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"title": "Documentation",
|
||||
"pages": [
|
||||
"index",
|
||||
"---Cryptography---",
|
||||
"crypto",
|
||||
"---DEX---",
|
||||
"dex",
|
||||
"---Privacy---",
|
||||
"fhe",
|
||||
"---Infrastructure---",
|
||||
"oracle",
|
||||
"ai"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
---
|
||||
title: Oracle Precompiles
|
||||
description: Native price feeds and GraphQL queries
|
||||
---
|
||||
|
||||
# Oracle Precompiles
|
||||
|
||||
Native precompiles for oracle data access and G-Chain GraphQL queries.
|
||||
|
||||
## Address
|
||||
|
||||
| Address | Precompile | Description |
|
||||
|---------|------------|-------------|
|
||||
| `0x0500` | GraphQL | Native G-Chain queries |
|
||||
|
||||
## Features
|
||||
|
||||
- **Native GraphQL** - Query blockchain data without subgraphs
|
||||
- **Real-time Data** - Direct access to chain state
|
||||
- **Cross-Chain** - Query any Lux chain from C-Chain
|
||||
- **Low Latency** - Sub-millisecond response times
|
||||
|
||||
## Usage
|
||||
|
||||
The GraphQL precompile allows executing queries directly on-chain:
|
||||
|
||||
```solidity
|
||||
import {IGraphQL} from "@luxfi/precompile/oracle/IGraphQL.sol";
|
||||
|
||||
contract QueryExample {
|
||||
IGraphQL constant GRAPHQL = IGraphQL(0x0500);
|
||||
|
||||
function getBlockNumber() external view returns (uint256) {
|
||||
bytes memory query = abi.encodePacked('{ block { number } }');
|
||||
bytes memory result = GRAPHQL.query(query);
|
||||
// Parse result...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Schema
|
||||
|
||||
The G-Chain GraphQL schema includes:
|
||||
|
||||
```graphql
|
||||
type Query {
|
||||
block(number: Int, hash: Bytes32): Block
|
||||
transaction(hash: Bytes32!): Transaction
|
||||
account(address: Address!): Account
|
||||
logs(filter: LogFilter!): [Log!]!
|
||||
}
|
||||
|
||||
type Block {
|
||||
number: Int!
|
||||
hash: Bytes32!
|
||||
timestamp: Int!
|
||||
transactions: [Transaction!]!
|
||||
}
|
||||
```
|
||||
|
||||
## Price Oracle Integration
|
||||
|
||||
For price feeds, the Oracle precompile works with the price aggregation system:
|
||||
|
||||
```solidity
|
||||
import {IOracle} from "@luxfi/contracts/oracle/IOracle.sol";
|
||||
|
||||
// The standard Oracle contract aggregates from:
|
||||
// - Chainlink
|
||||
// - Pyth
|
||||
// - TWAP
|
||||
// - DEX Precompile (0x0400)
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- **[Lux Standard Contracts](https://standard.lux.network/docs/oracle)** - Oracle aggregation contracts
|
||||
- **[G-Chain Documentation](https://docs.lux.network)** - Full G-Chain query reference
|
||||
+451
@@ -0,0 +1,451 @@
|
||||
# LX Architecture
|
||||
|
||||
LX is a native EVM DEX combining Uniswap v4-style AMM with Hyperliquid-class CLOB in a unified, permissionless protocol.
|
||||
|
||||
## Overview
|
||||
|
||||
```
|
||||
+------------------+ +------------------+ +------------------+
|
||||
| Protocol Layer | | Gateway Layer | | Operations Layer |
|
||||
| (Canonical) | | (Low Latency) | | (HFT/Colo) |
|
||||
+------------------+ +------------------+ +------------------+
|
||||
| LXPool (LP-9010) |<--->| JSON-RPC API |<--->| Colo Connectivity|
|
||||
| LXBook (LP-9020) | | FIX Protocol | | Session Mgmt |
|
||||
| LXVault(LP-9030) | | WebSocket Streams| | Risk Controls |
|
||||
| LXOracle/Feed | | REST Endpoints | | Pre-trade Checks |
|
||||
+------------------+ +------------------+ +------------------+
|
||||
```
|
||||
|
||||
## Layer A: Protocol Layer (Canonical)
|
||||
|
||||
All settlement and state changes happen on-chain via EVM precompiles.
|
||||
|
||||
### Address Registry (LP-9xxx)
|
||||
|
||||
| Component | LP | Address | Description |
|
||||
|-----------|-----|----------------------------------------------|-------------|
|
||||
| LXPool | LP-9010 | `0x0000000000000000000000000000000000009010` | v4 PoolManager-compatible AMM |
|
||||
| LXOracle | LP-9011 | `0x0000000000000000000000000000000000009011` | Multi-source price aggregation |
|
||||
| LXRouter | LP-9012 | `0x0000000000000000000000000000000000009012` | Optimized swap routing |
|
||||
| LXHooks | LP-9013 | `0x0000000000000000000000000000000000009013` | Hook contract registry |
|
||||
| LXFlash | LP-9014 | `0x0000000000000000000000000000000000009014` | Flash loan facility |
|
||||
| LXBook | LP-9020 | `0x0000000000000000000000000000000000009020` | CLOB matching engine |
|
||||
| LXVault | LP-9030 | `0x0000000000000000000000000000000000009030` | Clearinghouse (margin/positions) |
|
||||
| LXFeed | LP-9040 | `0x0000000000000000000000000000000000009040` | Computed prices (mark/index) |
|
||||
| LXLend | LP-9050 | `0x0000000000000000000000000000000000009050` | Lending pool (Aave-style) |
|
||||
| LXLiquid | LP-9060 | `0x0000000000000000000000000000000000009060` | Self-repaying loans |
|
||||
| Liquidator | LP-9070 | `0x0000000000000000000000000000000000009070` | Liquidation engine |
|
||||
| LiquidFX | LP-9080 | `0x0000000000000000000000000000000000009080` | Transmuter |
|
||||
|
||||
### Settlement Flow
|
||||
|
||||
```
|
||||
User Order → LXBook (match) → LXVault.applyFills() → State Update
|
||||
↓
|
||||
LXFeed.markPrice() ← LXOracle.indexPrice()
|
||||
↓
|
||||
Margin/Risk Checks
|
||||
```
|
||||
|
||||
**Pattern 1 (Recommended)**: LXBook calls LXVault
|
||||
- `LXBook.placeOrder()` matches and produces `Fill[]`
|
||||
- LXBook atomically calls `LXVault.applyFills(Fill[])`
|
||||
- LXVault validates risk and updates positions
|
||||
|
||||
### Core Interfaces
|
||||
|
||||
- **ILXPool.sol** (LP-9010): Uniswap v4-compatible PoolManager
|
||||
- **ILXBook.sol** (LP-9020): CLOB with execute() endpoint
|
||||
- **ILXVault.sol** (LP-9030): Clearinghouse for margin and positions
|
||||
- **ILXOracle.sol** (LP-9011): Multi-source price aggregation
|
||||
- **ILXFeed.sol** (LP-9040): Mark price, funding rate computation
|
||||
|
||||
---
|
||||
|
||||
## Layer B: Gateway Layer (Low Latency)
|
||||
|
||||
Off-chain interfaces for order entry and market data streaming.
|
||||
|
||||
### JSON-RPC API
|
||||
|
||||
```
|
||||
POST /rpc
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "lx_placeOrder",
|
||||
"params": { /* OrderRequest */ },
|
||||
"id": 1
|
||||
}
|
||||
```
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `lx_placeOrder` | Submit new order |
|
||||
| `lx_cancelOrder` | Cancel order by ID |
|
||||
| `lx_cancelAll` | Cancel all orders |
|
||||
| `lx_amendOrder` | Modify existing order |
|
||||
| `lx_getOpenOrders` | List open orders |
|
||||
| `lx_getPositions` | Get account positions |
|
||||
| `lx_getAccountState` | Full account state |
|
||||
| `lx_getBBO` | Best bid/offer |
|
||||
| `lx_getDepth` | Order book depth |
|
||||
|
||||
### WebSocket Streams
|
||||
|
||||
```
|
||||
ws://api.lux.exchange/ws
|
||||
|
||||
// Subscribe to market data
|
||||
{"op": "subscribe", "channel": "trades", "market": "BTC-PERP"}
|
||||
{"op": "subscribe", "channel": "orderbook", "market": "BTC-PERP", "depth": 20}
|
||||
{"op": "subscribe", "channel": "ticker", "market": "BTC-PERP"}
|
||||
|
||||
// Subscribe to account updates
|
||||
{"op": "subscribe", "channel": "orders", "account": "0x..."}
|
||||
{"op": "subscribe", "channel": "fills", "account": "0x..."}
|
||||
{"op": "subscribe", "channel": "positions", "account": "0x..."}
|
||||
```
|
||||
|
||||
### FIX Protocol (4.4)
|
||||
|
||||
| MsgType | Name | Description |
|
||||
|---------|------|-------------|
|
||||
| D | NewOrderSingle | Place new order |
|
||||
| F | OrderCancelRequest | Cancel order |
|
||||
| G | OrderCancelReplaceRequest | Amend order |
|
||||
| 8 | ExecutionReport | Fill/status notification |
|
||||
| H | OrderStatusRequest | Query order status |
|
||||
| AF | OrderMassStatusRequest | Query all orders |
|
||||
|
||||
**FIX Tag Mapping to OrderRequest**:
|
||||
|
||||
| FIX Tag | Field | OrderRequest Field |
|
||||
|---------|-------|-------------------|
|
||||
| 1 | Account | (derived from session) |
|
||||
| 11 | ClOrdId | clOrdId |
|
||||
| 38 | OrderQty | szX18 |
|
||||
| 40 | OrdType | orderType |
|
||||
| 44 | Price | pxX18 |
|
||||
| 54 | Side | side |
|
||||
| 55 | Symbol | marketId |
|
||||
| 59 | TimeInForce | tif |
|
||||
| 99 | StopPx | triggerPxX18 |
|
||||
| 18 | ExecInst | reduceOnly flag |
|
||||
|
||||
---
|
||||
|
||||
## Layer C: Operations Layer (HFT/Colo)
|
||||
|
||||
### Colocation
|
||||
|
||||
- **Location**: Same rack as validator nodes
|
||||
- **Latency**: <100μs to matching engine
|
||||
- **Connectivity**: Direct fiber, dedicated NICs
|
||||
- **Sessions**: Authenticated FIX sessions per account
|
||||
|
||||
### Risk Controls
|
||||
|
||||
| Control | Description |
|
||||
|---------|-------------|
|
||||
| Pre-trade margin | Orders validated against available margin |
|
||||
| Position limits | Per-market and per-account limits |
|
||||
| Rate limits | Orders/second per session |
|
||||
| Kill switch | Emergency session termination |
|
||||
| Self-trade prevention | STP modes: cancel-newest, cancel-oldest |
|
||||
|
||||
### Permissionless vs Enrolled
|
||||
|
||||
| Feature | Permissionless | Enrolled (Colo) |
|
||||
|---------|---------------|-----------------|
|
||||
| Order placement | Yes | Yes |
|
||||
| FIX access | No | Yes |
|
||||
| Colo connectivity | No | Yes |
|
||||
| HFT packed ABI | Yes | Yes |
|
||||
| Market making | Yes | Yes (rebates) |
|
||||
| KYC required | No | Optional |
|
||||
|
||||
**HFT Packed ABI** (ILXBookHFT.sol):
|
||||
- 64-byte packed order encoding
|
||||
- Batch operations in single call
|
||||
- Minimal decoding overhead
|
||||
- Same semantics as standard ABI
|
||||
|
||||
---
|
||||
|
||||
## Trading Semantics
|
||||
|
||||
### Order Types
|
||||
|
||||
| Type | Trigger | Execution |
|
||||
|------|---------|-----------|
|
||||
| LIMIT | Immediate | Resting on book until filled/cancelled |
|
||||
| MARKET | Immediate | IOC execution at best available |
|
||||
| STOP_LIMIT | Mark price crosses trigger | Becomes LIMIT order |
|
||||
| STOP_MARKET | Mark price crosses trigger | Becomes MARKET order |
|
||||
| TAKE_PROFIT_LIMIT | Mark price crosses trigger | Becomes LIMIT order |
|
||||
| TAKE_PROFIT_MARKET | Mark price crosses trigger | Becomes MARKET order |
|
||||
| TRAILING_STOP | Dynamic trigger tracks price | Becomes MARKET on trigger |
|
||||
| TWAP | Time intervals | Splits into child orders |
|
||||
| ICEBERG | Display qty exhausted | Refreshes visible quantity |
|
||||
|
||||
### Time-in-Force
|
||||
|
||||
| TIF | Behavior |
|
||||
|-----|----------|
|
||||
| GTC | Good-til-cancelled (default) |
|
||||
| IOC | Immediate-or-cancel (partial fills OK) |
|
||||
| FOK | Fill-or-kill (full fill or reject) |
|
||||
| GTD | Good-til-date (expires at timestamp) |
|
||||
| ALO | Add-liquidity-only (post-only, maker-only) |
|
||||
|
||||
### Trigger Price Rules
|
||||
|
||||
- **STOP orders**: Trigger on MARK price
|
||||
- Long position stop: triggers when mark ≤ trigger
|
||||
- Short position stop: triggers when mark ≥ trigger
|
||||
- **TAKE_PROFIT orders**: Trigger on MARK price
|
||||
- Long TP: triggers when mark ≥ trigger
|
||||
- Short TP: triggers when mark ≤ trigger
|
||||
|
||||
---
|
||||
|
||||
## Margin & Risk
|
||||
|
||||
### Margin Modes
|
||||
|
||||
| Mode | Description |
|
||||
|------|-------------|
|
||||
| ISOLATED | Each position has separate margin |
|
||||
| CROSS | All positions share account margin |
|
||||
| PORTFOLIO | Cross-asset margin with netting |
|
||||
|
||||
### Margin Calculations
|
||||
|
||||
```
|
||||
Initial Margin = Σ(position_notional × initial_margin_rate)
|
||||
Maintenance Margin = Σ(position_notional × maintenance_margin_rate)
|
||||
|
||||
Account Equity = Total Collateral + Unrealized PnL
|
||||
Margin Ratio = Account Equity / Maintenance Margin
|
||||
|
||||
Liquidatable when Margin Ratio < 1.0
|
||||
```
|
||||
|
||||
### Margin Tiers (Example: BTC-PERP)
|
||||
|
||||
| Position Size | Max Leverage | Initial Margin | Maintenance |
|
||||
|---------------|--------------|----------------|-------------|
|
||||
| 0 - 100 BTC | 50x | 2.0% | 1.0% |
|
||||
| 100 - 500 BTC | 25x | 4.0% | 2.0% |
|
||||
| 500 - 1000 BTC | 10x | 10.0% | 5.0% |
|
||||
| >1000 BTC | 5x | 20.0% | 10.0% |
|
||||
|
||||
---
|
||||
|
||||
## Liquidation Flow
|
||||
|
||||
```
|
||||
1. Account falls below maintenance margin
|
||||
↓
|
||||
2. Liquidation order placed at bankruptcy price
|
||||
↓
|
||||
3. Matched against order book
|
||||
↓
|
||||
4. Liquidation fee to insurance fund
|
||||
↓
|
||||
5. If shortfall: insurance fund covers
|
||||
↓
|
||||
6. If insurance insufficient: ADL triggered
|
||||
```
|
||||
|
||||
### Auto-Deleverage (ADL)
|
||||
|
||||
When insurance fund cannot cover losses:
|
||||
1. Rank profitable traders by PnL + leverage score
|
||||
2. Force-close positions against most profitable counterparties
|
||||
3. ADL fills use mark price (no slippage)
|
||||
4. Affected traders notified via ADL event
|
||||
|
||||
### Insurance Fund
|
||||
|
||||
- Funded by liquidation penalties
|
||||
- Covers socialized losses before ADL
|
||||
- Separate fund per market
|
||||
- Transparent balance via `LXVault.insuranceFundBalance()`
|
||||
|
||||
---
|
||||
|
||||
## Funding Rate
|
||||
|
||||
Perpetual contracts use funding to anchor perp price to index.
|
||||
|
||||
### Calculation
|
||||
|
||||
```
|
||||
Premium = (Mark Price - Index Price) / Index Price
|
||||
Funding Rate = clamp(Premium × Interest Rate, -maxRate, +maxRate)
|
||||
|
||||
// Applied every 8 hours
|
||||
Funding Payment = Position Size × Funding Rate
|
||||
```
|
||||
|
||||
### Rules
|
||||
|
||||
- **Positive rate**: Longs pay shorts (perp > index)
|
||||
- **Negative rate**: Shorts pay longs (perp < index)
|
||||
- **Interval**: Every 8 hours (configurable per market)
|
||||
- **Cap**: ±0.05% per interval (configurable)
|
||||
|
||||
---
|
||||
|
||||
## Oracle Architecture
|
||||
|
||||
### Robust Index Construction
|
||||
|
||||
Following Hyperliquid methodology:
|
||||
1. Collect prices from multiple CEX/DEX sources
|
||||
2. Remove outliers (>1% deviation from median)
|
||||
3. Compute TWAP over 15-minute window
|
||||
4. Require minimum 3 valid sources
|
||||
|
||||
### Mark Price
|
||||
|
||||
```
|
||||
Mark = Index + EWMA(Premium)
|
||||
|
||||
// Premium smoothed with 5-minute EWMA
|
||||
// Capped at ±5% deviation from index
|
||||
```
|
||||
|
||||
### Price Sources
|
||||
|
||||
| Source | Weight | Latency |
|
||||
|--------|--------|---------|
|
||||
| Binance | 25% | <100ms |
|
||||
| Coinbase | 25% | <100ms |
|
||||
| OKX | 20% | <100ms |
|
||||
| Bybit | 15% | <100ms |
|
||||
| LXPool | 15% | Native |
|
||||
|
||||
---
|
||||
|
||||
## Canonical Schemas
|
||||
|
||||
### OrderRequest (Solidity)
|
||||
|
||||
```solidity
|
||||
struct OrderRequest {
|
||||
MarketId marketId; // uint32
|
||||
Side side; // enum: BUY=0, SELL=1
|
||||
OrderType orderType; // enum: 0-8
|
||||
uint128 pxX18; // Limit price (18 decimals)
|
||||
uint128 szX18; // Size (18 decimals)
|
||||
TimeInForce tif; // enum: 0-4
|
||||
bool reduceOnly; // Reduce-only flag
|
||||
ClOrdId clOrdId; // uint128 client order ID
|
||||
uint64 expireTime; // GTD expiration (0 = no expiry)
|
||||
uint128 triggerPxX18; // Stop/TP trigger price
|
||||
uint128 trailingDeltaX18; // Trailing stop delta
|
||||
}
|
||||
```
|
||||
|
||||
### Fill (Settlement)
|
||||
|
||||
```solidity
|
||||
struct Fill {
|
||||
MarketId marketId; // uint32
|
||||
address maker; // Maker address
|
||||
address taker; // Taker address
|
||||
bool takerIsBuy; // Taker direction
|
||||
uint128 pxX18; // Execution price
|
||||
uint128 szX18; // Execution size
|
||||
uint128 makerFeeX18; // Maker fee (can be negative)
|
||||
uint128 takerFeeX18; // Taker fee
|
||||
uint8 flags; // LIQUIDATION=0x01, REDUCE_ONLY=0x02, ADL=0x04
|
||||
}
|
||||
```
|
||||
|
||||
### JSON Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"OrderRequest": {
|
||||
"marketId": "uint32",
|
||||
"side": "BUY | SELL",
|
||||
"orderType": "LIMIT | MARKET | STOP_LIMIT | ...",
|
||||
"price": "string (decimal, 18 places)",
|
||||
"size": "string (decimal, 18 places)",
|
||||
"timeInForce": "GTC | IOC | FOK | GTD | ALO",
|
||||
"reduceOnly": "boolean",
|
||||
"clOrdId": "string (uint128 as hex or decimal)",
|
||||
"expireTime": "uint64 (unix timestamp, 0 = none)",
|
||||
"triggerPrice": "string (decimal, optional)",
|
||||
"trailingDelta": "string (decimal, optional)"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Enum Stability Policy
|
||||
|
||||
**APPEND-ONLY**: Existing enum values MUST NOT be reordered or removed.
|
||||
|
||||
```solidity
|
||||
// CORRECT: Append new values
|
||||
enum OrderType {
|
||||
LIMIT, // 0 - never change
|
||||
MARKET, // 1 - never change
|
||||
// ... existing values ...
|
||||
NEW_TYPE // N - append at end
|
||||
}
|
||||
|
||||
// WRONG: Never reorder or remove
|
||||
enum OrderType {
|
||||
MARKET, // DON'T move MARKET to 0
|
||||
LIMIT, // DON'T move LIMIT to 1
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance
|
||||
|
||||
### Matching Engine (M1 Max benchmarks)
|
||||
|
||||
| Operation | Latency | Throughput |
|
||||
|-----------|---------|------------|
|
||||
| Swap (AMM) | 2.26μs | 443K ops/sec |
|
||||
| Place Order | 1.5μs | 667K ops/sec |
|
||||
| Cancel Order | 0.8μs | 1.25M ops/sec |
|
||||
| Match + Settle | 3.2μs | 312K ops/sec |
|
||||
|
||||
### Gateway Latency
|
||||
|
||||
| Path | Latency |
|
||||
|------|---------|
|
||||
| JSON-RPC → Chain | <1ms |
|
||||
| FIX → Chain | <500μs |
|
||||
| Colo → Chain | <100μs |
|
||||
|
||||
---
|
||||
|
||||
## Files Reference
|
||||
|
||||
```
|
||||
precompile/solidity/dex/
|
||||
├── IPoolManager.sol # LP-9010 LXPool (v4 PoolManager)
|
||||
├── ILXBook.sol # LP-9020 CLOB matching engine
|
||||
├── ILXVault.sol # LP-9030 Clearinghouse
|
||||
├── ILXOracle.sol # LP-9011 Price aggregation
|
||||
├── ILXFeed.sol # LP-9040 Mark/funding prices
|
||||
├── IHooks.sol # LP-9013 Hook interface
|
||||
├── Types.sol # Shared types
|
||||
├── IERC20Minimal.sol # ERC20 interface
|
||||
└── LX.md # This document
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Last Updated: 2026-01-05*
|
||||
*Version: 1.0.0*
|
||||
@@ -0,0 +1,903 @@
|
||||
# LX Precompile API Specification
|
||||
|
||||
> **Generated from:** `~/work/lux/precompile/solidity/dex/ILX*.sol`
|
||||
> **Last Updated:** 2026-01-05
|
||||
|
||||
## Address Registry (LP-Aligned)
|
||||
|
||||
| Precompile | LP Number | Address | Interface |
|
||||
|------------|-----------|---------|-----------|
|
||||
| LXPool | LP-9010 | `0x0000000000000000000000000000000000009010` | `ILXPool.sol` |
|
||||
| LXOracle | LP-9011 | `0x0000000000000000000000000000000000009011` | `ILXOracle.sol` |
|
||||
| LXBook | LP-9020 | `0x0000000000000000000000000000000000009020` | `ILXBook.sol` |
|
||||
| LXVault | LP-9030 | `0x0000000000000000000000000000000000009030` | `ILXVault.sol` |
|
||||
| LXFeed | LP-9040 | `0x0000000000000000000000000000000000009040` | `ILXFeed.sol` |
|
||||
|
||||
---
|
||||
|
||||
## Shared Types (`Types.sol`)
|
||||
|
||||
### Custom Types
|
||||
|
||||
```solidity
|
||||
type Currency is address; // address(0) = native LUX
|
||||
type BalanceDelta is int256; // Positive = user owes pool
|
||||
type HookPermissions is uint16; // Bitmap of hook capabilities
|
||||
```
|
||||
|
||||
### PoolKey
|
||||
|
||||
```solidity
|
||||
struct PoolKey {
|
||||
Currency currency0; // Lower address token (sorted)
|
||||
Currency currency1; // Higher address token (sorted)
|
||||
uint24 fee; // Fee in basis points (3000 = 0.30%)
|
||||
int24 tickSpacing; // Tick spacing for concentrated liquidity
|
||||
address hooks; // Hook contract (address(0) = no hooks)
|
||||
}
|
||||
```
|
||||
|
||||
### SwapParams
|
||||
|
||||
```solidity
|
||||
struct SwapParams {
|
||||
bool zeroForOne; // Direction: true = currency0 → currency1
|
||||
int256 amountSpecified; // Positive = exact input, Negative = exact output
|
||||
uint160 sqrtPriceLimitX96; // Price limit (0 = no limit)
|
||||
}
|
||||
```
|
||||
|
||||
### ModifyLiquidityParams
|
||||
|
||||
```solidity
|
||||
struct ModifyLiquidityParams {
|
||||
int24 tickLower; // Lower tick bound
|
||||
int24 tickUpper; // Upper tick bound
|
||||
int128 liquidityDelta; // Positive = add, Negative = remove
|
||||
bytes32 salt; // Salt for position key uniqueness
|
||||
}
|
||||
```
|
||||
|
||||
### Fee Constants
|
||||
|
||||
| Constant | Value | Description |
|
||||
|----------|-------|-------------|
|
||||
| `FEE_001` | 100 | 0.01% (stablecoins) |
|
||||
| `FEE_005` | 500 | 0.05% (stable pairs) |
|
||||
| `FEE_030` | 3000 | 0.30% (standard) |
|
||||
| `FEE_100` | 10000 | 1.00% (exotic) |
|
||||
| `FEE_MAX` | 100000 | 10% maximum |
|
||||
|
||||
---
|
||||
|
||||
## ILXPool (LP-9010) — Singleton AMM
|
||||
|
||||
Uniswap v4-compatible singleton pool manager with flash accounting.
|
||||
|
||||
### Errors
|
||||
|
||||
| Error | Description |
|
||||
|-------|-------------|
|
||||
| `Unauthorized()` | Caller not authorized |
|
||||
| `Reentrant()` | Reentrancy detected |
|
||||
| `PoolAlreadyInitialized()` | Pool already exists |
|
||||
| `PoolNotInitialized()` | Pool doesn't exist |
|
||||
| `CurrencyNotSorted()` | Currencies not in order |
|
||||
| `InvalidFee()` | Fee out of bounds |
|
||||
| `InvalidSqrtPrice()` | Invalid sqrt price |
|
||||
| `TickOutOfRange()` | Tick outside bounds |
|
||||
| `InvalidTickRange()` | tickLower >= tickUpper |
|
||||
| `NonZeroDelta()` | Balance delta not settled |
|
||||
| `NoLiquidity()` | No liquidity in range |
|
||||
|
||||
### Functions
|
||||
|
||||
#### Pool Management
|
||||
|
||||
```solidity
|
||||
function initialize(
|
||||
PoolKey calldata key,
|
||||
uint160 sqrtPriceX96,
|
||||
bytes calldata hookData
|
||||
) external returns (int24 tick);
|
||||
```
|
||||
Initialize a new pool. Returns the initial tick.
|
||||
|
||||
```solidity
|
||||
function getPool(
|
||||
PoolKey calldata key
|
||||
) external view returns (uint160 sqrtPriceX96, int24 tick, uint128 liquidity);
|
||||
```
|
||||
Get pool state.
|
||||
|
||||
#### Flash Accounting
|
||||
|
||||
```solidity
|
||||
function lock(bytes calldata data) external returns (bytes memory result);
|
||||
```
|
||||
Acquire callback context for flash accounting. All operations within track balance changes. Deltas must net to zero.
|
||||
|
||||
```solidity
|
||||
function settle(Currency currency, int256 amount) external;
|
||||
```
|
||||
Settle a currency delta. Positive = pay pool, Negative = receive.
|
||||
|
||||
```solidity
|
||||
function take(Currency currency, address to, uint256 amount) external;
|
||||
```
|
||||
Take tokens owed to recipient.
|
||||
|
||||
```solidity
|
||||
function sync(Currency currency) external;
|
||||
```
|
||||
Sync reserves after external transfer.
|
||||
|
||||
#### Core Operations
|
||||
|
||||
```solidity
|
||||
function swap(
|
||||
PoolKey calldata key,
|
||||
SwapParams calldata params,
|
||||
bytes calldata hookData
|
||||
) external returns (BalanceDelta delta);
|
||||
```
|
||||
Execute a swap. Returns balance delta.
|
||||
|
||||
```solidity
|
||||
function modifyLiquidity(
|
||||
PoolKey calldata key,
|
||||
ModifyLiquidityParams calldata params,
|
||||
bytes calldata hookData
|
||||
) external returns (BalanceDelta delta0, BalanceDelta delta1);
|
||||
```
|
||||
Add or remove liquidity.
|
||||
|
||||
```solidity
|
||||
function donate(
|
||||
PoolKey calldata key,
|
||||
uint256 amount0,
|
||||
uint256 amount1,
|
||||
bytes calldata hookData
|
||||
) external;
|
||||
```
|
||||
Donate tokens to pool (protocol revenue).
|
||||
|
||||
#### Flash Loans
|
||||
|
||||
```solidity
|
||||
function flash(
|
||||
address borrower,
|
||||
Currency currency,
|
||||
uint256 amount,
|
||||
bytes calldata data
|
||||
) external;
|
||||
```
|
||||
Flash loan callback.
|
||||
|
||||
#### Protocol Fees
|
||||
|
||||
```solidity
|
||||
function setProtocolFee(PoolKey calldata key, uint8 newProtocolFee) external;
|
||||
```
|
||||
Set protocol fee (basis points).
|
||||
|
||||
```solidity
|
||||
function collectProtocol(
|
||||
PoolKey calldata key,
|
||||
address recipient
|
||||
) external returns (uint256 amount0, uint256 amount1);
|
||||
```
|
||||
Collect accumulated protocol fees.
|
||||
|
||||
### Events
|
||||
|
||||
```solidity
|
||||
event PoolInitialized(bytes32 indexed poolId, PoolKey key, uint160 sqrtPriceX96, int24 tick);
|
||||
event Swap(bytes32 indexed poolId, address indexed sender, int256 amount0, int256 amount1, uint160 sqrtPriceX96, int24 tick);
|
||||
event ModifyLiquidity(bytes32 indexed poolId, address indexed sender, int24 tickLower, int24 tickUpper, int128 liquidityDelta, int256 amount0, int256 amount1);
|
||||
event Donate(bytes32 indexed poolId, address indexed sender, uint256 amount0, uint256 amount1);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ILXBook (LP-9020) — CLOB Matching Engine
|
||||
|
||||
Hyperliquid-style CLOB with execute() endpoint.
|
||||
|
||||
### Custom Types
|
||||
|
||||
```solidity
|
||||
type MarketId is uint32; // Market identifier
|
||||
type OrderId is uint64; // Exchange order ID
|
||||
type ClOrdId is uint128; // Client order ID
|
||||
```
|
||||
|
||||
### Enums
|
||||
|
||||
#### Side
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | `BUY` | Buy order |
|
||||
| 1 | `SELL` | Sell order |
|
||||
|
||||
#### OrderType (append-only)
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | `LIMIT` | Standard limit order |
|
||||
| 1 | `MARKET` | Market order (IOC) |
|
||||
| 2 | `STOP_LIMIT` | Stop-limit on mark price |
|
||||
| 3 | `STOP_MARKET` | Stop-market on mark price |
|
||||
| 4 | `TAKE_PROFIT_LIMIT` | TP limit on mark price |
|
||||
| 5 | `TAKE_PROFIT_MARKET` | TP market on mark price |
|
||||
| 6 | `TRAILING_STOP` | Trailing stop |
|
||||
| 7 | `TWAP` | Time-weighted average |
|
||||
| 8 | `ICEBERG` | Iceberg (partial display) |
|
||||
|
||||
#### TimeInForce (append-only)
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | `GTC` | Good-til-cancelled |
|
||||
| 1 | `IOC` | Immediate-or-cancel |
|
||||
| 2 | `FOK` | Fill-or-kill |
|
||||
| 3 | `GTD` | Good-til-date |
|
||||
| 4 | `ALO` | Add-liquidity-only (post-only) |
|
||||
|
||||
#### OrderStatus
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | `NEW` | Accepted, not on book |
|
||||
| 1 | `OPEN` | On book |
|
||||
| 2 | `FILLED` | Completely filled |
|
||||
| 3 | `CANCELLED` | Cancelled |
|
||||
| 4 | `REJECTED` | Rejected |
|
||||
| 5 | `EXPIRED` | Expired (GTD) |
|
||||
| 6 | `TRIGGERED` | Stop/TP triggered |
|
||||
|
||||
### Structs
|
||||
|
||||
#### OrderRequest
|
||||
```solidity
|
||||
struct OrderRequest {
|
||||
MarketId marketId; // Market to trade
|
||||
Side side; // BUY or SELL
|
||||
OrderType orderType; // Order type
|
||||
uint128 pxX18; // Limit price (X18), 0 for market
|
||||
uint128 szX18; // Size in base (X18)
|
||||
TimeInForce tif; // Time-in-force
|
||||
bool reduceOnly; // Only reduce position
|
||||
ClOrdId clOrdId; // Client order ID
|
||||
uint64 expireTime; // GTD expiration, 0 = no expiry
|
||||
uint128 triggerPxX18; // Stop/TP trigger price
|
||||
uint128 trailingDeltaX18; // Trailing stop delta
|
||||
}
|
||||
```
|
||||
|
||||
#### Order
|
||||
```solidity
|
||||
struct Order {
|
||||
OrderId orderId;
|
||||
address owner;
|
||||
MarketId marketId;
|
||||
Side side;
|
||||
OrderType orderType;
|
||||
uint128 pxX18;
|
||||
uint128 origSzX18;
|
||||
uint128 remainingSzX18;
|
||||
uint128 filledSzX18;
|
||||
TimeInForce tif;
|
||||
OrderStatus status;
|
||||
uint64 timestamp;
|
||||
ClOrdId clOrdId;
|
||||
bool reduceOnly;
|
||||
}
|
||||
```
|
||||
|
||||
#### CancelRequest
|
||||
```solidity
|
||||
struct CancelRequest {
|
||||
OrderId orderId; // By exchange ID
|
||||
ClOrdId clOrdId; // OR by client ID (if orderId=0)
|
||||
MarketId marketId; // Required if using clOrdId
|
||||
}
|
||||
```
|
||||
|
||||
#### AmendRequest
|
||||
```solidity
|
||||
struct AmendRequest {
|
||||
OrderId orderId;
|
||||
uint128 newPxX18; // 0 = keep current
|
||||
uint128 newSzX18; // 0 = keep current
|
||||
}
|
||||
```
|
||||
|
||||
#### ExecReport
|
||||
```solidity
|
||||
struct ExecReport {
|
||||
OrderId orderId;
|
||||
ClOrdId clOrdId;
|
||||
MarketId marketId;
|
||||
Side side;
|
||||
uint128 pxX18; // Execution price
|
||||
uint128 szX18; // Execution size
|
||||
uint128 feeX18; // Fee charged
|
||||
uint64 timestamp;
|
||||
uint64 tradeId;
|
||||
bool isMaker;
|
||||
OrderStatus newStatus;
|
||||
}
|
||||
```
|
||||
|
||||
#### MarketSpec
|
||||
```solidity
|
||||
struct MarketSpec {
|
||||
MarketId marketId;
|
||||
string symbol; // e.g., "BTC-PERP"
|
||||
address baseAsset;
|
||||
address quoteAsset;
|
||||
uint128 tickSizeX18; // Min price increment
|
||||
uint128 lotSizeX18; // Min size increment
|
||||
uint128 minOrderSzX18;
|
||||
uint128 maxOrderSzX18;
|
||||
uint16 makerFeeBps; // Can be negative (rebate)
|
||||
uint16 takerFeeBps;
|
||||
bool active;
|
||||
bool perpMarket; // true = perp, false = spot
|
||||
}
|
||||
```
|
||||
|
||||
### Errors
|
||||
|
||||
| Error | Description |
|
||||
|-------|-------------|
|
||||
| `InvalidMarket()` | Market doesn't exist |
|
||||
| `InvalidPrice()` | Price out of bounds |
|
||||
| `InvalidSize()` | Size too small/large |
|
||||
| `InvalidOrderType()` | Order type not supported |
|
||||
| `InvalidTIF()` | TIF not supported |
|
||||
| `DuplicateClOrdId()` | Client order ID reused |
|
||||
| `OrderNotFound()` | Order doesn't exist |
|
||||
| `NotOrderOwner()` | Caller doesn't own order |
|
||||
| `RiskCheckFailed()` | Pre-trade risk failed |
|
||||
| `PostOnlyFailed()` | Post-only would take |
|
||||
| `ReduceOnlyFailed()` | Would increase position |
|
||||
| `SelfTrade()` | Would self-trade |
|
||||
| `MarketClosed()` | Market not accepting orders |
|
||||
| `RateLimited()` | Too many requests |
|
||||
|
||||
### Functions
|
||||
|
||||
#### Core Trading
|
||||
|
||||
```solidity
|
||||
function placeOrder(OrderRequest calldata req) external returns (OrderId orderId);
|
||||
function placeOrders(OrderRequest[] calldata reqs) external returns (OrderId[] memory orderIds);
|
||||
function cancelOrder(CancelRequest calldata req) external returns (bool success);
|
||||
function cancelOrders(CancelRequest[] calldata reqs) external returns (bool[] memory results);
|
||||
function cancelAllOrders(MarketId marketId) external returns (uint32 cancelled);
|
||||
function amendOrder(AmendRequest calldata req) external returns (OrderId newOrderId);
|
||||
```
|
||||
|
||||
#### Hyperliquid-Style Execute
|
||||
|
||||
```solidity
|
||||
function execute(string calldata action, bytes calldata data) external returns (bytes memory result);
|
||||
function executeBatch(string[] calldata actions, bytes[] calldata datas) external returns (bytes[] memory results);
|
||||
```
|
||||
|
||||
Action types: `"order"`, `"cancel"`, `"cancelByClOrdId"`, `"cancelAll"`, `"amend"`
|
||||
|
||||
#### Order Queries
|
||||
|
||||
```solidity
|
||||
function getOrder(OrderId orderId) external view returns (Order memory order);
|
||||
function getOrderByClOrdId(address owner, MarketId marketId, ClOrdId clOrdId) external view returns (Order memory order);
|
||||
function getOpenOrders(address owner, MarketId marketId) external view returns (Order[] memory orders);
|
||||
function orderCount(address owner) external view returns (uint32 count);
|
||||
```
|
||||
|
||||
#### Market Data
|
||||
|
||||
```solidity
|
||||
function getBBO(MarketId marketId) external view returns (uint128 bidPxX18, uint128 bidSzX18, uint128 askPxX18, uint128 askSzX18);
|
||||
function getDepth(MarketId marketId, uint8 levels) external view returns (uint128[] memory bidPrices, uint128[] memory bidSizes, uint128[] memory askPrices, uint128[] memory askSizes);
|
||||
function lastTrade(MarketId marketId) external view returns (uint128 pxX18, uint64 timestamp);
|
||||
function getMarketSpec(MarketId marketId) external view returns (MarketSpec memory spec);
|
||||
function getActiveMarkets() external view returns (MarketId[] memory marketIds);
|
||||
```
|
||||
|
||||
### Events
|
||||
|
||||
```solidity
|
||||
event OrderAccepted(OrderId indexed orderId, address indexed owner, MarketId indexed marketId, ClOrdId clOrdId);
|
||||
event OrderRejected(address indexed owner, MarketId indexed marketId, ClOrdId clOrdId, string reason);
|
||||
event OrderFilled(OrderId indexed orderId, uint128 pxX18, uint128 szX18, bool isMaker);
|
||||
event OrderCancelled(OrderId indexed orderId, address indexed owner, uint128 remainingSzX18);
|
||||
event OrderExpired(OrderId indexed orderId, address indexed owner);
|
||||
event OrderTriggered(OrderId indexed orderId, uint128 triggerPxX18);
|
||||
event Trade(MarketId indexed marketId, uint64 indexed tradeId, OrderId makerOrderId, OrderId takerOrderId, uint128 pxX18, uint128 szX18, bool takerIsBuy);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ILXBookHFT — Packed ABI Extension
|
||||
|
||||
Optimized encoding for colo participants.
|
||||
|
||||
```solidity
|
||||
function placeOrdersPacked(bytes calldata packed) external returns (uint64[] memory orderIds);
|
||||
function cancelOrdersPacked(bytes calldata packed) external returns (bytes memory results);
|
||||
function amendOrdersPacked(bytes calldata packed) external returns (uint64[] memory newOrderIds);
|
||||
```
|
||||
|
||||
Packed encoding:
|
||||
- Order: 64 bytes (marketId:4 + side:1 + type:1 + tif:1 + flags:1 + px:16 + sz:16 + clOrdId:16 + triggerPx:8)
|
||||
- Cancel: 8 bytes (orderId:8)
|
||||
- Amend: 32 bytes (orderId:8 + newPx:16 + newSz:8)
|
||||
|
||||
---
|
||||
|
||||
## ILXVault (LP-9030) — Clearinghouse
|
||||
|
||||
Custody, margin, positions, liquidations.
|
||||
|
||||
### Custom Types
|
||||
|
||||
```solidity
|
||||
type MarketId is uint32;
|
||||
```
|
||||
|
||||
### Enums
|
||||
|
||||
#### MarginMode
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | `ISOLATED` | Per-position margin |
|
||||
| 1 | `CROSS` | Shared margin (default) |
|
||||
| 2 | `PORTFOLIO` | Cross-asset netting |
|
||||
|
||||
#### Side
|
||||
| Value | Name |
|
||||
|-------|------|
|
||||
| 0 | `LONG` |
|
||||
| 1 | `SHORT` |
|
||||
|
||||
### Structs
|
||||
|
||||
#### Fill (from LXBook)
|
||||
```solidity
|
||||
struct Fill {
|
||||
MarketId marketId;
|
||||
address maker;
|
||||
address taker;
|
||||
bool takerIsBuy;
|
||||
uint128 pxX18;
|
||||
uint128 szX18;
|
||||
uint128 makerFeeX18; // Negative = rebate
|
||||
uint128 takerFeeX18;
|
||||
uint8 flags; // FILL_FLAG_* constants
|
||||
}
|
||||
```
|
||||
|
||||
#### ApplyResult
|
||||
```solidity
|
||||
struct ApplyResult {
|
||||
uint128 appliedFills;
|
||||
uint128 appliedSzX18;
|
||||
uint8 status; // 0=rejected, 1=ok, 2=partial
|
||||
}
|
||||
```
|
||||
|
||||
#### AccountState
|
||||
```solidity
|
||||
struct AccountState {
|
||||
int256 equityX18;
|
||||
uint256 totalCollateralX18;
|
||||
int256 unrealizedPnlX18;
|
||||
uint256 maintenanceReqX18;
|
||||
uint256 initialReqX18;
|
||||
MarginMode mode;
|
||||
bool isLiquidatable;
|
||||
}
|
||||
```
|
||||
|
||||
#### Position
|
||||
```solidity
|
||||
struct Position {
|
||||
MarketId marketId;
|
||||
Side side;
|
||||
uint128 sizeX18;
|
||||
uint128 avgEntryPxX18;
|
||||
int128 unrealizedPnlX18;
|
||||
uint128 marginX18; // Isolated mode
|
||||
int128 fundingAccrued;
|
||||
}
|
||||
```
|
||||
|
||||
#### MarketConfig
|
||||
```solidity
|
||||
struct MarketConfig {
|
||||
MarketId marketId;
|
||||
uint128 maxLeverageX18; // e.g., 50e18 = 50x
|
||||
uint128 maintenanceMarginX18; // e.g., 0.03e18 = 3%
|
||||
uint128 initialMarginX18; // e.g., 0.05e18 = 5%
|
||||
uint128 liquidationFeeX18; // e.g., 0.025e18 = 2.5%
|
||||
uint128 maxPositionSzX18;
|
||||
uint128 maxOIX18;
|
||||
bool active;
|
||||
}
|
||||
```
|
||||
|
||||
### Fill Flags
|
||||
|
||||
| Constant | Value | Description |
|
||||
|----------|-------|-------------|
|
||||
| `FILL_FLAG_LIQUIDATION` | 0x01 | Fill is liquidation |
|
||||
| `FILL_FLAG_REDUCE_ONLY` | 0x02 | Reduce-only fill |
|
||||
| `FILL_FLAG_ADL` | 0x04 | Auto-deleverage |
|
||||
| `FILL_FLAG_MARKET` | 0x08 | Market order |
|
||||
| `FILL_FLAG_POST_ONLY_FAIL` | 0x10 | Post-only violation |
|
||||
|
||||
### Errors
|
||||
|
||||
| Error | Description |
|
||||
|-------|-------------|
|
||||
| `NotBook()` | Caller not LXBook |
|
||||
| `NotOracle()` | Caller not oracle |
|
||||
| `RiskRejected()` | Risk check failed |
|
||||
| `InvalidFill()` | Fill parameters invalid |
|
||||
| `InsufficientMargin()` | Not enough margin |
|
||||
| `InsufficientBalance()` | Not enough balance |
|
||||
| `MarketNotActive()` | Market paused |
|
||||
| `PositionNotFound()` | No position |
|
||||
| `NotLiquidatable()` | Above maintenance |
|
||||
| `MaxOIExceeded()` | Max OI exceeded |
|
||||
| `WithdrawalLocked()` | Cooldown active |
|
||||
|
||||
### Functions
|
||||
|
||||
#### Settlement (LXBook only)
|
||||
|
||||
```solidity
|
||||
function applyFills(Fill[] calldata fills) external returns (ApplyResult memory result);
|
||||
function preCheckFills(Fill[] calldata fills) external view returns (bool valid, string memory reason);
|
||||
```
|
||||
|
||||
#### Custody
|
||||
|
||||
```solidity
|
||||
function deposit(Currency currency, uint256 amount) external payable;
|
||||
function withdraw(Currency currency, uint256 amount, address to) external;
|
||||
function balanceOf(address user, Currency currency) external view returns (uint256 balance);
|
||||
function totalCollateralValue(address user) external view returns (uint256 valueX18);
|
||||
```
|
||||
|
||||
#### Margin Account
|
||||
|
||||
```solidity
|
||||
function getAccountState(address user) external view returns (AccountState memory state);
|
||||
function accountEquityX18(address user) external view returns (int256 equityX18);
|
||||
function maintenanceMarginReqX18(address user) external view returns (uint256 reqX18);
|
||||
function initialMarginReqX18(address user) external view returns (uint256 reqX18);
|
||||
function marginRatioX18(address user) external view returns (uint256 ratioX18);
|
||||
function setMarginMode(MarginMode mode) external;
|
||||
```
|
||||
|
||||
#### Positions
|
||||
|
||||
```solidity
|
||||
function getPosition(address user, MarketId marketId) external view returns (Position memory position);
|
||||
function getAllPositions(address user) external view returns (Position[] memory positions);
|
||||
function addMargin(MarketId marketId, uint256 amount) external;
|
||||
function removeMargin(MarketId marketId, uint256 amount) external;
|
||||
```
|
||||
|
||||
#### Liquidation
|
||||
|
||||
```solidity
|
||||
function isLiquidatable(address user) external view returns (bool liquidatable);
|
||||
function liquidate(address user, MarketId marketId, uint128 maxSzX18) external returns (uint128 liqSzX18);
|
||||
function runADL(MarketId marketId, uint32 maxAccounts) external;
|
||||
function insuranceFundBalance() external view returns (uint256 balance);
|
||||
```
|
||||
|
||||
#### Funding
|
||||
|
||||
```solidity
|
||||
function accrueFunding(MarketId marketId) external;
|
||||
function fundingRateX18(MarketId marketId) external view returns (int256 rateX18);
|
||||
function nextFundingTime(MarketId marketId) external view returns (uint256 timestamp);
|
||||
```
|
||||
|
||||
#### Configuration
|
||||
|
||||
```solidity
|
||||
function getMarketConfig(MarketId marketId) external view returns (MarketConfig memory config);
|
||||
function openInterest(MarketId marketId) external view returns (uint128 longOIX18, uint128 shortOIX18);
|
||||
```
|
||||
|
||||
### Events
|
||||
|
||||
```solidity
|
||||
event Deposit(address indexed user, Currency indexed currency, uint256 amount);
|
||||
event Withdraw(address indexed user, Currency indexed currency, uint256 amount);
|
||||
event FillApplied(MarketId indexed marketId, address indexed maker, address indexed taker, uint128 pxX18, uint128 szX18, bool takerIsBuy);
|
||||
event PositionOpened(address indexed user, MarketId indexed marketId, Side side, uint128 szX18, uint128 pxX18);
|
||||
event PositionClosed(address indexed user, MarketId indexed marketId, int256 realizedPnlX18);
|
||||
event PositionModified(address indexed user, MarketId indexed marketId, uint128 newSzX18, uint128 avgPxX18);
|
||||
event Liquidation(address indexed user, MarketId indexed marketId, address indexed liquidator, uint128 szX18);
|
||||
event ADLExecuted(MarketId indexed marketId, address indexed winner, address indexed loser, uint128 szX18);
|
||||
event FundingAccrued(MarketId indexed marketId, int256 fundingRateX18, uint256 timestamp);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ILXOracle (LP-9011) — Multi-Source Oracle
|
||||
|
||||
Robust index construction with outlier filtering.
|
||||
|
||||
### Custom Types
|
||||
|
||||
```solidity
|
||||
type AssetId is uint32;
|
||||
```
|
||||
|
||||
### Enums
|
||||
|
||||
#### PriceSource
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | `CEX_BINANCE` | Binance spot |
|
||||
| 1 | `CEX_COINBASE` | Coinbase Pro |
|
||||
| 2 | `CEX_OKX` | OKX |
|
||||
| 3 | `CEX_BYBIT` | Bybit |
|
||||
| 4 | `DEX_UNISWAP` | Uniswap TWAP |
|
||||
| 5 | `DEX_LXPOOL` | LXPool (LP-9010) |
|
||||
| 6 | `CHAINLINK` | Chainlink |
|
||||
| 7 | `PYTH` | Pyth network |
|
||||
| 8 | `CUSTOM` | Custom oracle |
|
||||
|
||||
#### AggMethod
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | `MEDIAN` | Median of valid sources |
|
||||
| 1 | `TWAP` | Time-weighted average |
|
||||
| 2 | `VWAP` | Volume-weighted average |
|
||||
| 3 | `TRIMMED_MEAN` | Mean after outlier removal |
|
||||
| 4 | `WEIGHTED_MEDIAN` | Weighted by confidence |
|
||||
|
||||
### Structs
|
||||
|
||||
#### PriceData
|
||||
```solidity
|
||||
struct PriceData {
|
||||
uint128 priceX18;
|
||||
uint64 timestamp;
|
||||
uint32 confidence; // 0-10000 = 0-100%
|
||||
PriceSource source;
|
||||
bool isValid;
|
||||
}
|
||||
```
|
||||
|
||||
#### OracleConfig
|
||||
```solidity
|
||||
struct OracleConfig {
|
||||
AssetId assetId;
|
||||
string symbol;
|
||||
PriceSource[] sources;
|
||||
AggMethod aggMethod;
|
||||
uint32 minSources;
|
||||
uint32 maxStalenessSeconds;
|
||||
uint128 maxDeviationBps;
|
||||
bool active;
|
||||
}
|
||||
```
|
||||
|
||||
#### RobustIndexParams
|
||||
```solidity
|
||||
struct RobustIndexParams {
|
||||
uint32 windowSeconds; // e.g., 900 = 15 min
|
||||
uint32 minSamples;
|
||||
uint128 outlierThresholdBps; // e.g., 100 = 1%
|
||||
bool trimOutliers;
|
||||
}
|
||||
```
|
||||
|
||||
### Errors
|
||||
|
||||
| Error | Description |
|
||||
|-------|-------------|
|
||||
| `AssetNotFound()` | Asset not configured |
|
||||
| `InsufficientSources()` | Not enough valid sources |
|
||||
| `StalePrice()` | All prices too old |
|
||||
| `SourceDeviationTooHigh()` | Sources diverge too much |
|
||||
| `InvalidConfig()` | Invalid configuration |
|
||||
| `Unauthorized()` | Caller not authorized |
|
||||
|
||||
### Functions
|
||||
|
||||
#### Price Queries
|
||||
|
||||
```solidity
|
||||
function getPrice(AssetId assetId) external view returns (uint128 priceX18, uint64 timestamp);
|
||||
function getPriceData(AssetId assetId) external view returns (PriceData memory data);
|
||||
function getPrices(AssetId[] calldata assetIds) external view returns (uint128[] memory prices, uint64[] memory timestamps);
|
||||
function getSourcePrice(AssetId assetId, PriceSource source) external view returns (uint128 priceX18, uint64 timestamp);
|
||||
function getAllSourcePrices(AssetId assetId) external view returns (PriceData[] memory data);
|
||||
```
|
||||
|
||||
#### Index Price
|
||||
|
||||
```solidity
|
||||
function indexPrice(AssetId assetId) external view returns (uint128 indexPriceX18);
|
||||
function indexPriceDetailed(AssetId assetId) external view returns (uint128 indexPriceX18, uint32 sourcesUsed, uint32 outliersTrimmed);
|
||||
```
|
||||
|
||||
#### TWAP
|
||||
|
||||
```solidity
|
||||
function getTWAP(AssetId assetId, uint32 windowSeconds) external view returns (uint128 twapX18);
|
||||
```
|
||||
|
||||
#### Configuration
|
||||
|
||||
```solidity
|
||||
function getConfig(AssetId assetId) external view returns (OracleConfig memory config);
|
||||
function getRobustParams(AssetId assetId) external view returns (RobustIndexParams memory params);
|
||||
function getAssetId(string calldata symbol) external view returns (AssetId assetId);
|
||||
```
|
||||
|
||||
### Events
|
||||
|
||||
```solidity
|
||||
event PriceUpdated(AssetId indexed assetId, uint128 priceX18, uint64 timestamp, uint32 numSources);
|
||||
event SourcePriceReceived(AssetId indexed assetId, PriceSource indexed source, uint128 priceX18);
|
||||
event OracleConfigured(AssetId indexed assetId, string symbol);
|
||||
event PriceDeviation(AssetId indexed assetId, uint128 lowX18, uint128 highX18, uint128 deviationBps);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ILXFeed (LP-9040) — Computed Price Feeds
|
||||
|
||||
Mark price, funding rate, liquidation triggers.
|
||||
|
||||
### Custom Types
|
||||
|
||||
```solidity
|
||||
type MarketId is uint32;
|
||||
```
|
||||
|
||||
### Enums
|
||||
|
||||
#### PriceType
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | `INDEX` | Robust index from LXOracle |
|
||||
| 1 | `MARK` | Index + premium |
|
||||
| 2 | `LAST` | Last trade from LXBook |
|
||||
| 3 | `MID` | Order book mid |
|
||||
| 4 | `ORACLE` | Raw oracle price |
|
||||
|
||||
### Structs
|
||||
|
||||
#### MarketPrices
|
||||
```solidity
|
||||
struct MarketPrices {
|
||||
uint128 indexPriceX18;
|
||||
uint128 markPriceX18;
|
||||
uint128 lastPriceX18;
|
||||
uint128 midPriceX18;
|
||||
int128 premiumX18; // mark - index
|
||||
int128 fundingRateX18; // Per hour
|
||||
uint64 timestamp;
|
||||
}
|
||||
```
|
||||
|
||||
#### FundingParams
|
||||
```solidity
|
||||
struct FundingParams {
|
||||
int128 premiumX18;
|
||||
int128 fundingRateX18;
|
||||
int128 cappedRateX18;
|
||||
uint64 nextFundingTime;
|
||||
uint32 fundingIntervalSecs; // e.g., 28800 = 8 hours
|
||||
}
|
||||
```
|
||||
|
||||
#### MarkPriceConfig
|
||||
```solidity
|
||||
struct MarkPriceConfig {
|
||||
uint32 ewmaWindowSeconds; // e.g., 300 = 5 min
|
||||
uint128 maxPremiumBps; // e.g., 500 = 5%
|
||||
uint128 dampingFactor; // X18
|
||||
bool useMidPrice;
|
||||
}
|
||||
```
|
||||
|
||||
### Errors
|
||||
|
||||
| Error | Description |
|
||||
|-------|-------------|
|
||||
| `MarketNotFound()` | Market doesn't exist |
|
||||
| `StalePrice()` | Prices too old |
|
||||
| `InvalidPriceType()` | Invalid type |
|
||||
|
||||
### Functions
|
||||
|
||||
#### Core Prices
|
||||
|
||||
```solidity
|
||||
function indexPrice(MarketId marketId) external view returns (uint128 priceX18);
|
||||
function markPrice(MarketId marketId) external view returns (uint128 priceX18);
|
||||
function lastPrice(MarketId marketId) external view returns (uint128 priceX18);
|
||||
function midPrice(MarketId marketId) external view returns (uint128 priceX18);
|
||||
function getPrice(MarketId marketId, PriceType priceType) external view returns (uint128 priceX18);
|
||||
function getAllPrices(MarketId marketId) external view returns (MarketPrices memory prices);
|
||||
function getMultipleMarketPrices(MarketId[] calldata marketIds) external view returns (MarketPrices[] memory prices);
|
||||
```
|
||||
|
||||
#### Funding Rate
|
||||
|
||||
```solidity
|
||||
function fundingRate(MarketId marketId) external view returns (int128 rateX18);
|
||||
function getFundingParams(MarketId marketId) external view returns (FundingParams memory params);
|
||||
function predictedFundingRate(MarketId marketId) external view returns (int128 predictedRateX18);
|
||||
```
|
||||
|
||||
#### Trigger Prices
|
||||
|
||||
```solidity
|
||||
function checkTrigger(MarketId marketId, uint128 triggerPxX18, bool isAbove, PriceType priceType) external view returns (bool triggered);
|
||||
function liquidationPrice(address account, MarketId marketId) external view returns (uint128 liqPriceX18);
|
||||
```
|
||||
|
||||
#### Premium/Basis
|
||||
|
||||
```solidity
|
||||
function premium(MarketId marketId) external view returns (int128 premiumX18);
|
||||
function basis(MarketId marketId) external view returns (int128 basisBps);
|
||||
function premiumEWMA(MarketId marketId) external view returns (int128 ewmaX18);
|
||||
```
|
||||
|
||||
#### Configuration
|
||||
|
||||
```solidity
|
||||
function getMarkPriceConfig(MarketId marketId) external view returns (MarkPriceConfig memory config);
|
||||
function fundingInterval(MarketId marketId) external view returns (uint32 intervalSecs);
|
||||
function maxFundingRate(MarketId marketId) external view returns (uint128 maxRateX18);
|
||||
```
|
||||
|
||||
### Events
|
||||
|
||||
```solidity
|
||||
event MarkPriceUpdated(MarketId indexed marketId, uint128 markPriceX18, int128 premiumX18);
|
||||
event FundingRateUpdated(MarketId indexed marketId, int128 fundingRateX18, uint64 timestamp);
|
||||
event PriceTriggered(MarketId indexed marketId, PriceType priceType, uint128 triggerPriceX18);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Price Trigger Rules
|
||||
|
||||
### Stop Orders
|
||||
- Trigger on **MARK** price by default
|
||||
- Long position: triggers when `mark <= trigger`
|
||||
- Short position: triggers when `mark >= trigger`
|
||||
|
||||
### Take-Profit Orders
|
||||
- Trigger on **MARK** price by default
|
||||
- Long position: triggers when `mark >= trigger`
|
||||
- Short position: triggers when `mark <= trigger`
|
||||
|
||||
### Liquidation
|
||||
- Always uses **MARK** price
|
||||
- Triggered when `marginRatio < 1.0`
|
||||
|
||||
### Funding
|
||||
- Calculated from premium (`MARK - INDEX`)
|
||||
- Capped at max funding rate
|
||||
- Applied every funding interval (default: 8 hours)
|
||||
|
||||
### ADL (Auto-Deleverage)
|
||||
- Triggered when insurance fund insufficient
|
||||
- Uses **MARK** price for position valuation
|
||||
@@ -0,0 +1,151 @@
|
||||
# LXDEX Enum Definitions
|
||||
|
||||
**APPEND-ONLY POLICY**: Existing enum values MUST NOT be reordered or removed. New values may only be appended at the end.
|
||||
|
||||
## Side
|
||||
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | BUY | Buy order (go long) |
|
||||
| 1 | SELL | Sell order (go short) |
|
||||
|
||||
## OrderType
|
||||
|
||||
| Value | Name | FIX OrdType | Description |
|
||||
|-------|------|-------------|-------------|
|
||||
| 0 | LIMIT | 2 | Standard limit order |
|
||||
| 1 | MARKET | 1 | Market order (IOC execution) |
|
||||
| 2 | STOP_LIMIT | 4 | Stop-limit (triggers on mark) |
|
||||
| 3 | STOP_MARKET | 3 | Stop-market (triggers on mark) |
|
||||
| 4 | TAKE_PROFIT_LIMIT | K | Take-profit limit |
|
||||
| 5 | TAKE_PROFIT_MARKET | J | Take-profit market |
|
||||
| 6 | TRAILING_STOP | P | Trailing stop (dynamic trigger) |
|
||||
| 7 | TWAP | - | Time-weighted average price |
|
||||
| 8 | ICEBERG | - | Iceberg (partial display) |
|
||||
|
||||
## TimeInForce
|
||||
|
||||
| Value | Name | FIX TIF | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| 0 | GTC | 1 | Good-til-cancelled (default) |
|
||||
| 1 | IOC | 3 | Immediate-or-cancel |
|
||||
| 2 | FOK | 4 | Fill-or-kill |
|
||||
| 3 | GTD | 6 | Good-til-date |
|
||||
| 4 | ALO | B | Add-liquidity-only (post-only) |
|
||||
|
||||
## OrderStatus
|
||||
|
||||
| Value | Name | FIX OrdStatus | Description |
|
||||
|-------|------|---------------|-------------|
|
||||
| 0 | NEW | 0 | Order accepted, not yet on book |
|
||||
| 1 | OPEN | 1 | Order on book, partially/unfilled |
|
||||
| 2 | FILLED | 2 | Completely filled |
|
||||
| 3 | CANCELLED | 4 | Cancelled by user |
|
||||
| 4 | REJECTED | 8 | Rejected (risk, validation) |
|
||||
| 5 | EXPIRED | C | Expired (GTD) |
|
||||
| 6 | TRIGGERED | - | Stop/TP triggered |
|
||||
|
||||
## MarginMode
|
||||
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | ISOLATED | Each position has separate margin |
|
||||
| 1 | CROSS | All positions share account margin |
|
||||
| 2 | PORTFOLIO | Cross-asset margin with netting |
|
||||
|
||||
## PositionSide
|
||||
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | LONG | Long position (bought) |
|
||||
| 1 | SHORT | Short position (sold) |
|
||||
|
||||
## PriceSource (LXOracle)
|
||||
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | CEX_BINANCE | Binance spot price |
|
||||
| 1 | CEX_COINBASE | Coinbase Pro price |
|
||||
| 2 | CEX_OKX | OKX price |
|
||||
| 3 | CEX_BYBIT | Bybit price |
|
||||
| 4 | DEX_UNISWAP | Uniswap TWAP |
|
||||
| 5 | DEX_LXPOOL | LXPool (native) |
|
||||
| 6 | CHAINLINK | Chainlink oracle |
|
||||
| 7 | PYTH | Pyth network |
|
||||
| 8 | CUSTOM | Custom oracle |
|
||||
|
||||
## AggMethod (LXOracle)
|
||||
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | MEDIAN | Median of all valid sources |
|
||||
| 1 | TWAP | Time-weighted average |
|
||||
| 2 | VWAP | Volume-weighted average |
|
||||
| 3 | TRIMMED_MEAN | Mean after removing outliers |
|
||||
| 4 | WEIGHTED_MEDIAN | Weighted median by confidence |
|
||||
|
||||
## PriceType (LXFeed)
|
||||
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0 | INDEX | Robust index price from LXOracle |
|
||||
| 1 | MARK | Mark price (index + premium) |
|
||||
| 2 | LAST | Last trade price from LXBook |
|
||||
| 3 | MID | Mid price from order book |
|
||||
| 4 | ORACLE | Raw oracle price |
|
||||
|
||||
## Fill Flags (bitmask)
|
||||
|
||||
| Bit | Value | Name | Description |
|
||||
|-----|-------|------|-------------|
|
||||
| 0 | 0x01 | LIQUIDATION | Fill is from liquidation |
|
||||
| 1 | 0x02 | REDUCE_ONLY | Fill is reduce-only |
|
||||
| 2 | 0x04 | ADL | Fill is from auto-deleverage |
|
||||
| 3 | 0x08 | MARKET | Fill is from market order |
|
||||
| 4 | 0x10 | POST_ONLY_FAIL | Post-only violation |
|
||||
|
||||
---
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Date | Changes |
|
||||
|---------|------|---------|
|
||||
| 1.0.0 | 2026-01-05 | Initial enum definitions |
|
||||
|
||||
---
|
||||
|
||||
## Stability Guarantees
|
||||
|
||||
1. **Numeric values are immutable**: Once assigned, a numeric value will never change meaning
|
||||
2. **Names may be aliased**: Old names may be aliased but never removed
|
||||
3. **New values append only**: New enum values are always added at the end
|
||||
4. **Deprecation**: Values may be deprecated but will remain valid indefinitely
|
||||
|
||||
### Example: Adding New Order Type
|
||||
|
||||
```solidity
|
||||
// CORRECT: Append at end
|
||||
enum OrderType {
|
||||
LIMIT, // 0 - immutable
|
||||
MARKET, // 1 - immutable
|
||||
STOP_LIMIT, // 2 - immutable
|
||||
STOP_MARKET, // 3 - immutable
|
||||
TAKE_PROFIT_LIMIT, // 4 - immutable
|
||||
TAKE_PROFIT_MARKET, // 5 - immutable
|
||||
TRAILING_STOP, // 6 - immutable
|
||||
TWAP, // 7 - immutable
|
||||
ICEBERG, // 8 - immutable
|
||||
NEW_ORDER_TYPE // 9 - NEW: append only
|
||||
}
|
||||
|
||||
// WRONG: Never reorder
|
||||
enum OrderType {
|
||||
NEW_ORDER_TYPE, // DON'T insert at position 0
|
||||
LIMIT, // Values would shift
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Last Updated: 2026-01-05*
|
||||
@@ -0,0 +1,215 @@
|
||||
# FIX Protocol Mapping for LXDEX
|
||||
|
||||
FIX 4.4 protocol mapping to canonical LXDEX OrderRequest and ExecReport structures.
|
||||
|
||||
## NewOrderSingle (MsgType=D) → OrderRequest
|
||||
|
||||
| FIX Tag | FIX Name | Type | OrderRequest Field | Notes |
|
||||
|---------|----------|------|-------------------|-------|
|
||||
| 1 | Account | String | (session) | Derived from FIX session |
|
||||
| 11 | ClOrdId | String | `clOrdId` | Client order ID (unique per account) |
|
||||
| 21 | HandlInst | Char | - | Always "1" (automated) |
|
||||
| 38 | OrderQty | Qty | `szX18` | Convert to X18 (multiply by 1e18) |
|
||||
| 40 | OrdType | Char | `orderType` | See OrdType mapping below |
|
||||
| 44 | Price | Price | `pxX18` | Convert to X18 |
|
||||
| 54 | Side | Char | `side` | "1"=BUY, "2"=SELL |
|
||||
| 55 | Symbol | String | `marketId` | Market symbol → MarketId lookup |
|
||||
| 59 | TimeInForce | Char | `tif` | See TimeInForce mapping |
|
||||
| 60 | TransactTime | UTCTimestamp | - | Ignored (use server time) |
|
||||
| 99 | StopPx | Price | `triggerPxX18` | For Stop/TP orders |
|
||||
| 18 | ExecInst | MultipleChar | `reduceOnly` | "r"=reduce-only |
|
||||
| 126 | ExpireTime | UTCTimestamp | `expireTime` | For GTD orders |
|
||||
| 7928 | TrailingDelta | Price | `trailingDeltaX18` | Custom tag for trailing stop |
|
||||
|
||||
### OrdType Mapping (Tag 40)
|
||||
|
||||
| FIX Value | FIX Name | OrderRequest.orderType |
|
||||
|-----------|----------|----------------------|
|
||||
| 1 | Market | MARKET (1) |
|
||||
| 2 | Limit | LIMIT (0) |
|
||||
| 3 | Stop | STOP_MARKET (3) |
|
||||
| 4 | StopLimit | STOP_LIMIT (2) |
|
||||
| J | MarketIfTouched | TAKE_PROFIT_MARKET (5) |
|
||||
| K | LimitIfTouched | TAKE_PROFIT_LIMIT (4) |
|
||||
| P | Pegged | TRAILING_STOP (6) |
|
||||
|
||||
### TimeInForce Mapping (Tag 59)
|
||||
|
||||
| FIX Value | FIX Name | OrderRequest.tif |
|
||||
|-----------|----------|-----------------|
|
||||
| 0 | Day | GTC (0) - treated as GTC |
|
||||
| 1 | GoodTillCancel | GTC (0) |
|
||||
| 3 | ImmediateOrCancel | IOC (1) |
|
||||
| 4 | FillOrKill | FOK (2) |
|
||||
| 6 | GoodTillDate | GTD (3) |
|
||||
| B | GoodTillCrossing | ALO (4) - post-only |
|
||||
|
||||
### Side Mapping (Tag 54)
|
||||
|
||||
| FIX Value | FIX Name | OrderRequest.side |
|
||||
|-----------|----------|------------------|
|
||||
| 1 | Buy | BUY (0) |
|
||||
| 2 | Sell | SELL (1) |
|
||||
|
||||
### ExecInst Flags (Tag 18)
|
||||
|
||||
| FIX Value | Meaning | OrderRequest Field |
|
||||
|-----------|---------|-------------------|
|
||||
| r | ReduceOnly | `reduceOnly = true` |
|
||||
| 6 | ParticipateDoNotInitiate | `tif = ALO` (post-only) |
|
||||
|
||||
---
|
||||
|
||||
## ExecutionReport (MsgType=8) ← ExecReport
|
||||
|
||||
| FIX Tag | FIX Name | Type | ExecReport Field | Notes |
|
||||
|---------|----------|------|-----------------|-------|
|
||||
| 6 | AvgPx | Price | (calculated) | Average fill price |
|
||||
| 11 | ClOrdId | String | `clOrdId` | Client order ID |
|
||||
| 14 | CumQty | Qty | (calculated) | Cumulative filled |
|
||||
| 17 | ExecID | String | `tradeId` | Unique execution ID |
|
||||
| 31 | LastPx | Price | `pxX18` | Last fill price (X18→decimal) |
|
||||
| 32 | LastQty | Qty | `szX18` | Last fill size (X18→decimal) |
|
||||
| 37 | OrderID | String | `orderId` | Exchange order ID |
|
||||
| 38 | OrderQty | Qty | - | Original order quantity |
|
||||
| 39 | OrdStatus | Char | `newStatus` | See OrdStatus mapping |
|
||||
| 44 | Price | Price | - | Limit price |
|
||||
| 54 | Side | Char | `side` | "1"=BUY, "2"=SELL |
|
||||
| 55 | Symbol | String | `marketId` | Market symbol |
|
||||
| 60 | TransactTime | UTCTimestamp | `timestamp` | Execution time |
|
||||
| 150 | ExecType | Char | - | See ExecType mapping |
|
||||
| 151 | LeavesQty | Qty | (calculated) | Remaining quantity |
|
||||
| 12 | Commission | Amt | `feeX18` | Fee amount |
|
||||
| 13 | CommType | Char | - | "3" (absolute) |
|
||||
| 851 | LastLiquidityInd | Int | `isMaker` | 1=added, 2=removed |
|
||||
|
||||
### OrdStatus Mapping (Tag 39)
|
||||
|
||||
| FIX Value | FIX Name | ExecReport.newStatus |
|
||||
|-----------|----------|---------------------|
|
||||
| 0 | New | NEW (0) |
|
||||
| 1 | PartiallyFilled | OPEN (1) |
|
||||
| 2 | Filled | FILLED (2) |
|
||||
| 4 | Canceled | CANCELLED (3) |
|
||||
| 8 | Rejected | REJECTED (4) |
|
||||
| C | Expired | EXPIRED (5) |
|
||||
| A | PendingNew | NEW (0) |
|
||||
| 6 | PendingCancel | OPEN (1) |
|
||||
|
||||
### ExecType Mapping (Tag 150)
|
||||
|
||||
| FIX Value | FIX Name | Meaning |
|
||||
|-----------|----------|---------|
|
||||
| 0 | New | Order accepted |
|
||||
| F | Trade | Fill occurred |
|
||||
| 4 | Canceled | Order canceled |
|
||||
| 8 | Rejected | Order rejected |
|
||||
| C | Expired | Order expired |
|
||||
| D | Restated | Order amended |
|
||||
|
||||
### LastLiquidityInd Mapping (Tag 851)
|
||||
|
||||
| FIX Value | Meaning | ExecReport.isMaker |
|
||||
|-----------|---------|-------------------|
|
||||
| 1 | AddedLiquidity | `true` (maker) |
|
||||
| 2 | RemovedLiquidity | `false` (taker) |
|
||||
|
||||
---
|
||||
|
||||
## OrderCancelRequest (MsgType=F) → CancelRequest
|
||||
|
||||
| FIX Tag | FIX Name | Type | CancelRequest Field |
|
||||
|---------|----------|------|---------------------|
|
||||
| 11 | ClOrdId | String | `clOrdId` |
|
||||
| 37 | OrderID | String | `orderId` |
|
||||
| 41 | OrigClOrdId | String | `clOrdId` (original) |
|
||||
| 55 | Symbol | String | `marketId` |
|
||||
|
||||
---
|
||||
|
||||
## OrderCancelReplaceRequest (MsgType=G) → AmendRequest
|
||||
|
||||
| FIX Tag | FIX Name | Type | AmendRequest Field |
|
||||
|---------|----------|------|-------------------|
|
||||
| 11 | ClOrdId | String | (new client ID) |
|
||||
| 37 | OrderID | String | `orderId` |
|
||||
| 38 | OrderQty | Qty | `newSzX18` |
|
||||
| 41 | OrigClOrdId | String | (original client ID) |
|
||||
| 44 | Price | Price | `newPxX18` |
|
||||
|
||||
---
|
||||
|
||||
## Session Messages
|
||||
|
||||
### Logon (MsgType=A)
|
||||
|
||||
| Tag | Name | Required |
|
||||
|-----|------|----------|
|
||||
| 98 | EncryptMethod | 0 (none) |
|
||||
| 108 | HeartBtInt | 30 |
|
||||
| 553 | Username | API key |
|
||||
| 554 | Password | API secret signature |
|
||||
|
||||
### Heartbeat (MsgType=0)
|
||||
|
||||
| Tag | Name | Required |
|
||||
|-----|------|----------|
|
||||
| 112 | TestReqID | If responding to TestRequest |
|
||||
|
||||
### TestRequest (MsgType=1)
|
||||
|
||||
| Tag | Name | Required |
|
||||
|-----|------|----------|
|
||||
| 112 | TestReqID | Yes |
|
||||
|
||||
---
|
||||
|
||||
## Drop Copy (MsgType=AQ, AR)
|
||||
|
||||
Drop copy feed provides real-time execution reports without order entry capability.
|
||||
|
||||
### TradeCaptureReport (MsgType=AE)
|
||||
|
||||
| Tag | Name | Type | Description |
|
||||
|-----|------|------|-------------|
|
||||
| 571 | TradeReportID | String | Unique trade ID |
|
||||
| 487 | TradeReportTransType | Int | 0=New |
|
||||
| 55 | Symbol | String | Market symbol |
|
||||
| 32 | LastQty | Qty | Trade size |
|
||||
| 31 | LastPx | Price | Trade price |
|
||||
| 75 | TradeDate | LocalMktDate | Trade date |
|
||||
| 60 | TransactTime | UTCTimestamp | Trade time |
|
||||
|
||||
---
|
||||
|
||||
## Example Messages
|
||||
|
||||
### NewOrderSingle (Limit Buy)
|
||||
|
||||
```
|
||||
8=FIX.4.4|9=148|35=D|49=CLIENT|56=LXDEX|34=2|52=20260105-12:00:00.000|
|
||||
11=order123|21=1|38=1.5|40=2|44=50000.00|54=1|55=BTC-PERP|59=1|10=XXX|
|
||||
```
|
||||
|
||||
### ExecutionReport (Fill)
|
||||
|
||||
```
|
||||
8=FIX.4.4|9=200|35=8|49=LXDEX|56=CLIENT|34=3|52=20260105-12:00:00.001|
|
||||
37=ex123456|11=order123|17=trade789|150=F|39=2|55=BTC-PERP|54=1|
|
||||
38=1.5|44=50000.00|32=1.5|31=50000.00|14=1.5|151=0|6=50000.00|
|
||||
12=0.00075|13=3|851=2|60=20260105-12:00:00.001|10=XXX|
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
1. **Price Precision**: All prices converted to/from X18 (18 decimal places)
|
||||
2. **Quantity Precision**: All quantities converted to/from X18
|
||||
3. **Timestamps**: FIX uses UTCTimestamp format; convert to Unix timestamp for on-chain
|
||||
4. **ClOrdId Uniqueness**: Must be unique per account, per day
|
||||
5. **Session Persistence**: FIX sessions maintain sequence numbers across reconnects
|
||||
|
||||
---
|
||||
|
||||
*Last Updated: 2026-01-05*
|
||||
@@ -0,0 +1,352 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "LXDEX JSON-RPC Schema",
|
||||
"description": "Canonical JSON-RPC types for LXDEX trading API",
|
||||
"definitions": {
|
||||
"MarketId": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 4294967295,
|
||||
"description": "Market identifier (uint32)"
|
||||
},
|
||||
"OrderId": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]+$",
|
||||
"description": "Exchange order ID (uint64 as string)"
|
||||
},
|
||||
"ClOrdId": {
|
||||
"type": "string",
|
||||
"pattern": "^(0x[0-9a-fA-F]+|[0-9]+)$",
|
||||
"description": "Client order ID (uint128 as hex or decimal string)"
|
||||
},
|
||||
"X18Amount": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]+(\\.[0-9]+)?$",
|
||||
"description": "Fixed-point amount with 18 decimals (as decimal string)"
|
||||
},
|
||||
"Address": {
|
||||
"type": "string",
|
||||
"pattern": "^0x[0-9a-fA-F]{40}$",
|
||||
"description": "Ethereum address"
|
||||
},
|
||||
"Timestamp": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "Unix timestamp in seconds"
|
||||
},
|
||||
"Side": {
|
||||
"type": "string",
|
||||
"enum": ["BUY", "SELL"],
|
||||
"description": "Order side"
|
||||
},
|
||||
"OrderType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"LIMIT",
|
||||
"MARKET",
|
||||
"STOP_LIMIT",
|
||||
"STOP_MARKET",
|
||||
"TAKE_PROFIT_LIMIT",
|
||||
"TAKE_PROFIT_MARKET",
|
||||
"TRAILING_STOP",
|
||||
"TWAP",
|
||||
"ICEBERG"
|
||||
],
|
||||
"description": "Order type (append-only enum)"
|
||||
},
|
||||
"TimeInForce": {
|
||||
"type": "string",
|
||||
"enum": ["GTC", "IOC", "FOK", "GTD", "ALO"],
|
||||
"description": "Time-in-force (append-only enum)"
|
||||
},
|
||||
"OrderStatus": {
|
||||
"type": "string",
|
||||
"enum": ["NEW", "OPEN", "FILLED", "CANCELLED", "REJECTED", "EXPIRED", "TRIGGERED"],
|
||||
"description": "Order status"
|
||||
},
|
||||
"OrderRequest": {
|
||||
"type": "object",
|
||||
"required": ["marketId", "side", "orderType", "size"],
|
||||
"properties": {
|
||||
"marketId": { "$ref": "#/definitions/MarketId" },
|
||||
"side": { "$ref": "#/definitions/Side" },
|
||||
"orderType": { "$ref": "#/definitions/OrderType" },
|
||||
"price": {
|
||||
"$ref": "#/definitions/X18Amount",
|
||||
"description": "Limit price (required for LIMIT orders)"
|
||||
},
|
||||
"size": {
|
||||
"$ref": "#/definitions/X18Amount",
|
||||
"description": "Order size in base asset"
|
||||
},
|
||||
"timeInForce": {
|
||||
"$ref": "#/definitions/TimeInForce",
|
||||
"default": "GTC"
|
||||
},
|
||||
"reduceOnly": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "If true, order can only reduce position"
|
||||
},
|
||||
"clOrdId": {
|
||||
"$ref": "#/definitions/ClOrdId",
|
||||
"description": "Client order ID for idempotency"
|
||||
},
|
||||
"expireTime": {
|
||||
"$ref": "#/definitions/Timestamp",
|
||||
"description": "Expiration timestamp for GTD orders"
|
||||
},
|
||||
"triggerPrice": {
|
||||
"$ref": "#/definitions/X18Amount",
|
||||
"description": "Trigger price for Stop/TP orders"
|
||||
},
|
||||
"trailingDelta": {
|
||||
"$ref": "#/definitions/X18Amount",
|
||||
"description": "Trailing delta for trailing stop orders"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Order": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"orderId": { "$ref": "#/definitions/OrderId" },
|
||||
"owner": { "$ref": "#/definitions/Address" },
|
||||
"marketId": { "$ref": "#/definitions/MarketId" },
|
||||
"side": { "$ref": "#/definitions/Side" },
|
||||
"orderType": { "$ref": "#/definitions/OrderType" },
|
||||
"price": { "$ref": "#/definitions/X18Amount" },
|
||||
"originalSize": { "$ref": "#/definitions/X18Amount" },
|
||||
"remainingSize": { "$ref": "#/definitions/X18Amount" },
|
||||
"filledSize": { "$ref": "#/definitions/X18Amount" },
|
||||
"timeInForce": { "$ref": "#/definitions/TimeInForce" },
|
||||
"status": { "$ref": "#/definitions/OrderStatus" },
|
||||
"timestamp": { "$ref": "#/definitions/Timestamp" },
|
||||
"clOrdId": { "$ref": "#/definitions/ClOrdId" },
|
||||
"reduceOnly": { "type": "boolean" }
|
||||
}
|
||||
},
|
||||
"CancelRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"orderId": {
|
||||
"$ref": "#/definitions/OrderId",
|
||||
"description": "Cancel by exchange order ID"
|
||||
},
|
||||
"clOrdId": {
|
||||
"$ref": "#/definitions/ClOrdId",
|
||||
"description": "Cancel by client order ID (requires marketId)"
|
||||
},
|
||||
"marketId": {
|
||||
"$ref": "#/definitions/MarketId",
|
||||
"description": "Required when using clOrdId"
|
||||
}
|
||||
},
|
||||
"description": "Provide either orderId OR (clOrdId + marketId)"
|
||||
},
|
||||
"AmendRequest": {
|
||||
"type": "object",
|
||||
"required": ["orderId"],
|
||||
"properties": {
|
||||
"orderId": { "$ref": "#/definitions/OrderId" },
|
||||
"newPrice": {
|
||||
"$ref": "#/definitions/X18Amount",
|
||||
"description": "New price (omit to keep current)"
|
||||
},
|
||||
"newSize": {
|
||||
"$ref": "#/definitions/X18Amount",
|
||||
"description": "New size (omit to keep current)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Fill": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"marketId": { "$ref": "#/definitions/MarketId" },
|
||||
"orderId": { "$ref": "#/definitions/OrderId" },
|
||||
"clOrdId": { "$ref": "#/definitions/ClOrdId" },
|
||||
"side": { "$ref": "#/definitions/Side" },
|
||||
"price": { "$ref": "#/definitions/X18Amount" },
|
||||
"size": { "$ref": "#/definitions/X18Amount" },
|
||||
"fee": { "$ref": "#/definitions/X18Amount" },
|
||||
"timestamp": { "$ref": "#/definitions/Timestamp" },
|
||||
"tradeId": { "type": "string" },
|
||||
"isMaker": { "type": "boolean" },
|
||||
"newStatus": { "$ref": "#/definitions/OrderStatus" }
|
||||
}
|
||||
},
|
||||
"Position": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"marketId": { "$ref": "#/definitions/MarketId" },
|
||||
"side": { "type": "string", "enum": ["LONG", "SHORT"] },
|
||||
"size": { "$ref": "#/definitions/X18Amount" },
|
||||
"avgEntryPrice": { "$ref": "#/definitions/X18Amount" },
|
||||
"unrealizedPnl": { "$ref": "#/definitions/X18Amount" },
|
||||
"margin": { "$ref": "#/definitions/X18Amount" },
|
||||
"fundingAccrued": { "$ref": "#/definitions/X18Amount" }
|
||||
}
|
||||
},
|
||||
"AccountState": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"equity": { "$ref": "#/definitions/X18Amount" },
|
||||
"totalCollateral": { "$ref": "#/definitions/X18Amount" },
|
||||
"unrealizedPnl": { "$ref": "#/definitions/X18Amount" },
|
||||
"maintenanceMargin": { "$ref": "#/definitions/X18Amount" },
|
||||
"initialMargin": { "$ref": "#/definitions/X18Amount" },
|
||||
"marginMode": { "type": "string", "enum": ["ISOLATED", "CROSS", "PORTFOLIO"] },
|
||||
"isLiquidatable": { "type": "boolean" }
|
||||
}
|
||||
},
|
||||
"BBO": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"marketId": { "$ref": "#/definitions/MarketId" },
|
||||
"bidPrice": { "$ref": "#/definitions/X18Amount" },
|
||||
"bidSize": { "$ref": "#/definitions/X18Amount" },
|
||||
"askPrice": { "$ref": "#/definitions/X18Amount" },
|
||||
"askSize": { "$ref": "#/definitions/X18Amount" },
|
||||
"timestamp": { "$ref": "#/definitions/Timestamp" }
|
||||
}
|
||||
},
|
||||
"DepthLevel": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"price": { "$ref": "#/definitions/X18Amount" },
|
||||
"size": { "$ref": "#/definitions/X18Amount" }
|
||||
}
|
||||
},
|
||||
"OrderBook": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"marketId": { "$ref": "#/definitions/MarketId" },
|
||||
"bids": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/DepthLevel" }
|
||||
},
|
||||
"asks": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/DepthLevel" }
|
||||
},
|
||||
"timestamp": { "$ref": "#/definitions/Timestamp" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"methods": {
|
||||
"lxdex_placeOrder": {
|
||||
"description": "Submit a new order",
|
||||
"params": { "$ref": "#/definitions/OrderRequest" },
|
||||
"result": { "$ref": "#/definitions/OrderId" }
|
||||
},
|
||||
"lxdex_placeOrders": {
|
||||
"description": "Submit multiple orders atomically",
|
||||
"params": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/OrderRequest" }
|
||||
},
|
||||
"result": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/OrderId" }
|
||||
}
|
||||
},
|
||||
"lxdex_cancelOrder": {
|
||||
"description": "Cancel an order",
|
||||
"params": { "$ref": "#/definitions/CancelRequest" },
|
||||
"result": { "type": "boolean" }
|
||||
},
|
||||
"lxdex_cancelOrders": {
|
||||
"description": "Cancel multiple orders",
|
||||
"params": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/CancelRequest" }
|
||||
},
|
||||
"result": {
|
||||
"type": "array",
|
||||
"items": { "type": "boolean" }
|
||||
}
|
||||
},
|
||||
"lxdex_cancelAll": {
|
||||
"description": "Cancel all orders (optionally for specific market)",
|
||||
"params": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"marketId": { "$ref": "#/definitions/MarketId" }
|
||||
}
|
||||
},
|
||||
"result": { "type": "integer", "description": "Number cancelled" }
|
||||
},
|
||||
"lxdex_amendOrder": {
|
||||
"description": "Amend an existing order",
|
||||
"params": { "$ref": "#/definitions/AmendRequest" },
|
||||
"result": { "$ref": "#/definitions/OrderId" }
|
||||
},
|
||||
"lxdex_getOrder": {
|
||||
"description": "Get order by ID",
|
||||
"params": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"orderId": { "$ref": "#/definitions/OrderId" }
|
||||
}
|
||||
},
|
||||
"result": { "$ref": "#/definitions/Order" }
|
||||
},
|
||||
"lxdex_getOpenOrders": {
|
||||
"description": "Get all open orders for account",
|
||||
"params": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"account": { "$ref": "#/definitions/Address" },
|
||||
"marketId": { "$ref": "#/definitions/MarketId" }
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/Order" }
|
||||
}
|
||||
},
|
||||
"lxdex_getPositions": {
|
||||
"description": "Get all positions for account",
|
||||
"params": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"account": { "$ref": "#/definitions/Address" }
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/Position" }
|
||||
}
|
||||
},
|
||||
"lxdex_getAccountState": {
|
||||
"description": "Get full account state",
|
||||
"params": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"account": { "$ref": "#/definitions/Address" }
|
||||
}
|
||||
},
|
||||
"result": { "$ref": "#/definitions/AccountState" }
|
||||
},
|
||||
"lxdex_getBBO": {
|
||||
"description": "Get best bid/offer",
|
||||
"params": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"marketId": { "$ref": "#/definitions/MarketId" }
|
||||
}
|
||||
},
|
||||
"result": { "$ref": "#/definitions/BBO" }
|
||||
},
|
||||
"lxdex_getDepth": {
|
||||
"description": "Get order book depth",
|
||||
"params": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"marketId": { "$ref": "#/definitions/MarketId" },
|
||||
"levels": { "type": "integer", "default": 20 }
|
||||
}
|
||||
},
|
||||
"result": { "$ref": "#/definitions/OrderBook" }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { docs, meta } from '@/.source/server';
|
||||
import { toFumadocsSource } from 'fumadocs-mdx/runtime/server';
|
||||
import { loader } from 'fumadocs-core/source';
|
||||
|
||||
export const source = loader(toFumadocsSource(docs, meta), {
|
||||
baseUrl: '/docs',
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createMDX } from 'fumadocs-mdx/next';
|
||||
|
||||
const withMDX = createMDX();
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const config = {
|
||||
reactStrictMode: true,
|
||||
output: 'export',
|
||||
distDir: 'out',
|
||||
};
|
||||
|
||||
export default withMDX(config);
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "@luxfi/precompile-docs",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --port 3008",
|
||||
"build": "fumadocs-mdx && TURBOPACK=0 next build",
|
||||
"start": "next start",
|
||||
"lint": "fumadocs-mdx && next lint",
|
||||
"postinstall": "fumadocs-mdx"
|
||||
},
|
||||
"dependencies": {
|
||||
"@luxfi/logo": "^1.0.0",
|
||||
"fumadocs-core": "^16.0.0",
|
||||
"fumadocs-mdx": "^14.1.1",
|
||||
"fumadocs-ui": "^16.0.0",
|
||||
"lucide-react": "^0.468.0",
|
||||
"next": "16.0.1",
|
||||
"react": "19.2.0",
|
||||
"react-dom": "19.2.0",
|
||||
"shiki": "^1.27.2",
|
||||
"tailwind-merge": "^3.4.0",
|
||||
"tailwindcss": "^4.1.16",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"zod": "^3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4.1.16",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@types/node": "^22.10.2",
|
||||
"@types/react": "^19.0.1",
|
||||
"@types/react-dom": "^19.0.2",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"postcss": "^8.4.49",
|
||||
"typescript": "^5.7.2"
|
||||
},
|
||||
"packageManager": "[email protected]"
|
||||
}
|
||||
Generated
+4168
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
/** @type {import('postcss-load-config').Config} */
|
||||
const config = {
|
||||
plugins: {
|
||||
"@tailwindcss/postcss": {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -0,0 +1 @@
|
||||
precompile.lux.network
|
||||
@@ -0,0 +1,16 @@
|
||||
import { defineDocs, defineConfig } from 'fumadocs-mdx/config';
|
||||
|
||||
export const { docs, meta } = defineDocs({
|
||||
dir: 'content/docs',
|
||||
});
|
||||
|
||||
export default defineConfig({
|
||||
mdxOptions: {
|
||||
rehypeCodeOptions: {
|
||||
themes: {
|
||||
light: 'github-light',
|
||||
dark: 'github-dark',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "react-jsx",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./*"
|
||||
]
|
||||
},
|
||||
"target": "ES2017"
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
".next/dev/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
# FHE Precompile
|
||||
|
||||
Fully Homomorphic Encryption (FHE) precompile for Lux blockchain, enabling privacy-preserving smart contracts.
|
||||
|
||||
## Overview
|
||||
|
||||
This precompile provides FHE operations using the CKKS (Cheon-Kim-Kim-Song) scheme implemented in pure Go via `luxfi/lattice`. It supports threshold decryption through the T-Chain (67-of-100 validators via LP-333).
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ C-Chain (EVM) │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ Smart Contracts │ │
|
||||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │
|
||||
│ │ │ FHERC20.sol │ │ Auction.sol │ │ PrivateVote.sol │ │ │
|
||||
│ │ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ │ │
|
||||
│ └──────────┼────────────────┼──────────────────┼──────────┘ │
|
||||
│ │ │ │ │
|
||||
│ ┌──────────▼────────────────▼──────────────────▼──────────┐ │
|
||||
│ │ FHE Precompiles │ │
|
||||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │
|
||||
│ │ │ FHE (0x80) │ │ ACL (0x81) │ │ Gateway (0x83) │ │ │
|
||||
│ │ │ Operations │ │ Access Ctrl │ │ Decryption │ │ │
|
||||
│ │ └──────┬──────┘ └─────────────┘ └────────┬────────┘ │ │
|
||||
│ └─────────┼───────────────────────────────────┼───────────┘ │
|
||||
└────────────┼───────────────────────────────────┼───────────────┘
|
||||
│ Warp Message │ Warp Message
|
||||
▼ ▼
|
||||
┌────────────────────────┐ ┌─────────────────────────────┐
|
||||
│ Z-Chain (zkVM) │ │ T-Chain (Threshold) │
|
||||
│ ┌──────────────────┐ │ │ ┌───────────────────────┐ │
|
||||
│ │ FHE Processor │ │ │ │ Threshold Decryptor │ │
|
||||
│ │ - CKKS Ops │ │ │ │ - 67-of-100 shares │ │
|
||||
│ │ - Coprocessor │ │ │ │ - CKKS Multiparty │ │
|
||||
│ │ - luxfi/lattice│ │ │ │ - Share Combiner │ │
|
||||
│ └──────────────────┘ │ │ └───────────────────────┘ │
|
||||
└────────────────────────┘ └─────────────────────────────┘
|
||||
```
|
||||
|
||||
## Precompile Addresses
|
||||
|
||||
| Precompile | Address | Purpose |
|
||||
|------------|---------|---------|
|
||||
| FHE | `0x0200000000000000000000000000000000000080` | Core FHE operations |
|
||||
| ACL | `0x0200000000000000000000000000000000000081` | Access control |
|
||||
| InputVerifier | `0x0200000000000000000000000000000000000082` | Input validation |
|
||||
| FHEDecrypt | `0x0200000000000000000000000000000000000083` | Threshold decryption via T-Chain |
|
||||
|
||||
## Encrypted Types
|
||||
|
||||
| Type | Description | Solidity |
|
||||
|------|-------------|----------|
|
||||
| `ebool` | Encrypted boolean | `type ebool is bytes32` |
|
||||
| `euint8` | Encrypted 8-bit uint | `type euint8 is bytes32` |
|
||||
| `euint16` | Encrypted 16-bit uint | `type euint16 is bytes32` |
|
||||
| `euint32` | Encrypted 32-bit uint | `type euint32 is bytes32` |
|
||||
| `euint64` | Encrypted 64-bit uint | `type euint64 is bytes32` |
|
||||
| `euint128` | Encrypted 128-bit uint | `type euint128 is bytes32` |
|
||||
| `euint256` | Encrypted 256-bit uint | `type euint256 is bytes32` |
|
||||
| `eaddress` | Encrypted address | `type eaddress is bytes32` |
|
||||
|
||||
## Operations
|
||||
|
||||
### Arithmetic
|
||||
- `add(a, b)` - Addition
|
||||
- `sub(a, b)` - Subtraction
|
||||
- `mul(a, b)` - Multiplication
|
||||
- `div(a, b)` - Division
|
||||
- `rem(a, b)` - Remainder
|
||||
- `neg(a)` - Negation
|
||||
|
||||
### Comparison
|
||||
- `lt(a, b)` - Less than
|
||||
- `le(a, b)` - Less than or equal
|
||||
- `gt(a, b)` - Greater than
|
||||
- `ge(a, b)` - Greater than or equal
|
||||
- `eq(a, b)` - Equal
|
||||
- `ne(a, b)` - Not equal
|
||||
- `min(a, b)` - Minimum
|
||||
- `max(a, b)` - Maximum
|
||||
|
||||
### Bitwise
|
||||
- `and(a, b)` - Bitwise AND
|
||||
- `or(a, b)` - Bitwise OR
|
||||
- `xor(a, b)` - Bitwise XOR
|
||||
- `not(a)` - Bitwise NOT
|
||||
- `shl(a, bits)` - Shift left
|
||||
- `shr(a, bits)` - Shift right
|
||||
|
||||
### Conditional
|
||||
- `select(cond, ifTrue, ifFalse)` - Conditional select
|
||||
|
||||
### Randomness
|
||||
- `rand(type)` - Generate encrypted random value
|
||||
|
||||
## Gas Costs
|
||||
|
||||
| Operation | Gas Cost |
|
||||
|-----------|----------|
|
||||
| Encryption | 50,000 |
|
||||
| Add/Sub | 65,000 |
|
||||
| Mul | 150,000 |
|
||||
| Div/Rem | 500,000 |
|
||||
| Comparison | 60,000 |
|
||||
| Bitwise | 50,000 |
|
||||
| Select | 100,000 |
|
||||
| Random | 100,000 |
|
||||
| Decrypt Request | 10,000 |
|
||||
|
||||
## Usage Example
|
||||
|
||||
```solidity
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.24;
|
||||
|
||||
import {FHE, euint64, ebool} from "lux-standard/contracts/fhe/FHE.sol";
|
||||
|
||||
contract PrivateBalance {
|
||||
mapping(address => euint64) private balances;
|
||||
|
||||
function deposit(uint64 amount) external {
|
||||
euint64 encrypted = FHE.asEuint64(amount);
|
||||
balances[msg.sender] = FHE.add(balances[msg.sender], encrypted);
|
||||
FHE.allowThis(balances[msg.sender]);
|
||||
}
|
||||
|
||||
function transfer(address to, uint64 amount) external {
|
||||
euint64 encAmount = FHE.asEuint64(amount);
|
||||
|
||||
// Check sufficient balance (encrypted comparison)
|
||||
ebool sufficient = FHE.ge(balances[msg.sender], encAmount);
|
||||
|
||||
// Conditional update (works on encrypted data)
|
||||
balances[msg.sender] = FHE.select(
|
||||
sufficient,
|
||||
FHE.sub(balances[msg.sender], encAmount),
|
||||
balances[msg.sender]
|
||||
);
|
||||
|
||||
balances[to] = FHE.select(
|
||||
sufficient,
|
||||
FHE.add(balances[to], encAmount),
|
||||
balances[to]
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Decryption Flow
|
||||
|
||||
1. **Request**: Contract calls `FHE.decrypt(value)` or `Gateway.decrypt(handle, type)`
|
||||
2. **Warp**: Request sent to T-Chain via Warp messaging
|
||||
3. **Threshold**: 67-of-100 validators contribute decryption shares
|
||||
4. **Combine**: Shares combined to recover plaintext
|
||||
5. **Fulfill**: Result returned via `fulfill(requestId, result)` callback
|
||||
6. **Poll/Callback**: Contract retrieves result via `reveal(requestId)` or receives callback
|
||||
|
||||
## Files
|
||||
|
||||
- `module.go` - Module registration
|
||||
- `contract.go` - FHE precompile implementation
|
||||
- `acl.go` - Access control implementation (in evm/precompile)
|
||||
- `gateway.go` - Decryption gateway (in evm/precompile)
|
||||
- `IFHE.sol` - Solidity interfaces
|
||||
|
||||
## Related Components
|
||||
|
||||
- `luxfi/lattice` - Pure Go CKKS implementation
|
||||
- `node/vms/zkvm/fhe` - Z-Chain FHE processor
|
||||
- `node/vms/thresholdvm` - T-Chain threshold operations
|
||||
- `standard/contracts/fhe` - Solidity FHE library
|
||||
|
||||
## License
|
||||
|
||||
Copyright (C) 2019-2024, Lux Partners Limited. All rights reserved.
|
||||
See the file LICENSE for licensing terms.
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
# FROST Threshold Signature Precompile
|
||||
|
||||
## Overview
|
||||
|
||||
The FROST (Flexible Round-Optimized Schnorr Threshold) precompile enables efficient threshold signature verification for Schnorr-based signatures. FROST allows any t-of-n parties to collaboratively produce a signature that appears to be from a single signer.
|
||||
|
||||
**Address**: `0x020000000000000000000000000000000000000C`
|
||||
|
||||
## Features
|
||||
|
||||
- **Threshold Signatures**: Any t out of n parties can sign
|
||||
- **Schnorr-Based**: Compatible with Ed25519 and secp256k1 Schnorr
|
||||
- **Bitcoin Taproot**: Used for Bitcoin BIP-340/341 multisig
|
||||
- **Efficient**: Lower gas cost than ECDSA threshold (CGGMP21)
|
||||
- **Standardized**: Based on IETF FROST specification
|
||||
|
||||
## Algorithm
|
||||
|
||||
FROST is a threshold signature scheme where:
|
||||
- **n** total parties hold shares of a private key
|
||||
- Any **t** parties can collaborate to produce a valid signature
|
||||
- The signature is indistinguishable from a single-party Schnorr signature
|
||||
- Compatible with BIP-340 (Bitcoin Taproot) and Ed25519
|
||||
|
||||
### Key Properties
|
||||
|
||||
- **Non-Interactive**: After setup, signing requires minimal rounds
|
||||
- **Compact Signatures**: 64 bytes (standard Schnorr)
|
||||
- **Flexible Threshold**: Configurable t-of-n threshold
|
||||
- **Efficient Verification**: Standard Schnorr verification
|
||||
|
||||
## Specifications
|
||||
|
||||
### Input Format
|
||||
|
||||
Total size: **136 bytes** (minimum)
|
||||
|
||||
| Offset | Size | Field | Description |
|
||||
|--------|------|-------|-------------|
|
||||
| 0-3 | 4 bytes | threshold | Minimum signers required (t) |
|
||||
| 4-7 | 4 bytes | totalSigners | Total number of parties (n) |
|
||||
| 8-39 | 32 bytes | publicKey | Aggregated public key |
|
||||
| 40-71 | 32 bytes | messageHash | SHA-256 hash of message |
|
||||
| 72-135 | 64 bytes | signature | Schnorr signature (R \|\| s) |
|
||||
|
||||
### Output Format
|
||||
|
||||
**32 bytes**: Boolean result as uint256
|
||||
- `0x0000...0001` = Valid signature
|
||||
- `0x0000...0000` = Invalid signature
|
||||
|
||||
### Gas Costs
|
||||
|
||||
| Operation | Base Gas | Per-Signer Gas |
|
||||
|-----------|----------|----------------|
|
||||
| FROST Verify | 50,000 | 5,000 |
|
||||
|
||||
**Examples**:
|
||||
- 2-of-3 threshold: 50,000 + (3 × 5,000) = **65,000 gas**
|
||||
- 3-of-5 threshold: 50,000 + (5 × 5,000) = **75,000 gas**
|
||||
- 10-of-15 threshold: 50,000 + (15 × 5,000) = **125,000 gas**
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Solidity
|
||||
|
||||
```solidity
|
||||
import "./IFROST.sol";
|
||||
|
||||
contract MyContract is FROSTVerifier {
|
||||
function processThresholdSignedData(
|
||||
uint32 threshold,
|
||||
uint32 totalSigners,
|
||||
bytes32 publicKey,
|
||||
bytes32 messageHash,
|
||||
bytes calldata signature
|
||||
) external {
|
||||
// Verify FROST threshold signature
|
||||
verifyFROSTSignature(
|
||||
threshold,
|
||||
totalSigners,
|
||||
publicKey,
|
||||
messageHash,
|
||||
signature
|
||||
);
|
||||
|
||||
// Process data - signature is valid
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### TypeScript (ethers.js)
|
||||
|
||||
```typescript
|
||||
const FROST = new ethers.Contract(
|
||||
'0x020000000000000000000000000000000000000C',
|
||||
[
|
||||
'function verify(uint32,uint32,bytes32,bytes32,bytes) view returns(bool)'
|
||||
],
|
||||
provider
|
||||
);
|
||||
|
||||
// Verify 3-of-5 threshold signature
|
||||
const isValid = await FROST.verify(
|
||||
3, // threshold
|
||||
5, // totalSigners
|
||||
publicKey, // 32 bytes
|
||||
messageHash, // 32 bytes
|
||||
signature // 64 bytes
|
||||
);
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/luxfi/threshold/protocols/frost"
|
||||
"github.com/luxfi/threshold/pkg/math/curve"
|
||||
)
|
||||
|
||||
// Generate FROST keys (3-of-5 threshold)
|
||||
group := curve.Secp256k1{}
|
||||
threshold := 3
|
||||
parties := []party.ID{"party1", "party2", "party3", "party4", "party5"}
|
||||
|
||||
// Each party runs keygen
|
||||
config, err := frost.Keygen(group, "party1", parties, threshold)
|
||||
|
||||
// Later, any 3 parties can sign
|
||||
signers := []party.ID{"party1", "party2", "party3"}
|
||||
sig, err := frost.Sign(config, signers, messageHash)
|
||||
|
||||
// Verify on-chain via precompile
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
|
||||
### Bitcoin Taproot Multisig
|
||||
|
||||
```solidity
|
||||
contract TaprootMultisig {
|
||||
using FROSTLib for *;
|
||||
|
||||
bytes32 public taprootPublicKey;
|
||||
uint32 public constant THRESHOLD = 2;
|
||||
uint32 public constant TOTAL_SIGNERS = 3;
|
||||
|
||||
function spendBitcoin(
|
||||
bytes32 messageHash,
|
||||
bytes calldata signature
|
||||
) external {
|
||||
FROSTLib.verifyOrRevert(
|
||||
THRESHOLD,
|
||||
TOTAL_SIGNERS,
|
||||
taprootPublicKey,
|
||||
messageHash,
|
||||
signature
|
||||
);
|
||||
|
||||
// Execute Bitcoin spend
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Multi-Chain Governance
|
||||
|
||||
```solidity
|
||||
contract CrossChainGovernance is FROSTVerifier {
|
||||
struct Proposal {
|
||||
bytes32 proposalHash;
|
||||
uint256 votesFor;
|
||||
bool executed;
|
||||
}
|
||||
|
||||
mapping(uint256 => Proposal) public proposals;
|
||||
|
||||
function executeProposal(
|
||||
uint256 proposalId,
|
||||
bytes calldata thresholdSignature
|
||||
) external {
|
||||
Proposal storage proposal = proposals[proposalId];
|
||||
|
||||
// Verify threshold signature from governance committee
|
||||
verifyFROSTSignature(
|
||||
GOVERNANCE_THRESHOLD,
|
||||
GOVERNANCE_TOTAL,
|
||||
GOVERNANCE_PUBLIC_KEY,
|
||||
proposal.proposalHash,
|
||||
thresholdSignature
|
||||
);
|
||||
|
||||
// Execute proposal
|
||||
proposal.executed = true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Threshold Selection
|
||||
|
||||
- **2-of-3**: Common for small multisig wallets
|
||||
- **3-of-5**: Standard for governance
|
||||
- **5-of-7** or **7-of-10**: High-security applications
|
||||
- Never use 1-of-n (defeats the purpose)
|
||||
|
||||
### Message Hashing
|
||||
|
||||
Always hash messages before signing:
|
||||
|
||||
```solidity
|
||||
bytes32 messageHash = keccak256(abi.encodePacked(data));
|
||||
```
|
||||
|
||||
### Public Key Management
|
||||
|
||||
- Store aggregated public keys securely on-chain
|
||||
- Validate threshold parameters (t ≤ n)
|
||||
- Use events to track configuration changes
|
||||
|
||||
## Performance
|
||||
|
||||
Benchmarks on Apple M1 Max:
|
||||
|
||||
| Configuration | Gas Cost | Verify Time |
|
||||
|--------------|----------|-------------|
|
||||
| 2-of-3 | 65,000 | ~45 μs |
|
||||
| 3-of-5 | 75,000 | ~55 μs |
|
||||
| 5-of-7 | 85,000 | ~65 μs |
|
||||
| 10-of-15 | 125,000 | ~95 μs |
|
||||
|
||||
## Comparison with Other Schemes
|
||||
|
||||
| Algorithm | Signature Size | Gas Cost | Quantum Safe |
|
||||
|-----------|---------------|----------|--------------|
|
||||
| FROST (this) | 64 bytes | 50k-125k | ❌ |
|
||||
| CGGMP21 | 65 bytes | 75k-175k | ❌ |
|
||||
| Corona | 4KB | 150k-300k | ✅ |
|
||||
| BLS (Warp) | 96 bytes | 120k | ❌ |
|
||||
|
||||
## Integration with Lux Threshold
|
||||
|
||||
This precompile integrates with `/Users/z/work/lux/threshold/protocols/frost`:
|
||||
|
||||
```go
|
||||
import "github.com/luxfi/threshold/protocols/frost"
|
||||
|
||||
// The threshold library provides:
|
||||
// - frost.Keygen() - Distributed key generation
|
||||
// - frost.Sign() - Threshold signing
|
||||
// - frost.Refresh() - Share refreshing
|
||||
// - frost.KeygenTaproot() - Bitcoin Taproot keys
|
||||
```
|
||||
|
||||
## Standards Compliance
|
||||
|
||||
- **IETF FROST**: [draft-irtf-cfrg-frost](https://datatracker.ietf.org/doc/draft-irtf-cfrg-frost/)
|
||||
- **BIP-340**: Bitcoin Schnorr signatures
|
||||
- **BIP-341**: Bitcoin Taproot
|
||||
|
||||
## References
|
||||
|
||||
- [FROST Paper (ePrint 2020/852)](https://eprint.iacr.org/2020/852.pdf)
|
||||
- [Lux Threshold Library](https://github.com/luxfi/threshold)
|
||||
- [Bitcoin BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki)
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
# ML-DSA Precompile (FIPS 204)
|
||||
|
||||
Post-quantum digital signature verification precompile for Lux EVM.
|
||||
|
||||
## Overview
|
||||
|
||||
The ML-DSA (Module-Lattice-Based Digital Signature Algorithm) precompile provides quantum-resistant signature verification based on the Dilithium algorithm and standardized in FIPS 204.
|
||||
|
||||
**Precompile Address**: `0x0200000000000000000000000000000000000006`
|
||||
|
||||
## Features
|
||||
|
||||
- **Quantum Resistant**: Secure against attacks from both classical and quantum computers
|
||||
- **NIST Standardized**: Implements FIPS 204 (ML-DSA-65)
|
||||
- **High Performance**: ~108μs verification time on Apple M1
|
||||
- **Security Level 3**: Equivalent to AES-192 security
|
||||
|
||||
## Specifications
|
||||
|
||||
### ML-DSA-65 Parameters
|
||||
|
||||
| Parameter | Value |
|
||||
|-----------|-------|
|
||||
| Public Key Size | 1952 bytes |
|
||||
| Signature Size | 3309 bytes |
|
||||
| Security Level | NIST Level 3 |
|
||||
| Quantum Security | ~192 bits |
|
||||
|
||||
### Gas Costs
|
||||
|
||||
| Operation | Cost |
|
||||
|-----------|------|
|
||||
| Base Cost | 100,000 gas |
|
||||
| Per Message Byte | 10 gas |
|
||||
|
||||
**Examples:**
|
||||
- Empty message: 100,000 gas
|
||||
- 100-byte message: 101,000 gas
|
||||
- 1KB message: 110,240 gas
|
||||
- 10KB message: 202,400 gas
|
||||
|
||||
## Input Format
|
||||
|
||||
The precompile expects a specific binary input format:
|
||||
|
||||
```
|
||||
[Offset] [Size] [Description]
|
||||
0 1952 ML-DSA-65 public key
|
||||
1952 32 Message length (uint256, big-endian)
|
||||
1984 3309 ML-DSA-65 signature
|
||||
5293 variable Message bytes
|
||||
```
|
||||
|
||||
## Output Format
|
||||
|
||||
Returns a 32-byte word:
|
||||
- `0x0000...0001` - Signature is **valid**
|
||||
- `0x0000...0000` - Signature is **invalid**
|
||||
|
||||
## Usage
|
||||
|
||||
### Solidity
|
||||
|
||||
```solidity
|
||||
// Interface
|
||||
IMLDSA mldsa = IMLDSA(0x0200000000000000000000000000000000000006);
|
||||
bool isValid = mldsa.verify(publicKey, message, signature);
|
||||
require(isValid, "Invalid signature");
|
||||
|
||||
// Using library
|
||||
using MLDSALib for bytes;
|
||||
|
||||
function verifyData(
|
||||
bytes calldata publicKey,
|
||||
bytes calldata data,
|
||||
bytes calldata signature
|
||||
) external view {
|
||||
MLDSALib.verifyOrRevert(publicKey, data, signature);
|
||||
// Signature is valid
|
||||
}
|
||||
|
||||
// Gas estimation
|
||||
uint256 estimatedGas = MLDSALib.estimateGas(message.length);
|
||||
```
|
||||
|
||||
### TypeScript/ethers.js
|
||||
|
||||
```typescript
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
const MLDSA_ADDRESS = '0x0200000000000000000000000000000000000006';
|
||||
|
||||
// ABI for the verify function
|
||||
const abi = [
|
||||
'function verify(bytes calldata publicKey, bytes calldata message, bytes calldata signature) external view returns (bool)'
|
||||
];
|
||||
|
||||
const mldsa = new ethers.Contract(MLDSA_ADDRESS, abi, provider);
|
||||
|
||||
// Verify signature
|
||||
const isValid = await mldsa.verify(publicKey, message, signature);
|
||||
console.log('Signature valid:', isValid);
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/luxfi/node/crypto/mldsa"
|
||||
"github.com/luxfi/evm/precompile/contracts/mldsa"
|
||||
)
|
||||
|
||||
// Generate key pair
|
||||
seed := make([]byte, 32)
|
||||
sk, _ := mldsa.NewSigningKey(mldsa.ModeML_DSA_65, seed)
|
||||
pk := sk.PublicKey()
|
||||
|
||||
// Sign message
|
||||
message := []byte("Hello, quantum world!")
|
||||
signature := sk.Sign(message, nil)
|
||||
|
||||
// Verify via precompile
|
||||
input := prepareMLDSAInput(pk, message, signature)
|
||||
result, gas, err := mldsa.MLDSAVerifyPrecompile.Run(
|
||||
nil, addr, addr, input, 200000, false,
|
||||
)
|
||||
|
||||
valid := result[31] == 1 // Check last byte
|
||||
```
|
||||
|
||||
## Performance Benchmarks
|
||||
|
||||
Measured on Apple M1 Max:
|
||||
|
||||
| Message Size | Verification Time | Gas Used |
|
||||
|--------------|-------------------|----------|
|
||||
| 18 bytes (small) | ~170μs | 100,180 |
|
||||
| 10KB (large) | ~218μs | 202,400 |
|
||||
|
||||
**Memory Usage:**
|
||||
- 33,314 bytes per operation
|
||||
- 6 allocations per operation
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Quantum Resistance**: ML-DSA-65 provides Level 3 security (~192-bit quantum security)
|
||||
2. **Side-Channel Protection**: Implementation uses constant-time operations
|
||||
3. **FIPS 204 Compliance**: Follows NIST's standardized algorithm
|
||||
4. **No Context Support**: Current implementation doesn't support context strings (passes empty context)
|
||||
|
||||
## Comparison with Other Algorithms
|
||||
|
||||
| Algorithm | Type | Signature Size | Verify Time | Quantum Secure |
|
||||
|-----------|------|----------------|-------------|----------------|
|
||||
| ECDSA (secp256k1) | Classical | 65 bytes | ~88μs | ❌ No |
|
||||
| ML-DSA-65 | Post-Quantum | 3,309 bytes | ~108μs | ✅ Yes |
|
||||
| SLH-DSA-128s | Post-Quantum | 7,856 bytes | ~4.2ms | ✅ Yes |
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### From ECDSA to ML-DSA
|
||||
|
||||
```solidity
|
||||
// Old ECDSA verification
|
||||
bytes32 hash = keccak256(message);
|
||||
address signer = ecrecover(hash, v, r, s);
|
||||
require(signer == expectedSigner, "Invalid signature");
|
||||
|
||||
// New ML-DSA verification
|
||||
IMLDSA mldsa = IMLDSA(0x0200000000000000000000000000000000000006);
|
||||
bool valid = mldsa.verify(mldsaPublicKey, message, mldsaSignature);
|
||||
require(valid, "Invalid ML-DSA signature");
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
# Run unit tests
|
||||
cd /Users/z/work/lux/evm/precompile/contracts/mldsa
|
||||
go test -v
|
||||
|
||||
# Run benchmarks
|
||||
go test -bench=. -benchmem
|
||||
|
||||
# Test with different message sizes
|
||||
go test -v -run TestMLDSAVerify_LargeMessage
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [FIPS 204: Module-Lattice-Based Digital Signature Standard](https://csrc.nist.gov/pubs/fips/204/final)
|
||||
- [Dilithium Specification](https://pq-crystals.org/dilithium/)
|
||||
- [Cloudflare CIRCL Library](https://github.com/cloudflare/circl)
|
||||
|
||||
## Related Precompiles
|
||||
|
||||
- **SLH-DSA** (`0x0200000000000000000000000000000000000007`): Hash-based signatures
|
||||
- **ML-KEM** (`0x0200000000000000000000000000000000000008`): Post-quantum key encapsulation
|
||||
- **PQCrypto** (`0x0200000000000000000000000000000000000005`): General post-quantum operations
|
||||
|
||||
## License
|
||||
|
||||
Copyright (C) 2025, Lux Industries, Inc. All rights reserved.
|
||||
@@ -0,0 +1,97 @@
|
||||
# ML-KEM Precompile
|
||||
|
||||
Post-quantum key encapsulation mechanism precompile implementing FIPS 203 (ML-KEM).
|
||||
|
||||
## Address
|
||||
|
||||
`0x0200000000000000000000000000000000000007`
|
||||
|
||||
## Specification
|
||||
|
||||
See [LP-4318: ML-KEM Post-Quantum Key Encapsulation](https://lps.lux.network/docs/lp-4318-ml-kem-post-quantum-key-encapsulation/)
|
||||
|
||||
## Operations
|
||||
|
||||
### Encapsulate (0x01)
|
||||
|
||||
Generate a shared secret and ciphertext from a public key.
|
||||
|
||||
**Input:**
|
||||
| Offset | Size | Description |
|
||||
|--------|------|-------------|
|
||||
| 0 | 1 | Operation (0x01) |
|
||||
| 1 | 1 | Mode (0x00=512, 0x01=768, 0x02=1024) |
|
||||
| 2 | varies | Public key |
|
||||
|
||||
**Output:**
|
||||
| Offset | Size | Description |
|
||||
|--------|------|-------------|
|
||||
| 0 | varies | Ciphertext |
|
||||
| varies | 32 | Shared secret |
|
||||
|
||||
### Decapsulate (0x02)
|
||||
|
||||
Recover the shared secret from a ciphertext using a private key.
|
||||
|
||||
**Input:**
|
||||
| Offset | Size | Description |
|
||||
|--------|------|-------------|
|
||||
| 0 | 1 | Operation (0x02) |
|
||||
| 1 | 1 | Mode (0x00=512, 0x01=768, 0x02=1024) |
|
||||
| 2 | varies | Private key |
|
||||
| varies | varies | Ciphertext |
|
||||
|
||||
**Output:**
|
||||
| Offset | Size | Description |
|
||||
|--------|------|-------------|
|
||||
| 0 | 32 | Shared secret |
|
||||
|
||||
## Key Sizes
|
||||
|
||||
| Mode | Public Key | Private Key | Ciphertext | Shared Secret |
|
||||
|------|------------|-------------|------------|---------------|
|
||||
| ML-KEM-512 | 800 | 1632 | 768 | 32 |
|
||||
| ML-KEM-768 | 1184 | 2400 | 1088 | 32 |
|
||||
| ML-KEM-1024 | 1568 | 3168 | 1568 | 32 |
|
||||
|
||||
## Gas Costs
|
||||
|
||||
| Operation | ML-KEM-512 | ML-KEM-768 | ML-KEM-1024 |
|
||||
|-----------|------------|------------|-------------|
|
||||
| Encapsulate | 50,000 | 75,000 | 100,000 |
|
||||
| Decapsulate | 60,000 | 90,000 | 120,000 |
|
||||
|
||||
## Security Levels
|
||||
|
||||
- **ML-KEM-512**: 128-bit security (NIST Level 1)
|
||||
- **ML-KEM-768**: 192-bit security (NIST Level 3) - **Recommended**
|
||||
- **ML-KEM-1024**: 256-bit security (NIST Level 5)
|
||||
|
||||
## Usage Example (Solidity)
|
||||
|
||||
```solidity
|
||||
import {MLKEMCaller} from "./IMLKEM.sol";
|
||||
|
||||
contract QuantumSecureExchange {
|
||||
using MLKEMCaller for *;
|
||||
|
||||
function establishSecret(bytes calldata recipientPubKey)
|
||||
external view
|
||||
returns (bytes memory ciphertext, bytes32 sharedSecret)
|
||||
{
|
||||
return MLKEMCaller.encapsulate768(recipientPubKey);
|
||||
}
|
||||
|
||||
function recoverSecret(
|
||||
bytes calldata privateKey,
|
||||
bytes calldata ciphertext
|
||||
) external view returns (bytes32 sharedSecret) {
|
||||
return MLKEMCaller.decapsulate768(privateKey, ciphertext);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism Standard](https://csrc.nist.gov/pubs/fips/203/final)
|
||||
- [NIST Post-Quantum Cryptography](https://csrc.nist.gov/projects/post-quantum-cryptography)
|
||||
@@ -0,0 +1,120 @@
|
||||
# secp256r1 (P-256) Signature Verification Precompile
|
||||
|
||||
Implementation of the secp256r1 (NIST P-256) signature verification precompile for the Lux Network EVM.
|
||||
|
||||
## Overview
|
||||
|
||||
This precompile enables efficient verification of ECDSA signatures using the NIST P-256 curve, commonly used by:
|
||||
|
||||
- **WebAuthn/Passkeys**: Modern password-less authentication
|
||||
- **Apple Secure Enclave**: Face ID / Touch ID
|
||||
- **Windows Hello**: Biometric authentication
|
||||
- **Android Keystore**: Device-backed keys
|
||||
- **Enterprise HSMs**: NIST-approved cryptography
|
||||
|
||||
## Precompile Details
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Address | `0x0000000000000000000000000000000000000100` |
|
||||
| Gas Cost | 3,450 |
|
||||
| Input Size | 160 bytes |
|
||||
| Output Size | 32 bytes (success) or 0 bytes (failure) |
|
||||
|
||||
## Input Format
|
||||
|
||||
```
|
||||
[32 bytes] message hash
|
||||
[32 bytes] r (signature component)
|
||||
[32 bytes] s (signature component)
|
||||
[32 bytes] x (public key x-coordinate)
|
||||
[32 bytes] y (public key y-coordinate)
|
||||
```
|
||||
|
||||
## Output Format
|
||||
|
||||
- **Success**: 32 bytes with value `0x0000000000000000000000000000000000000000000000000000000000000001`
|
||||
- **Failure**: Empty (0 bytes)
|
||||
|
||||
## Usage
|
||||
|
||||
### Solidity
|
||||
|
||||
```solidity
|
||||
import {Secp256r1Lib, P256PublicKey} from "./ISecp256r1.sol";
|
||||
|
||||
contract MyContract {
|
||||
using Secp256r1Lib for bytes32;
|
||||
|
||||
function verifyBiometric(
|
||||
bytes32 hash,
|
||||
bytes32 r,
|
||||
bytes32 s,
|
||||
bytes32 pubX,
|
||||
bytes32 pubY
|
||||
) external view returns (bool) {
|
||||
return Secp256r1Lib.verify(hash, r, s, pubX, pubY);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
```go
|
||||
import "github.com/luxfi/precompiles/secp256r1"
|
||||
|
||||
func verify(hash []byte, r, s, x, y *big.Int) bool {
|
||||
return secp256r1.Verify(hash, r, s, x, y)
|
||||
}
|
||||
```
|
||||
|
||||
## Gas Comparison
|
||||
|
||||
| Method | Gas Cost | Savings |
|
||||
|--------|----------|---------|
|
||||
| Solidity implementation | 200,000 - 330,000 | - |
|
||||
| This precompile | 3,450 | **99%** |
|
||||
|
||||
## Use Cases
|
||||
|
||||
1. **Biometric Wallets**: Sign transactions with Face ID/Touch ID
|
||||
2. **Enterprise SSO**: Integrate with corporate identity systems
|
||||
3. **WebAuthn/Passkeys**: Password-less authentication for dApps
|
||||
4. **Cross-Chain Identity**: Unified authentication across Lux chains
|
||||
|
||||
## Standards Compliance
|
||||
|
||||
- [EIP-7212](https://eips.ethereum.org/EIPS/eip-7212): secp256r1 Curve Support
|
||||
- [RIP-7212](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md): Rollup precompile
|
||||
- [NIST FIPS 186-3](https://csrc.nist.gov/publications/detail/fips/186/3/archive/2009-06-25): Digital Signature Standard
|
||||
- [LP-3651](https://github.com/luxfi/lps): Lux Network specification
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
go test -v ./...
|
||||
```
|
||||
|
||||
## Benchmarks
|
||||
|
||||
```bash
|
||||
go test -bench=. -benchmem
|
||||
```
|
||||
|
||||
Typical results (Apple M1 Max):
|
||||
|
||||
```
|
||||
BenchmarkContract_Run-10 100000 10.5 µs/op 0 B/op 0 allocs/op
|
||||
BenchmarkVerify-10 100000 10.3 µs/op 0 B/op 0 allocs/op
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Constant Time**: Uses Go stdlib `crypto/ecdsa` which provides constant-time operations
|
||||
2. **Point Validation**: Validates that public key is on curve before verification
|
||||
3. **Range Checks**: Validates r, s are in range [1, n-1]
|
||||
4. **No Malleability Check**: Follows NIST specification exactly
|
||||
|
||||
## License
|
||||
|
||||
MIT License - Copyright (C) 2025, Lux Industries, Inc.
|
||||
@@ -0,0 +1,278 @@
|
||||
# SLH-DSA Signature Verification Precompile
|
||||
|
||||
## Overview
|
||||
|
||||
This precompile implements **SLH-DSA (Stateless Hash-Based Digital Signature Algorithm)** signature verification as specified in [FIPS 205](https://csrc.nist.gov/pubs/fips/205/final).
|
||||
|
||||
**Address**: `0x0200000000000000000000000000000000000007`
|
||||
|
||||
## FIPS 205 - SLH-DSA
|
||||
|
||||
SLH-DSA (formerly SPHINCS+) is a **post-quantum digital signature scheme** based on hash functions. It provides:
|
||||
|
||||
- **Quantum Resistance**: Secure against attacks by quantum computers
|
||||
- **Stateless Operation**: No state management required (unlike XMSS)
|
||||
- **Minimal Assumptions**: Security based only on collision-resistant hash functions
|
||||
- **Conservative Security**: Well-understood hash-based construction
|
||||
|
||||
## Parameter Sets
|
||||
|
||||
SLH-DSA supports 12 parameter sets across 3 security levels:
|
||||
|
||||
### Category 1 (128-bit security)
|
||||
| Parameter Set | Hash Function | Signature Size | Sign Speed | Verify Speed |
|
||||
|--------------|---------------|----------------|------------|--------------|
|
||||
| SHA2-128s | SHA-256 | 7,856 bytes | Slow | Fast |
|
||||
| SHA2-128f | SHA-256 | 17,088 bytes | Fast | Fast |
|
||||
| SHAKE-128s | SHAKE256 | 7,856 bytes | Slow | Fast |
|
||||
| SHAKE-128f | SHAKE256 | 17,088 bytes | Fast | Fast |
|
||||
|
||||
### Category 3 (192-bit security)
|
||||
| Parameter Set | Hash Function | Signature Size | Sign Speed | Verify Speed |
|
||||
|--------------|---------------|----------------|------------|--------------|
|
||||
| SHA2-192s | SHA-256/512 | 16,224 bytes | Slow | Fast |
|
||||
| SHA2-192f | SHA-256/512 | 35,664 bytes | Fast | Fast |
|
||||
| SHAKE-192s | SHAKE256 | 16,224 bytes | Slow | Fast |
|
||||
| SHAKE-192f | SHAKE256 | 35,664 bytes | Fast | Fast |
|
||||
|
||||
### Category 5 (256-bit security)
|
||||
| Parameter Set | Hash Function | Signature Size | Sign Speed | Verify Speed |
|
||||
|--------------|---------------|----------------|------------|--------------|
|
||||
| SHA2-256s | SHA-512 | 29,792 bytes | Slow | Fast |
|
||||
| SHA2-256f | SHA-512 | 49,856 bytes | Fast | Fast |
|
||||
| SHAKE-256s | SHAKE256 | 29,792 bytes | Slow | Fast |
|
||||
| SHAKE-256f | SHAKE256 | 49,856 bytes | Fast | Fast |
|
||||
|
||||
**Trade-offs**:
|
||||
- **"s" (small)**: Smaller signatures, slower signing (~300-600ms)
|
||||
- **"f" (fast)**: Larger signatures, faster signing (~10-50ms)
|
||||
- Verification speed is similar for both variants (~300-600μs)
|
||||
|
||||
## Performance Benchmarks
|
||||
|
||||
**Apple M1 Max Results**:
|
||||
|
||||
| Operation | SHA2-128s | SHA2-256s |
|
||||
|-----------|-----------|-----------|
|
||||
| Sign | ~309ms | ~603ms |
|
||||
| Verify | ~286μs | ~593μs |
|
||||
| KeyGen | ~35ms | ~71ms |
|
||||
|
||||
**Verification Throughput**:
|
||||
- SHA2-128s: ~3,500 signatures/second
|
||||
- SHA2-256s: ~1,700 signatures/second
|
||||
|
||||
## Gas Costs
|
||||
|
||||
```
|
||||
Gas = BaseGas + (MessageLength * PerByteGas)
|
||||
BaseGas = 15,000
|
||||
PerByteGas = 10
|
||||
```
|
||||
|
||||
**Examples**:
|
||||
- Empty message: 15,000 gas
|
||||
- 100-byte message: 16,000 gas
|
||||
- 1KB message: 25,240 gas
|
||||
- 10KB message: 115,000 gas
|
||||
|
||||
## Usage
|
||||
|
||||
### Solidity Interface
|
||||
|
||||
```solidity
|
||||
interface ISLHDSA {
|
||||
function verify(
|
||||
bytes calldata publicKey,
|
||||
bytes calldata message,
|
||||
bytes calldata signature
|
||||
) external view returns (bool valid);
|
||||
}
|
||||
```
|
||||
|
||||
### Example Contract
|
||||
|
||||
```solidity
|
||||
import {SLHDSAVerifier} from "./ISLHDSA.sol";
|
||||
|
||||
contract MyContract is SLHDSAVerifier {
|
||||
function processSignedData(
|
||||
bytes calldata publicKey,
|
||||
bytes calldata data,
|
||||
bytes calldata signature
|
||||
) external {
|
||||
// Verify signature with automatic revert on failure
|
||||
require(
|
||||
verifySLHDSASignature(publicKey, data, signature),
|
||||
"Invalid signature"
|
||||
);
|
||||
|
||||
// Process data - signature is valid
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Using the Library
|
||||
|
||||
```solidity
|
||||
import {SLHDSALib} from "./ISLHDSA.sol";
|
||||
|
||||
contract Example {
|
||||
function verifyWithRevert(
|
||||
bytes memory publicKey,
|
||||
bytes memory message,
|
||||
bytes memory signature
|
||||
) public view {
|
||||
// Automatically reverts if signature is invalid
|
||||
SLHDSALib.verifyOrRevert(publicKey, message, signature);
|
||||
}
|
||||
|
||||
function estimateVerificationGas(uint256 messageLength)
|
||||
public
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
return SLHDSALib.estimateGas(messageLength);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### TypeScript/ethers.js
|
||||
|
||||
```typescript
|
||||
const SLHDSA_ADDRESS = '0x0200000000000000000000000000000000000007';
|
||||
const SLHDSA = new ethers.Contract(
|
||||
SLHDSA_ADDRESS,
|
||||
['function verify(bytes,bytes,bytes) view returns(bool)'],
|
||||
provider
|
||||
);
|
||||
|
||||
const isValid = await SLHDSA.verify(publicKey, message, signature);
|
||||
console.log('Signature valid:', isValid);
|
||||
```
|
||||
|
||||
## Input Format
|
||||
|
||||
The precompile expects input in the following format:
|
||||
|
||||
```
|
||||
[mode(1 byte)] [pubKeyLen(2 bytes)] [publicKey] [msgLen(2 bytes)] [message] [signature]
|
||||
```
|
||||
|
||||
**Fields**:
|
||||
1. `mode` (1 byte): Parameter set identifier (0-11)
|
||||
- 0: SHA2-128s, 1: SHAKE-128s, 2: SHA2-128f, 3: SHAKE-128f
|
||||
- 4: SHA2-192s, 5: SHAKE-192s, 6: SHA2-192f, 7: SHAKE-192f
|
||||
- 8: SHA2-256s, 9: SHAKE-256s, 10: SHA2-256f, 11: SHAKE-256f
|
||||
2. `pubKeyLen` (2 bytes, big-endian): Length of public key
|
||||
3. `publicKey` (32, 48, or 64 bytes): The SLH-DSA public key
|
||||
4. `msgLen` (2 bytes, big-endian): Length of message
|
||||
5. `message` (variable): The message that was signed
|
||||
6. `signature` (7856-49856 bytes): The SLH-DSA signature
|
||||
|
||||
## Output Format
|
||||
|
||||
Single byte indicating verification result:
|
||||
- `0x01`: Signature is valid
|
||||
- `0x00`: Signature is invalid
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Post-Quantum Security
|
||||
|
||||
SLH-DSA provides security against quantum computer attacks because:
|
||||
1. Based on hash functions (no algebraic structure to exploit)
|
||||
2. No known quantum algorithm for breaking collision resistance
|
||||
3. Conservative security assumptions
|
||||
|
||||
### Hash Function Requirements
|
||||
|
||||
- **SHA-2**: Industry standard, widely deployed
|
||||
- **SHAKE**: SHA-3 based, newer but standardized
|
||||
|
||||
### Signature Size Trade-offs
|
||||
|
||||
Large signatures are a characteristic of hash-based schemes:
|
||||
- **Small variants** ("s"): More efficient for storage
|
||||
- **Fast variants** ("f"): Better for high-throughput signing
|
||||
|
||||
### Recommended Parameter Sets
|
||||
|
||||
- **General use**: SHA2-128s or SHA2-256s
|
||||
- Smaller signatures, acceptable signing speed for most applications
|
||||
|
||||
- **High-throughput signing**: SHA2-128f or SHA2-256f
|
||||
- When signing speed is critical and storage is available
|
||||
|
||||
- **Conservative security**: SHA2-256s
|
||||
- Maximum security level, reasonable signature size
|
||||
|
||||
## Comparison with Other Schemes
|
||||
|
||||
| Scheme | Type | Signature Size | Verify Time | Quantum Secure |
|
||||
|--------|------|----------------|-------------|----------------|
|
||||
| ECDSA | Elliptic Curve | 65 bytes | ~88μs | ❌ |
|
||||
| ML-DSA-65 | Lattice | 3,309 bytes | ~108μs | ✅ |
|
||||
| SLH-DSA-SHA2-128s | Hash-based | 7,856 bytes | ~286μs | ✅ |
|
||||
| SLH-DSA-SHA2-256s | Hash-based | 29,792 bytes | ~593μs | ✅ |
|
||||
|
||||
**Trade-offs**:
|
||||
- SLH-DSA has larger signatures than ML-DSA
|
||||
- SLH-DSA has slower verification than ML-DSA
|
||||
- SLH-DSA has more conservative security assumptions
|
||||
- SLH-DSA requires no state management
|
||||
|
||||
## Implementation Details
|
||||
|
||||
- **Library**: Cloudflare CIRCL v1.6.1
|
||||
- **Standard**: FIPS 205 (Final)
|
||||
- **Algorithm**: SPHINCS+ with FIPS 205 parameters
|
||||
- **Hash Functions**: SHA-256, SHA-512, SHAKE256
|
||||
- **Security Levels**: 128-bit, 192-bit, 256-bit
|
||||
|
||||
## Error Handling
|
||||
|
||||
The precompile returns `0x00` (invalid) for:
|
||||
- Invalid mode identifier
|
||||
- Incorrect public key size
|
||||
- Incorrect signature size
|
||||
- Failed signature verification
|
||||
- Malformed input
|
||||
|
||||
No exceptions are thrown - all errors result in `0x00` output.
|
||||
|
||||
## Gas Optimization Tips
|
||||
|
||||
1. **Batch Verification**: Group multiple verifications to amortize overhead
|
||||
2. **Off-chain Verification**: Verify off-chain when possible, only verify on-chain when necessary
|
||||
3. **Signature Aggregation**: Use BLS or other aggregatable schemes when applicable
|
||||
4. **Parameter Selection**: Use 128-bit security when 256-bit is not required
|
||||
|
||||
## Migration from Classical Signatures
|
||||
|
||||
When migrating from ECDSA to SLH-DSA:
|
||||
|
||||
1. **Storage**: Account for larger signatures in data structures
|
||||
2. **Gas Costs**: Budget for higher verification costs
|
||||
3. **Signing Infrastructure**: Update to support SLH-DSA key generation
|
||||
4. **Backwards Compatibility**: Support both schemes during transition
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
cd /Users/z/work/lux/standard
|
||||
forge test --match-path "**/slhdsa/**"
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [FIPS 205: Stateless Hash-Based Digital Signature Standard](https://csrc.nist.gov/pubs/fips/205/final)
|
||||
- [SPHINCS+ Website](https://sphincs.org/)
|
||||
- [Cloudflare CIRCL Library](https://github.com/cloudflare/circl)
|
||||
- [NIST PQC Standardization](https://csrc.nist.gov/projects/post-quantum-cryptography)
|
||||
|
||||
## License
|
||||
|
||||
Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
||||
See the file LICENSE for licensing terms.
|
||||
+318
@@ -0,0 +1,318 @@
|
||||
# ZK Precompiles
|
||||
|
||||
Zero-Knowledge proof verification and privacy operations for Lux EVM.
|
||||
|
||||
## Overview
|
||||
|
||||
The ZK precompile suite provides comprehensive support for:
|
||||
|
||||
- **Proof Verification**: Groth16, PLONK, fflonk, Halo2
|
||||
- **Commitment Schemes**: KZG, Pedersen, IPA
|
||||
- **Privacy Operations**: Confidential pools, nullifiers, range proofs
|
||||
- **Rollup Support**: ZK rollup batch verification, state roots
|
||||
|
||||
## Precompile Addresses
|
||||
|
||||
### Core ZK Verification
|
||||
|
||||
| Address | Precompile | Gas Cost | Description |
|
||||
|---------|-----------|----------|-------------|
|
||||
| `0x0900` | ZKVerifier | Variable | Generic ZK proof verification |
|
||||
| `0x0901` | Groth16 | ~200,000 | Groth16 SNARK verification |
|
||||
| `0x0902` | PLONK | ~250,000 | PLONK proof verification |
|
||||
| `0x0903` | fflonk | ~180,000 | Optimized PLONK variant |
|
||||
| `0x0904` | Halo2 | ~300,000 | Recursive proof verification |
|
||||
|
||||
### Commitment Schemes
|
||||
|
||||
| Address | Precompile | Gas Cost | Description |
|
||||
|---------|-----------|----------|-------------|
|
||||
| `0x0501` | Poseidon2 | ~5,000 | PQ-safe hash commitment |
|
||||
| `0x0502` | Pedersen | ~10,000 | Elliptic curve commitment |
|
||||
| `0x0910` | KZG | ~50,000 | Polynomial commitment (EIP-4844) |
|
||||
| `0x0912` | IPA | ~30,000 | Inner product argument |
|
||||
|
||||
### Privacy Operations
|
||||
|
||||
| Address | Precompile | Gas Cost | Description |
|
||||
|---------|-----------|----------|-------------|
|
||||
| `0x0920` | PrivacyPool | ~100,000 | Confidential transaction pool |
|
||||
| `0x0921` | Nullifier | ~5,000 | Double-spend prevention |
|
||||
| `0x0922` | Commitment | ~10,000 | Commitment verification |
|
||||
| `0x0923` | RangeProof | ~100,000 | Bulletproofs range verification |
|
||||
|
||||
### Rollup Support
|
||||
|
||||
| Address | Precompile | Gas Cost | Description |
|
||||
|---------|-----------|----------|-------------|
|
||||
| `0x0930` | RollupVerify | ~500,000 | ZK rollup batch verification |
|
||||
| `0x0931` | StateRoot | ~50,000 | State root verification |
|
||||
| `0x0932` | BatchProof | ~200,000 | Proof aggregation |
|
||||
|
||||
## Usage
|
||||
|
||||
### Solidity
|
||||
|
||||
```solidity
|
||||
import "@luxfi/precompile/zk/IZK.sol";
|
||||
|
||||
contract MyZKApp {
|
||||
using ZKLib for *;
|
||||
|
||||
bytes32 public verifyingKeyId;
|
||||
|
||||
function verifyTransfer(
|
||||
uint256[2] calldata proofA,
|
||||
uint256[2][2] calldata proofB,
|
||||
uint256[2] calldata proofC,
|
||||
uint256[] calldata publicInputs
|
||||
) external view returns (bool) {
|
||||
return ZKLib.verifyGroth16(
|
||||
verifyingKeyId,
|
||||
proofA,
|
||||
proofB,
|
||||
proofC,
|
||||
publicInputs
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### PLONK Verification
|
||||
|
||||
```solidity
|
||||
contract PLONKVerifier {
|
||||
using ZKLib for *;
|
||||
|
||||
function verifyPlonkProof(
|
||||
bytes32 vkId,
|
||||
bytes calldata proof,
|
||||
uint256[] calldata publicInputs
|
||||
) external view returns (bool) {
|
||||
return ZKLib.verifyPlonk(vkId, proof, publicInputs);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Range Proofs (Bulletproofs)
|
||||
|
||||
```solidity
|
||||
contract ConfidentialToken {
|
||||
using ZKLib for *;
|
||||
|
||||
function verifyConfidentialTransfer(
|
||||
bytes calldata senderCommitment,
|
||||
bytes calldata recipientCommitment,
|
||||
bytes calldata rangeProofSender,
|
||||
bytes calldata rangeProofRecipient
|
||||
) external view returns (bool) {
|
||||
// Verify both amounts are in valid range (64-bit)
|
||||
require(ZKLib.verifyRange(senderCommitment, rangeProofSender, 64), "Invalid sender range");
|
||||
require(ZKLib.verifyRange(recipientCommitment, rangeProofRecipient, 64), "Invalid recipient range");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ZK Rollup Integration
|
||||
|
||||
```solidity
|
||||
contract L2Settlement {
|
||||
using ZKLib for *;
|
||||
|
||||
bytes32 public rollupId;
|
||||
bytes32 public stateRoot;
|
||||
|
||||
function settleBatch(RollupBatch calldata batch) external {
|
||||
require(ZKLib.verifyRollupBatch(rollupId, batch), "Invalid batch proof");
|
||||
require(batch.prevStateRoot == stateRoot, "State mismatch");
|
||||
stateRoot = batch.newStateRoot;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## GPU Acceleration
|
||||
|
||||
The ZK precompiles leverage GPU acceleration via Metal shaders for Apple Silicon:
|
||||
|
||||
### Accelerated Operations
|
||||
|
||||
| Operation | CPU Time | GPU Time | Speedup |
|
||||
|-----------|----------|----------|---------|
|
||||
| Groth16 Verify | 12ms | 1.5ms | 8x |
|
||||
| PLONK Verify | 18ms | 2ms | 9x |
|
||||
| KZG Verify | 3ms | 0.4ms | 7.5x |
|
||||
| MSM (256 pts) | 45ms | 3ms | 15x |
|
||||
| FFT (2^16) | 120ms | 8ms | 15x |
|
||||
|
||||
### Metal Shader Files
|
||||
|
||||
```
|
||||
luxcpp/crypto/src/metal/
|
||||
├── bn254.metal # BN254 curve operations (Pedersen, Groth16)
|
||||
├── kzg.metal # KZG polynomial commitments
|
||||
├── blake3.metal # Blake3 hash (Merkle trees)
|
||||
├── metal_zk.h # C++ header
|
||||
└── metal_zk.mm # Objective-C++ implementation
|
||||
```
|
||||
|
||||
## Proof Systems
|
||||
|
||||
### Groth16
|
||||
|
||||
- **Verification**: Constant size (3 G1 + 1 G2)
|
||||
- **Trusted Setup**: Required (circuit-specific)
|
||||
- **Use Cases**: Token transfers, DeFi, identity
|
||||
|
||||
```solidity
|
||||
struct Groth16Proof {
|
||||
uint256[2] a; // G1 point
|
||||
uint256[2][2] b; // G2 point
|
||||
uint256[2] c; // G1 point
|
||||
}
|
||||
```
|
||||
|
||||
### PLONK
|
||||
|
||||
- **Verification**: Larger proofs (~1KB)
|
||||
- **Trusted Setup**: Universal (one-time)
|
||||
- **Use Cases**: General computation, rollups
|
||||
|
||||
### Halo2
|
||||
|
||||
- **Verification**: Recursive composition
|
||||
- **Trusted Setup**: None required
|
||||
- **Use Cases**: Incremental verification, IVC
|
||||
|
||||
## Privacy Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ PRIVACY POOL ARCHITECTURE │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ DEPOSIT WITHDRAW │
|
||||
│ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Generate │ │ Generate │ │
|
||||
│ │ Commitment │ │ Nullifier │ │
|
||||
│ │ C = H(v,r) │ │ N = H(sk) │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Deposit │───>│ Merkle │<───│ ZK Proof │ │
|
||||
│ │ Token │ │ Tree │ │ Verify + │ │
|
||||
│ └─────────────┘ └──────┬──────┘ │ Withdraw │ │
|
||||
│ │ └─────────────┘ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────┐ │
|
||||
│ │ Commitment │ │
|
||||
│ │ Pool │ │
|
||||
│ └─────────────┘ │
|
||||
│ │
|
||||
│ Proof verifies: │
|
||||
│ 1. Commitment exists in Merkle tree │
|
||||
│ 2. Nullifier correctly derived from secret │
|
||||
│ 3. Output commitment correctly formed │
|
||||
│ 4. No double-spending (nullifier not in spent set) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Rollup Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ZK ROLLUP ARCHITECTURE │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ L2 SEQUENCER L1 VERIFIER │
|
||||
│ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Batch │ │ Verify │ │
|
||||
│ │ Transactions│ │ ZK Proof │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Execute │───>│ Generate │───>│ Update │ │
|
||||
│ │ & Compute │ │ ZK Proof │ │ State Root │ │
|
||||
│ │ New State │ │ │ │ │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
│ │
|
||||
│ Batch contains: │
|
||||
│ - Previous state root │
|
||||
│ - New state root │
|
||||
│ - Transaction count │
|
||||
│ - Validity proof (Groth16/PLONK/Halo2) │
|
||||
│ - L1 batch number │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Post-Quantum Status
|
||||
|
||||
| Precompile | PQ-Safe | Notes |
|
||||
|------------|---------|-------|
|
||||
| Groth16 | ❌ | Discrete log on BN254 |
|
||||
| PLONK | ❌ | Discrete log on BN254 |
|
||||
| KZG | ❌ | Pairing-based |
|
||||
| Pedersen | ❌ | Elliptic curve DL |
|
||||
| Poseidon2 | ✅ | Hash-based |
|
||||
| Bulletproofs | ❌ | Discrete log |
|
||||
|
||||
For post-quantum security, use:
|
||||
- **Poseidon2** (`0x0501`) for commitments
|
||||
- **ML-DSA** (`0x0300`) for signatures
|
||||
- **Corona** for threshold signatures
|
||||
|
||||
### Trusted Setup
|
||||
|
||||
| System | Setup Type | Trust Assumption |
|
||||
|--------|------------|------------------|
|
||||
| Groth16 | Circuit-specific | Ceremony participants |
|
||||
| PLONK | Universal | Single ceremony |
|
||||
| KZG | Universal | Powers of tau ceremony |
|
||||
| Halo2 | None | Cryptographic assumptions |
|
||||
|
||||
## Integration with Lux Privacy Layer
|
||||
|
||||
The ZK precompiles integrate with the Z-Chain privacy layer:
|
||||
|
||||
1. **Shielded Transactions**: Use privacy pools for confidential transfers
|
||||
2. **Private DeFi**: Range proofs for confidential AMM operations
|
||||
3. **ZK Rollups**: Native L2 scaling with validity proofs
|
||||
4. **Cross-Chain Privacy**: Warp messaging with ZK attestations
|
||||
|
||||
## Files
|
||||
|
||||
```
|
||||
zk/
|
||||
├── commitment.go # Commitment utilities
|
||||
├── commitment_test.go # Commitment tests
|
||||
├── IZK.sol # Solidity interfaces
|
||||
├── module.go # Module registration
|
||||
├── pedersen.go # Pedersen commitments
|
||||
├── poseidon.go # Poseidon2 hash
|
||||
├── README.md # This file
|
||||
├── stark.go # STARK support
|
||||
├── types.go # Type definitions
|
||||
├── verifier.go # Main verifier
|
||||
└── verifier_test.go # Verifier tests
|
||||
```
|
||||
|
||||
## Related Precompiles
|
||||
|
||||
- **Blake3** (`0x0504`): Fast hashing for Merkle trees
|
||||
- **KZG4844** (`0x031D`): EIP-4844 blob commitments
|
||||
- **FHE** (`0x0200`): Homomorphic encryption
|
||||
- **Warp** (`0x0008`): Cross-chain messaging
|
||||
|
||||
## References
|
||||
|
||||
- [Groth16 Paper](https://eprint.iacr.org/2016/260)
|
||||
- [PLONK Paper](https://eprint.iacr.org/2019/953)
|
||||
- [Halo2 Book](https://zcash.github.io/halo2/)
|
||||
- [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844)
|
||||
- [Bulletproofs](https://eprint.iacr.org/2017/1066)
|
||||
Reference in New Issue
Block a user