Browse Source

DHEBP Initial commit

master
Captain 1 year ago
commit
6d9f023c67
100 changed files with 17427 additions and 0 deletions
  1. +61
    -0
      Readme.md
  2. +373
    -0
      blockchain.go
  3. +446
    -0
      fieldvector.go
  4. +145
    -0
      generatorparams.go
  5. +161
    -0
      generatorvector.go
  6. +168
    -0
      innerproduct.go
  7. +123
    -0
      main.go
  8. +75
    -0
      polynomial.go
  9. +803
    -0
      proof_generate.go
  10. +505
    -0
      proof_verify.go
  11. +16
    -0
      src/github.com/clearmatics/bn256/.editorconfig
  12. +26
    -0
      src/github.com/clearmatics/bn256/.github/CONTRIBUTING.md
  13. +22
    -0
      src/github.com/clearmatics/bn256/.github/ISSUE_TEMPLATE.md
  14. +10
    -0
      src/github.com/clearmatics/bn256/.github/PULL_REQUEST_TEMPLATE.md
  15. +3
    -0
      src/github.com/clearmatics/bn256/.gitignore
  16. +20
    -0
      src/github.com/clearmatics/bn256/.travis.yml
  17. +47
    -0
      src/github.com/clearmatics/bn256/CODE_OF_CONDUCT.md
  18. +27
    -0
      src/github.com/clearmatics/bn256/LICENSE
  19. +34
    -0
      src/github.com/clearmatics/bn256/Makefile
  20. +33
    -0
      src/github.com/clearmatics/bn256/README.md
  21. +481
    -0
      src/github.com/clearmatics/bn256/bn256.go
  22. +116
    -0
      src/github.com/clearmatics/bn256/bn256_test.go
  23. +59
    -0
      src/github.com/clearmatics/bn256/constants.go
  24. +238
    -0
      src/github.com/clearmatics/bn256/curve.go
  25. +51
    -0
      src/github.com/clearmatics/bn256/example_test.go
  26. +81
    -0
      src/github.com/clearmatics/bn256/gfp.go
  27. +160
    -0
      src/github.com/clearmatics/bn256/gfp12.go
  28. +156
    -0
      src/github.com/clearmatics/bn256/gfp2.go
  29. +213
    -0
      src/github.com/clearmatics/bn256/gfp6.go
  30. +129
    -0
      src/github.com/clearmatics/bn256/gfp_amd64.s
  31. +113
    -0
      src/github.com/clearmatics/bn256/gfp_arm64.s
  32. +25
    -0
      src/github.com/clearmatics/bn256/gfp_decl.go
  33. +173
    -0
      src/github.com/clearmatics/bn256/gfp_generic.go
  34. +60
    -0
      src/github.com/clearmatics/bn256/gfp_test.go
  35. +8
    -0
      src/github.com/clearmatics/bn256/go.mod
  36. +9
    -0
      src/github.com/clearmatics/bn256/go.sum
  37. +115
    -0
      src/github.com/clearmatics/bn256/lattice.go
  38. +29
    -0
      src/github.com/clearmatics/bn256/lattice_test.go
  39. +71
    -0
      src/github.com/clearmatics/bn256/main_test.go
  40. +181
    -0
      src/github.com/clearmatics/bn256/mul_amd64.h
  41. +133
    -0
      src/github.com/clearmatics/bn256/mul_arm64.h
  42. +112
    -0
      src/github.com/clearmatics/bn256/mul_bmi2_amd64.h
  43. +271
    -0
      src/github.com/clearmatics/bn256/optate.go
  44. +204
    -0
      src/github.com/clearmatics/bn256/twist.go
  45. +201
    -0
      src/github.com/go-logr/logr/LICENSE
  46. +181
    -0
      src/github.com/go-logr/logr/README.md
  47. +90
    -0
      src/github.com/go-logr/logr/examples/tab_logger.go
  48. +165
    -0
      src/github.com/go-logr/logr/examples/usage_example.go
  49. +3
    -0
      src/github.com/go-logr/logr/go.mod
  50. +178
    -0
      src/github.com/go-logr/logr/logr.go
  51. +48
    -0
      src/github.com/go-logr/logr/testing/null.go
  52. +55
    -0
      src/github.com/go-logr/logr/testing/test.go
  53. +17
    -0
      src/github.com/kubernetes/klog/.github/ISSUE_TEMPLATE/bug_report.md
  54. +14
    -0
      src/github.com/kubernetes/klog/.github/ISSUE_TEMPLATE/feature_request.md
  55. +25
    -0
      src/github.com/kubernetes/klog/.github/PULL_REQUEST_TEMPLATE.md
  56. +56
    -0
      src/github.com/kubernetes/klog/.github/workflows/test.yml
  57. +17
    -0
      src/github.com/kubernetes/klog/.gitignore
  58. +22
    -0
      src/github.com/kubernetes/klog/CONTRIBUTING.md
  59. +191
    -0
      src/github.com/kubernetes/klog/LICENSE
  60. +19
    -0
      src/github.com/kubernetes/klog/OWNERS
  61. +99
    -0
      src/github.com/kubernetes/klog/README.md
  62. +9
    -0
      src/github.com/kubernetes/klog/RELEASE.md
  63. +20
    -0
      src/github.com/kubernetes/klog/SECURITY_CONTACTS
  64. +3
    -0
      src/github.com/kubernetes/klog/code-of-conduct.md
  65. +30
    -0
      src/github.com/kubernetes/klog/examples/coexist_glog/coexist_glog.go
  66. +73
    -0
      src/github.com/kubernetes/klog/examples/coexist_klog_v1_and_v2/coexist_klog_v1_and_v2.go
  67. +8
    -0
      src/github.com/kubernetes/klog/examples/coexist_klog_v1_and_v2/go.mod
  68. +8
    -0
      src/github.com/kubernetes/klog/examples/go.mod
  69. +6
    -0
      src/github.com/kubernetes/klog/examples/go.sum
  70. +28
    -0
      src/github.com/kubernetes/klog/examples/klogr/main.go
  71. +18
    -0
      src/github.com/kubernetes/klog/examples/log_file/usage_log_file.go
  72. +22
    -0
      src/github.com/kubernetes/klog/examples/set_output/usage_set_output.go
  73. +5
    -0
      src/github.com/kubernetes/klog/go.mod
  74. +2
    -0
      src/github.com/kubernetes/klog/go.sum
  75. +125
    -0
      src/github.com/kubernetes/klog/hack/verify-apidiff.sh
  76. +46
    -0
      src/github.com/kubernetes/klog/integration_tests/internal/main.go
  77. +349
    -0
      src/github.com/kubernetes/klog/integration_tests/klog_test.go
  78. +1525
    -0
      src/github.com/kubernetes/klog/klog.go
  79. +164
    -0
      src/github.com/kubernetes/klog/klog_file.go
  80. +1025
    -0
      src/github.com/kubernetes/klog/klog_test.go
  81. +8
    -0
      src/github.com/kubernetes/klog/klogr/README.md
  82. +201
    -0
      src/github.com/kubernetes/klog/klogr/klogr.go
  83. +132
    -0
      src/github.com/kubernetes/klog/klogr/klogr_test.go
  84. +10
    -0
      src/golang.org/x/crypto/.gitattributes
  85. +2
    -0
      src/golang.org/x/crypto/.gitignore
  86. +3
    -0
      src/golang.org/x/crypto/AUTHORS
  87. +26
    -0
      src/golang.org/x/crypto/CONTRIBUTING.md
  88. +3
    -0
      src/golang.org/x/crypto/CONTRIBUTORS
  89. +27
    -0
      src/golang.org/x/crypto/LICENSE
  90. +22
    -0
      src/golang.org/x/crypto/PATENTS
  91. +21
    -0
      src/golang.org/x/crypto/README.md
  92. +1098
    -0
      src/golang.org/x/crypto/acme/acme.go
  93. +1471
    -0
      src/golang.org/x/crypto/acme/acme_test.go
  94. +1249
    -0
      src/golang.org/x/crypto/acme/autocert/autocert.go
  95. +1232
    -0
      src/golang.org/x/crypto/acme/autocert/autocert_test.go
  96. +136
    -0
      src/golang.org/x/crypto/acme/autocert/cache.go
  97. +67
    -0
      src/golang.org/x/crypto/acme/autocert/cache_test.go
  98. +34
    -0
      src/golang.org/x/crypto/acme/autocert/example_test.go
  99. +552
    -0
      src/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go
  100. +0
    -0
      src/golang.org/x/crypto/acme/autocert/listener.go

+ 61
- 0
Readme.md View File

@@ -0,0 +1,61 @@
DHEBP(DERO Homomorphic Encryption Blockchain Protocol)
=======================================================

** NB: DERO ALPHA code to demonstrate FHE blockchain transactions.

Transaction Details:
===================
Each transaction consists of 2 parts,
1) Statement which contains ring members keys, commitments, encrypted balances ( this grows linear ) basicaly 4 curve points per ring member.
2) Proof which grows log in ring members for Eg :
8 ring size proof is only 1997 bytes
512 ring size proof is only 3965 bytes

Ring Size, Tx Size data
=========================
Ring size, tx size (fixed) in bytes irrespective of balance

2 1669 bytes ( 328 byte statement, 1341 bytes proof )
4 2261 bytes ( 592 byte statement, 1669 bytes proof )
8 3117 bytes ( 1120 byte statement, 1997 bytes proof )
16 4501 bytes ( 2176 byte statement, 2325 bytes proof )
32 6941 bytes ( 4288 byte statement, 2653 bytes proof )
64 11493 bytes ( 8512 byte statement, 2981 bytes proof )
128 20269 bytes ( 16960 byte statement, 3309 bytes proof )
256 37493 bytes ( 33856 byte statement, 3637 bytes proof )
512 71613 bytes ( 67648 byte statement, 3965 bytes proof )


Compile guide
==============

1) switch to directory containing this readme file
2) export GOPATH=`pwd`
3) go run *.go

