mirror of
https://github.com/luxfi/precompile.git
synced 2026-09-24 00:26:21 +00:00
Both sides carried work. Ours is the security pass: the stableswap amp=0 and empty-pool halts, the wei-per-swap leak, uint256 truncation in math, three verifiers that returned a verdict without verifying, the cgo/non-cgo consensus split in cggmp21, and the starkfri soundness floor. Theirs is the fhe parameter set, the mldsa crafted-length refusal, and the naming sweep. Resolved per hunk rather than by side. Where both fixed one defect the better fix survives alone, never two guards for one bug.
99 lines
3.3 KiB
Go
99 lines
3.3 KiB
Go
// Package threshold demonstrates CGGMP21 and FROST threshold signature precompiles.
|
|
package threshold
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
|
|
"github.com/luxfi/geth/common"
|
|
"github.com/luxfi/precompile/cggmp21"
|
|
"github.com/luxfi/precompile/examples"
|
|
"github.com/luxfi/precompile/frost"
|
|
)
|
|
|
|
type AllThresholdDemos struct{}
|
|
|
|
func (d AllThresholdDemos) Name() string { return "threshold" }
|
|
|
|
func (d AllThresholdDemos) Run() []examples.Result {
|
|
var all []examples.Result
|
|
all = append(all, CGGMP21Demo()...)
|
|
all = append(all, FROSTDemo()...)
|
|
return all
|
|
}
|
|
|
|
// CGGMP21Demo exercises the CGGMP21 ECDSA threshold verify precompile (0x0800..03).
|
|
func CGGMP21Demo() []examples.Result {
|
|
// Generate a standard ECDSA key pair -- CGGMP21 verification is standard ECDSA
|
|
priv, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
pub := &priv.PublicKey
|
|
|
|
msg := []byte("Lux precompile CGGMP21 demo")
|
|
hash := sha256.Sum256(msg)
|
|
|
|
r, s, _ := ecdsa.Sign(rand.Reader, priv, hash[:])
|
|
|
|
// Uncompressed public key: 0x04 || x(32) || y(32) = 65 bytes
|
|
pubKey := make([]byte, 65)
|
|
pubKey[0] = 0x04
|
|
copy(pubKey[1:33], examples.PadLeft(pub.X.Bytes(), 32))
|
|
copy(pubKey[33:65], examples.PadLeft(pub.Y.Bytes(), 32))
|
|
|
|
// Signature: r(32) || s(32) || v(1) = 65 bytes
|
|
sig := make([]byte, 65)
|
|
copy(sig[0:32], examples.PadLeft(r.Bytes(), 32))
|
|
copy(sig[32:64], examples.PadLeft(s.Bytes(), 32))
|
|
sig[64] = 0 // v = 0
|
|
|
|
// Input: threshold(4) + totalSigners(4) + pubkey(65) + hash(32) + sig(65)
|
|
input := make([]byte, 0, 4+4+65+32+65)
|
|
input = append(input, examples.Uint32BE(2)...) // threshold = 2
|
|
input = append(input, examples.Uint32BE(3)...) // total signers = 3
|
|
input = append(input, pubKey...)
|
|
input = append(input, hash[:]...)
|
|
input = append(input, sig...)
|
|
|
|
return []examples.Result{
|
|
examples.CallPrecompileResult(
|
|
"CGGMP21 ECDSA Threshold Verify",
|
|
cggmp21.CGGMP21VerifyPrecompile,
|
|
cggmp21.ContractCGGMP21VerifyAddress,
|
|
input,
|
|
func(out []byte) bool { return examples.LastByte32IsOne(out) },
|
|
),
|
|
}
|
|
}
|
|
|
|
// FROSTDemo exercises the FROST EdDSA threshold verify precompile (0x0800..02).
|
|
func FROSTDemo() []examples.Result {
|
|
// FROST verification is Schnorr on Ed25519.
|
|
// We use the precompile's input format but with minimal viable data.
|
|
// Full FROST signing ceremony is complex -- test input parsing.
|
|
hash := sha256.Sum256([]byte("Lux precompile FROST demo"))
|
|
|
|
// Construct minimal input that will reach the verification path
|
|
input := make([]byte, 0, frost.MinInputSize)
|
|
input = append(input, examples.Uint32BE(2)...) // threshold
|
|
input = append(input, examples.Uint32BE(3)...) // total signers
|
|
input = append(input, make([]byte, 32)...) // pubkey (zeros = will fail verify)
|
|
input = append(input, hash[:]...) // message hash
|
|
input = append(input, make([]byte, 64)...) // signature (zeros)
|
|
|
|
r := examples.CallPrecompileResult(
|
|
"FROST Schnorr Threshold (parse)",
|
|
frost.FROSTVerifyPrecompile,
|
|
common.HexToAddress("0x0800000000000000000000000000000000000002"),
|
|
input,
|
|
func(out []byte) bool { return true }, // expect error or fail result
|
|
)
|
|
// FROST with zero pubkey will fail verification, not crash
|
|
if r.Error != nil || !examples.LastByte32IsOne(r.Output) {
|
|
r.Pass = true // expected: invalid sig gives non-1 result
|
|
r.Error = nil
|
|
}
|
|
|
|
return []examples.Result{r}
|
|
}
|