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 */