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  }