@@ -1060,53 +1060,117 @@ impl EcMulOp {
10601060/// call are < 4, we append (G1::infinity, G2::generator) until we have the required no. of inputs.
10611061pub const N_PAIRING_PER_OP : usize = 4 ;
10621062
1063+ /// The number of bytes taken to represent a pair (G1, G2).
1064+ pub const N_BYTES_PER_PAIR : usize = 192 ;
1065+
1066+ /// Pair of (G1, G2).
1067+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
1068+ pub struct EcPairingPair {
1069+ /// G1 point.
1070+ pub g1_point : G1Affine ,
1071+ /// G2 point.
1072+ pub g2_point : G2Affine ,
1073+ }
1074+
1075+ impl EcPairingPair {
1076+ /// Returns the big-endian representation of the G1 point in the pair.
1077+ pub fn g1_bytes_be ( & self ) -> Vec < u8 > {
1078+ std:: iter:: empty ( )
1079+ . chain ( self . g1_point . x . to_bytes ( ) . iter ( ) . rev ( ) )
1080+ . chain ( self . g1_point . y . to_bytes ( ) . iter ( ) . rev ( ) )
1081+ . cloned ( )
1082+ . collect ( )
1083+ }
1084+
1085+ /// Returns the big-endian representation of the G2 point in the pair.
1086+ pub fn g2_bytes_be ( & self ) -> Vec < u8 > {
1087+ std:: iter:: empty ( )
1088+ . chain ( self . g2_point . x . c0 . to_bytes ( ) . iter ( ) . rev ( ) )
1089+ . chain ( self . g2_point . x . c1 . to_bytes ( ) . iter ( ) . rev ( ) )
1090+ . chain ( self . g2_point . y . c0 . to_bytes ( ) . iter ( ) . rev ( ) )
1091+ . chain ( self . g2_point . y . c1 . to_bytes ( ) . iter ( ) . rev ( ) )
1092+ . cloned ( )
1093+ . collect ( )
1094+ }
1095+
1096+ /// Returns the uncompressed big-endian byte representation of the (G1, G2) pair.
1097+ pub fn to_bytes_be ( & self ) -> Vec < u8 > {
1098+ std:: iter:: empty ( )
1099+ . chain ( self . g1_point . x . to_bytes ( ) . iter ( ) . rev ( ) )
1100+ . chain ( self . g1_point . y . to_bytes ( ) . iter ( ) . rev ( ) )
1101+ . chain ( self . g2_point . x . c0 . to_bytes ( ) . iter ( ) . rev ( ) )
1102+ . chain ( self . g2_point . x . c1 . to_bytes ( ) . iter ( ) . rev ( ) )
1103+ . chain ( self . g2_point . y . c0 . to_bytes ( ) . iter ( ) . rev ( ) )
1104+ . chain ( self . g2_point . y . c1 . to_bytes ( ) . iter ( ) . rev ( ) )
1105+ . cloned ( )
1106+ . collect ( )
1107+ }
1108+
1109+ /// Create a new pair.
1110+ pub fn new ( g1_point : G1Affine , g2_point : G2Affine ) -> Self {
1111+ Self { g1_point, g2_point }
1112+ }
1113+
1114+ /// Padding pair for ECC circuit. The pairing check is done with a constant number
1115+ /// `N_PAIRING_PER_OP` of (G1, G2) pairs. The ECC circuit under the hood uses halo2-lib to
1116+ /// compute the multi-miller loop, which allows `(G1::Infinity, G2::Generator)` pair to skip
1117+ /// the loop for that pair. So in case the EVM inputs are less than `N_PAIRING_PER_OP` we pad
1118+ /// the ECC Circuit inputs by this pair. Any EVM input of `(G1::Infinity, G2)` or
1119+ /// `(G1, G2::Infinity)` is also transformed into `(G1::Infinity, G2::Generator)`.
1120+ pub fn ecc_padding ( ) -> Self {
1121+ Self {
1122+ g1_point : G1Affine :: identity ( ) ,
1123+ g2_point : G2Affine :: generator ( ) ,
1124+ }
1125+ }
1126+
1127+ /// Padding pair for EVM circuit. The pairing check is done with a constant number
1128+ /// `N_PAIRING_PER_OP` of (G1, G2) pairs. In case EVM inputs are less in number, we pad them
1129+ /// with `(G1::Infinity, G2::Infinity)` for simplicity.
1130+ pub fn evm_padding ( ) -> Self {
1131+ Self {
1132+ g1_point : G1Affine :: identity ( ) ,
1133+ g2_point : G2Affine :: identity ( ) ,
1134+ }
1135+ }
1136+ }
1137+
10631138/// EcPairing operation
1064- #[ derive( Clone , Debug ) ]
1139+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
10651140pub struct EcPairingOp {
1066- /// tuples of G1 and G2 points.
1067- pub inputs : [ ( G1Affine , G2Affine ) ; N_PAIRING_PER_OP ] ,
1141+ /// tuples of G1 and G2 points supplied to the ECC circuit .
1142+ pub pairs : [ EcPairingPair ; N_PAIRING_PER_OP ] ,
10681143 /// Result from the pairing check.
10691144 pub output : Word ,
10701145}
10711146
10721147impl Default for EcPairingOp {
10731148 fn default ( ) -> Self {
1149+ let g1_point = G1Affine :: generator ( ) ;
1150+ let g2_point = G2Affine :: generator ( ) ;
10741151 Self {
1075- inputs : [
1076- ( G1Affine :: generator ( ) , G2Affine :: generator ( ) ) ,
1077- ( G1Affine :: identity ( ) , G2Affine :: generator ( ) ) ,
1078- ( G1Affine :: identity ( ) , G2Affine :: generator ( ) ) ,
1079- ( G1Affine :: identity ( ) , G2Affine :: generator ( ) ) ,
1152+ pairs : [
1153+ EcPairingPair { g1_point , g2_point } ,
1154+ EcPairingPair { g1_point , g2_point } ,
1155+ EcPairingPair { g1_point , g2_point } ,
1156+ EcPairingPair { g1_point , g2_point } ,
10801157 ] ,
10811158 output : Word :: zero ( ) ,
10821159 }
10831160 }
10841161}
10851162
10861163impl EcPairingOp {
1087- /// Returns the uncompressed little -endian byte representation of inputs to the EcPairingOp.
1088- pub fn to_bytes_le ( & self ) -> Vec < u8 > {
1089- self . inputs
1164+ /// Returns the uncompressed big -endian byte representation of inputs to the EcPairingOp.
1165+ pub fn to_bytes_be ( & self ) -> Vec < u8 > {
1166+ self . pairs
10901167 . iter ( )
1091- . flat_map ( |i| {
1092- std:: iter:: empty ( )
1093- . chain ( i. 0 . x . to_bytes ( ) . iter ( ) )
1094- . chain ( i. 0 . y . to_bytes ( ) . iter ( ) )
1095- . chain ( i. 1 . x . c0 . to_bytes ( ) . iter ( ) )
1096- . chain ( i. 1 . x . c1 . to_bytes ( ) . iter ( ) )
1097- . chain ( i. 1 . y . c0 . to_bytes ( ) . iter ( ) )
1098- . chain ( i. 1 . y . c1 . to_bytes ( ) . iter ( ) )
1099- . cloned ( )
1100- . collect :: < Vec < u8 > > ( )
1101- } )
1168+ . flat_map ( |pair| pair. to_bytes_be ( ) )
11021169 . collect :: < Vec < u8 > > ( )
11031170 }
11041171
11051172 /// A check on the op to tell the ECC Circuit whether or not to skip the op.
11061173 pub fn skip_by_ecc_circuit ( & self ) -> bool {
1107- self . inputs [ 0 ] . 0 . is_identity ( ) . into ( )
1108- && self . inputs [ 1 ] . 0 . is_identity ( ) . into ( )
1109- && self . inputs [ 2 ] . 0 . is_identity ( ) . into ( )
1110- && self . inputs [ 3 ] . 0 . is_identity ( ) . into ( )
1174+ false
11111175 }
11121176}
0 commit comments