github.com/iden3/go-circom-witnesscalc@v0.2.1-0.20230314155733-dd1f248a91b6/utils.go (about) 1 package witnesscalc 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "hash/fnv" 7 "math/big" 8 "reflect" 9 ) 10 11 // swap the order of the bytes in a slice. This allows flipping the endianness. 12 func swap(b []byte) []byte { 13 bs := make([]byte, len(b)) 14 for i := 0; i < len(b); i++ { 15 bs[len(b)-1-i] = b[i] 16 } 17 return bs 18 } 19 20 // parseInput is a recurisve helper function for ParseInputs 21 func parseInput(v interface{}) (interface{}, error) { 22 rv := reflect.ValueOf(v) 23 switch rv.Kind() { 24 case reflect.String: 25 n, ok := new(big.Int).SetString(v.(string), 0) 26 if !ok { 27 return nil, fmt.Errorf("Error parsing input %v", v) 28 } 29 return n, nil 30 case reflect.Float64: 31 return new(big.Int).SetInt64(int64(v.(float64))), nil 32 case reflect.Slice: 33 res := make([]interface{}, rv.Len()) 34 for i := 0; i < rv.Len(); i++ { 35 var err error 36 res[i], err = parseInput(rv.Index(i).Interface()) 37 if err != nil { 38 return nil, fmt.Errorf("Error parsing input %v: %w", v, err) 39 } 40 } 41 return res, nil 42 default: 43 return nil, fmt.Errorf("Unexpected type for input %v: %T", v, v) 44 } 45 } 46 47 // ParseInputs parses WitnessCalc inputs from JSON that consist of a map of 48 // types which contain a recursive combination of: numbers, base-10 encoded 49 // numbers in string format, arrays. 50 func ParseInputs(inputsJSON []byte) (map[string]interface{}, error) { 51 inputsRAW := make(map[string]interface{}) 52 if err := json.Unmarshal(inputsJSON, &inputsRAW); err != nil { 53 return nil, err 54 } 55 inputs := make(map[string]interface{}) 56 for inputName, inputValue := range inputsRAW { 57 v, err := parseInput(inputValue) 58 if err != nil { 59 return nil, err 60 } 61 inputs[inputName] = v 62 } 63 return inputs, nil 64 } 65 66 // _flatSlice is a recursive helper function for flatSlice. 67 func _flatSlice(acc *[]*big.Int, v interface{}) { 68 rv := reflect.ValueOf(v) 69 switch rv.Kind() { 70 case reflect.Slice: 71 for i := 0; i < rv.Len(); i++ { 72 _flatSlice(acc, rv.Index(i).Interface()) 73 } 74 default: 75 *acc = append(*acc, v.(*big.Int)) 76 } 77 } 78 79 // flatSlice takes a structure that contains a recursive combination of slices 80 // and *big.Int and flattens it into a single slice. 81 func flatSlice(v interface{}) []*big.Int { 82 res := make([]*big.Int, 0) 83 _flatSlice(&res, v) 84 return res 85 } 86 87 // fnvHash returns the 64 bit FNV-1a hash split into two 32 bit values: (MSB, LSB) 88 func fnvHash(s string) (int32, int32) { 89 hash := fnv.New64a() 90 hash.Write([]byte(s)) 91 h := hash.Sum64() 92 return int32(h >> 32), int32(h & 0xffffffff) 93 }