public static readonly NType Bool = new NType("bool") { GetCommonConstantValueFunc = commonConstant => { if (commonConstant == VariableCommonConstant.Zero) { return(new RawVariable() { Type = NType.Bool, Value = new NizkBoolValue() { IsConstant = true, Value = false, } }); } else if (commonConstant == VariableCommonConstant.One) { return(new RawVariable() { Type = NType.Bool, Value = new NizkBoolValue() { IsConstant = true, Value = true, } }); } else { throw new Exception($"Type \"{ NType.Bool}\" doesn't provide a constant for \"{commonConstant}\"."); } }, ParseFunc = (str) => { if (System.Boolean.TryParse(str, out System.Boolean retV)) { return(new Variable(new RawVariable() { Type = NType.Bool, Value = new NizkBoolValue() { IsConstant = true, Value = retV, } })); } else { throw new Exception($"Can't parse \"{str}\" as \"{NType.Bool.TypeCodeName}\"."); } }, GetVariableStringFunc = variable => ((NizkBoolValue)variable.Value).Value.ToString(CultureInfo.InvariantCulture), GetVariableIntFunc = variable => ((NizkBoolValue)variable.Value).Value == false ? 0 : 1, GetNewNizkVariableFunc = () => new Variable(new RawVariable() { Type = NType.Bool, Value = new NizkBoolValue() { IsConstant = false, Value = false, } }), InternalConvertFunc = (variable, type) => NType.Bool.ImplicitConvertFunc(variable, type), ImplicitConvertFunc = (variable, type) => { var selfType = NType.Bool; if (type == selfType) { return(variable); } if (!variable.Value.IsConstant) { return(type.GetNewNizkVariable()); } if (type == NType.Field) { return(NType.Field.GetCommonConstantValue(((NizkBoolValue)variable.Value).Value ? VariableCommonConstant.One : VariableCommonConstant.Zero)); } else if (type == NType.UInt32) { return(NType.UInt32.GetCommonConstantValue(((NizkBoolValue)variable.Value).Value ? VariableCommonConstant.One : VariableCommonConstant.Zero)); } else if (type == NType.Bool) { throw CommonException.AssertFailedException(); } else { throw new Exception($"Can't convert \"{selfType.TypeCodeName }\" to \"{type.TypeCodeName}\"."); } }, ExplicitConvertFunc = (variable, type) => NType.Bool.ImplicitConvertFunc(variable, type), UnaryOperationFuncs = new Dictionary <VariableOperationType, Func <Variable, Variable> >() { { VariableOperationType.Unary_BooleanNot, (var1) => { var v1 = ((NizkBoolValue)var1.Value); return(new Variable(new RawVariable() { Type = NType.Bool, Value = (v1.IsConstant) ? new NizkBoolValue() { IsConstant = true, Value = !v1.Value, } : new NizkBoolValue() { IsConstant = false, } })); } }, }, BinaryOperationFuncs = new Dictionary <VariableOperationType, Func <Variable, Variable, Variable> >() { { VariableOperationType.Binary_EqualTo, (var1, var2) => { var newVar1 = var1; var newVar2 = var2.Assign(NType.Bool); var v1 = ((NizkBoolValue)newVar1.Value); var v2 = ((NizkBoolValue)newVar2.Value); return(new Variable(new RawVariable() { Type = NType.Bool, Value = (v1.IsConstant && v2.IsConstant) ? new NizkBoolValue() { IsConstant = true, Value = v1.Value == v2.Value, } : new NizkBoolValue() { IsConstant = false, } })); } }, { VariableOperationType.Binary_NotEqualTo, (var1, var2) => { var newVar1 = var1; var newVar2 = var2.Assign(NType.Bool); var v1 = ((NizkBoolValue)newVar1.Value); var v2 = ((NizkBoolValue)newVar2.Value); return(new Variable(new RawVariable() { Type = NType.Bool, Value = (v1.IsConstant && v2.IsConstant) ? new NizkBoolValue() { IsConstant = true, Value = v1.Value != v2.Value, } : new NizkBoolValue() { IsConstant = false, } })); } }, { VariableOperationType.Binary_BooleanAnd, (var1, var2) => { var newVar1 = var1; var newVar2 = var2.Assign(NType.Bool); var v1 = ((NizkBoolValue)newVar1.Value); var v2 = ((NizkBoolValue)newVar2.Value); return(new Variable(new RawVariable() { Type = NType.Bool, Value = (v1.IsConstant && v2.IsConstant) ? new NizkBoolValue() { IsConstant = true, Value = v1.Value && v2.Value, } : new NizkBoolValue() { IsConstant = false, } })); } }, { VariableOperationType.Binary_BooleanOr, (var1, var2) => { var newVar1 = var1; var newVar2 = var2.Assign(NType.Bool); var v1 = ((NizkBoolValue)newVar1.Value); var v2 = ((NizkBoolValue)newVar2.Value); return(new Variable(new RawVariable() { Type = NType.Bool, Value = (v1.IsConstant && v2.IsConstant) ? new NizkBoolValue() { IsConstant = true, Value = v1.Value || v2.Value, } : new NizkBoolValue() { IsConstant = false, } })); } }, { VariableOperationType.Binary_BooleanXor, (var1, var2) => { var newVar1 = var1; var newVar2 = var2.Assign(NType.Bool); var v1 = ((NizkBoolValue)newVar1.Value); var v2 = ((NizkBoolValue)newVar2.Value); return(new Variable(new RawVariable() { Type = NType.Bool, Value = (v1.IsConstant && v2.IsConstant) ? new NizkBoolValue() { IsConstant = true, Value = v1.Value != v2.Value, } : new NizkBoolValue() { IsConstant = false, } })); } }, }, VariableNodeToPinocchioFunc = (rawVariable, commonArg, checkRange) => { var ret = new PinocchioSubOutput(); var retWire = new PinocchioWire(); ret.VariableWires = new PinocchioVariableWires(rawVariable, retWire); if (rawVariable.Value.IsConstant) { //var con = new ConstWireConstraint(); //ret.Constraints.Add(con); //con.ConstVariableWires = ret.VariableWires; } else { if (checkRange) { // R * (R-1) = 0 var wire3 = new PinocchioWire(); ret.AnonymousWires.Add(wire3); var addCon = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Add); ret.Constraints.Add(addCon); addCon.InWires.Add(retWire); addCon.InWires.Add(commonArg.MinusOneWire); addCon.OutWires.Add(wire3); var mulCom = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Mul); ret.Constraints.Add(mulCom); mulCom.InWires.Add(retWire); mulCom.InWires.Add(wire3); mulCom.OutWires.Add(commonArg.ZeroWire); } } return(ret); }, OperationNodeToPinocchioFunc = (operationType, inVars, outputVariable, commonArg) => { switch (operationType.Type) { case VariableOperationTypeType.TypeCast: Debug.Assert(inVars.Count == 1); Debug.Assert(inVars[0].Wires.Count == 1); if (operationType == VariableOperationType.TypeCast_NoCheckRange || operationType == VariableOperationType.TypeCast_Trim) { Debug.Assert(outputVariable.Type == NType.Field || outputVariable.Type == NType.UInt32 || outputVariable.Type == NType.Bool); PinocchioSubOutput ret; PinocchioWire outputWire; { var outVarWires = outputVariable.Type.VariableNodeToPinocchio(outputVariable, commonArg, false); Debug.Assert(outVarWires.VariableWires.Wires.Count == 1); outputWire = outVarWires.VariableWires.Wires[0]; ret = new PinocchioSubOutput() { VariableWires = outVarWires.VariableWires }; outVarWires.Constraints.ForEach(ret.Constraints.Add); } if (operationType == VariableOperationType.TypeCast_NoCheckRange || operationType == VariableOperationType.TypeCast_Trim && outputVariable.Type == NType.Field || operationType == VariableOperationType.TypeCast_Trim && outputVariable.Type == NType.UInt32) { var con = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Mul); ret.Constraints.Add(con); con.InWires.Add(inVars[0].Wires[0]); con.InWires.Add(commonArg.OneWire); con.OutWires.Add(outputWire); return(ret); } else { throw CommonException.AssertFailedException(); } } else { break; } case VariableOperationTypeType.Unary: Debug.Assert(inVars.Count == 1); Debug.Assert(inVars[0].Wires.Count == 1); if (operationType == VariableOperationType.Unary_BooleanNot) { Debug.Assert(outputVariable.Type == NType.Bool); PinocchioSubOutput ret; PinocchioWire outputWire; { var outVarWires = outputVariable.Type.VariableNodeToPinocchio(outputVariable, commonArg, false); Debug.Assert(outVarWires.VariableWires.Wires.Count == 1); outputWire = outVarWires.VariableWires.Wires[0]; ret = new PinocchioSubOutput() { VariableWires = outVarWires.VariableWires }; outVarWires.Constraints.ForEach(ret.Constraints.Add); } //operationType == VariableOperationType.Unary_BooleanNot var con = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Xor); ret.Constraints.Add(con); con.InWires.Add(inVars[0].Wires[0]); con.InWires.Add(commonArg.OneWire); con.OutWires.Add(outputWire); return(ret); } else { break; } case VariableOperationTypeType.Binary: Debug.Assert(inVars.Count == 2); Debug.Assert(inVars[0].Wires.Count == 1); Debug.Assert(inVars[1].Wires.Count == 1); if (operationType == VariableOperationType.Binary_EqualTo || operationType == VariableOperationType.Binary_NotEqualTo || operationType == VariableOperationType.Binary_BooleanAnd || operationType == VariableOperationType.Binary_BooleanOr || operationType == VariableOperationType.Binary_BooleanXor) { Debug.Assert(outputVariable.Type == NType.Bool); PinocchioSubOutput ret; PinocchioWire outputWire; { var outVarWires = outputVariable.Type.VariableNodeToPinocchio(outputVariable, commonArg, false); Debug.Assert(outVarWires.VariableWires.Wires.Count == 1); outputWire = outVarWires.VariableWires.Wires[0]; ret = new PinocchioSubOutput() { VariableWires = outVarWires.VariableWires }; outVarWires.Constraints.ForEach(ret.Constraints.Add); } if (operationType == VariableOperationType.Binary_BooleanAnd) { var con = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Mul); ret.Constraints.Add(con); con.InWires.Add(inVars[0].Wires[0]); con.InWires.Add(inVars[0].Wires[1]); con.OutWires.Add(outputWire); return(ret); } else if (operationType == VariableOperationType.Binary_BooleanOr) { var con = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Or); ret.Constraints.Add(con); con.InWires.Add(inVars[0].Wires[0]); con.InWires.Add(inVars[0].Wires[1]); con.OutWires.Add(outputWire); return(ret); } else if (operationType == VariableOperationType.Binary_BooleanXor || operationType == VariableOperationType.Binary_NotEqualTo) { var con = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Xor); ret.Constraints.Add(con); con.InWires.Add(inVars[0].Wires[0]); con.InWires.Add(inVars[0].Wires[1]); con.OutWires.Add(outputWire); return(ret); } else if (operationType == VariableOperationType.Binary_EqualTo) { var wire1 = new PinocchioWire(); ret.AnonymousWires.Add(wire1); var con1 = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Xor); ret.Constraints.Add(con1); con1.InWires.Add(inVars[0].Wires[0]); con1.InWires.Add(inVars[0].Wires[1]); con1.OutWires.Add(wire1); var con2 = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Xor); ret.Constraints.Add(con2); con2.InWires.Add(wire1); con2.InWires.Add(commonArg.OneWire); con2.OutWires.Add(outputWire); return(ret); } else { throw CommonException.AssertFailedException(); } } else { break; } default: throw CommonException.AssertFailedException(); } throw new Exception($"Type \"{NType.Field}\" doesn't support \"{operationType.ToString()}\" operation."); }, };
public static readonly NType Field = new NType("field") { GetCommonConstantValueFunc = commonConstant => { if (commonConstant == VariableCommonConstant.Zero) { return(new RawVariable() { Type = NType.Field, Value = new NizkFieldValue() { IsConstant = true, Value = BigInteger.Zero, } }); } else if (commonConstant == VariableCommonConstant.One) { return(new RawVariable() { Type = NType.Field, Value = new NizkFieldValue() { IsConstant = true, Value = BigInteger.One, } }); } else if (commonConstant == VariableCommonConstant.MinusOne) { return(new RawVariable() { Type = NType.Field, Value = new NizkFieldValue() { IsConstant = true, Value = My.Config.ModulusPrimeField_Prime, } }); } else { throw new Exception($"Type \"{ NType.Field}\" doesn't provide a constant for \"{commonConstant}\"."); } }, ParseFunc = (str) => { if (BigInteger.TryParse(str, out BigInteger retV)) { return(new Variable(new RawVariable() { Type = NType.Field, Value = new NizkFieldValue() { IsConstant = true, Value = retV, } })); } else { throw new Exception($"Can't parse \"{str}\" as \"{NType.Field.TypeCodeName}\"."); } }, GetVariableStringFunc = variable => ((NizkFieldValue)variable.Value).Value.ToString(CultureInfo.InvariantCulture), GetVariableIntFunc = variable => ((NizkFieldValue)variable.Value).Value, GetNewNizkVariableFunc = () => new Variable(new RawVariable() { Type = NType.Field, Value = new NizkFieldValue() { IsConstant = false, Value = BigInteger.Zero, } }), InternalConvertFunc = (variable, type) => { var selfType = NType.Field; if (type == selfType) { return(variable); } var allowedType = new List <NType>() { NType.UInt32, NType.Bool, }; if (!allowedType.Contains(type)) { throw new Exception($"Can't do internal convert from \"{selfType.TypeCodeName }\" to \"{type.TypeCodeName}\"."); } if (!variable.Value.IsConstant) { return(type.GetNewNizkVariable()); } if (type == NType.UInt32) { if (((NizkFieldValue)variable.Value).Value <= new BigInteger(System.UInt32.MaxValue)) { return(new Variable(new RawVariable() { Type = NType.UInt32, Value = new NizkUInt32Value() { IsConstant = true, Value = System.UInt32.Parse((((NizkFieldValue)variable.Value).Value).ToString(CultureInfo.InvariantCulture), CultureInfo.InvariantCulture), } })); } else { throw new Exception($"Overflow detected while doing internal convert from \"{selfType.TypeCodeName }\" to \"{type.TypeCodeName}\"."); } } else if (type == NType.Bool) { if (((NizkFieldValue)variable.Value).Value <= BigInteger.One) { return(NType.Bool.GetCommonConstantValue(((NizkFieldValue)variable.Value).Value == BigInteger.One ? VariableCommonConstant.One : VariableCommonConstant.Zero)); } else { throw new Exception($"Overflow detected while doing internal convert from \"{selfType.TypeCodeName }\" to \"{type.TypeCodeName}\"."); } } else { throw CommonException.AssertFailedException(); } }, // Implicit Convert: not supported ExplicitConvertFunc = (variable, type) => { var selfType = NType.Field; if (type == selfType) { return(variable); } var allowedType = new List <NType>() { NType.UInt32, NType.Bool, }; if (!allowedType.Contains(type)) { throw new Exception($"Can't explicit convert \"{selfType.TypeCodeName }\" to \"{type.TypeCodeName}\"."); } if (!variable.Value.IsConstant) { return(type.GetNewNizkVariable()); } if (type == NType.UInt32) { return(new Variable(new RawVariable() { Type = NType.UInt32, Value = new NizkUInt32Value() { IsConstant = true, Value = System.UInt32.Parse((((NizkFieldValue)variable.Value).Value % (new BigInteger(System.UInt32.MaxValue) + 1)).ToString(CultureInfo.InvariantCulture), CultureInfo.InvariantCulture), } })); } else if (type == NType.Bool) { return(NType.Bool.GetCommonConstantValue(((NizkUInt32Value)variable.Value).Value % 2 == 0 ? VariableCommonConstant.One : VariableCommonConstant.Zero)); } else { throw CommonException.AssertFailedException(); } }, BinaryOperationFuncs = new Dictionary <VariableOperationType, Func <Variable, Variable, Variable> >() { { VariableOperationType.Binary_Addition, (var1, var2) => { var newVar1 = var1; var newVar2 = var2.Assign(NType.Field); var v1 = ((NizkFieldValue)newVar1.Value); var v2 = ((NizkFieldValue)newVar2.Value); return(new Variable(new RawVariable() { Type = NType.Field, Value = (v1.IsConstant && v2.IsConstant) ? new NizkFieldValue() { IsConstant = true, Value = (v1.Value + v2.Value) % My.Config.ModulusPrimeField_Prime, } : new NizkFieldValue() { IsConstant = false, } })); } }, { VariableOperationType.Binary_Subtract, (var1, var2) => { var newVar1 = var1; var newVar2 = var2.Assign(NType.Field); var v1 = ((NizkFieldValue)newVar1.Value); var v2 = ((NizkFieldValue)newVar2.Value); return(new Variable(new RawVariable() { Type = NType.Field, Value = (v1.IsConstant && v2.IsConstant) ? new NizkFieldValue() { IsConstant = true, Value = (My.Config.ModulusPrimeField_Prime + v1.Value - v2.Value) % My.Config.ModulusPrimeField_Prime, } : new NizkFieldValue() { IsConstant = false, } })); } }, { VariableOperationType.Binary_Multiplication, (var1, var2) => { var newVar1 = var1; var newVar2 = var2.Assign(NType.Field); var v1 = ((NizkFieldValue)newVar1.Value); var v2 = ((NizkFieldValue)newVar2.Value); return(new Variable(new RawVariable() { Type = NType.Field, Value = (v1.IsConstant && v2.IsConstant) ? new NizkFieldValue() { IsConstant = true, Value = (v1.Value * v2.Value) % My.Config.ModulusPrimeField_Prime, } : new NizkFieldValue() { IsConstant = false, } })); } }, }, VariableNodeToPinocchioFunc = (rawVariable, commonArg, checkRange) => { var ret = new PinocchioSubOutput(); var retWire = new PinocchioWire(); ret.VariableWires = new PinocchioVariableWires(rawVariable, retWire); return(ret); }, OperationNodeToPinocchioFunc = (operationType, inVars, outputVariable, commonArg) => { switch (operationType.Type) { case VariableOperationTypeType.TypeCast: Debug.Assert(inVars.Count == 1); Debug.Assert(inVars[0].Wires.Count == 1); if (operationType == VariableOperationType.TypeCast_NoCheckRange || operationType == VariableOperationType.TypeCast_Trim) { Debug.Assert(outputVariable.Type == NType.Field || outputVariable.Type == NType.UInt32 || outputVariable.Type == NType.Bool); PinocchioSubOutput ret; PinocchioWire outputWire; { var outVarWires = outputVariable.Type.VariableNodeToPinocchio(outputVariable, commonArg, false); Debug.Assert(outVarWires.VariableWires.Wires.Count == 1); outputWire = outVarWires.VariableWires.Wires[0]; ret = new PinocchioSubOutput() { VariableWires = outVarWires.VariableWires }; outVarWires.Constraints.ForEach(ret.Constraints.Add); } if (operationType == VariableOperationType.TypeCast_NoCheckRange) { var con = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Mul); ret.Constraints.Add(con); con.InWires.Add(inVars[0].Wires[0]); con.InWires.Add(commonArg.OneWire); con.OutWires.Add(outputWire); return(ret); } else if (operationType == VariableOperationType.TypeCast_Trim) { if (outputVariable.Type == NType.Bool) { var con = new BasicPinocchioConstraint(BasicPinocchioConstraintType.ZeroP); ret.Constraints.Add(con); con.InWires.Add(inVars[0].Wires[0]); con.OutWires.Add(outputWire); return(ret); } else if (outputVariable.Type == NType.UInt32) { var splitCon = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Split); ret.Constraints.Add(splitCon); splitCon.InWires.Add(inVars[0].Wires[0]); //todo: [MaxPossibleValue] design "Variable.MaxPossibleValue" and minimize the number of bits here foreach (var _ in Enumerable.Range(0, My.Config.ModulusPrimeField_Prime_Bit)) { var boolWire = new PinocchioWire(); ret.AnonymousWires.Add(boolWire); // [boolWire01] splitCon.OutWires.Add(boolWire); } var packCon = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Pack); ret.Constraints.Add(packCon); packCon.OutWires.Add(outputWire); for (int i = My.Config.ModulusPrimeField_Prime_Bit - 1; i <= My.Config.ModulusPrimeField_Prime_Bit - 32; --i) { var boolWire = new PinocchioWire(); ret.AnonymousWires.Add(boolWire); // [boolWire01] packCon.InWires.Add(boolWire); } return(ret); } else { break; } } else { throw CommonException.AssertFailedException(); } } else { break; } case VariableOperationTypeType.Unary: Debug.Assert(inVars.Count == 1); Debug.Assert(inVars[0].Wires.Count == 1); break; case VariableOperationTypeType.Binary: Debug.Assert(inVars.Count == 2); Debug.Assert(inVars[0].Wires.Count == 1); Debug.Assert(inVars[1].Wires.Count == 1); if (operationType == VariableOperationType.Binary_Addition || operationType == VariableOperationType.Binary_Multiplication || operationType == VariableOperationType.Binary_Subtract) { PinocchioSubOutput ret; PinocchioWire outputWire; { var outVarWires = outputVariable.Type.VariableNodeToPinocchio(outputVariable, commonArg, false); Debug.Assert(outVarWires.VariableWires.Wires.Count == 1); outputWire = outVarWires.VariableWires.Wires[0]; ret = new PinocchioSubOutput() { VariableWires = outVarWires.VariableWires }; outVarWires.Constraints.ForEach(ret.Constraints.Add); } if (operationType == VariableOperationType.Binary_Addition) { var con = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Add); ret.Constraints.Add(con); con.InWires.Add(inVars[0].Wires[0]); con.InWires.Add(inVars[1].Wires[0]); con.OutWires.Add(outputWire); } else if (operationType == VariableOperationType.Binary_Multiplication) { var con = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Mul); ret.Constraints.Add(con); con.InWires.Add(inVars[0].Wires[0]); con.InWires.Add(inVars[1].Wires[0]); con.OutWires.Add(outputWire); } else if (operationType == VariableOperationType.Binary_Subtract) { // var3= var2 * (-1) var con1 = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Mul); ret.Constraints.Add(con1); con1.InWires.Add(inVars[1].Wires[0]); con1.InWires.Add(commonArg.MinusOneWire); var var3 = new PinocchioWire(); ret.AnonymousWires.Add(var3); con1.OutWires.Add(var3); // ret = var1 + var 3 var con = new BasicPinocchioConstraint(BasicPinocchioConstraintType.Add); ret.Constraints.Add(con); con.InWires.Add(inVars[0].Wires[0]); con.InWires.Add(var3); con.OutWires.Add(outputWire); } else { throw CommonException.AssertFailedException(); } return(ret); } else { break; } default: throw CommonException.AssertFailedException(); } throw new Exception($"Type \"{NType.Field}\" doesn't support \"{operationType.ToString()}\" operation."); }, };