Note: Developed and tested on linux go version 1.12.7

Output Sample
========================================================
Creating Transaction
I0706 16:05:28.258801 93136 main.go:101] Transferring 10 from sender to receiver (ring size 8) tx size 3117 bytes
I0706 16:05:28.258810 93136 main.go:102] Total tx size 3117 bytes ( 1120 byte statement, 1997 bytes proof )
I0706 16:05:28.341387 93136 main.go:107] Transfer successful
I0706 16:05:28.343528 93136 main.go:116] Sender Balance 150 - 10 = 140
I0706 16:05:28.343533 93136 main.go:117] Receiver Balance 0 + 10 = 10
I0706 16:05:28.345662 93136 main.go:98]

Creating Transaction
I0706 16:05:28.568605 93136 main.go:101] Transferring 90 from sender to receiver (ring size 16) tx size 4501 bytes
I0706 16:05:28.568614 93136 main.go:102] Total tx size 4501 bytes ( 2176 byte statement, 2325 bytes proof )
I0706 16:05:28.680647 93136 main.go:107] Transfer successful
I0706 16:05:28.682788 93136 main.go:116] Sender Balance 140 - 90 = 50
I0706 16:05:28.682792 93136 main.go:117] Receiver Balance 10 + 90 = 100
I0706 16:05:28.682796 93136 main.go:74]
Successful






+ 373
- 0
blockchain.go View File

@@ -0,0 +1,373 @@
package main

import "fmt"
import "math/big"
import "crypto/rand"

import mrand "math/rand"
import "encoding/binary"

//import "encoding/hex"

import "github.com/kubernetes/klog"
import "github.com/clearmatics/bn256"

type KeyPair struct {
x *big.Int
y *bn256.G1
}

func (k KeyPair) String() string {
x := fmt.Sprintf("x (secretkey): %x\n", k.x)
x += fmt.Sprintf("y: %s", k.y)
return x
}

var G *bn256.G1 = NewGeneratorParams(1).G // global generator point

// ToDo encode the balance so only the receiver can decode transferred amount easily
type Statement struct {
CLn []*bn256.G1
CRn []*bn256.G1
Publickeylist []*bn256.G1 // Todo these can be skipped and collected back later on from the chain, this will save ringsize * POINTSIZE bytes
C []*bn256.G1 // commitments
D *bn256.G1

roothash *big.Int // note roothash contains the merkle root hash of chain, when it was build

}

type Witness struct {
SecretKey *big.Int
R *big.Int
TransferAmount uint32 // total value being transferred
Balance uint32 // whatever is the the amount left after transfer
index []int // index of sender in the public key list

}

type Transaction struct {
statement *Statement
proof *Proof
}

func RandomScalar() *big.Int {
a, _ := rand.Int(rand.Reader, bn256.Order)
return a
}

// this will return fixed random scalar
func RandomScalarFixed() *big.Int {
return RandomScalar()
}

func GenerateKeyPair() *KeyPair {
var k KeyPair
var y bn256.G1
k.x = RandomScalar()
k.y = &y
y.ScalarMult(G, k.x)

return &k
}

// this basically does a Schnorr ignature
func sign(address *big.Int, k *KeyPair) (c, s *big.Int) {
var tmppoint bn256.G1
tmpsecret := RandomScalar()
tmppoint.ScalarMult(G, tmpsecret)

serialize := []byte(fmt.Sprintf("%s%s", k.y.String(), tmppoint.String()))

c = reducedhash(serialize)
s = new(big.Int).Mul(c, k.x) // basicaly scalar mul add
s = s.Mod(s, bn256.Order)
s = s.Add(s, tmpsecret)
s = s.Mod(s, bn256.Order)

return
}

func init_blockchain() *Blockchain {
return &Blockchain{registeredusers: map[string]*bn256.G1{}, balances: map[string]*Balance{}}
}

func (b *Blockchain) registerUser(u *KeyPair) error {
c, s := sign(new(big.Int).SetUint64(0), u)
return b.RegisterUser(u.y, c, s)

}

// register a user to blockchain
// this must be done via a empty transaction
// however, such transactions must themselves have some proof of work (independent from mining PoW) so as
// to avoid creation of billions of dummy accounts
// also, note we should have some sort of account destruction mechanism if someone wishes to do so,
// the leftover balance (if not empty can be donated and so on)
// will allow user u
func (b *Blockchain) RegisterUser(u *bn256.G1, c, s *big.Int) error {

tmppoint := new(bn256.G1).Add(new(bn256.G1).ScalarMult(G, s), new(bn256.G1).ScalarMult(u, new(big.Int).Neg(c)))

serialize := []byte(fmt.Sprintf("%s%s", u.String(), tmppoint.String()))

c_calculated := reducedhash(serialize)

if c.String() != c_calculated.String() {
return fmt.Errorf("Registration signature is invalid")
}

if _, ok := b.registeredusers[u.String()]; ok {
return fmt.Errorf("Already Registered ")
} else {
b.registeredusers[u.String()] = u
var balance Balance
balance.C[0].Set(u)
balance.C[1].Set(G)
b.balances[u.String()] = &balance
}

return nil
}

// fund a a user any arbitrary amount
func (b *Blockchain) FundUser(u *bn256.G1, amount uint32) error {

if _, ok := b.registeredusers[u.String()]; !ok {
return fmt.Errorf("user not Registered ")
} else {
balance := b.balances[u.String()]
balance.C[0].Add(&balance.C[0], new(bn256.G1).ScalarMult(G, new(big.Int).SetUint64(uint64(amount))))
klog.Infof("User %s funded %d", u.String(), amount)
return nil
}

}

// fund a a user any arbitrary amount
// this is a pure bruteforce, but can be optimized to instantly report under most of the conditions
func (b *Blockchain) ReadBalance(u *bn256.G1, secretkey *big.Int) (uint32, error) {

if _, ok := b.registeredusers[u.String()]; !ok {
return 0, fmt.Errorf("user not Registered ")
}
balance := b.balances[u.String()]

var CL, CR, gb bn256.G1
CL.Set(&balance.C[0])
CR.Set(&balance.C[1])

gb.Add(&CL, new(bn256.G1).Neg(new(bn256.G1).ScalarMult(&CR, secretkey)))

var acc bn256.G1
acc.ScalarMult(G, new(big.Int).SetUint64(0))

var tmp bn256.G1 // avoid allocation every loop
for i := 0; i <= 65536; i++ {
if acc.String() == gb.String() {
return uint32(i), nil
}
tmp.Set(&acc)
acc.Add(&tmp, G)
}

klog.Fatalf("balance not found or > 65535\n")
return 0, nil
}

// this currently does not do semantic checks
func (b *Blockchain) ExecuteTransaction(tx *Transaction) bool {

// Todo check whether all the public keys exist in the chain or not
for i := range tx.statement.Publickeylist {
if _, ok := b.balances[tx.statement.Publickeylist[i].String()]; !ok { // note these are pointer and updated real time
return false
}
}

if tx.proof.Verify(tx.statement) {
// this should be atomic, either all should be done or none at all
for i := range tx.statement.Publickeylist {
ebalance := b.balances[tx.statement.Publickeylist[i].String()] // note these are pointer and updated real time

ebalance.C[0].Add(new(bn256.G1).Set(&ebalance.C[0]), tx.statement.C[i])
ebalance.C[1].Add(new(bn256.G1).Set(&ebalance.C[1]), tx.statement.D)
}

return true

}

return false

}

// generate proof etc
func (b *Blockchain) BuildTransaction(sender *KeyPair, receiver_publickey *bn256.G1, value uint32, anonset_publickeys []*bn256.G1) *Transaction {

var tx Transaction

var publickeylist, C, CLn, CRn []*bn256.G1
var D bn256.G1

anonset_publickeys_copy := make([]*bn256.G1, len(anonset_publickeys))
copy(anonset_publickeys_copy, anonset_publickeys)

var buf [8]byte
_, err := rand.Read(buf[:])
if err != nil {
panic("cannot seed math/rand package with cryptographically secure random number generator")
}
mrand.Seed(int64(binary.LittleEndian.Uint64(buf[:]))) // mrand shuffle is backed by crypto seed

var witness_index []int
for i := 0; i < 2+len(anonset_publickeys); i++ { // todocheck whether this is power of 2 or not
witness_index = append(witness_index, i)
}

for {
mrand.Shuffle(len(witness_index), func(i, j int) {
witness_index[i], witness_index[j] = witness_index[j], witness_index[i]
})

// make sure sender and receiver are not both odd or both even
// sender will always be at witness_index[0] and receiver will always be at witness_index[1]
if witness_index[0]%2 != witness_index[1]%2 {
break
}
}

// Lots of ToDo for this, enables satisfying lots of other things
r := RandomScalar() // revealing this will disclose the amount and the sender and receiver and separate anonymouse rings memeber

for i := 0; i < 2+len(anonset_publickeys); i++ {
switch i {
case witness_index[0]:
publickeylist = append(publickeylist, sender.y)
case witness_index[1]:
publickeylist = append(publickeylist, receiver_publickey)

default:
publickeylist = append(publickeylist, anonset_publickeys_copy[0])
anonset_publickeys_copy = anonset_publickeys_copy[1:]
}

}

for i := range publickeylist { // setup commitments
var x bn256.G1
switch {
case i == witness_index[0]:
x.ScalarMult(G, new(big.Int).SetInt64(0-int64(value))) // decrease senders balance
case i == witness_index[1]:
x.ScalarMult(G, new(big.Int).SetInt64(int64(value))) // increase receiver's balance

default:
x.ScalarMult(G, new(big.Int).SetInt64(0))
}

x.Add(new(bn256.G1).Set(&x), new(bn256.G1).ScalarMult(publickeylist[i], r)) // hide all commitments behind r
C = append(C, &x)
}
D.ScalarMult(G, r)

for i := range publickeylist {
var ll, rr bn256.G1
ebalance := b.balances[publickeylist[i].String()] // note these are taken from the chain live

ll.Add(&ebalance.C[0], C[i])
CLn = append(CLn, &ll)

rr.Add(&ebalance.C[1], &D)
CRn = append(CRn, &rr)
}

// time for bullets-sigma
statement := GenerateStatement(CLn, CRn, publickeylist, C, &D) // generate statement
statement.roothash = new(big.Int).SetUint64(10) // currently it is a dummy param, until blockchain hash persistance

balance, _ := b.ReadBalance(sender.y, sender.x)
witness := GenerateWitness(sender.x, r, value, balance-value, witness_index)

u := new(bn256.G1).ScalarMult(HashToPoint(HashtoNumber(append([]byte(PROTOCOL_CONSTANT), convertbiginttobyte(statement.roothash)...))), sender.x) // this should be moved to generate proof
Print(statement, witness)
tx.statement = statement
tx.proof = GenerateProof(statement, witness, u)

return &tx
}

