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  }