gitee.com/lh-her-team/common@v1.5.1/crypto/bulletproofs/bulletproofs_cgo/proof.go (about)

     1  //+build linux,amd64
     2  
     3  /*
     4    Bulletproofs provide zero-knowledge proof for the statement integer x in the range [0, 2^64)
     5  */
     6  
     7  package bulletproofs_cgo
     8  
     9  //#cgo CFLAGS: -g -O2 -pthread -I./c_include
    10  //#cgo LDFLAGS: -L./c_lib -lbulletproofs -lm -L/usr/lib/x86_64-linux-gnu -ldl
    11  //#cgo LDFLAGS: -L/usr/bin/ld -lpthread
    12  //#include <stdlib.h>
    13  //#include <stdio.h>
    14  //#include <string.h>
    15  //#include <bulletproofs.h>
    16  import "C"
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"unsafe"
    21  )
    22  
    23  // ProveRandomOpening Generate proof with randomly pick opening
    24  // x: prove x is in the range [0, 2^64)
    25  // return 1: proof in []byte
    26  // return 2: commitment of x: xB + rB'
    27  // return 3: opening, the randomness r used to commit x (secret key)
    28  func ProveRandomOpening(x uint64) ([]byte, []byte, []byte, error) {
    29  	var proofData C.proof_content
    30  	ret := C.bulletproofs_prove_with_random_opening(&proofData, C.uint(x))
    31  	if ret != OK {
    32  		return nil, nil, nil, fmt.Errorf("fail to generate proof: " + getErrMsg(int64(ret)))
    33  	}
    34  	proofContent := C.GoBytes(proofData.proof, C.int(SINGLE_PROOF_SIZE))
    35  	commitment := C.GoBytes(proofData.commitment, C.int(POINT_SIZE))
    36  	opening := C.GoBytes(proofData.opening, C.int(POINT_SIZE))
    37  	defer C.free(proofData.proof)
    38  	defer C.free(proofData.commitment)
    39  	defer C.free(proofData.opening)
    40  	return proofContent, commitment, opening, nil
    41  }
    42  
    43  // ProveSpecificOpening Generate proof with a chosen opening
    44  // x: prove x is in the range [0, 2^64)
    45  // opening: the chosen randomness to commit x (secret key)
    46  // return 1: proof in []byte
    47  // return 2: commitment of x using opening
    48  func ProveSpecificOpening(x uint64, opening []byte) ([]byte, []byte, error) {
    49  	if len(opening) != POINT_SIZE {
    50  		return nil, nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": commitment opening")
    51  	}
    52  	var proofData C.proof_content
    53  	ret := C.bulletproofs_prove_with_specific_opening(&proofData, C.uint(x), unsafe.Pointer(&opening[0]))
    54  	if ret != OK {
    55  		return nil, nil, fmt.Errorf("fail to generate proof: " + getErrMsg(int64(ret)))
    56  	}
    57  	proofContent := C.GoBytes(proofData.proof, C.int(SINGLE_PROOF_SIZE))
    58  	commitment := C.GoBytes(proofData.commitment, C.int(POINT_SIZE))
    59  	defer C.free(proofData.proof)
    60  	defer C.free(proofData.commitment)
    61  	defer C.free(proofData.opening)
    62  	return proofContent, commitment, nil
    63  }
    64  
    65  // Verify Verify the validity of a proof
    66  // proof: the zero-knowledge proof proving the number committed in commitment is in the range [0, 2^64)
    67  // commitment: commitment bindingly hiding the number x
    68  // return: true on valid proof, false otherwise
    69  func Verify(proof []byte, commitment []byte) (bool, error) {
    70  	if len(proof) != SINGLE_PROOF_SIZE || len(commitment) != POINT_SIZE {
    71  		return false, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": proof length should be 672-byte and commitment length should be 32-byte")
    72  	}
    73  	ret := C.bulletproofs_verify_single(unsafe.Pointer(&proof[0]), unsafe.Pointer(&commitment[0]))
    74  	if ret != OK {
    75  		return false, nil
    76  	}
    77  	return true, nil
    78  }
    79  
    80  // ProveAfterAddNum Update a commitment of x (xB + rB') to x + y and generate a proof of it with the same opening
    81  // x, y: prove x + y is in the range [0, 2^64)
    82  // openingX: the randomness r used to commit x, also used in the new proof
    83  // commitmentX: commitment of x: xB + rB'
    84  // return 1: proof in []byte
    85  // return 2: commitment of x + y: (x + y)B + rB'
    86  func ProveAfterAddNum(x, y uint64, openingX, commitmentX []byte) ([]byte, []byte, error) {
    87  	ret, err := PedersenVerify(commitmentX, openingX, x)
    88  	if err != nil {
    89  		return nil, nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": " + err.Error())
    90  	}
    91  	if ret != true {
    92  		return nil, nil, fmt.Errorf(ERR_MSG_DEFAULT + ": verify fail")
    93  	}
    94  	z := x + y
    95  	if int64(z) < 0 {
    96  		return nil, nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": result summation is not in the range [0, 2^64)")
    97  	}
    98  	proof, commitment, err := ProveSpecificOpening(z, openingX)
    99  	if err != nil {
   100  		return nil, nil, err
   101  	}
   102  	commitmentDup, err := PedersenAddNum(commitmentX, y)
   103  	if err != nil {
   104  		return nil, nil, fmt.Errorf("fail to generate proof: " + err.Error())
   105  	}
   106  	if bytes.Compare(commitment, commitmentDup) != 0 {
   107  		return nil, nil, fmt.Errorf("fail to generate proof: result summation is not in the range [0, 2^64)")
   108  	}
   109  	return proof, commitment, nil
   110  }
   111  
   112  // ProveAfterAddCommitment Update commitments of x (xB + rB') and y (yB + sB') to x + y and generate a proof of it with the sum of the two opening
   113  // x, y: prove x + y is in the range [0, 2^64)
   114  // openingX: the randomness r used to commit x
   115  // openingY: the randomness s used to commit y
   116  // commitmentX: commitment of x: xB + rB'
   117  // commitmentX: commitment of y: yB + sB'
   118  // return 1: proof in []byte
   119  // return 2: commitment of x + y: (x + y)B + (r + s)B'
   120  // return 3: new opening for the result commitment (r + s)
   121  func ProveAfterAddCommitment(x, y uint64, openingX, openingY, commitmentX, commitmentY []byte) ([]byte, []byte, []byte, error) {
   122  	ret, err := PedersenVerify(commitmentX, openingX, x)
   123  	if err != nil {
   124  		return nil, nil, nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": " + err.Error())
   125  	}
   126  	if ret != true {
   127  		return nil, nil, nil, fmt.Errorf(ERR_MSG_DEFAULT + ": verify fail")
   128  	}
   129  	ret, err = PedersenVerify(commitmentY, openingY, y)
   130  	if err != nil {
   131  		return nil, nil, nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": " + err.Error())
   132  	}
   133  	if ret != true {
   134  		return nil, nil, nil, fmt.Errorf(ERR_MSG_DEFAULT + ": verify fail")
   135  	}
   136  	z := x + y
   137  	if int64(z) < 0 {
   138  		return nil, nil, nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": result summation is not in the range [0, 2^64)")
   139  	}
   140  	commitmentDup, opening, err := PedersenAddCommitmentWithOpening(commitmentX, commitmentY, openingX, openingY)
   141  	if err != nil {
   142  		return nil, nil, nil, fmt.Errorf("fail to generate proof: " + err.Error())
   143  	}
   144  	proof, commitment, err := ProveSpecificOpening(z, opening)
   145  	if err != nil {
   146  		return nil, nil, nil, err
   147  	}
   148  	if bytes.Compare(commitment, commitmentDup) != 0 {
   149  		return nil, nil, nil, fmt.Errorf("fail to generate proof: result summation is not in the range [0, 2^64)")
   150  	}
   151  	return proof, commitment, opening, nil
   152  }
   153  
   154  // ProveAfterSubNum Update a commitment of x (xB + rB') to x - y and generate a proof of it with the same opening
   155  // x, y: prove x - y is in the range [0, 2^64)
   156  // openingX: the randomness r used to commit x, also used in the new proof
   157  // commitmentX: commitment of x (old commitment)
   158  // return 1: proof in []byte
   159  // return 2: commitment of x - y: (x - y)B + rB'
   160  func ProveAfterSubNum(x, y uint64, openingX, commitmentX []byte) ([]byte, []byte, error) {
   161  	ret, err := PedersenVerify(commitmentX, openingX, x)
   162  	if err != nil {
   163  		return nil, nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": " + err.Error())
   164  	}
   165  	if ret != true {
   166  		return nil, nil, fmt.Errorf(ERR_MSG_DEFAULT + ": verify fail")
   167  	}
   168  	z := x - y
   169  	if int64(z) < 0 {
   170  		return nil, nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": result subtraction is not in the range [0, 2^64)")
   171  	}
   172  	proof, commitment, err := ProveSpecificOpening(z, openingX)
   173  	if err != nil {
   174  		return nil, nil, err
   175  	}
   176  	commitmentDup, err := PedersenSubNum(commitmentX, y)
   177  	if err != nil {
   178  		return nil, nil, fmt.Errorf("fail to generate proof: " + err.Error())
   179  	}
   180  	if bytes.Compare(commitment, commitmentDup) != 0 {
   181  		return nil, nil, fmt.Errorf("fail to generate proof: result subtraction is not in the range [0, 2^64)")
   182  	}
   183  	return proof, commitment, nil
   184  }
   185  
   186  // ProveAfterSubCommitment Update commitments of x (xB + rB') and y (yB + sB') to x - y and generate a proof of it with the subtraction of the two openings
   187  // x, y: prove x + y is in the range [0, 2^64)
   188  // openingX: the randomness r used to commit x
   189  // openingY: the randomness s used to commit y
   190  // commitmentX: commitment of x: xB + rB'
   191  // commitmentX: commitment of y: yB + sB'
   192  // return 1: proof in []byte
   193  // return 2: commitment of x - y: (x - y)B + (r - s)B'
   194  // return 3: new opening for the result commitment (r - s)
   195  func ProveAfterSubCommitment(x, y uint64, openingX, openingY, commitmentX, commitmentY []byte) ([]byte, []byte, []byte, error) {
   196  	ret, err := PedersenVerify(commitmentX, openingX, x)
   197  	if err != nil {
   198  		return nil, nil, nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": " + err.Error())
   199  	}
   200  	if ret != true {
   201  		return nil, nil, nil, fmt.Errorf(ERR_MSG_DEFAULT + ": verify fail")
   202  	}
   203  	ret, err = PedersenVerify(commitmentY, openingY, y)
   204  	if err != nil {
   205  		return nil, nil, nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": " + err.Error())
   206  	}
   207  	if ret != true {
   208  		return nil, nil, nil, fmt.Errorf(ERR_MSG_DEFAULT + ": verify fail")
   209  	}
   210  	z := x - y
   211  	if int64(z) < 0 {
   212  		return nil, nil, nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": result subtraction is not in the range [0, 2^64)")
   213  	}
   214  	commitmentDup, opening, err := PedersenSubCommitmentWithOpening(commitmentX, commitmentY, openingX, openingY)
   215  	if err != nil {
   216  		return nil, nil, nil, fmt.Errorf("fail to generate proof: " + err.Error())
   217  	}
   218  	proof, commitment, err := ProveSpecificOpening(z, opening)
   219  	if err != nil {
   220  		return nil, nil, nil, err
   221  	}
   222  	if bytes.Compare(commitment, commitmentDup) != 0 {
   223  		return nil, nil, nil, fmt.Errorf("fail to generate proof: result subtraction is not in the range [0, 2^64)")
   224  	}
   225  	return proof, commitment, opening, nil
   226  }
   227  
   228  // ProveAfterMulNum Update commitment of x (xB + rB') to commitment of x * y and generate a proof of it with the an updated opening, where y is a value
   229  // x, y: prove x * y is in the range [0, 2^64)
   230  // openingX: the randomness r used to commit x
   231  // commitmentX: commitment of x: xB + rB'
   232  // return 1: proof in []byte
   233  // return 2: commitment of x * y: (x * y)B + (r * y)B'
   234  // return 3: new opening for the result commitment: r * y
   235  func ProveAfterMulNum(x, y uint64, openingX, commitmentX []byte) ([]byte, []byte, []byte, error) {
   236  	ret, err := PedersenVerify(commitmentX, openingX, x)
   237  	if err != nil {
   238  		return nil, nil, nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": " + err.Error())
   239  	}
   240  	if ret != true {
   241  		return nil, nil, nil, fmt.Errorf(ERR_MSG_DEFAULT + ": verify fail")
   242  	}
   243  	z := x * y
   244  	if int64(z) < 0 {
   245  		return nil, nil, nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": result multiplication is not in the range [0, 2^64)")
   246  	}
   247  	var opening [POINT_SIZE]byte
   248  	openingSlice := opening[:]
   249  	rt := C.pedersen_scalar_mul(unsafe.Pointer(&openingSlice[0]), unsafe.Pointer(&openingX[0]), C.uint(y))
   250  	if rt != OK {
   251  		return nil, nil, nil, fmt.Errorf("fail to compute new opening for the multiplicaiton")
   252  	}
   253  	proof, commitment, err := ProveSpecificOpening(z, openingSlice)
   254  	if err != nil {
   255  		return nil, nil, nil, err
   256  	}
   257  	commitmentDup, openingDup, err := PedersenMulNumWithOpening(commitmentX, openingX, y)
   258  	if err != nil {
   259  		return nil, nil, nil, fmt.Errorf("fail to generate proof: " + err.Error())
   260  	}
   261  	if bytes.Compare(commitment, commitmentDup) != 0 || bytes.Compare(openingSlice, openingDup) != 0 {
   262  		return nil, nil, nil, fmt.Errorf("fail to generate proof: result multiplication is not in the range [0, 2^64)")
   263  	}
   264  	return proof, commitment, openingSlice, nil
   265  }