func Print(s *Statement, w *Witness) {

for i := range s.CLn {
klog.V(1).Infof("CLn[%d] %s\n", i, s.CLn[i].String())
}

for i := range s.CRn {
klog.V(1).Infof("CRn[%d] %s\n", i, s.CRn[i].String())
}

for i := range s.Publickeylist {
klog.V(1).Infof("P[%d] %s\n", i, s.Publickeylist[i].String())
}

for i := range s.C {
klog.V(1).Infof("C[%d] %s\n", i, s.C[i].String())
}

klog.V(1).Infof("D: %s\n", s.D.String())

klog.V(1).Infof("Merkle roothash): %s\n", s.roothash)

klog.V(1).Infof("secretkey 0x%s\n", w.SecretKey.Text(16))
klog.V(1).Infof("R 0x%s\n", w.R.Text(16))
klog.V(1).Infof("Value %d\n", w.TransferAmount)
klog.V(1).Infof("Balance %d\n", w.Balance)
klog.V(1).Infof("index %d\n", w.index)

}

func (tx *Transaction) Size() int {
return tx.statement.Size() + tx.proof.Size()
}
func (s *Statement) Size() int {
return (len(s.CLn)+len(s.CRn)+len(s.Publickeylist)+len(s.C))*POINT_SIZE + 2*FIELDELEMENT_SIZE
}

// statement hash
func (s *Statement) Hash() *big.Int {
var input []byte
for i := range s.CLn {
input = append(input, s.CLn[i].Marshal()...)
}
for i := range s.CRn {
input = append(input, s.CRn[i].Marshal()...)
}
for i := range s.C {
input = append(input, s.C[i].Marshal()...)
}
input = append(input, s.D.Marshal()...)
for i := range s.Publickeylist {
input = append(input, s.Publickeylist[i].Marshal()...)
}
input = append(input, convertbiginttobyte(s.roothash)...)

return reducedhash(input)
}

// generate statement
func GenerateStatement(CLn, CRn, publickeylist, C []*bn256.G1, D *bn256.G1) *Statement {
return &Statement{CLn: CLn, CRn: CRn, Publickeylist: publickeylist, C: C, D: D}
}

// generate witness
func GenerateWitness(secretkey, r *big.Int, TransferAmount, Balance uint32, index []int) *Witness {
return &Witness{SecretKey: secretkey, R: r, TransferAmount: TransferAmount, Balance: Balance, index: index}
}

// converts a big int to 32 bytes, prepending zeroes
func convertbiginttobyte(x *big.Int) []byte {
var dummy [128]byte
joined := append(dummy[:], x.Bytes()...)
return joined[len(joined)-32:]
}

+ 446
- 0
fieldvector.go View File

@@ -0,0 +1,446 @@
package main

//import "fmt"
import "math/big"

//import "crypto/rand"
//import "encoding/hex"

import "github.com/clearmatics/bn256"

//import "golang.org/x/crypto/sha3"

type FieldVector struct {
vector []*big.Int
}

func NewFieldVector(input []*big.Int) *FieldVector {
return &FieldVector{vector: input}
}

func (fv *FieldVector) Length() int {
return len(fv.vector)
}

// slice and return
func (fv *FieldVector) Slice(start, end int) *FieldVector {
var result FieldVector
for i := start; i < end; i++ {
result.vector = append(result.vector, new(big.Int).Set(fv.vector[i]))
}
return &result
}

//copy and return
func (fv *FieldVector) Clone() *FieldVector {
return fv.Slice(0, len(fv.vector))
}

func (fv *FieldVector) SliceRaw(start, end int) []*big.Int {
var result FieldVector
for i := start; i < end; i++ {
result.vector = append(result.vector, new(big.Int).Set(fv.vector[i]))
}
return result.vector
}

func (fv *FieldVector) Sum() *big.Int {
var accumulator big.Int

for i := range fv.vector {
var accopy big.Int

accopy.Add(&accumulator, fv.vector[i])
accumulator.Mod(&accopy, bn256.Order)
}

return &accumulator
}

func (fv *FieldVector) Add(addendum *FieldVector) *FieldVector {
var result FieldVector

if len(fv.vector) != len(addendum.vector) {
panic("mismatched number of elements")
}

for i := range fv.vector {
var ri big.Int
ri.Mod(new(big.Int).Add(fv.vector[i], addendum.vector[i]), bn256.Order)
result.vector = append(result.vector, &ri)
}

return &result
}

func (gv *FieldVector) AddConstant(c *big.Int) *FieldVector {
var result FieldVector

for i := range gv.vector {
var ri big.Int
ri.Mod(new(big.Int).Add(gv.vector[i], c), bn256.Order)
result.vector = append(result.vector, &ri)
}

return &result
}

func (fv *FieldVector) Hadamard(exponent *FieldVector) *FieldVector {
var result FieldVector

if len(fv.vector) != len(exponent.vector) {
panic("mismatched number of elements")
}
for i := range fv.vector {
result.vector = append(result.vector, new(big.Int).Mod(new(big.Int).Mul(fv.vector[i], exponent.vector[i]), bn256.Order))
}

return &result
}

func (fv *FieldVector) InnerProduct(exponent *FieldVector) *big.Int {
if len(fv.vector) != len(exponent.vector) {
panic("mismatched number of elements")
}

accumulator := new(big.Int)
for i := range fv.vector {
tmp := new(big.Int).Mod(new(big.Int).Mul(fv.vector[i], exponent.vector[i]), bn256.Order)
accumulator.Add(accumulator, tmp)
accumulator.Mod(accumulator, bn256.Order)
}

return accumulator
}

func (fv *FieldVector) Negate() *FieldVector {
var result FieldVector
for i := range fv.vector {
result.vector = append(result.vector, new(big.Int).Mod(new(big.Int).Neg(fv.vector[i]), bn256.Order))
}
return &result
}

func (fv *FieldVector) Flip() *FieldVector {
var result FieldVector
for i := range fv.vector {
result.vector = append(result.vector, new(big.Int).Set(fv.vector[(len(fv.vector)-i)%len(fv.vector)]))
}
return &result
}

func (fv *FieldVector) Times(multiplier *big.Int) *FieldVector {
var result FieldVector
for i := range fv.vector {
res := new(big.Int).Mul(fv.vector[i], multiplier)
res.Mod(res, bn256.Order)
result.vector = append(result.vector, res)
}
return &result
}

func (fv *FieldVector) Invert() *FieldVector {
var result FieldVector
for i := range fv.vector {
result.vector = append(result.vector, new(big.Int).ModInverse(fv.vector[i], bn256.Order))
}
return &result
}

func (fv *FieldVector) Concat(addendum *FieldVector) *FieldVector {
var result FieldVector
for i := range fv.vector {
result.vector = append(result.vector, new(big.Int).Set(fv.vector[i]))
}

for i := range addendum.vector {
result.vector = append(result.vector, new(big.Int).Set(addendum.vector[i]))
}

return &result
}

func (fv *FieldVector) Extract(parity bool) *FieldVector {
var result FieldVector

remainder := 0
if parity {
remainder = 1
}
for i := range fv.vector {
if i%2 == remainder {

result.vector = append(result.vector, new(big.Int).Set(fv.vector[i]))
}
}
return &result
}

type FieldVectorPolynomial struct {
coefficients []*FieldVector
}

func NewFieldVectorPolynomial(inputs ...*FieldVector) *FieldVectorPolynomial {
fv := &FieldVectorPolynomial{}
for _, input := range inputs {
fv.coefficients = append(fv.coefficients, input.Clone())
}
return fv
}

func (fv *FieldVectorPolynomial) Length() int {
return len(fv.coefficients)
}

func (fv *FieldVectorPolynomial) Evaluate(x *big.Int) *FieldVector {

result := fv.coefficients[0].Clone()

accumulator := new(big.Int).Set(x)

for i := 1; i < len(fv.coefficients); i++ {
result = result.Add(fv.coefficients[i].Times(accumulator))
accumulator.Mul(accumulator, x)
accumulator.Mod(accumulator, bn256.Order)

}
return result
}

func (fv *FieldVectorPolynomial) InnerProduct(other *FieldVectorPolynomial) []*big.Int {

var result []*big.Int

result_length := fv.Length() + other.Length() - 1
for i := 0; i < result_length; i++ {
result = append(result, new(big.Int)) // 0 value fill
}

for i := range fv.coefficients {
for j := range other.coefficients {
tmp := new(big.Int).Set(result[i+j])
result[i+j].Add(tmp, fv.coefficients[i].InnerProduct(other.coefficients[j]))
result[i+j].Mod(result[i+j], bn256.Order)
}
}
return result
}

type PedersenCommitment struct {
X *big.Int
R *big.Int
Params *GeneratorParams
}

