github.com/consensys/gnark-crypto@v0.14.0/internal/generator/test_vector_utils/utils.go (about)

     1  package test_vector_utils
     2  
     3  /*
     4  var hashCache = make(map[string]HashMap)
     5  
     6  func GetHash(path string) (HashMap, error) {
     7  	path, err := filepath.Abs(path)
     8  	if err != nil {
     9  		return nil, err
    10  	}
    11  	if h, ok := hashCache[path]; ok {
    12  		return h, nil
    13  	}
    14  	var bytes []byte
    15  	if bytes, err = os.ReadFile(path); err == nil {
    16  		var asMap map[string]interface{}
    17  		if err = json.Unmarshal(bytes, &asMap); err != nil {
    18  			return nil, err
    19  		}
    20  
    21  		res := make(HashMap, 0, len(asMap))
    22  
    23  		for k, v := range asMap {
    24  			var entry RationalTriplet
    25  			if _, err = entry.value.SetInterface(v); err != nil {
    26  				return nil, err
    27  			}
    28  
    29  			key := strings.Split(k, ",")
    30  
    31  			switch len(key) {
    32  			case 1:
    33  				entry.key2Present = false
    34  			case 2:
    35  				entry.key2Present = true
    36  				if _, err = entry.key2.SetInterface(key[1]); err != nil {
    37  					return nil, err
    38  				}
    39  			default:
    40  				return nil, fmt.Errorf("cannot parse %T as one or two field elements", v)
    41  			}
    42  			if _, err = entry.key1.SetInterface(key[0]); err != nil {
    43  				return nil, err
    44  			}
    45  
    46  			res = append(res, &entry)
    47  		}
    48  
    49  		res.sort()
    50  
    51  		hashCache[path] = res
    52  
    53  		return res, nil
    54  
    55  	} else {
    56  		return nil, err
    57  	}
    58  }
    59  
    60  func (m *HashMap) SaveUsedEntries(path string) error {
    61  
    62  	var sb strings.Builder
    63  	sb.WriteRune('[')
    64  
    65  	first := true
    66  
    67  	for _, element := range *m {
    68  		if !element.used {
    69  			continue
    70  		}
    71  		if !first {
    72  			sb.WriteRune(',')
    73  		}
    74  		first = false
    75  		sb.WriteString("\n\t")
    76  		element.WriteKeyValue(&sb)
    77  	}
    78  
    79  	if !first {
    80  		sb.WriteRune(',')
    81  	}
    82  
    83  	sb.WriteString("\n]")
    84  
    85  	return os.WriteFile(path, []byte(sb.String()), 0)
    86  }
    87  
    88  type HashMap []*RationalTriplet
    89  
    90  type RationalTriplet struct {
    91  	key1        small_rational.SmallRational
    92  	key2        small_rational.SmallRational
    93  	key2Present bool
    94  	value       small_rational.SmallRational
    95  	used        bool
    96  }
    97  
    98  func (t *RationalTriplet) WriteKeyValue(sb *strings.Builder) {
    99  	sb.WriteString("\t\"")
   100  	sb.WriteString(t.key1.String())
   101  	if t.key2Present {
   102  		sb.WriteRune(',')
   103  		sb.WriteString(t.key2.String())
   104  	}
   105  	sb.WriteString("\":")
   106  	if valueBytes, err := json.Marshal(ElementToInterface(&t.value)); err == nil {
   107  		sb.WriteString(string(valueBytes))
   108  	} else {
   109  		panic(err.Error())
   110  	}
   111  }
   112  
   113  func (m *HashMap) sort() {
   114  	sort.Slice(*m, func(i, j int) bool {
   115  		return (*m)[i].CmpKey((*m)[j]) <= 0
   116  	})
   117  }
   118  
   119  func (m *HashMap) find(toFind *RationalTriplet) small_rational.SmallRational {
   120  	i := sort.Search(len(*m), func(i int) bool { return (*m)[i].CmpKey(toFind) >= 0 })
   121  
   122  	if i < len(*m) && (*m)[i].CmpKey(toFind) == 0 {
   123  		(*m)[i].used = true
   124  		return (*m)[i].value
   125  	}
   126  
   127  	// if not found, add it:
   128  	if _, err := toFind.value.SetInterface(rand.Int63n(11) - 5); err != nil {
   129  		panic(err.Error())
   130  	}
   131  	toFind.used = true
   132  	*m = append(*m, toFind)
   133  	m.sort() //Inefficient, but it's okay. This is only run when a new test case is introduced
   134  
   135  	return toFind.value
   136  }
   137  
   138  func (t *RationalTriplet) CmpKey(o *RationalTriplet) int {
   139  	if cmp1 := t.key1.Cmp(&o.key1); cmp1 != 0 {
   140  		return cmp1
   141  	}
   142  
   143  	if t.key2Present {
   144  		if o.key2Present {
   145  			return t.key2.Cmp(&o.key2)
   146  		}
   147  		return 1
   148  	} else {
   149  		if o.key2Present {
   150  			return -1
   151  		}
   152  		return 0
   153  	}
   154  }
   155  
   156  type MapHashTranscript struct {
   157  	HashMap         HashMap
   158  	stateValid      bool
   159  	resultAvailable bool
   160  	state           small_rational.SmallRational
   161  }
   162  
   163  func (m *HashMap) Hash(x *small_rational.SmallRational, y *small_rational.SmallRational) small_rational.SmallRational {
   164  
   165  	toFind := RationalTriplet{
   166  		key1:        *x,
   167  		key2Present: y != nil,
   168  	}
   169  
   170  	if y != nil {
   171  		toFind.key2 = *y
   172  	}
   173  
   174  	return m.find(&toFind)
   175  }
   176  
   177  func (m *MapHashTranscript) Update(i ...interface{}) {
   178  	if len(i) > 0 {
   179  		for _, x := range i {
   180  
   181  			var xElement small_rational.SmallRational
   182  			if _, err := xElement.SetInterface(x); err != nil {
   183  				panic(err.Error())
   184  			}
   185  			if m.stateValid {
   186  				m.state = m.HashMap.Hash(&xElement, &m.state)
   187  			} else {
   188  				m.state = m.HashMap.Hash(&xElement, nil)
   189  			}
   190  
   191  			m.stateValid = true
   192  		}
   193  	} else { //just hash the state itself
   194  		if !m.stateValid {
   195  			panic("nothing to hash")
   196  		}
   197  		m.state = m.HashMap.Hash(&m.state, nil)
   198  	}
   199  	m.resultAvailable = true
   200  }
   201  
   202  func (m *MapHashTranscript) Next(i ...interface{}) small_rational.SmallRational {
   203  
   204  	if len(i) > 0 || !m.resultAvailable {
   205  		m.Update(i...)
   206  	}
   207  	m.resultAvailable = false
   208  	return m.state
   209  }
   210  
   211  func (m *MapHashTranscript) NextN(N int, i ...interface{}) []small_rational.SmallRational {
   212  
   213  	if len(i) > 0 {
   214  		m.Update(i...)
   215  	}
   216  
   217  	res := make([]small_rational.SmallRational, N)
   218  
   219  	for n := range res {
   220  		res[n] = m.Next()
   221  	}
   222  
   223  	return res
   224  }
   225  
   226  func SliceToElementSlice(slice []interface{}) ([]small_rational.SmallRational, error) {
   227  	elementSlice := make([]small_rational.SmallRational, len(slice))
   228  	for i, v := range slice {
   229  		if _, err := elementSlice[i].SetInterface(v); err != nil {
   230  			return nil, err
   231  		}
   232  	}
   233  	return elementSlice, nil
   234  }
   235  
   236  func SliceEquals(a []small_rational.SmallRational, b []small_rational.SmallRational) error {
   237  	if len(a) != len(b) {
   238  		return fmt.Errorf("length mismatch %d≠%d", len(a), len(b))
   239  	}
   240  	for i := range a {
   241  		if !a[i].Equal(&b[i]) {
   242  			return fmt.Errorf("at index %d: %s ≠ %s", i, a[i].String(), b[i].String())
   243  		}
   244  	}
   245  	return nil
   246  }
   247  
   248  */