github.com/consensys/gnark@v0.11.0/constraint/blueprint_hint.go (about) 1 package constraint 2 3 import ( 4 "github.com/consensys/gnark/constraint/solver" 5 "github.com/consensys/gnark/debug" 6 ) 7 8 type BlueprintGenericHint struct{} 9 10 func (b *BlueprintGenericHint) DecompressHint(h *HintMapping, inst Instruction) { 11 // ignore first call data == nbInputs 12 h.HintID = solver.HintID(inst.Calldata[1]) 13 lenInputs := int(inst.Calldata[2]) 14 if cap(h.Inputs) >= lenInputs { 15 h.Inputs = h.Inputs[:lenInputs] 16 } else { 17 h.Inputs = make([]LinearExpression, lenInputs) 18 } 19 20 j := 3 21 for i := 0; i < lenInputs; i++ { 22 n := int(inst.Calldata[j]) // len of linear expr 23 j++ 24 if cap(h.Inputs[i]) >= n { 25 h.Inputs[i] = h.Inputs[i][:0] 26 } else { 27 h.Inputs[i] = make(LinearExpression, 0, n) 28 } 29 for k := 0; k < n; k++ { 30 h.Inputs[i] = append(h.Inputs[i], Term{CID: inst.Calldata[j], VID: inst.Calldata[j+1]}) 31 j += 2 32 } 33 } 34 h.OutputRange.Start = inst.Calldata[j] 35 h.OutputRange.End = inst.Calldata[j+1] 36 } 37 38 func (b *BlueprintGenericHint) CompressHint(h HintMapping, to *[]uint32) { 39 nbInputs := 1 // storing nb inputs 40 nbInputs++ // hintID 41 nbInputs++ // len(h.Inputs) 42 for i := 0; i < len(h.Inputs); i++ { 43 nbInputs++ // len of h.Inputs[i] 44 nbInputs += len(h.Inputs[i]) * 2 45 } 46 47 nbInputs += 2 // output range start / end 48 49 (*to) = append((*to), uint32(nbInputs)) 50 (*to) = append((*to), uint32(h.HintID)) 51 (*to) = append((*to), uint32(len(h.Inputs))) 52 53 for _, l := range h.Inputs { 54 (*to) = append((*to), uint32(len(l))) 55 for _, t := range l { 56 (*to) = append((*to), uint32(t.CoeffID()), uint32(t.WireID())) 57 } 58 } 59 60 (*to) = append((*to), h.OutputRange.Start) 61 (*to) = append((*to), h.OutputRange.End) 62 } 63 64 func (b *BlueprintGenericHint) CalldataSize() int { 65 return -1 66 } 67 func (b *BlueprintGenericHint) NbConstraints() int { 68 return 0 69 } 70 71 func (b *BlueprintGenericHint) NbOutputs(inst Instruction) int { 72 return 0 73 } 74 75 func (b *BlueprintGenericHint) UpdateInstructionTree(inst Instruction, tree InstructionTree) Level { 76 // BlueprintGenericHint knows the input and output to the instruction 77 maxLevel := LevelUnset 78 79 // iterate over the inputs and find the max level 80 lenInputs := int(inst.Calldata[2]) 81 j := 3 82 for i := 0; i < lenInputs; i++ { 83 n := int(inst.Calldata[j]) // len of linear expr 84 j++ 85 86 for k := 0; k < n; k++ { 87 wireID := inst.Calldata[j+1] 88 j += 2 89 if !tree.HasWire(wireID) { 90 continue 91 } 92 if level := tree.GetWireLevel(wireID); level > maxLevel { 93 maxLevel = level 94 } 95 if debug.Debug && tree.GetWireLevel(wireID) == LevelUnset { 96 panic("wire we depend on is not in the instruction tree") 97 } 98 } 99 } 100 101 // iterate over the outputs and insert them at maxLevel + 1 102 outputLevel := maxLevel + 1 103 for k := inst.Calldata[j]; k < inst.Calldata[j+1]; k++ { 104 tree.InsertWire(k, outputLevel) 105 } 106 return outputLevel 107 }