func NewPedersenCommitment(params *GeneratorParams, x, r *big.Int) *PedersenCommitment {
pc := &PedersenCommitment{Params: params, X: new(big.Int).Set(x), R: new(big.Int).Set(r)}
return pc
}
func (pc *PedersenCommitment) Commit() *bn256.G1 {
var left, right, result bn256.G1
left.ScalarMult(pc.Params.G, pc.X)
right.ScalarMult(pc.Params.H, pc.R)
result.Add(&left, &right)
return &result
}
func (pc *PedersenCommitment) Add(other *PedersenCommitment) *PedersenCommitment {
var x, r big.Int
x.Mod(new(big.Int).Add(pc.X, other.X), bn256.Order)
r.Mod(new(big.Int).Add(pc.R, other.R), bn256.Order)
return NewPedersenCommitment(pc.Params, &x, &r)
}
func (pc *PedersenCommitment) Times(constant *big.Int) *PedersenCommitment {
var x, r big.Int
x.Mod(new(big.Int).Mul(pc.X, constant), bn256.Order)
r.Mod(new(big.Int).Mul(pc.R, constant), bn256.Order)
return NewPedersenCommitment(pc.Params, &x, &r)
}

type PolyCommitment struct {
coefficient_commitments []*PedersenCommitment
Params *GeneratorParams
}

func NewPolyCommitment(params *GeneratorParams, coefficients []*big.Int) *PolyCommitment {
pc := &PolyCommitment{Params: params}
pc.coefficient_commitments = append(pc.coefficient_commitments, NewPedersenCommitment(params, coefficients[0], new(big.Int).SetUint64(0)))

for i := 1; i < len(coefficients); i++ {
pc.coefficient_commitments = append(pc.coefficient_commitments, NewPedersenCommitment(params, coefficients[i], RandomScalarFixed()))

}
return pc
}

func (pc *PolyCommitment) GetCommitments() []*bn256.G1 {
var result []*bn256.G1
for i := 1; i < len(pc.coefficient_commitments); i++ {
result = append(result, pc.coefficient_commitments[i].Commit())
}
return result
}

func (pc *PolyCommitment) Evaluate(constant *big.Int) *PedersenCommitment {
result := pc.coefficient_commitments[0]

accumulator := new(big.Int).Set(constant)

for i := 1; i < len(pc.coefficient_commitments); i++ {

tmp := new(big.Int).Set(accumulator)
result = result.Add(pc.coefficient_commitments[i].Times(accumulator))
accumulator.Mod(new(big.Int).Mul(tmp, constant), bn256.Order)
}

return result
}

/*
// bother FieldVector and GeneratorVector satisfy this
type Vector interface{
Length() int
Extract(parity bool) Vector
Add(other Vector)Vector
Hadamard( []*big.Int) Vector
Times (*big.Int) Vector
Negate() Vector
}
*/

// check this https://pdfs.semanticscholar.org/d38d/e48ee4127205a0f25d61980c8f241718b66e.pdf
// https://arxiv.org/pdf/1802.03932.pdf

var unity *big.Int

func init() {
// primitive 2^28th root of unity modulo q
unity, _ = new(big.Int).SetString("14a3074b02521e3b1ed9852e5028452693e87be4e910500c7ba9bbddb2f46edd", 16)

}

func fft_FieldVector(input *FieldVector, inverse bool) *FieldVector {
length := input.Length()
if length == 1 {
return input
}

// lngth must be multiple of 2 ToDO
if length%2 != 0 {
panic("length must be multiple of 2")
}

//unity,_ := new(big.Int).SetString("14a3074b02521e3b1ed9852e5028452693e87be4e910500c7ba9bbddb2f46edd",16)

omega := new(big.Int).Exp(unity, new(big.Int).SetUint64((1<<28)/uint64(length)), bn256.Order)
if inverse {
omega = new(big.Int).ModInverse(omega, bn256.Order)
}

even := fft_FieldVector(input.Extract(false), inverse)
odd := fft_FieldVector(input.Extract(true), inverse)

omegas := []*big.Int{new(big.Int).SetUint64(1)}

for i := 1; i < length/2; i++ {
omegas = append(omegas, new(big.Int).Mod(new(big.Int).Mul(omegas[i-1], omega), bn256.Order))
}

omegasv := NewFieldVector(omegas)
result := even.Add(odd.Hadamard(omegasv)).Concat(even.Add(odd.Hadamard(omegasv).Negate()))
if inverse {
result = result.Times(new(big.Int).ModInverse(new(big.Int).SetUint64(2), bn256.Order))
}

return result

}

// this is exactly same as fft_FieldVector, alternate implementation
func fftints(input []*big.Int) (result []*big.Int) {
size := len(input)
if size == 1 {
return input
}
//require(size % 2 == 0, "Input size is not a power of 2!");

unity, _ := new(big.Int).SetString("14a3074b02521e3b1ed9852e5028452693e87be4e910500c7ba9bbddb2f46edd", 16)

omega := new(big.Int).Exp(unity, new(big.Int).SetUint64((1<<28)/uint64(size)), bn256.Order)

even := fftints(extractbits(input, 0))
odd := fftints(extractbits(input, 1))
omega_run := new(big.Int).SetUint64(1)
result = make([]*big.Int, len(input), len(input))
for i := 0; i < len(input)/2; i++ {
temp := new(big.Int).Mod(new(big.Int).Mul(odd[i], omega_run), bn256.Order)
result[i] = new(big.Int).Mod(new(big.Int).Add(even[i], temp), bn256.Order)
result[i+size/2] = new(big.Int).Mod(new(big.Int).Sub(even[i], temp), bn256.Order)
omega_run = new(big.Int).Mod(new(big.Int).Mul(omega, omega_run), bn256.Order)
}
return result
}

func extractbits(input []*big.Int, parity int) (result []*big.Int) {
result = make([]*big.Int, len(input)/2, len(input)/2)
for i := 0; i < len(input)/2; i++ {
result[i] = new(big.Int).Set(input[2*i+parity])
}
return
}

func fft_GeneratorVector(input *GeneratorVector, inverse bool) *GeneratorVector {
length := input.Length()
if length == 1 {
return input
}

// lngth must be multiple of 2 ToDO
if length%2 != 0 {
panic("length must be multiple of 2")
}

// unity,_ := new(big.Int).SetString("14a3074b02521e3b1ed9852e5028452693e87be4e910500c7ba9bbddb2f46edd",16)

omega := new(big.Int).Exp(unity, new(big.Int).SetUint64((1<<28)/uint64(length)), bn256.Order)
if inverse {
omega = new(big.Int).ModInverse(omega, bn256.Order)
}

even := fft_GeneratorVector(input.Extract(false), inverse)

//fmt.Printf("exponent_fft %d %s \n",i, exponent_fft.vector[i].Text(16))

odd := fft_GeneratorVector(input.Extract(true), inverse)

omegas := []*big.Int{new(big.Int).SetUint64(1)}

for i := 1; i < length/2; i++ {
omegas = append(omegas, new(big.Int).Mod(new(big.Int).Mul(omegas[i-1], omega), bn256.Order))
}

omegasv := omegas
result := even.Add(odd.Hadamard(omegasv)).Concat(even.Add(odd.Hadamard(omegasv).Negate()))
if inverse {
result = result.Times(new(big.Int).ModInverse(new(big.Int).SetUint64(2), bn256.Order))
}

return result

}

func Convolution(exponent *FieldVector, base *GeneratorVector) *GeneratorVector {
size := base.Length()

exponent_fft := fft_FieldVector(exponent.Flip(), false)

/*exponent_fft2 := fftints( exponent.Flip().vector) // aternate implementation proof checking
for i := range exponent_fft.vector{
fmt.Printf("exponent_fft %d %s \n",i, exponent_fft.vector[i].Text(16))
fmt.Printf("exponent_ff2 %d %s \n",i, exponent_fft2[i].Text(16))
}
*/

temp := fft_GeneratorVector(base, false).Hadamard(exponent_fft.vector)
return fft_GeneratorVector(temp.Slice(0, size/2).Add(temp.Slice(size/2, size)).Times(new(big.Int).ModInverse(new(big.Int).SetUint64(2), bn256.Order)), true)
// using the optimization described here https://dsp.stackexchange.com/a/30699
}

+ 145
- 0
generatorparams.go View File

@@ -0,0 +1,145 @@
package main

import "fmt"
import "math/big"

//import "crypto/rand"
import "encoding/hex"

import "github.com/clearmatics/bn256"
import "golang.org/x/crypto/sha3"

var FIELD_MODULUS, w = new(big.Int).SetString("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47", 16)
var GROUP_MODULUS, w1 = new(big.Int).SetString("30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001", 16)

// this file basically implements curve based items

type GeneratorParams struct {
G *bn256.G1
H *bn256.G1
GSUM *bn256.G1

Gs *GeneratorVector
Hs *GeneratorVector
}

// the number if already reduced
func HashtoNumber(input []byte) *big.Int {

hasher := sha3.NewLegacyKeccak256()
hasher.Write(input)

hash := hasher.Sum(nil)
return new(big.Int).SetBytes(hash[:])
}

// calculate hash and reduce it by curve's order
func reducedhash(input []byte) *big.Int {
return new(big.Int).Mod(HashtoNumber(input), bn256.Order)
}

func makestring64(input string) string {
for len(input) != 64 {
input = "0" + input
}
return input
}

func hextobytes(input string) []byte {
ibytes, err := hex.DecodeString(input)
if err != nil {
panic(err)
}
return ibytes
}

