ceremonyclient/node/crypto/kzg_test.go
Cassandra Heart 2e2a1e4789
v1.2.0 (#31)
2024-01-03 01:31:42 -06:00

359 lines
12 KiB
Go

package crypto_test
import (
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"os"
"sync"
"testing"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/sha3"
"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/core/curves"
"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/core/curves/native/bls48581"
"source.quilibrium.com/quilibrium/monorepo/node/crypto"
)
func TestMain(m *testing.M) {
csBytes, err := os.ReadFile("../ceremony.json")
if err != nil {
panic(err)
}
cs := &crypto.CeremonyState{}
if err := json.Unmarshal(csBytes, cs); err != nil {
panic(err)
}
g1s := make([]curves.PairingPoint, 16)
g2s := make([]curves.PairingPoint, 2)
g1ffts := make([]curves.PairingPoint, 16)
wg := sync.WaitGroup{}
wg.Add(16)
for i := 0; i < 16; i++ {
i := i
go func() {
b, err := hex.DecodeString(cs.PowersOfTau.G1Affines[i][2:])
if err != nil {
panic(err)
}
g1, err := curves.BLS48581G1().NewGeneratorPoint().FromAffineCompressed(b)
if err != nil {
panic(err)
}
g1s[i] = g1.(curves.PairingPoint)
f, err := hex.DecodeString(cs.PowersOfTau.G1FFT[i][2:])
if err != nil {
panic(err)
}
g1fft, err := curves.BLS48581G1().NewGeneratorPoint().FromAffineCompressed(f)
if err != nil {
panic(err)
}
g1ffts[i] = g1fft.(curves.PairingPoint)
if i < 2 {
b, err := hex.DecodeString(cs.PowersOfTau.G2Affines[i][2:])
if err != nil {
panic(err)
}
g2, err := curves.BLS48581G2().NewGeneratorPoint().FromAffineCompressed(
b,
)
if err != nil {
panic(err)
}
g2s[i] = g2.(curves.PairingPoint)
}
wg.Done()
}()
}
wg.Wait()
crypto.CeremonyBLS48581G1 = g1s
crypto.CeremonyBLS48581G2 = g2s
// Post-ceremony, precompute everything and put it in the finalized ceremony
// state
modulus := make([]byte, 73)
bls48581.NewBIGints(bls48581.CURVE_Order, nil).ToBytes(modulus)
q := new(big.Int).SetBytes(modulus)
sizes := []int64{16}
wg.Add(len(sizes))
root := make([]curves.PairingScalar, 1)
roots := make([][]curves.PairingScalar, 1)
reverseRoots := make([][]curves.PairingScalar, 1)
ffts := make([][]curves.PairingPoint, 1)
for idx, i := range sizes {
i := i
idx := idx
go func() {
exp := new(big.Int).Quo(
new(big.Int).Sub(q, big.NewInt(1)),
big.NewInt(i),
)
rootOfUnity := new(big.Int).Exp(big.NewInt(int64(37)), exp, q)
roots[idx] = make([]curves.PairingScalar, i+1)
reverseRoots[idx] = make([]curves.PairingScalar, i+1)
wg2 := sync.WaitGroup{}
wg2.Add(int(i))
for j := int64(0); j < i; j++ {
j := j
go func() {
rev := big.NewInt(int64(j))
r := new(big.Int).Exp(
rootOfUnity,
rev,
q,
)
scalar, _ := (&curves.ScalarBls48581{}).SetBigInt(r)
if rev.Cmp(big.NewInt(1)) == 0 {
root[idx] = scalar.(curves.PairingScalar)
}
roots[idx][j] = scalar.(curves.PairingScalar)
reverseRoots[idx][i-j] = roots[idx][j]
wg2.Done()
}()
}
wg2.Wait()
roots[idx][i] = roots[idx][0]
reverseRoots[idx][0] = reverseRoots[idx][i]
wg.Done()
}()
}
wg.Wait()
wg.Add(len(sizes))
for i := range root {
i := i
crypto.RootOfUnityBLS48581[uint64(sizes[i])] = root[i]
crypto.RootsOfUnityBLS48581[uint64(sizes[i])] = roots[i]
crypto.ReverseRootsOfUnityBLS48581[uint64(sizes[i])] = reverseRoots[i]
go func() {
// We precomputed 65536, others are cheap and will be fully precomputed
// post-ceremony
if sizes[i] < 65536 {
fftG1, err := crypto.FFTG1(
crypto.CeremonyBLS48581G1[:sizes[i]],
*curves.BLS48581(
curves.BLS48581G1().NewGeneratorPoint(),
),
uint64(sizes[i]),
true,
)
if err != nil {
panic(err)
}
ffts[i] = fftG1
} else {
ffts[i] = g1ffts
}
wg.Done()
}()
}
wg.Wait()
for i := range root {
crypto.FFTBLS48581[uint64(sizes[i])] = ffts[i]
}
code := m.Run()
os.Exit(code)
}
func TestKzgBytesToPoly(t *testing.T) {
modulus := make([]byte, 73)
bls48581.NewBIGints(bls48581.CURVE_Order, nil).ToBytes(modulus)
q := new(big.Int).SetBytes(modulus)
p := crypto.NewKZGProver(curves.BLS48581(curves.BLS48581G1().Point), sha3.New256, q)
poly, err := p.BytesToPolynomial([]byte(
"Did you ever hear the tragedy of Darth Plagueis The Wise? I thought not." +
" It's not a story the Jedi would tell you. It's a Sith legend. Darth " +
"Plagueis was a Dark Lord of the Sith, so powerful and so wise he could " +
"use the Force to influence the midichlorians to create life… He had such" +
" a knowledge of the dark side that he could even keep the ones he cared " +
"about from dying. The dark side of the Force is a pathway to many " +
"abilities some consider to be unnatural. He became so powerful… the only" +
" thing he was afraid of was losing his power, which eventually, of " +
"course, he did. Unfortunately, he taught his apprentice everything he " +
"knew, then his apprentice killed him in his sleep. Ironic. He could " +
"save others from death, but not himself."))
require.NoError(t, err)
t1, _ := hex.DecodeString("00000000000000000044696420796f7520657665722068656172207468652074726167656479206f6620446172746820506c6167756569732054686520576973653f20492074686f75")
t2, _ := hex.DecodeString("000000000000000000676874206e6f742e2049742773206e6f7420612073746f727920746865204a65646920776f756c642074656c6c20796f752e204974277320612053697468206c")
t3, _ := hex.DecodeString("0000000000000000006567656e642e20446172746820506c616775656973207761732061204461726b204c6f7264206f662074686520536974682c20736f20706f77657266756c2061")
t4, _ := hex.DecodeString("0000000000000000006e6420736f207769736520686520636f756c64207573652074686520466f72636520746f20696e666c75656e636520746865206d69646963686c6f7269616e73")
t5, _ := hex.DecodeString("00000000000000000020746f20637265617465206c696665e280a62048652068616420737563682061206b6e6f776c65646765206f6620746865206461726b20736964652074686174")
t6, _ := hex.DecodeString("00000000000000000020686520636f756c64206576656e206b65657020746865206f6e65732068652063617265642061626f75742066726f6d206479696e672e20546865206461726b")
t7, _ := hex.DecodeString("0000000000000000002073696465206f662074686520466f7263652069732061207061746877617920746f206d616e79206162696c697469657320736f6d6520636f6e736964657220")
t8, _ := hex.DecodeString("000000000000000000746f20626520756e6e61747572616c2e20486520626563616d6520736f20706f77657266756ce280a620746865206f6e6c79207468696e672068652077617320")
t9, _ := hex.DecodeString("000000000000000000616672616964206f6620776173206c6f73696e672068697320706f7765722c207768696368206576656e7475616c6c792c206f6620636f757273652c20686520")
t10, _ := hex.DecodeString("0000000000000000006469642e20556e666f7274756e6174656c792c20686520746175676874206869732061707072656e746963652065766572797468696e67206865206b6e65772c")
t11, _ := hex.DecodeString("000000000000000000207468656e206869732061707072656e74696365206b696c6c65642068696d20696e2068697320736c6565702e2049726f6e69632e20486520636f756c642073")
t12, _ := hex.DecodeString("00000000000000000000000000000000000000000000000000000000000000000000617665206f74686572732066726f6d2064656174682c20627574206e6f742068696d73656c662e")
target := [][]byte{t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12}
actual := [][]byte{}
for _, p := range poly {
actual = append(actual, p.Bytes())
fmt.Println(hex.EncodeToString(p.Bytes()))
}
require.Equal(t, target, actual)
}
func TestPolynomialCommitment(t *testing.T) {
modulus := make([]byte, 73)
bls48581.NewBIGints(bls48581.CURVE_Order, nil).ToBytes(modulus)
q := new(big.Int).SetBytes(modulus)
p := crypto.NewKZGProver(curves.BLS48581(curves.BLS48581G1().Point), sha3.New256, q)
poly, err := p.BytesToPolynomial([]byte(
"Did you ever hear the tragedy of Darth Plagueis The Wise? I thought not." +
" It's not a story the Jedi would tell you. It's a Sith legend. Darth " +
"Plagueis was a Dark Lord of the Sith, so powerful and so wise he could " +
"use the Force to influence the midichlorians to create life… He had such" +
" a knowledge of the dark side that he could even keep the ones he cared " +
"about from dying. The dark side of the Force is a pathway to many " +
"abilities some consider to be unnatural. He became so powerful… the only" +
" thing he was afraid of was losing his power, which eventually, of " +
"course, he did. Unfortunately, he taught his apprentice everything he " +
"knew, then his apprentice killed him in his sleep. Ironic. He could " +
"save others from death, but not himself."))
for i := len(poly); i < 16; i++ {
poly = append(poly, curves.BLS48581G1().NewScalar().(curves.PairingScalar))
}
require.NoError(t, err)
evalPoly, err := crypto.FFT(
poly,
*curves.BLS48581(
curves.BLS48581G1().NewGeneratorPoint(),
),
16,
false,
)
require.NoError(t, err)
require.NoError(t, err)
commitByCoeffs, err := p.PointLinearCombination(
crypto.CeremonyBLS48581G1[:16],
poly,
)
require.NoError(t, err)
commitByEval, err := p.PointLinearCombination(
crypto.FFTBLS48581[16],
evalPoly,
)
require.NoError(t, err)
fmt.Println(commitByCoeffs.ToAffineCompressed())
fmt.Println(commitByEval.ToAffineCompressed())
require.True(t, commitByCoeffs.Equal(commitByEval))
}
func TestKZGProof(t *testing.T) {
modulus := make([]byte, 73)
bls48581.NewBIGints(bls48581.CURVE_Order, nil).ToBytes(modulus)
q := new(big.Int).SetBytes(modulus)
p := crypto.NewKZGProver(curves.BLS48581(curves.BLS48581G1().Point), sha3.New256, q)
poly, err := p.BytesToPolynomial([]byte(
"Did you ever hear the tragedy of Darth Plagueis The Wise? I thought not." +
" It's not a story the Jedi would tell you. It's a Sith legend. Darth " +
"Plagueis was a Dark Lord of the Sith, so powerful and so wise he could " +
"use the Force to influence the midichlorians to create life… He had such" +
" a knowledge of the dark side that he could even keep the ones he cared " +
"about from dying. The dark side of the Force is a pathway to many " +
"abilities some consider to be unnatural. He became so powerful… the only" +
" thing he was afraid of was losing his power, which eventually, of " +
"course, he did. Unfortunately, he taught his apprentice everything he " +
"knew, then his apprentice killed him in his sleep. Ironic. He could " +
"save others from death, but not himself."))
require.NoError(t, err)
for i := len(poly); i < 16; i++ {
poly = append(poly, curves.BLS48581G1().NewScalar().(curves.PairingScalar))
}
evalPoly, err := crypto.FFT(
poly,
*curves.BLS48581(
curves.BLS48581G1().NewGeneratorPoint(),
),
16,
true,
)
require.NoError(t, err)
commit, err := p.Commit(poly)
require.NoError(t, err)
z := crypto.RootsOfUnityBLS48581[16][2]
require.NoError(t, err)
checky := evalPoly[len(poly)-1]
for i := len(evalPoly) - 2; i >= 0; i-- {
checky = checky.Mul(z).Add(evalPoly[i]).(curves.PairingScalar)
}
fmt.Printf("%+x\n", checky.Bytes())
divisors := make([]curves.PairingScalar, 2)
divisors[0] = (&curves.ScalarBls48581{}).Zero().Sub(z).(*curves.ScalarBls48581)
divisors[1] = (&curves.ScalarBls48581{}).One().(*curves.ScalarBls48581)
a := make([]curves.PairingScalar, len(evalPoly))
for i := 0; i < len(a); i++ {
a[i] = evalPoly[i].Clone().(*curves.ScalarBls48581)
}
// Adapted from Feist's amortized proofs:
aPos := len(a) - 1
bPos := len(divisors) - 1
diff := aPos - bPos
out := make([]curves.PairingScalar, diff+1, diff+1)
for diff >= 0 {
out[diff] = a[aPos].Div(divisors[bPos]).(*curves.ScalarBls48581)
for i := bPos; i >= 0; i-- {
a[diff+i] = a[diff+i].Sub(
out[diff].Mul(divisors[i]),
).(*curves.ScalarBls48581)
}
aPos -= 1
diff -= 1
}
proof, err := p.PointLinearCombination(crypto.CeremonyBLS48581G1[:15], out)
// proof, err := p.Prove(evalPoly, commit, z.(curves.PairingScalar))
require.NoError(t, err)
require.True(t, p.Verify(commit, z, checky, proof))
commitments, err := p.CommitAggregate(
[][]curves.PairingScalar{evalPoly},
)
require.NoError(t, err)
proof, commitment, err := p.ProveAggregate(
[][]curves.PairingScalar{evalPoly},
commitments,
)
require.NoError(t, err)
valid, err := p.VerifyAggregateProof(
[][]curves.PairingScalar{evalPoly},
commitments,
commitment,
proof,
)
require.False(t, proof.IsIdentity())
require.NoError(t, err)
require.True(t, valid)
}