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

     1  //+build linux,amd64
     2  
     3  /*
     4    Pedersen commitment is a commitment scheme which bindingly hides a value with a randomness (called opening). This commitment scheme has two major properties: hiding and binding.
     5    Hiding: given a commitment, it is hard to guess the right value committed to it.
     6    Binding: given a commitment, the value committed to it, and the opening, it is hard to find another value-opening pair for the commitment.
     7    A commitment can be opened. This does not mean that the committed value can be extracted from it like a decryption on a ciphertext. It means that with the opening and the value, the validity of this commitment can be verified.
     8  */
     9  
    10  package bulletproofs_cgo
    11  
    12  //#cgo CFLAGS: -g -O2 -pthread -I./c_include
    13  //#cgo LDFLAGS: -L./c_lib -lbulletproofs -lm -L/usr/lib/x86_64-linux-gnu -ldl
    14  //#cgo LDFLAGS: -L/usr/bin/ld -lpthread
    15  //#include <stdlib.h>
    16  //#include <stdio.h>
    17  //#include <string.h>
    18  //#include <bulletproofs.h>
    19  import "C"
    20  import (
    21  	"fmt"
    22  	"unsafe"
    23  )
    24  
    25  // PedersenRNG generate a truly random scalar (which can be used as an opening to generate a commitment).
    26  // return: a random scalar in []byte format
    27  func PedersenRNG() ([]byte, error) {
    28  	var r [POINT_SIZE]byte
    29  	randomness := r[:]
    30  	ret := C.bulletproofs_generate_random_scalar(unsafe.Pointer(&randomness[0]))
    31  	if ret != OK {
    32  		return nil, fmt.Errorf("fail to generate random scalar: " + getErrMsg(int64(ret)))
    33  	}
    34  	return randomness, nil
    35  }
    36  
    37  // PedersenCommitRandomOpening compute Pedersen commitment on a value x with a randomly chosen opening
    38  // x: the value to commit
    39  // return1: commitment C = xB + rB'
    40  // return2: opening r (randomly picked)
    41  func PedersenCommitRandomOpening(x uint64) ([]byte, []byte, error) {
    42  	var commitment [POINT_SIZE]byte
    43  	var opening [POINT_SIZE]byte
    44  	commitmentSlice := commitment[:]
    45  	openingSlice := opening[:]
    46  	ret := C.pedersen_commit_with_random_opening(unsafe.Pointer(&commitmentSlice[0]), unsafe.Pointer(&openingSlice[0]), C.uint(x))
    47  	if ret != OK {
    48  		return nil, nil, fmt.Errorf("fail to generate commitment:" + getErrMsg(int64(ret)))
    49  	}
    50  	return commitmentSlice, openingSlice, nil
    51  }
    52  
    53  // PedersenCommitSpecificOpening compute Pedersen commitment on a value x with a given opening
    54  // x: the value to commit
    55  // return1: commitment C = xB + rB'
    56  func PedersenCommitSpecificOpening(x uint64, r []byte) ([]byte, error) {
    57  	if len(r) != POINT_SIZE {
    58  		return nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": commitment opening length should 32-byte")
    59  	}
    60  	var commitment [POINT_SIZE]byte
    61  	commitmentSlice := commitment[:]
    62  	ret := C.pedersen_commit_with_specific_opening(unsafe.Pointer(&commitmentSlice[0]), unsafe.Pointer(&r[0]), C.uint(x))
    63  	if ret != OK {
    64  		return nil, fmt.Errorf("fail to generate commitment: " + getErrMsg(int64(ret)))
    65  	}
    66  	return commitmentSlice, nil
    67  }
    68  
    69  // PedersenVerify verify the validity of a commitment with respect to a value-opening pair
    70  // commitment: the commitment to be opened or verified: xB + rB'
    71  // opening: the opening of the commitment: r
    72  // value: the value claimed being binding to commitment: x
    73  // return1: true if commitment is valid, false otherwise
    74  func PedersenVerify(commitment, opening []byte, value uint64) (bool, error) {
    75  	if len(commitment) != POINT_SIZE || len(opening) != POINT_SIZE {
    76  		return false, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": commitment or opening length should 32-byte")
    77  	}
    78  	ret := C.pedersen_verify(unsafe.Pointer(&commitment[0]), unsafe.Pointer(&opening[0]), C.uint(value))
    79  	if ret == 1 {
    80  		return true, nil
    81  	}
    82  	return false, nil
    83  }
    84  
    85  // PedersenNeg Compute a commitment to -x from a commitment to x without revealing the value x
    86  // commitment: C = xB + rB'
    87  // value: the value y
    88  // return1: the new commitment to x + y: C' = (x + y)B + rB'
    89  func PedersenNeg(commitment []byte) ([]byte, error) {
    90  	if len(commitment) != POINT_SIZE {
    91  		return nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": commitment length should 32-byte")
    92  	}
    93  	var result [POINT_SIZE]byte
    94  	resultSlice := result[:]
    95  	ret := C.pedersen_point_neg(unsafe.Pointer(&resultSlice[0]), unsafe.Pointer(&commitment[0]))
    96  	if ret != OK {
    97  		return nil, fmt.Errorf("fail to compute negation: " + getErrMsg(int64(ret)))
    98  	}
    99  	return resultSlice, nil
   100  }
   101  
   102  // PedersenNegOpening Compute the negation of opening. Openings are big numbers with 256 bits.
   103  // opening: the opening r to be negated
   104  // return: the result opening: -r
   105  func PedersenNegOpening(opening []byte) ([]byte, error) {
   106  	if len(opening) != POINT_SIZE {
   107  		return nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": opening length should 32-byte")
   108  	}
   109  	var openingNeg [POINT_SIZE]byte
   110  	openingSlice := openingNeg[:]
   111  	ret := C.pedersen_scalar_neg(unsafe.Pointer(&openingSlice[0]),
   112  		unsafe.Pointer(&opening[0]))
   113  	if ret != OK {
   114  		return nil, fmt.Errorf("fail to compute opening negation: " + getErrMsg(int64(ret)))
   115  	}
   116  	return openingSlice, nil
   117  }
   118  
   119  // PedersenAddNum Compute a commitment to x + y from a commitment to x without revealing the value x, where y is a scalar
   120  // commitment: C = xB + rB'
   121  // value: the value y
   122  // return1: the new commitment to x + y: C' = (x + y)B + rB'
   123  func PedersenAddNum(commitment []byte, value uint64) ([]byte, error) {
   124  	if len(commitment) != POINT_SIZE {
   125  		return nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": commitment length should 32-byte")
   126  	}
   127  	var result [POINT_SIZE]byte
   128  	resultSlice := result[:]
   129  	ret := C.pedersen_commitment_add_num(unsafe.Pointer(&resultSlice[0]), unsafe.Pointer(&commitment[0]), C.uint(value))
   130  	if ret != OK {
   131  		return nil, fmt.Errorf("fail to compute Pedersen addition: " + getErrMsg(int64(ret)))
   132  	}
   133  	return resultSlice, nil
   134  }
   135  
   136  // PedersenAddCommitment Compute a commitment to x + y from commitments to x and y, without revealing the value x and y
   137  // commitment1: commitment to x: Cx = xB + rB'
   138  // commitment2: commitment to y: Cy = yB + sB'
   139  // return: commitment to x + y: C = (x + y)B + (r + s)B'
   140  func PedersenAddCommitment(commitment1, commitment2 []byte) ([]byte, error) {
   141  	if len(commitment1) != POINT_SIZE || len(commitment2) != POINT_SIZE {
   142  		return nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": commitment length should 32-byte")
   143  	}
   144  	var commitment [POINT_SIZE]byte
   145  	commitmentSlice := commitment[:]
   146  	ret := C.pedersen_point_add(unsafe.Pointer(&commitmentSlice[0]),
   147  		unsafe.Pointer(&commitment1[0]),
   148  		unsafe.Pointer(&commitment2[0]))
   149  	if ret != OK {
   150  		return nil, fmt.Errorf("fail to compute Pedersen addition: " + getErrMsg(int64(ret)))
   151  	}
   152  	return commitmentSlice, nil
   153  }
   154  
   155  // PedersenAddOpening Compute the sum of two openings. Openings are big numbers with 256 bits.
   156  // opening1, opening2: the two openings r and s to be summed
   157  // return: the result opening: r + s
   158  func PedersenAddOpening(opening1, opening2 []byte) ([]byte, error) {
   159  	if len(opening1) != POINT_SIZE || len(opening2) != POINT_SIZE {
   160  		return nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": opening length should 32-byte")
   161  	}
   162  	var opening [POINT_SIZE]byte
   163  	openingSlice := opening[:]
   164  	ret := C.pedersen_scalar_add(unsafe.Pointer(&openingSlice[0]),
   165  		unsafe.Pointer(&opening1[0]),
   166  		unsafe.Pointer(&opening2[0]))
   167  	if ret != OK {
   168  		return nil, fmt.Errorf("fail to compute opening addition: " + getErrMsg(int64(ret)))
   169  	}
   170  	return openingSlice, nil
   171  }
   172  
   173  // PedersenAddCommitmentWithOpening Compute a commitment to x + y without revealing the value x and y
   174  // commitment1: commitment to x: Cx = xB + rB'
   175  // commitment2: commitment to y: Cy = yB + sB'
   176  // return1: the new commitment to x + y: C' = (x + y)B + rB'
   177  // return2: the new opening r + s
   178  func PedersenAddCommitmentWithOpening(commitment1, commitment2, opening1, opening2 []byte) ([]byte, []byte, error) {
   179  	commitment, err := PedersenAddCommitment(commitment1, commitment2)
   180  	if err != nil {
   181  		return nil, nil, err
   182  	}
   183  	opening, err := PedersenAddOpening(opening1, opening2)
   184  	if err != nil {
   185  		return nil, nil, err
   186  	}
   187  	return commitment, opening, nil
   188  }
   189  
   190  // PedersenSubNum Compute a commitment to x - y from a commitment to x without revealing the value x, where y is a scalar
   191  // commitment: C = xB + rB'
   192  // value: the value y
   193  // return1: the new commitment to x - y: C' = (x - y)B + rB'
   194  func PedersenSubNum(commitment []byte, value uint64) ([]byte, error) {
   195  	if len(commitment) != POINT_SIZE {
   196  		return nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": commitment length should 32-byte")
   197  	}
   198  	var result [POINT_SIZE]byte
   199  	resultSlice := result[:]
   200  	ret := C.pedersen_commitment_sub_num(unsafe.Pointer(&resultSlice[0]), unsafe.Pointer(&commitment[0]), C.uint(value))
   201  	if ret != OK {
   202  		return nil, fmt.Errorf("fail to compute Pedersen subtraction: " + getErrMsg(int64(ret)))
   203  	}
   204  	return resultSlice, nil
   205  }
   206  
   207  // PedersenSubCommitment Compute a commitment to x - y from commitments to x and y, without revealing the value x and y
   208  // commitment1: commitment to x: Cx = xB + rB'
   209  // commitment2: commitment to y: Cy = yB + sB'
   210  // return: commitment to x - y: C = (x - y)B + (r - s)B'
   211  func PedersenSubCommitment(commitment1, commitment2 []byte) ([]byte, error) {
   212  	if len(commitment1) != POINT_SIZE || len(commitment2) != POINT_SIZE {
   213  		return nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": commitment length should 32-byte")
   214  	}
   215  	var commitment [POINT_SIZE]byte
   216  	commitmentSlice := commitment[:]
   217  	ret := C.pedersen_point_sub(unsafe.Pointer(&commitmentSlice[0]),
   218  		unsafe.Pointer(&commitment1[0]),
   219  		unsafe.Pointer(&commitment2[0]))
   220  	if ret != OK {
   221  		return nil, fmt.Errorf("fail to compute Pedersen subtraction: " + getErrMsg(int64(ret)))
   222  	}
   223  	return commitmentSlice, nil
   224  }
   225  
   226  // PedersenSubOpening Compute opening1 - opening2. Openings are big numbers with 256 bits.
   227  // opening1, opening2: two openings r and s
   228  // return: the result opening r - s
   229  func PedersenSubOpening(opening1, opening2 []byte) ([]byte, error) {
   230  	if len(opening1) != POINT_SIZE || len(opening2) != POINT_SIZE {
   231  		return nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": commitment or opening length should 32-byte")
   232  	}
   233  	var opening [POINT_SIZE]byte
   234  	openingSlice := opening[:]
   235  	ret := C.pedersen_scalar_sub(unsafe.Pointer(&openingSlice[0]),
   236  		unsafe.Pointer(&opening1[0]),
   237  		unsafe.Pointer(&opening2[0]))
   238  	if ret != OK {
   239  		return nil, fmt.Errorf("fail to compute opening subtraction: " + getErrMsg(int64(ret)))
   240  	}
   241  	return openingSlice, nil
   242  }
   243  
   244  // PedersenSubCommitmentWithOpening Compute a commitment to x - y without from two commitments of x and y respectively
   245  // commitment1: commitment to x: Cx = xB + rB'
   246  // commitment2: commitment to y: Cy = yB + sB'
   247  // return1: the new commitment to x - y: C' = (x - y)B + (r - s)B'
   248  // return2: the new opening r - s
   249  func PedersenSubCommitmentWithOpening(commitment1, commitment2, opening1, opening2 []byte) ([]byte, []byte, error) {
   250  	commitment, err := PedersenSubCommitment(commitment1, commitment2)
   251  	if err != nil {
   252  		return nil, nil, err
   253  	}
   254  	opening, err := PedersenSubOpening(opening1, opening2)
   255  	if err != nil {
   256  		return nil, nil, err
   257  	}
   258  	return commitment, opening, nil
   259  }
   260  
   261  // PedersenMulNum Compute a commitment to x * y from a commitment to x and an integer y, without revealing the value x and y
   262  // commitment1: commitment to x: Cx = xB + rB'
   263  // value: integer value y
   264  // return: commitment to x * y: C = (x * y)B + (r * y)B'
   265  func PedersenMulNum(commitment1 []byte, value uint64) ([]byte, error) {
   266  	if len(commitment1) != POINT_SIZE {
   267  		return nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": commitment length should 32-byte")
   268  	}
   269  	var commitment [POINT_SIZE]byte
   270  	commitmentSlice := commitment[:]
   271  	ret := C.pedersen_commitment_mul_num(unsafe.Pointer(&commitmentSlice[0]),
   272  		unsafe.Pointer(&commitment1[0]),
   273  		C.uint(value))
   274  	if ret != OK {
   275  		return nil, fmt.Errorf("fail to compute Pedersen multiplication: " + getErrMsg(int64(ret)))
   276  	}
   277  	return commitmentSlice, nil
   278  }
   279  
   280  // PedersenMulOpening Compute opening1 * integer. Openings are big numbers with 256 bits.
   281  // opening1: the input opening r
   282  // value: the input integer value y
   283  // return: the multiplication r * y as a big number with 256 bits in []byte form
   284  func PedersenMulOpening(opening1 []byte, value uint64) ([]byte, error) {
   285  	if len(opening1) != POINT_SIZE {
   286  		return nil, fmt.Errorf(ERR_MSG_INVALID_INPUT + ": opening length should 32-byte")
   287  	}
   288  	var opening [POINT_SIZE]byte
   289  	openingSlice := opening[:]
   290  	ret := C.pedersen_scalar_mul(unsafe.Pointer(&openingSlice[0]),
   291  		unsafe.Pointer(&opening1[0]),
   292  		C.uint(value))
   293  	if ret != OK {
   294  		return nil, fmt.Errorf("fail to compute opening multiplication: " + getErrMsg(int64(ret)))
   295  	}
   296  	return openingSlice, nil
   297  }
   298  
   299  // PedersenMulNumWithOpening Compute a commitment to x * y from a commitment to x and an integer y, without revealing the value x and y
   300  // commitment: commitment to x: Cx = xB + rB'
   301  // opening: opening to Cx: r
   302  // value: integer value y
   303  // return1: commitment to x * y: C = (x * y)B + (r * y)B'
   304  // return2: opening to the result commitment: r * y
   305  func PedersenMulNumWithOpening(commitment []byte, opening []byte, value uint64) ([]byte, []byte, error) {
   306  	commitmentNew, err := PedersenMulNum(commitment, value)
   307  	if err != nil {
   308  		return nil, nil, err
   309  	}
   310  	openingNew, err := PedersenMulOpening(opening, value)
   311  	if err != nil {
   312  		return nil, nil, err
   313  	}
   314  	return commitmentNew, openingNew, nil
   315  }