// this should be merged , simplified just as simple as 25519
func HashToPoint(seed *big.Int) *bn256.G1 {
seed_reduced := new(big.Int)
seed_reduced.Mod(seed, FIELD_MODULUS)

p_1_4 := new(big.Int).Add(FIELD_MODULUS, new(big.Int).SetInt64(1))
p_1_4 = p_1_4.Div(p_1_4, new(big.Int).SetInt64(4))

for {
tmp := new(big.Int)
y, y_squared, y_resquare := new(big.Int), new(big.Int), new(big.Int) // basically y_sqaured = seed ^3 + 3 mod group order
tmp.Exp(seed_reduced, new(big.Int).SetInt64(3), FIELD_MODULUS)
y_squared.Add(tmp, new(big.Int).SetInt64(3))
y_squared.Mod(y_squared, FIELD_MODULUS)

y = y.Exp(y_squared, p_1_4, FIELD_MODULUS)

y_resquare = y_resquare.Exp(y, new(big.Int).SetInt64(2), FIELD_MODULUS)

if y_resquare.Cmp(y_squared) == 0 { // seed becomes x and y iis usy
xstring := seed_reduced.Text(16)
ystring := y.Text(16)

var point bn256.G1
xbytes, err := hex.DecodeString(makestring64(xstring))
if err != nil {
panic(err)
}
ybytes, err := hex.DecodeString(makestring64(ystring))
if err != nil {
panic(err)
}

point.Unmarshal(append(xbytes, ybytes...))
return &point

}
seed_reduced.Add(seed_reduced, new(big.Int).SetInt64(1))
seed_reduced.Mod(seed_reduced, FIELD_MODULUS)
}

return nil
}

func NewGeneratorParams(count int) *GeneratorParams {
GP := &GeneratorParams{}
var zeroes [64]byte

GP.G = HashToPoint(HashtoNumber([]byte(PROTOCOL_CONSTANT + "G"))) // this is same as mybase or vice-versa
GP.H = HashToPoint(HashtoNumber([]byte(PROTOCOL_CONSTANT + "H")))

var gs, hs []*bn256.G1

GP.GSUM = new(bn256.G1)
GP.GSUM.Unmarshal(zeroes[:])

for i := 0; i < count; i++ {
gs = append(gs, HashToPoint(HashtoNumber(append([]byte(PROTOCOL_CONSTANT+"G"), hextobytes(makestring64(fmt.Sprintf("%x", i)))...))))
hs = append(hs, HashToPoint(HashtoNumber(append([]byte(PROTOCOL_CONSTANT+"H"), hextobytes(makestring64(fmt.Sprintf("%x", i)))...))))

GP.GSUM = new(bn256.G1).Add(GP.GSUM, gs[i])
}
GP.Gs = NewGeneratorVector(gs)
GP.Hs = NewGeneratorVector(hs)

return GP
}

func NewGeneratorParams3(h *bn256.G1, gs, hs *GeneratorVector) *GeneratorParams {
GP := &GeneratorParams{}

GP.G = HashToPoint(HashtoNumber([]byte(PROTOCOL_CONSTANT + "G"))) // this is same as mybase or vice-versa
GP.H = h
GP.Gs = gs
GP.Hs = hs
return GP
}

func (gp *GeneratorParams) Commit(blind *big.Int, gexps, hexps *FieldVector) *bn256.G1 {
result := new(bn256.G1).ScalarMult(gp.H, blind)
for i := range gexps.vector {
result = new(bn256.G1).Add(result, new(bn256.G1).ScalarMult(gp.Gs.vector[i], gexps.vector[i]))
}
if hexps != nil {
for i := range hexps.vector {
result = new(bn256.G1).Add(result, new(bn256.G1).ScalarMult(gp.Hs.vector[i], hexps.vector[i]))
}
}
return result
}

+ 161
- 0
generatorvector.go View File

@@ -0,0 +1,161 @@
package main

//import "fmt"
import "math/big"

//import "crypto/rand"
//import "encoding/hex"

import "github.com/clearmatics/bn256"

//import "golang.org/x/crypto/sha3"

// ToDO evaluate others curves such as BLS12 used by zcash, also BLS24 or others , providing ~200 bits of security , may be required for long time use( say 50 years)
type GeneratorVector struct {
vector []*bn256.G1
}

func NewGeneratorVector(input []*bn256.G1) *GeneratorVector {
return &GeneratorVector{vector: input}
}

func (gv *GeneratorVector) Length() int {
return len(gv.vector)
}

// slice and return
func (gv *GeneratorVector) Slice(start, end int) *GeneratorVector {
var result GeneratorVector
for i := start; i < end; i++ {
var ri bn256.G1
ri.Set(gv.vector[i])
result.vector = append(result.vector, &ri)
}
return &result
}

func (gv *GeneratorVector) Commit(exponent []*big.Int) *bn256.G1 {
var accumulator, zero bn256.G1
var zeroes [64]byte
accumulator.Unmarshal(zeroes[:]) // obtain zero element, this should be static and
zero.Unmarshal(zeroes[:])

accumulator.ScalarMult(G, new(big.Int))

//fmt.Printf("zero %s\n", accumulator.String())

if len(gv.vector) != len(exponent) {
panic("mismatched number of elements")
}
for i := range gv.vector { // TODO a bug exists somewhere deep here
var tmp, accopy bn256.G1
tmp.ScalarMult(gv.vector[i], exponent[i])

accopy.Set(&accumulator)
accumulator.Add(&accopy, &tmp)
}

return &accumulator
}

func (gv *GeneratorVector) Sum() *bn256.G1 {
var accumulator bn256.G1

accumulator.ScalarMult(G, new(big.Int)) // set it to zero

for i := range gv.vector {
var accopy bn256.G1

accopy.Set(&accumulator)
accumulator.Add(&accopy, gv.vector[i])
}

return &accumulator
}

func (gv *GeneratorVector) Add(addendum *GeneratorVector) *GeneratorVector {
var result GeneratorVector

if len(gv.vector) != len(addendum.vector) {
panic("mismatched number of elements")
}

for i := range gv.vector {
var ri bn256.G1

ri.Add(gv.vector[i], addendum.vector[i])
result.vector = append(result.vector, &ri)
}

return &result
}

func (gv *GeneratorVector) Hadamard(exponent []*big.Int) *GeneratorVector {
var result GeneratorVector

if len(gv.vector) != len(exponent) {
panic("mismatched number of elements")
}
for i := range gv.vector {
var ri bn256.G1
ri.ScalarMult(gv.vector[i], exponent[i])
result.vector = append(result.vector, &ri)

}

return &result
}

func (gv *GeneratorVector) Negate() *GeneratorVector {
var result GeneratorVector
for i := range gv.vector {
var ri bn256.G1
ri.Neg(gv.vector[i])
result.vector = append(result.vector, &ri)
}
return &result
}

func (gv *GeneratorVector) Times(multiplier *big.Int) *GeneratorVector {
var result GeneratorVector
for i := range gv.vector {
var ri bn256.G1
ri.ScalarMult(gv.vector[i], multiplier)
result.vector = append(result.vector, &ri)
}
return &result
}

func (gv *GeneratorVector) Extract(parity bool) *GeneratorVector {
var result GeneratorVector

remainder := 0
if parity {
remainder = 1
}
for i := range gv.vector {
if i%2 == remainder {
var ri bn256.G1
ri.Set(gv.vector[i])
result.vector = append(result.vector, &ri)
}
}
return &result
}

func (gv *GeneratorVector) Concat(addendum *GeneratorVector) *GeneratorVector {
var result GeneratorVector
for i := range gv.vector {
var ri bn256.G1
ri.Set(gv.vector[i])
result.vector = append(result.vector, &ri)
}

for i := range addendum.vector {
var ri bn256.G1
ri.Set(addendum.vector[i])
result.vector = append(result.vector, &ri)
}

return &result
}

+ 168
- 0
innerproduct.go View File

@@ -0,0 +1,168 @@
package main

//import "fmt"
import "math"
import "math/big"

//import "crypto/rand"
//import "encoding/hex"

import "github.com/clearmatics/bn256"

//import "golang.org/x/crypto/sha3"

// basically the Σ-protocol
type InnerProduct struct {
a, b *big.Int
ls, rs []*bn256.G1
}

func (ip *InnerProduct) Size() int {
return FIELDELEMENT_SIZE + FIELDELEMENT_SIZE + len(ip.ls)*POINT_SIZE + len(ip.rs)*POINT_SIZE
}

func NewInnerProductProof(ips *IPStatement, witness *IPWitness, salt *big.Int) *InnerProduct {
var ip InnerProduct

ip.generateInnerProductProof(ips.PrimeBase, ips.P, witness.L, witness.R, salt)
return &ip
}

func (ip *InnerProduct) generateInnerProductProof(base *GeneratorParams, P *bn256.G1, as, bs *FieldVector, prev_challenge *big.Int) {
n := as.Length()

if n == 1 { // the proof is done, ls,rs are already in place
ip.a = as.vector[0]
ip.b = bs.vector[0]
return
}

nPrime := n / 2
asLeft := as.Slice(0, nPrime)
asRight := as.Slice(nPrime, n)
bsLeft := bs.Slice(0, nPrime)
bsRight := bs.Slice(nPrime, n)
gLeft := base.Gs.Slice(0, nPrime)
gRight := base.Gs.Slice(nPrime, n)
hLeft := base.Hs.Slice(0, nPrime)
hRight := base.Hs.Slice(nPrime, n)

cL := asLeft.InnerProduct(bsRight)
cR := asRight.InnerProduct(bsLeft)

u := base.H
L := new(bn256.G1).Add(gRight.Commit(asLeft.vector), hLeft.Commit(bsRight.vector))
L = new(bn256.G1).Add(L, new(bn256.G1).ScalarMult(u, cL))

R := new(bn256.G1).Add(gLeft.Commit(asRight.vector), hRight.Commit(bsLeft.vector))
R = new(bn256.G1).Add(R, new(bn256.G1).ScalarMult(u, cR))

ip.ls = append(ip.ls, L)
ip.rs = append(ip.rs, R)

var input []byte
input = append(input, convertbiginttobyte(prev_challenge)...)
input = append(input, L.Marshal()...)
input = append(input, R.Marshal()...)
x := reducedhash(input)

xinv := new(big.Int).ModInverse(x, bn256.Order)

gPrime := gLeft.Times(xinv).Add(gRight.Times(x))
hPrime := hLeft.Times(x).Add(hRight.Times(xinv))
aPrime := asLeft.Times(x).Add(asRight.Times(xinv))
bPrime := bsLeft.Times(xinv).Add(bsRight.Times(x))

basePrime := NewGeneratorParams3(u, gPrime, hPrime)

PPrimeL := new(bn256.G1).ScalarMult(L, new(big.Int).Mod(new(big.Int).Mul(x, x), bn256.Order)) //L * (x*x)
PPrimeR := new(bn256.G1).ScalarMult(R, new(big.Int).Mod(new(big.Int).Mul(xinv, xinv), bn256.Order)) //R * (xinv*xinv)

PPrime := new(bn256.G1).Add(PPrimeL, PPrimeR)
PPrime = new(bn256.G1).Add(PPrime, P)

ip.generateInnerProductProof(basePrime, PPrime, aPrime, bPrime, x)

return

}

