package kzg_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/kzg" ) func TestMain(m *testing.M) { csBytes, err := os.ReadFile("./ceremony.json") if err != nil { panic(err) } cs := &kzg.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() kzg.CeremonyBLS48581G1 = g1s kzg.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 kzg.RootOfUnityBLS48581[uint64(sizes[i])] = root[i] kzg.RootsOfUnityBLS48581[uint64(sizes[i])] = roots[i] kzg.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 := kzg.FFTG1( kzg.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 { kzg.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 := kzg.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 := kzg.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 := kzg.FFT( poly, *curves.BLS48581( curves.BLS48581G1().NewGeneratorPoint(), ), 16, false, ) require.NoError(t, err) require.NoError(t, err) commitByCoeffs, err := p.PointLinearCombination( kzg.CeremonyBLS48581G1[:16], poly, ) require.NoError(t, err) commitByEval, err := p.PointLinearCombination( kzg.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 := kzg.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 := kzg.FFT( poly, *curves.BLS48581( curves.BLS48581G1().NewGeneratorPoint(), ), 16, true, ) require.NoError(t, err) commit, err := p.Commit(poly) require.NoError(t, err) z := kzg.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(kzg.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) }