mirror of
https://github.com/luxfi/precompile.git
synced 2026-07-27 03:33:45 +00:00
Public permissionless launch policy: enable basically every precompile for builder convenience, ESPECIALLY wallet-curve VERIFY so users sign natively on Lux from other chains (ed25519=Solana, sr25519=Polkadot, secp256r1=WebAuthn, secp256k1/ecrecover=Ethereum). Disable ONLY actual security risks. Lux's own consensus and identity stay PQ (quasar/p3q) — enforced in the consensus layer, never by refusing an EVM verifier a dapp asked for. Two layers, decomplected: - builder EVM precompile surface : enable-all-verify (this change) - chain consensus / finality : PQ-strict (consensus module, untouched) Removed the RefuseUnderStrictPQ gate from 17 verify-only / key-safe custom precompiles: ed25519, sr25519, secp256r1, bls12381 (EIP-2537, x7 ops), kzg4844 (EIP-4844), blake3, poseidon, pedersen, babyjubjub, pasta, ring, vrf, hpke, curve25519, x25519, cggmp21, frost, and the classical SNARK verifiers in zk (Groth16/PLONK/Halo2/KZG/IPA/range/batch/commitment). zk fflonk (0x03) stays DISABLED — but on its OWN forge-bug mechanism (ErrFflonkDisabled, returned at dispatch), NOT strict-PQ: verifyFflonk has a nil-vk soundness hole that forges any statement. Security disable, fully PQ-independent. The RefuseUnderStrictPQ helper + ErrClassicalForbiddenInPQ + StrictPQReporter had zero remaining code callers (evm uses a local structural interface) — deleted contract/strict_pq.go and its test. Rewrote zk's gate test to assert the new policy (classical ops enabled, fflonk disabled). Removed the now- orphaned isPedersenCommitment; fixed stale comments referencing deleted symbols. Build: full module green. Tests: contract + zk + all 17 edited packages pass. NOTE: the STANDARD eth precompiles (ecrecover, p256Verify, sha256, ripemd160, blake2f, bls12381, kzg) are still refused by LuxStrictPQ() in the evm plugin — a follow-up commit flips that to Permissive so ecrecover (every Ethereum dapp) works at launch.
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 signature0x0000...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
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)
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
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
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
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
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:
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:
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
- ECDSA: secp256k1 curve (Bitcoin/Ethereum)
- EIP-191: Signed data standard