func (ip *InnerProduct) Verify(hs []*bn256.G1, u, P *bn256.G1, salt *big.Int, gp *GeneratorParams) bool {
log_n := uint(len(ip.ls))

if len(ip.ls) != len(ip.rs) { // length must be same
return false
}
n := uint(math.Pow(2, float64(log_n)))

o := salt
var challenges []*big.Int
for i := uint(0); i < log_n; i++ {

var input []byte
input = append(input, convertbiginttobyte(o)...)
input = append(input, ip.ls[i].Marshal()...)
input = append(input, ip.rs[i].Marshal()...)
o = reducedhash(input)
challenges = append(challenges, o)

o_inv := new(big.Int).ModInverse(o, bn256.Order)

PPrimeL := new(bn256.G1).ScalarMult(ip.ls[i], new(big.Int).Mod(new(big.Int).Mul(o, o), bn256.Order)) //L * (x*x)
PPrimeR := new(bn256.G1).ScalarMult(ip.rs[i], new(big.Int).Mod(new(big.Int).Mul(o_inv, o_inv), bn256.Order)) //L * (x*x)

PPrime := new(bn256.G1).Add(PPrimeL, PPrimeR)
P = new(bn256.G1).Add(PPrime, P)
}

exp := new(big.Int).SetUint64(1)
for i := uint(0); i < log_n; i++ {
exp = new(big.Int).Mod(new(big.Int).Mul(exp, challenges[i]), bn256.Order)
}

exp_inv := new(big.Int).ModInverse(exp, bn256.Order)

exponents := make([]*big.Int, n, n)

exponents[0] = exp_inv // initializefirst element

bits := make([]bool, n, n)
for i := uint(0); i < n/2; i++ {
for j := uint(0); (1<<j)+i < n; j++ {
i1 := (1 << j) + i
if !bits[i1] {
temp := new(big.Int).Mod(new(big.Int).Mul(challenges[log_n-1-j], challenges[log_n-1-j]), bn256.Order)
exponents[i1] = new(big.Int).Mod(new(big.Int).Mul(exponents[i], temp), bn256.Order)
bits[i1] = true
}
}
}

var zeroes [64]byte
gtemp := new(bn256.G1) // obtain zero element, this should be static and
htemp := new(bn256.G1) // obtain zero element, this should be static and

gtemp.Unmarshal(zeroes[:])
htemp.Unmarshal(zeroes[:])

for i := uint(0); i < n; i++ {
gtemp = new(bn256.G1).Add(gtemp, new(bn256.G1).ScalarMult(gp.Gs.vector[i], exponents[i]))
htemp = new(bn256.G1).Add(htemp, new(bn256.G1).ScalarMult(hs[i], exponents[n-1-i]))
}
gtemp = new(bn256.G1).ScalarMult(gtemp, ip.a)
htemp = new(bn256.G1).ScalarMult(htemp, ip.b)
utemp := new(bn256.G1).ScalarMult(u, new(big.Int).Mod(new(big.Int).Mul(ip.a, ip.b), bn256.Order))

P_calculated := new(bn256.G1).Add(gtemp, htemp)
P_calculated = new(bn256.G1).Add(P_calculated, utemp)

// fmt.Printf("P %s\n",P.String())
// fmt.Printf("P_calculated %s\n",P_calculated.String())

if P_calculated.String() != P.String() { // need something better here
panic("Faulty or invalid proof")
return false
}

return true
}

+ 123
- 0
main.go View File

@@ -0,0 +1,123 @@
package main

import "fmt"
import "flag"

import "github.com/kubernetes/klog"
import "github.com/clearmatics/bn256"

const POINT_SIZE = 33 // this can be optimized to 33 bytes
const FIELDELEMENT_SIZE = 32 // why not have bigger curves

const RING_SIZE = 8 // use powers of 2, note this is not currently sanity checked

// protocol supports amounts upto this, however this pre=alpha wallet supports only 65535 as we use bruteforce to decode balance
const MAX_AMOUNT = 18446744073709551616 // 2^64 - 1,, current wallet supports amounts of only 65535 are supported

const PROTOCOL_CONSTANT = "DERO"

// as you can see overhead per account is 3 curve points, , user public key, 2 points for encrypted balances
type Blockchain struct {
registeredusers map[string]*bn256.G1 // registered users,, public key of user
balances map[string]*Balance // encrypted balances of registered users
}

type Balance struct { // all balances are kept here and overhead of per account in blockchain is 66 bytes
C [2]bn256.G1
}

func init() {
klog.InitFlags(nil) // setup logging
flag.Set("logtostderr", "true")
flag.Set("stderrthreshold", "WARNING")
flag.Set("v", "0") // set this to 1 or 2 to enable verbose logging
flag.Parse()

}

func main() {

fmt.Printf("\n\n DERO HOMO Protocol ( pre-alpha version )\n\n")

blockchain := init_blockchain() // init memory map based chain to validate concept
sender := GenerateKeyPair()
receiver := GenerateKeyPair()

if err := blockchain.registerUser(sender); err != nil { // register sender
panic(err)
}

if err := blockchain.registerUser(receiver); err != nil { // register receiver
panic(err)
}

klog.V(0).Infof("sender \n%s\n", *sender)
klog.V(0).Infof("receiver \n%s\n", *receiver)

var dummies []*KeyPair // generate dummies to be used as anonymous groups
for i := 0; i < 2100; i++ {
dummies = append(dummies, GenerateKeyPair()) // generate a random user
if err := blockchain.registerUser(dummies[i]); err != nil { // register a user
panic(err)
}
}

// this basicaly is a mining transaction, in this poc you can give any one any balance
if err := blockchain.FundUser(sender.y, 150); err != nil { // sender now has balance 150
panic(err)
}

// do 2 transfers, one of 10, other 90 with ring size 8 and 16 respectively
blockchain.transfer(sender, receiver, 10, dummies, 8) // transfer 10 from sender to receiver ring size 8
blockchain.transfer(sender, receiver, 90, dummies, 16) // transfer 90 from sender to receiver, ring size 16

klog.V(0).Infof("\n\t\t\tSuccessful\n")
}



// wrap transfer in a function for better understanding of users
func (blockchain *Blockchain) transfer(sender, receiver *KeyPair, amount uint32, dummies []*KeyPair, ring_size int) {

defer func() {
if r := recover(); r != nil {
fmt.Println("Transfer failed ", r)
}
}()

sender_balance_before_transfer, _ := blockchain.ReadBalance(sender.y, sender.x) // find balance via bruteforce
receiver_balance_before_transfer, _ := blockchain.ReadBalance(receiver.y, receiver.x) // find balance via bruteforce

var anonlist []*bn256.G1 // choose anonymous peers, this should be done carefully
for i := 0; i < ring_size-2; i++ { // it must (2^n) -2 , example 2,6,14,30,62, 126,254,510,1022,2046 etc
anonlist = append(anonlist, dummies[i].y)
}

transfer_amount := amount // total value to transfer

klog.V(0).Infof("\n\nCreating Transaction")
tx := blockchain.BuildTransaction(sender, receiver.y, transfer_amount, anonlist) // generate proof for sending value 10

klog.V(0).Infof("Transferring %d from sender to receiver (ring size %d) tx size %d bytes ", transfer_amount, len(anonlist)+2, tx.Size())
klog.V(0).Infof("Total tx size %d bytes ( %d byte statement, %d bytes proof ) ", tx.Size(), tx.statement.Size(), tx.proof.Size())

// at this point tx has strong anonymity and deniablity and leak proof, you are welcome to analyse it for any leakages

if blockchain.ExecuteTransaction(tx) {
klog.V(0).Infof("Transfer successful")
} else {
klog.Fatalf("Transfer failed. please enable logs")
return
}

sender_balance_after_transfer, _ := blockchain.ReadBalance(sender.y, sender.x) // find balance via bruteforce
receiver_balance_after_transfer, _ := blockchain.ReadBalance(receiver.y, receiver.x) // find balance via bruteforce

klog.V(0).Infof("%20s %9d - %9d = %9d\n", "Sender Balance", sender_balance_before_transfer, transfer_amount, sender_balance_after_transfer)
klog.V(0).Infof("%20s %9d + %9d = %9d\n", "Receiver Balance", receiver_balance_before_transfer, transfer_amount, receiver_balance_after_transfer)

if (sender_balance_before_transfer-transfer_amount) != sender_balance_after_transfer ||
(receiver_balance_before_transfer+transfer_amount) != receiver_balance_after_transfer {
panic("something failed.. jump in")
}
}

+ 75
- 0
polynomial.go View File

@@ -0,0 +1,75 @@
package main

//import "fmt"
import "math/big"

//import "crypto/rand"
//import "encoding/hex"

import "github.com/clearmatics/bn256"

//import "golang.org/x/crypto/sha3"

type Polynomial struct {
coefficients []*big.Int
}

func NewPolynomial(input []*big.Int) *Polynomial {
if input == nil {
return &Polynomial{coefficients: []*big.Int{new(big.Int).SetInt64(1)}}
}
return &Polynomial{coefficients: input}
}

func (p *Polynomial) Length() int {
return len(p.coefficients)
}

