2121using  Neo . SmartContract ; 
2222using  Neo . SmartContract . Native ; 
2323using  Neo . VM ; 
24+ using  Neo . VM . Types ; 
2425using  Org . BouncyCastle . Utilities . Encoders ; 
2526using  System ; 
2627using  System . Collections . Generic ; 
2728using  System . Linq ; 
29+ using  System . Numerics ; 
2830using  System . Text ; 
31+ using  VMArray  =  Neo . VM . Types . Array ; 
2932
3033namespace  Neo . UnitTests . SmartContract . Native 
3134{ 
@@ -265,30 +268,98 @@ public void TestBls12381Pairing()
265268        } 
266269
267270        [ TestMethod ] 
268-         public  void  TestBls12AddAliases ( ) 
271+         public  void  TestBls12381MultiExpG1 ( ) 
269272        { 
270-             var  expected  =  InvokeBlsAddMethod ( "bls12381Add" ) ; 
271-             foreach   ( var  alias   in  new [ ]   {   "bls12_g1add" ,   "bls12_g2add"   } ) 
273+             var  g1Point  =  G1Affine . FromCompressed ( g1 ) ; 
274+             var  pair1   =  new   VMArray ( new   StackItem [ ] 
272275            { 
273-                 CollectionAssert . AreEqual ( expected ,  InvokeBlsAddMethod ( alias ) ) ; 
274-             } 
276+                 StackItem . FromInterface ( g1Point ) , 
277+                 new  ByteString ( CreateScalarBytes ( 1 ) ) 
278+             } ) ; 
279+             var  pair2  =  new  VMArray ( new  StackItem [ ] 
280+             { 
281+                 StackItem . FromInterface ( g1Point ) , 
282+                 new  ByteString ( CreateScalarBytes ( 2 ) ) 
283+             } ) ; 
284+             var  pairs  =  new  VMArray ( new  StackItem [ ]  {  pair1 ,  pair2  } ) ; 
285+ 
286+             var  result  =  CryptoLib . Bls12381MultiExp ( pairs ) ; 
287+             var  actual  =  result . GetInterface < G1Projective > ( ) ; 
288+ 
289+             var  expected  =  new  G1Projective ( g1Point )  *  CreateScalar ( 3 ) ; 
290+             Assert . AreEqual ( new  G1Affine ( expected ) . ToCompressed ( ) . ToHexString ( ) , 
291+                 new  G1Affine ( actual ) . ToCompressed ( ) . ToHexString ( ) ) ; 
275292        } 
276293
277294        [ TestMethod ] 
278-         public  void  TestBls12MulAliases ( ) 
295+         public  void  TestBls12381MultiExpG2 ( ) 
279296        { 
280-             var  expected  =  InvokeBlsMulMethod ( "bls12381Mul" ,   false ) ; 
281-             foreach   ( var  alias   in  new [ ]   {   "bls12_g1mul" ,   "bls12_g2mul"   } ) 
297+             var  g2Point  =  G2Affine . FromCompressed ( g2 ) ; 
298+             var  pair   =  new   VMArray ( new   StackItem [ ] 
282299            { 
283-                 CollectionAssert . AreEqual ( expected ,  InvokeBlsMulMethod ( alias ,  false ) ) ; 
284-             } 
300+                 StackItem . FromInterface ( new  G2Projective ( g2Point ) ) , 
301+                 new  ByteString ( CreateScalarBytes ( 5 ) ) 
302+             } ) ; 
303+             var  pairs  =  new  VMArray ( new  StackItem [ ]  {  pair  } ) ; 
304+ 
305+             var  result  =  CryptoLib . Bls12381MultiExp ( pairs ) ; 
306+             var  actual  =  result . GetInterface < G2Projective > ( ) ; 
307+ 
308+             var  expected  =  new  G2Projective ( g2Point )  *  CreateScalar ( 5 ) ; 
309+             Assert . AreEqual ( new  G2Affine ( expected ) . ToCompressed ( ) . ToHexString ( ) , 
310+                 new  G2Affine ( actual ) . ToCompressed ( ) . ToHexString ( ) ) ; 
285311        } 
286312
287313        [ TestMethod ] 
288-         public  void  TestBls12PairingAlias ( ) 
314+         public  void  TestBls12381MultiExpReducesScalar ( ) 
289315        { 
290-             var  expected  =  InvokeBlsPairingMethod ( "bls12381Pairing" ) ; 
291-             CollectionAssert . AreEqual ( expected ,  InvokeBlsPairingMethod ( "bls12_pairing" ) ) ; 
316+             var  g1Point  =  G1Affine . FromCompressed ( g1 ) ; 
317+             var  oversized  =  ( BigInteger . One  <<  260 )  +  5 ; 
318+             var  scalarBytes  =  CreateScalarBytes ( oversized ) ; 
319+             var  pair  =  new  VMArray ( new  StackItem [ ] 
320+             { 
321+                 StackItem . FromInterface ( g1Point ) , 
322+                 new  ByteString ( scalarBytes ) 
323+             } ) ; 
324+             var  pairs  =  new  VMArray ( new  StackItem [ ]  {  pair  } ) ; 
325+ 
326+             var  wide  =  new  byte [ Scalar . Size  *  2 ] ; 
327+             System . Array . Copy ( scalarBytes ,  wide ,  scalarBytes . Length ) ; 
328+             var  reducedScalar  =  Scalar . FromBytesWide ( wide ) ; 
329+ 
330+             var  result  =  CryptoLib . Bls12381MultiExp ( pairs ) ; 
331+             var  actual  =  result . GetInterface < G1Projective > ( ) ; 
332+ 
333+             var  expected  =  new  G1Projective ( g1Point )  *  reducedScalar ; 
334+             Assert . AreEqual ( new  G1Affine ( expected ) . ToCompressed ( ) . ToHexString ( ) , 
335+                 new  G1Affine ( actual ) . ToCompressed ( ) . ToHexString ( ) ) ; 
336+         } 
337+ 
338+         [ TestMethod ] 
339+         public  void  TestBls12381MultiExpMixedGroupFails ( ) 
340+         { 
341+             var  g1Point  =  G1Affine . FromCompressed ( g1 ) ; 
342+             var  g2Point  =  G2Affine . FromCompressed ( g2 ) ; 
343+             var  pair1  =  new  VMArray ( new  StackItem [ ] 
344+             { 
345+                 StackItem . FromInterface ( g1Point ) , 
346+                 new  ByteString ( CreateScalarBytes ( 1 ) ) 
347+             } ) ; 
348+             var  pair2  =  new  VMArray ( new  StackItem [ ] 
349+             { 
350+                 StackItem . FromInterface ( g2Point ) , 
351+                 new  ByteString ( CreateScalarBytes ( 1 ) ) 
352+             } ) ; 
353+             var  pairs  =  new  VMArray ( new  StackItem [ ]  {  pair1 ,  pair2  } ) ; 
354+ 
355+             Assert . ThrowsExactly < ArgumentException > ( ( )  =>  CryptoLib . Bls12381MultiExp ( pairs ) ) ; 
356+         } 
357+ 
358+         [ TestMethod ] 
359+         public  void  TestBls12381MultiExpEmptyFails ( ) 
360+         { 
361+             var  pairs  =  new  VMArray ( ) ; 
362+             Assert . ThrowsExactly < ArgumentException > ( ( )  =>  CryptoLib . Bls12381MultiExp ( pairs ) ) ; 
292363        } 
293364
294365        [ TestMethod ] 
@@ -1153,7 +1224,7 @@ public void TestVerifyWithEd25519()
11531224        { 
11541225            // byte[] privateKey = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".HexToBytes(); 
11551226            byte [ ]  publicKey  =  "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a" . HexToBytes ( ) ; 
1156-             byte [ ]  message  =  Array . Empty < byte > ( ) ; 
1227+             byte [ ]  message  =  System . Array . Empty < byte > ( ) ; 
11571228            byte [ ]  signature  =  ( "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e06522490155"  + 
11581229                                "5fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b" ) . HexToBytes ( ) ; 
11591230
@@ -1169,13 +1240,13 @@ public void TestVerifyWithEd25519()
11691240
11701241            // Test with an invalid signature 
11711242            byte [ ]  invalidSignature  =  new  byte [ signature . Length ] ; 
1172-             Array . Copy ( signature ,  invalidSignature ,  signature . Length ) ; 
1243+             System . Array . Copy ( signature ,  invalidSignature ,  signature . Length ) ; 
11731244            invalidSignature [ 0 ]  ^=  0x01 ;  // Flip one bit 
11741245            Assert . IsFalse ( CallVerifyWithEd25519 ( message ,  publicKey ,  invalidSignature ) ) ; 
11751246
11761247            // Test with an invalid public key 
11771248            byte [ ]  invalidPublicKey  =  new  byte [ publicKey . Length ] ; 
1178-             Array . Copy ( publicKey ,  invalidPublicKey ,  publicKey . Length ) ; 
1249+             System . Array . Copy ( publicKey ,  invalidPublicKey ,  publicKey . Length ) ; 
11791250            invalidPublicKey [ 0 ]  ^=  0x01 ;  // Flip one bit 
11801251            Assert . IsFalse ( CallVerifyWithEd25519 ( message ,  invalidPublicKey ,  signature ) ) ; 
11811252        } 
@@ -1203,61 +1274,22 @@ private bool CallVerifyWithEd25519(byte[] message, byte[] publicKey, byte[] sign
12031274            } 
12041275        } 
12051276
1206-         private  byte [ ]  InvokeBlsAddMethod ( string   methodName ) 
1277+         private  static   byte [ ]  CreateScalarBytes ( BigInteger   value ) 
12071278        { 
1208-             var  snapshotCache  =  TestBlockchain . GetTestSnapshotCache ( ) ; 
1209-             using  ScriptBuilder  script  =  new ( ) ; 
1210-             script . EmitDynamicCall ( NativeContract . CryptoLib . Hash ,  "bls12381Deserialize" ,  gt ) ; 
1211-             script . EmitDynamicCall ( NativeContract . CryptoLib . Hash ,  "bls12381Deserialize" ,  gt ) ; 
1212-             script . EmitPush ( 2 ) ; 
1213-             script . Emit ( OpCode . PACK ) ; 
1214-             script . EmitPush ( CallFlags . All ) ; 
1215-             script . EmitPush ( methodName ) ; 
1216-             script . EmitPush ( NativeContract . CryptoLib . Hash ) ; 
1217-             script . EmitSysCall ( ApplicationEngine . System_Contract_Call ) ; 
1218-             return  ExecuteBlsScript ( script ,  snapshotCache ) ; 
1279+             if  ( value  <  0 ) 
1280+                 throw  new  ArgumentOutOfRangeException ( nameof ( value ) ) ; 
1281+ 
1282+             var  bytes  =  new  byte [ Scalar . Size ] ; 
1283+             var  mask  =  ( BigInteger . One  <<  ( Scalar . Size  *  8 ) )  -  BigInteger . One ; 
1284+             var  truncated  =  value  &  mask ; 
1285+             if  ( ! truncated . TryWriteBytes ( bytes ,  out  _ ,  isBigEndian :  false ) ) 
1286+                 throw  new  InvalidOperationException ( "Unable to encode scalar value." ) ; 
1287+             return  bytes ; 
12191288        } 
12201289
1221-         private  byte [ ]  InvokeBlsMulMethod ( string  methodName ,  bool  neg ) 
1222-         { 
1223-             var  snapshotCache  =  TestBlockchain . GetTestSnapshotCache ( ) ; 
1224-             using  ScriptBuilder  script  =  new ( ) ; 
1225-             byte [ ]  data  =  new  byte [ 32 ] ; 
1226-             data [ 0 ]  =  0x03 ; 
1227-             script . EmitPush ( neg ) ; 
1228-             script . EmitPush ( data ) ; 
1229-             script . EmitDynamicCall ( NativeContract . CryptoLib . Hash ,  "bls12381Deserialize" ,  gt ) ; 
1230-             script . EmitPush ( 3 ) ; 
1231-             script . Emit ( OpCode . PACK ) ; 
1232-             script . EmitPush ( CallFlags . All ) ; 
1233-             script . EmitPush ( methodName ) ; 
1234-             script . EmitPush ( NativeContract . CryptoLib . Hash ) ; 
1235-             script . EmitSysCall ( ApplicationEngine . System_Contract_Call ) ; 
1236-             return  ExecuteBlsScript ( script ,  snapshotCache ) ; 
1237-         } 
1290+         private  static   byte [ ]  CreateScalarBytes ( uint  value )  =>  CreateScalarBytes ( new  BigInteger ( value ) ) ; 
12381291
1239-         private  byte [ ]  InvokeBlsPairingMethod ( string  methodName ) 
1240-         { 
1241-             var  snapshotCache  =  TestBlockchain . GetTestSnapshotCache ( ) ; 
1242-             using  ScriptBuilder  script  =  new ( ) ; 
1243-             script . EmitDynamicCall ( NativeContract . CryptoLib . Hash ,  "bls12381Deserialize" ,  g2 ) ; 
1244-             script . EmitDynamicCall ( NativeContract . CryptoLib . Hash ,  "bls12381Deserialize" ,  g1 ) ; 
1245-             script . EmitPush ( 2 ) ; 
1246-             script . Emit ( OpCode . PACK ) ; 
1247-             script . EmitPush ( CallFlags . All ) ; 
1248-             script . EmitPush ( methodName ) ; 
1249-             script . EmitPush ( NativeContract . CryptoLib . Hash ) ; 
1250-             script . EmitSysCall ( ApplicationEngine . System_Contract_Call ) ; 
1251-             return  ExecuteBlsScript ( script ,  snapshotCache ) ; 
1252-         } 
1292+         private  static   Scalar  CreateScalar ( uint  value )  =>  Scalar . FromBytes ( CreateScalarBytes ( value ) ) ; 
12531293
1254-         private  byte [ ]  ExecuteBlsScript ( ScriptBuilder  script ,  StoreCache  snapshotCache ) 
1255-         { 
1256-             using  var  engine  =  ApplicationEngine . Create ( TriggerType . Application ,  null ,  snapshotCache , 
1257-                 settings :  TestProtocolSettings . Default ) ; 
1258-             engine . LoadScript ( script . ToArray ( ) ) ; 
1259-             Assert . AreEqual ( VMState . HALT ,  engine . Execute ( ) ) ; 
1260-             return  engine . ResultStack . Pop ( ) . GetInterface < Gt > ( ) . ToArray ( ) ; 
1261-         } 
12621294    } 
12631295} 
0 commit comments