/**
 * Copyright 2021 Cloudflare Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ import { Commitment , PedersenParams } from '../commit/pedersen.js' ; import { EqualityProof , aggregateEquality , proveEquality } from '../commit/equality.js' ; import { MultProof , aggregateMult , proveMult } from '../commit/mult.js' ; import { invMod , posMod } from '../bignum/big.js' ; import { jsonMember , jsonObject , toJson } from 'typedjson' ; import { Group } from '../curves/group.js' ; import { MultiMult } from '../curves/multimult.js' ; @ jsonObject @ toJson export class PointAddProof { @ jsonMember ( { constructor : Group . Point , isRequired : true } ) C_8 : Group . Point ; @ jsonMember ( { constructor : Group . Point , isRequired : true } ) C_10 : Group . Point ; @ jsonMember ( { constructor : Group . Point , isRequired : true } ) C_11 : Group . Point ; @ jsonMember ( { constructor : Group . Point , isRequired : true } ) C_13 : Group . Point ; @ jsonMember ( { constructor : MultProof , isRequired : true } ) pi_8 : MultProof ; @ jsonMember ( { constructor : MultProof , isRequired : true } ) pi_10 : MultProof ; @ jsonMember ( { constructor : MultProof , isRequired : true } ) pi_11 : MultProof ; @ jsonMember ( { constructor : MultProof , isRequired : true } ) pi_13 : MultProof ; @ jsonMember ( { constructor : EqualityProof , isRequired : true } ) pi_x : EqualityProof ; @ jsonMember ( { constructor : EqualityProof , isRequired : true } ) pi_y : EqualityProof ; constructor ( C_8 , C_10 , C_11 , C_13 , pi_8 , pi_10 , pi_11 , pi_13 , pi_x , pi_y ) { this . C_8 = C_8 ; this . C_10 = C_10 ; this . C_11 = C_11 ; this . C_13 = C_13 ; this . pi_8 = pi_8 ; this . pi_10 = pi_10 ; this . pi_11 = pi_11 ; this . pi_13 = pi_13 ; this . pi_x = pi_x ; this . pi_y = pi_y ; } eq ( o ) { return ( this . C_8 . eq ( o . C_8 ) && this . C_10 . eq ( o . C_10 ) && this . C_11 . eq ( o . C_11 ) && this . C_13 . eq ( o . C_13 ) && this . pi_8 . eq ( o . pi_8 ) && this . pi_10 . eq ( o . pi_10 ) && this . pi_11 . eq ( o . pi_11 ) && this . pi_13 . eq ( o . pi_13 ) && this . pi_x . eq ( o . pi_x ) && this . pi_y . eq ( o . pi_y ) ) ; } } param params param P param Q param R param C1 param C2 param C3 param C4 param C5 param C6 export async function provePointAdd ( params , P , Q , R , PX , PY , QX , QY , RX , RY ) { if ( ! P . add ( Q ) . eq ( R ) ) { throw Error ( "Points don't add up!" ) ; } const prime = params . c . order , C1 = PX , C2 = QX , C3 = RX , C4 = PY , C5 = QY , C6 = RY , coordP = P . toAffine ( ) , coordQ = Q . toAffine ( ) , coordR = R . toAffine ( ) ; if ( ! coordP ) { throw new Error ( 'P is at infinity' ) ; } if ( ! coordQ ) { throw new Error ( 'Q is at infinity' ) ; } if ( ! coordR ) { throw new Error ( 'R is at infinity' ) ; } const { x : x1 , y : y1 } = coordP , { x : x2 , y : y2 } = coordQ , { x : x3 } = coordR , i7 = posMod ( x2 - x1 , prime ) , i8 = invMod ( i7 , prime ) , i9 = posMod ( y2 - y1 , prime ) , i10 = posMod ( i8 * i9 , prime ) , i11 = posMod ( i10 * i10 , prime ) , i12 = posMod ( x1 - x3 , prime ) , i13 = posMod ( i10 * i12 , prime ) , C7 = C2 . sub ( C1 ) , C8 = params . commit ( i8 ) , C9 = C5 . sub ( C4 ) , C10 = params . commit ( i10 ) , C11 = params . commit ( i11 ) , C12 = C1 . sub ( C3 ) , C13 = params . commit ( i13 ) , C14 = new Commitment ( params . g , params . c . newScalar ( BigInt ( 0 ) ) ) , pi8 = await proveMult ( params , i7 , i8 , BigInt ( 1 ) , C7 , C8 , C14 ) , pi10 = await proveMult ( params , i8 , i9 , i10 , C8 , C9 , C10 ) , pi11 = await proveMult ( params , i10 , i10 , i11 , C10 , C10 , C11 ) ; let Cint = new Commitment ( C3 . p . add ( C1 . p ) . add ( C2 . p ) , C3 . r . add ( C1 . r ) . add ( C2 . r ) ) ; const pix = await proveEquality ( params , i11 , C11 , Cint ) , pi13 = await proveMult ( params , i10 , i12 , i13 , C10 , C12 , C13 ) ; Cint = new Commitment ( C6 . p . add ( C4 . p ) , C6 . r . add ( C4 . r ) ) ; const piy = await proveEquality ( params , i13 , C13 , Cint ) ; return new PointAddProof ( C8 . p , C10 . p , C11 . p , C13 . p , pi8 , pi10 , pi11 , pi13 , pix , piy ) ; } param params param C1 param C2 param C3 param C4 param C5 param C6 param pi param challenge export async function verifyPointAdd ( params , PX , PY , QX , QY , RX , RY , pi ) { const multi = new MultiMult ( params . c ) , ok = await aggregatePointAdd ( params , PX , PY , QX , QY , RX , RY , pi , multi ) ; if ( ! ok ) { return false ; } return multi . evaluate ( ) . isIdentity ( ) ; } export async function aggregatePointAdd ( params , PX , PY , QX , QY , RX , RY , pi , multi ) { const C1 = PX , C2 = QX , C3 = RX , C4 = PY , C5 = QY , C6 = RY , C7 = C2 . sub ( C1 ) , C9 = C5 . sub ( C4 ) , C12 = C1 . sub ( C3 ) , C_14 = params . g ; if ( ! ( await aggregateMult ( params , C7 , pi . C_8 , C_14 , pi . pi_8 , multi ) ) ) { console . log ( 'pi8' ) ; return false ; } if ( ! ( await aggregateMult ( params , pi . C_8 , C9 , pi . C_10 , pi . pi_10 , multi ) ) ) { console . log ( 'pi10' ) ; return false ; } if ( ! ( await aggregateMult ( params , pi . C_10 , pi . C_10 , pi . C_11 , pi . pi_11 , multi ) ) ) { console . log ( 'pi11' ) ; return false ; } let Cint = C3 . add ( C1 ) . add ( C2 ) ; if ( ! ( await aggregateEquality ( params , pi . C_11 , Cint , pi . pi_x , multi ) ) ) { console . log ( 'pix' ) ; return false ; } if ( ! ( await aggregateMult ( params , pi . C_10 , C12 , pi . C_13 , pi . pi_13 , multi ) ) ) { console . log ( 'pi13' ) ; return false ; } Cint = C4 . add ( C6 ) ; if ( ! ( await aggregateEquality ( params , pi . C_13 , Cint , pi . pi_y , multi ) ) ) { console . log ( 'piy' ) ; return false ; } return true ; }