func (p *Polynomial) Mul(m *Polynomial) *Polynomial {
var product []*big.Int
for i := range p.coefficients {
product = append(product, new(big.Int).Mod(new(big.Int).Mul(p.coefficients[i], m.coefficients[0]), bn256.Order))
}
product = append(product, new(big.Int)) // add 0 element

if m.coefficients[1].IsInt64() && m.coefficients[1].Int64() == 1 {
for i := range product {
if i > 0 {
tmp := new(big.Int).Add(product[i], p.coefficients[i-1])

product[i] = new(big.Int).Mod(tmp, bn256.Order)

} else { // do nothing

}
}
}
return NewPolynomial(product)
}

type dummy struct {
list [][]*big.Int
}

func RecursivePolynomials(list [][]*big.Int, accum *Polynomial, a, b []*big.Int) (rlist [][]*big.Int) {
var d dummy
d.recursivePolynomialsinternal(accum, a, b)

return d.list
}

func (d *dummy) recursivePolynomialsinternal(accum *Polynomial, a, b []*big.Int) {
if len(a) == 0 {
d.list = append(d.list, accum.coefficients)
return
}

atop := a[len(a)-1]
btop := b[len(b)-1]

left := NewPolynomial([]*big.Int{new(big.Int).Mod(new(big.Int).Neg(atop), bn256.Order), new(big.Int).Mod(new(big.Int).Sub(new(big.Int).SetInt64(1), btop), bn256.Order)})
right := NewPolynomial([]*big.Int{atop, btop})

d.recursivePolynomialsinternal(accum.Mul(left), a[:len(a)-1], b[:len(b)-1])
d.recursivePolynomialsinternal(accum.Mul(right), a[:len(a)-1], b[:len(b)-1])
}

+ 803
- 0
proof_generate.go View File

@@ -0,0 +1,803 @@
package main

import "fmt"
import "math"
import "math/big"

//import "crypto/rand"
//import "encoding/hex"

import "github.com/clearmatics/bn256"

//import "golang.org/x/crypto/sha3"

import "github.com/kubernetes/klog"

type Proof struct {
BA *bn256.G1
BS *bn256.G1
A *bn256.G1
B *bn256.G1

CLnG, CRnG, C_0G, DG, y_0G, gG, C_XG, y_XG []*bn256.G1

u *bn256.G1

f *FieldVector

z_A *big.Int

tCommits *GeneratorVector

that *big.Int
mu *big.Int

c *big.Int
s_sk, s_r, s_b, s_tau *big.Int

ip *InnerProduct
}

type IPStatement struct {
PrimeBase *GeneratorParams
P *bn256.G1
}

type IPWitness struct {
L *FieldVector
R *FieldVector
}

func (p *Proof) Size() int {
size := 4*POINT_SIZE + (len(p.CLnG)+len(p.CRnG)+len(p.C_0G)+len(p.DG)+len(p.y_0G)+len(p.gG)+len(p.C_XG)+len(p.y_XG))*POINT_SIZE
size += POINT_SIZE
size += len(p.f.vector) * FIELDELEMENT_SIZE
size += FIELDELEMENT_SIZE
size += len(p.tCommits.vector) * POINT_SIZE
size += 7 * FIELDELEMENT_SIZE
size += p.ip.Size()
return size
}

func (proof *Proof) hashmash1(v *big.Int) *big.Int {
var input []byte
input = append(input, convertbiginttobyte(v)...)
for i := range proof.CLnG {
input = append(input, proof.CLnG[i].Marshal()...)
}
for i := range proof.CRnG {
input = append(input, proof.CRnG[i].Marshal()...)
}
for i := range proof.C_0G {
input = append(input, proof.C_0G[i].Marshal()...)
}
for i := range proof.DG {
input = append(input, proof.DG[i].Marshal()...)
}
for i := range proof.y_0G {
input = append(input, proof.y_0G[i].Marshal()...)
}
for i := range proof.gG {
input = append(input, proof.gG[i].Marshal()...)
}
for i := range proof.C_XG {
input = append(input, proof.C_XG[i].Marshal()...)
}
for i := range proof.y_XG {
input = append(input, proof.y_XG[i].Marshal()...)
}
return reducedhash(input)
}

// function, which takes a string as
// argument and return the reverse of string.
func reverse(s string) string {
rns := []rune(s) // convert to rune
for i, j := 0, len(rns)-1; i < j; i, j = i+1, j-1 {

// swap the letters of the string,
// like first with last and so on.
rns[i], rns[j] = rns[j], rns[i]
}

// return the reversed string.
return string(rns)
}

