Files
coreth/core/vm/contracts_falcon.go
zeekay 1d7cae0355 Add post-quantum cryptography precompiles and update crypto dependency
- Add post-quantum signature verification precompiles:
  - ML-DSA (FIPS 204) at address 0x0f
  - SLH-DSA (FIPS 205) at address 0x10
  - Falcon at address 0x11
  - ML-KEM key encapsulation at address 0x12

- Add api_lux.go with Lux-specific API extensions

- Add precompile infrastructure from SubnetEVM:
  - allowlist module
  - contract interfaces
  - precompile config and modules

- Update crypto dependency to v1.17.9 (with VerifySignature API)
- Remove local replace directives for CI compatibility
- Update import paths across 230+ files to use luxfi/crypto
2025-12-11 02:36:17 +00:00

170 lines
5.0 KiB
Go

// Copyright (C) 2025, Lux Industries Inc. All rights reserved.
// Post-quantum cryptography support - FALCON signature verification
package vm
import (
"crypto/sha256"
"errors"
"github.com/luxfi/geth/common"
)
const (
// FALCON-512 parameters
falcon512Degree = 512
falcon512Modulus = 12289
falcon512SaltLen = 40
falcon512PublicLen = 897 // Public key length in bytes
falcon512SigMaxLen = 690 // Maximum signature length
// Gas costs for FALCON operations
falconVerifyBaseGas = 1800000 // Base gas for FALCON verification (~1.8M gas)
falconRecoverBaseGas = 1900000 // Base gas for FALCON recovery (~1.9M gas)
dilithiumVerifyBaseGas = 6600000 // Base gas for Dilithium verification (~6.6M gas)
)
var (
// Precompile addresses for post-quantum signatures
falconVerifyAddress = common.HexToAddress("0x0000000000000000000000000000000000000100")
falconRecoverAddress = common.HexToAddress("0x0000000000000000000000000000000000000101")
dilithiumVerifyAddress = common.HexToAddress("0x0000000000000000000000000000000000000102")
)
// falconVerify implements FALCON-512 signature verification
type falconVerify struct{}
func (f *falconVerify) RequiredGas(input []byte) uint64 {
return falconVerifyBaseGas
}
func (f *falconVerify) Run(input []byte) ([]byte, error) {
// Input format:
// [32 bytes hash][40 bytes salt][variable sig s2][897 bytes public key]
if len(input) < 32+40+897 {
return nil, errors.New("invalid input length for FALCON verification")
}
hash := input[0:32]
salt := input[32:72]
// Find where signature ends and public key begins
// This is simplified - actual implementation would parse the signature format
pubKeyStart := len(input) - 897
if pubKeyStart <= 72 {
return nil, errors.New("invalid signature format")
}
sig := input[72:pubKeyStart]
pubKey := input[pubKeyStart:]
// Call the actual FALCON verification
// This would integrate with the Go FALCON library
valid, err := verifyFalcon512(hash, salt, sig, pubKey)
if err != nil {
return nil, err
}
if valid {
return common.LeftPadBytes([]byte{1}, 32), nil
}
return common.LeftPadBytes([]byte{0}, 32), nil
}
// falconRecover implements FALCON with recovery (EPERVIER variant)
type falconRecover struct{}
func (f *falconRecover) RequiredGas(input []byte) uint64 {
return falconRecoverBaseGas
}
func (f *falconRecover) Run(input []byte) ([]byte, error) {
// Input format similar to ecrecover:
// [32 bytes hash][40 bytes salt][variable sig]
if len(input) < 32+40 {
return nil, errors.New("invalid input length for FALCON recovery")
}
hash := input[0:32]
salt := input[32:72]
sig := input[72:]
// Recover the public key from signature
// This would integrate with the EPERVIER variant
pubKey, err := recoverFalconPublicKey(hash, salt, sig)
if err != nil {
return nil, err
}
// Convert public key to Ethereum address
// Hash the public key and take last 20 bytes
pubKeyHash := sha256.Sum256(pubKey)
addr := common.BytesToAddress(pubKeyHash[12:])
return common.LeftPadBytes(addr.Bytes(), 32), nil
}
// dilithiumVerify implements Dilithium signature verification
type dilithiumVerify struct{}
func (d *dilithiumVerify) RequiredGas(input []byte) uint64 {
return dilithiumVerifyBaseGas
}
func (d *dilithiumVerify) Run(input []byte) ([]byte, error) {
// Input format:
// [32 bytes message hash][dilithium signature][dilithium public key]
// Dilithium3 parameters
const (
dilithium3PubKeyLen = 1952
dilithium3SigLen = 3293
)
expectedLen := 32 + dilithium3SigLen + dilithium3PubKeyLen
if len(input) != expectedLen {
return nil, errors.New("invalid input length for Dilithium verification")
}
msgHash := input[0:32]
sig := input[32 : 32+dilithium3SigLen]
pubKey := input[32+dilithium3SigLen:]
// Call the actual Dilithium verification
valid, err := verifyDilithium3(msgHash, sig, pubKey)
if err != nil {
return nil, err
}
if valid {
return common.LeftPadBytes([]byte{1}, 32), nil
}
return common.LeftPadBytes([]byte{0}, 32), nil
}
// Stub functions - these would be implemented by integrating the actual FALCON/Dilithium libraries
func verifyFalcon512(hash, salt, sig, pubKey []byte) (bool, error) {
// TODO: Integrate with Go FALCON library
// This would call the actual FALCON verification algorithm
return false, errors.New("FALCON verification not yet implemented")
}
func recoverFalconPublicKey(hash, salt, sig []byte) ([]byte, error) {
// TODO: Integrate with EPERVIER variant for public key recovery
return nil, errors.New("FALCON recovery not yet implemented")
}
func verifyDilithium3(msgHash, sig, pubKey []byte) (bool, error) {
// TODO: Integrate with Go Dilithium library
return false, errors.New("Dilithium verification not yet implemented")
}
// AddPostQuantumPrecompiles adds the post-quantum signature precompiles to the given map
func AddPostQuantumPrecompiles(contracts PrecompiledContracts) {
contracts[falconVerifyAddress] = &falconVerify{}
contracts[falconRecoverAddress] = &falconRecover{}
contracts[dilithiumVerifyAddress] = &dilithiumVerify{}
}