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 }