func GenerateProof(s *Statement, witness *Witness, u *bn256.G1) *Proof {

var proof Proof
proof.u = u
params := NewGeneratorParams(128) // these can be pregenerated similarly as in DERO project
statementhash := s.Hash()

btransfer := new(big.Int).SetInt64(int64(witness.TransferAmount)) // this should be reduced
bdiff := new(big.Int).SetInt64(int64(witness.Balance)) // this should be reduced

number := btransfer.Add(btransfer, bdiff.Lsh(bdiff, 64)) // we are placing balance and left over balance, and doing a range proof of 128 bits

number_string := reverse("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + number.Text(2))
number_string_left_128bits := string(number_string[0:128])

var aLa, aRa []*big.Int // convert the amount to make sure it cannot be negative

klog.V(2).Infof("reverse %s\n", number_string_left_128bits)
for _, b := range []byte(number_string_left_128bits) {
var l, r big.Int
if b == '1' {
l.SetInt64(1)
} else {
r.Mod(new(big.Int).SetInt64(-1), bn256.Order)
}
aLa = append(aLa, &l)
aRa = append(aRa, &r)
}

//klog.V(2).Infof("aRa %+v\n", aRa)

aL := NewFieldVector(aLa)
aR := NewFieldVector(aRa)

alpha := RandomScalar()
klog.V(2).Infof("alpha %s\n", alpha.Text(16))

proof.BA = params.Commit(alpha, aL, aR)

var sLa, sRa []*big.Int
for i := 0; i < len(aLa); i++ {
sLa = append(sLa, RandomScalarFixed())
}
for i := 0; i < len(aRa); i++ {
sRa = append(sRa, RandomScalarFixed())
}
sL := NewFieldVector(sLa)
sR := NewFieldVector(sRa)
rho := RandomScalarFixed()

proof.BS = params.Commit(rho, sL, sR)

klog.V(2).Infof("Proof BA %s\n", proof.BA.String())
klog.V(2).Infof("Proof BS %s\n", proof.BS.String())

if len(s.Publickeylist) >= 1 && len(s.Publickeylist)&(len(s.Publickeylist)-1) != 0 {
panic("we need power of 2")
}

N := len(s.Publickeylist)
m := int(math.Log2(float64(N)))

if math.Pow(2, float64(m)) != float64(N) {
panic("log failed")
}

r_A := RandomScalarFixed()
r_B := RandomScalarFixed()
var aa, ba, bspecial []*big.Int
for i := 0; i < 2*m; i++ {
aa = append(aa, RandomScalarFixed())
}

witness_index := reverse(fmt.Sprintf("%0"+fmt.Sprintf("%db", m)+"%0"+fmt.Sprintf("%db", m), witness.index[1], witness.index[0]))

for _, b := range []byte(witness_index) {
var q, bs big.Int
if b == '1' {
q.SetInt64(1)
bs.Mod(new(big.Int).SetInt64(-1), bn256.Order)
} else {
bs.SetInt64(1)
}
ba = append(ba, &q)
bspecial = append(bspecial, &bs)

}

a := NewFieldVector(aa)
b := NewFieldVector(ba)

klog.V(1).Infof("witness_index of sender/receiver %s\n", witness_index)

c := a.Hadamard(NewFieldVector(bspecial))
d := a.Hadamard(a).Negate()

klog.V(2).Infof("d %s\n", d.vector[0].Text(16))

e := NewFieldVector([]*big.Int{new(big.Int).Mod(new(big.Int).Mul(a.vector[0], a.vector[m]), bn256.Order),
new(big.Int).Mod(new(big.Int).Mul(a.vector[0], a.vector[m]), bn256.Order)})

second := new(big.Int).Set(a.vector[b.vector[m].Uint64()*uint64(m)])
second.Neg(second)

proof.f = NewFieldVector([]*big.Int{a.vector[b.vector[0].Uint64()*uint64(m)], new(big.Int).Mod(second, bn256.Order)})

for i := range proof.f.vector {
klog.V(2).Infof("proof.f %d %s\n", i, proof.f.vector[i].Text(16))
}

proof.A = params.Commit(r_A, a.Concat(d).Concat(e), nil)
proof.B = params.Commit(r_B, b.Concat(c).Concat(proof.f), nil)

klog.V(2).Infof("Proof A %s\n", proof.A.String())
klog.V(2).Infof("Proof B %s\n", proof.B.String())

var v *big.Int

{ // hash mash
var input []byte
input = append(input, convertbiginttobyte(statementhash)...)
input = append(input, proof.BA.Marshal()...)
input = append(input, proof.BS.Marshal()...)
input = append(input, proof.A.Marshal()...)
input = append(input, proof.B.Marshal()...)
v = reducedhash(input)
}

var phi, chi, psi, omega FieldVector
for i := 0; i < m; i++ {
phi.vector = append(phi.vector, RandomScalarFixed())
chi.vector = append(chi.vector, RandomScalarFixed())
psi.vector = append(psi.vector, RandomScalarFixed())
omega.vector = append(omega.vector, RandomScalarFixed())

}

var P, Q, Pi, Qi [][]*big.Int
Pi = RecursivePolynomials(Pi, NewPolynomial(nil), a.SliceRaw(0, m), b.SliceRaw(0, m))
Qi = RecursivePolynomials(Qi, NewPolynomial(nil), a.SliceRaw(m, 2*m), b.SliceRaw(m, 2*m))

// transpose the matrices
for i := 0; i < m; i++ {
P = append(P, []*big.Int{})
Q = append(Q, []*big.Int{})
for j := range Pi {
P[i] = append(P[i], Pi[j][i])
Q[i] = append(Q[i], Qi[j][i])
}
}

for i := range P {
for j := range P[i] {
klog.V(2).Infof("P%d,%d %s\n", i, j, P[i][j].Text(16))
}
}

for i := 0; i < m; i++ {

{ // CLnG
var rightp, result bn256.G1
leftp := NewGeneratorVector(s.CLn).Commit(P[i])
rightp.ScalarMult(s.Publickeylist[witness.index[0]], phi.vector[i])
result.Add(leftp, &rightp)
proof.CLnG = append(proof.CLnG, &result)
//klog.V(2).Infof("CLnG %d %s\n",i, result.String())
}

{ // CRnG
var rightp, result bn256.G1
leftp := NewGeneratorVector(s.CRn).Commit(P[i])
rightp.ScalarMult(params.G, phi.vector[i])
result.Add(leftp, &rightp)
proof.CRnG = append(proof.CRnG, &result)
//klog.V(2).Infof("CRnG %d %s\n",i, result.String())
}

{ // C_0G
var rightp, result bn256.G1
leftp := NewGeneratorVector(s.C).Commit(P[i])
rightp.ScalarMult(s.Publickeylist[witness.index[0]], chi.vector[i])
result.Add(leftp, &rightp)
proof.C_0G = append(proof.C_0G, &result)
}

{ // DG
var result bn256.G1
result.ScalarMult(params.G, chi.vector[i])
proof.DG = append(proof.DG, &result)
//klog.V(2).Infof("DG %d %s\n",i, result.String())
}

{ // y_0G
var rightp, result bn256.G1
leftp := NewGeneratorVector(s.Publickeylist).Commit(P[i])
rightp.ScalarMult(s.Publickeylist[witness.index[0]], psi.vector[i])
result.Add(leftp, &rightp)
proof.y_0G = append(proof.y_0G, &result)
//klog.V(2).Infof("y_0G %d %s\n",i, result.String())
}

{ // gG
var result bn256.G1
result.ScalarMult(params.G, psi.vector[i])
proof.gG = append(proof.gG, &result)
//klog.V(2).Infof("gG %d %s\n",i, result.String())
}

{ // C_XG
var result bn256.G1
result.ScalarMult(s.D, omega.vector[i])
proof.C_XG = append(proof.C_XG, &result)
//klog.V(2).Infof("C_XG %d %s\n",i, result.String())
}

{ // y_XG
var result bn256.G1
result.ScalarMult(params.G, omega.vector[i])
proof.y_XG = append(proof.y_XG, &result)
klog.V(2).Infof("y_XG %d %s\n", i, result.String())
}

}

for i := range proof.CLnG {
klog.V(2).Infof("CLnG %d %s\n", i, proof.CLnG[i].String())
}
for i := range proof.CRnG {
klog.V(2).Infof("CRnG %d %s\n", i, proof.CRnG[i].String())
}
for i := range proof.C_0G {
klog.V(2).Infof("C_0G %d %s\n", i, proof.C_0G[i].String())
}
for i := range proof.DG {
klog.V(2).Infof("DG %d %s\n", i, proof.DG[i].String())
}
for i := range proof.y_0G {
klog.V(2).Infof("y_0G %d %s\n", i, proof.y_0G[i].String())
}
for i := range proof.gG {
klog.V(2).Infof("gG %d %s\n", i, proof.gG[i].String())
}
for i := range proof.C_XG {
klog.V(2).Infof("C_XG %d %s\n", i, proof.C_XG[i].String())
}
for i := range proof.y_XG {
klog.V(2).Infof("y_XG %d %s\n", i, proof.y_XG[i].String())
}

vPow := new(big.Int).SetInt64(1) // doesn't need reduction, since it' alredy reduced

for i := 0; i < N; i++ {
var temp bn256.G1
temp.ScalarMult(params.G, new(big.Int).Mod(new(big.Int).Mul(new(big.Int).SetUint64(uint64(witness.TransferAmount)), vPow), bn256.Order))

var poly [][]*big.Int
if i%2 == 0 {
poly = P
} else {
poly = Q
}

klog.V(2).Infof("\n\n")
for i := range proof.C_XG {
klog.V(2).Infof("C_XG before %d %s\n", i, proof.C_XG[i].String())
}

for j := range proof.C_XG {
var copy1, tmpmul bn256.G1
copy1.Set(proof.C_XG[j])
part1 := new(big.Int).Mod(poly[j][(witness.index[0]+N-(i-i%2))%N], bn256.Order)
part1 = new(big.Int).Mod(new(big.Int).Add(new(big.Int).Mod(part1.Neg(part1), bn256.Order), poly[j][(witness.index[1]+N-(i-i%2))%N]), bn256.Order)

tmpmul.ScalarMult(&temp, part1)

proof.C_XG[j].Add(&copy1, &tmpmul)

}

if i != 0 {
vPow.Mul(vPow, v)
vPow.Mod(vPow, bn256.Order)
}

//klog.V(2).Infof("vPow %d %s\n", i, vPow.Text(16)))

}

klog.V(2).Infof("\n\n")
for i := range proof.C_XG {
klog.V(2).Infof("C_XG after %d %s\n", i, proof.C_XG[i].String())
}

// for i:= range C_XG {
// klog.V(2).Infof("C_XG %d %s\n", i, C_XG[i].String())
//}

// calculate w hashmash

w := proof.hashmash1(v)

{
var input []byte

input = append(input, convertbiginttobyte(v)...)
for i := range proof.CLnG {
input = append(input, proof.CLnG[i].Marshal()...)
}
for i := range proof.CRnG {
input = append(input, proof.CRnG[i].Marshal()...)
}

for i := range proof.C_0G {
input = append(input, proof.C_0G[i].Marshal()...)
}
for i := range proof.DG {
input = append(input, proof.DG[i].Marshal()...)
}
for i := range proof.y_0G {
input = append(input, proof.y_0G[i].Marshal()...)
}
for i := range proof.gG {
input = append(input, proof.gG[i].Marshal()...)
}
for i := range proof.C_XG {
input = append(input, proof.C_XG[i].Marshal()...)
}
for i := range proof.y_XG {
input = append(input, proof.y_XG[i].Marshal()...)
}
klog.V(2).Infof("whash %s %s\n", reducedhash(input).Text(16), w.Text(16))

}

proof.f = b.Times(w).Add(a)

for i := range proof.f.vector {
klog.V(2).Infof("proof.f %d %s\n", i, proof.f.vector[i].Text(16))
}

ttttt := new(big.Int).Mod(new(big.Int).Mul(r_B, w), bn256.Order)
proof.z_A = new(big.Int).Mod(new(big.Int).Add(ttttt, r_A), bn256.Order)

klog.V(2).Infof("proofz_A %s\n", proof.z_A.Text(16))

y := reducedhash(convertbiginttobyte(w))

klog.V(2).Infof("yyyyyyyyyy %s\n", y.Text(16))

ys_raw := []*big.Int{new(big.Int).SetUint64(1)}
for i := 1; i < 128; i++ {
var tt big.Int
tt.Mul(ys_raw[len(ys_raw)-1], y)
tt.Mod(&tt, bn256.Order)
ys_raw = append(ys_raw, &tt)
}
ys := NewFieldVector(ys_raw)

z := reducedhash(convertbiginttobyte(y))
klog.V(2).Infof("zzzzzzzzzz %s %s\n", z.Text(16))

zs := []*big.Int{new(big.Int).Exp(z, new(big.Int).SetUint64(2), bn256.Order), new(big.Int).Exp(z, new(big.Int).SetUint64(3), bn256.Order)}
for i := range zs {
klog.V(2).Infof("zs %d %s\n", i, zs[i].Text(16))
}

twos := []*big.Int{new(big.Int).SetUint64(1)}
for i := 1; i < 64; i++ {
var tt big.Int
tt.Mul(twos[len(twos)-1], new(big.Int).SetUint64(2))
tt.Mod(&tt, bn256.Order)
twos = append(twos, &tt)
}

twoTimesZs := []*big.Int{}
for i := 0; i < 2; i++ {
for j := 0; j < 64; j++ {
var tt big.Int
tt.Mul(zs[i], twos[j])
tt.Mod(&tt, bn256.Order)
twoTimesZs = append(twoTimesZs, &tt)

klog.V(2).Infof("twoTimesZssss ============= %d %s\n", i*32+j, twoTimesZs[i*32+j].Text(16))

}
}

tmp := aL.AddConstant(new(big.Int).Mod(new(big.Int).Neg(z), bn256.Order))
lPoly := NewFieldVectorPolynomial(tmp, sL)
for i := range lPoly.coefficients {
for j := range lPoly.coefficients[i].vector {
//klog.V(2).Infof("tmp %d,%d %s\n", i,j, tmp.vector[j].Text(16))

klog.V(2).Infof("lPoly %d,%d %s\n", i, j, lPoly.coefficients[i].vector[j].Text(16))
}
}

rPoly := NewFieldVectorPolynomial(ys.Hadamard(aR.AddConstant(z)).Add(NewFieldVector(twoTimesZs)), sR.Hadamard(ys))
for i := range rPoly.coefficients {
for j := range rPoly.coefficients[i].vector {
//klog.V(2).Infof("tmp %d,%d %s\n", i,j, tmp.vector[j].Text(16))

klog.V(2).Infof("rPoly %d,%d %s\n", i, j, rPoly.coefficients[i].vector[j].Text(16))
}
}

tPolyCoefficients := lPoly.InnerProduct(rPoly) // just an array of BN Reds... should be length 3
for j := range tPolyCoefficients {
klog.V(2).Infof("tPolyCoefficients %d,%d %s\n", 0, j, tPolyCoefficients[j].Text(16))
}

polyCommitment := NewPolyCommitment(params, tPolyCoefficients)
proof.tCommits = NewGeneratorVector(polyCommitment.GetCommitments())

for j := range proof.tCommits.vector {
klog.V(2).Infof("tCommits %d %s\n", j, proof.tCommits.vector[j].String())
}