@@ -30,6 +30,8 @@ use crate::executor::token::execute_run_wasm;
3030use crate :: executor:: token:: execute_run_wasm_concat_multiarg;
3131use crate :: executor:: types:: Instruction ;
3232use crate :: executor:: types:: InstructionOptions ;
33+ use crate :: executor:: zk:: execute_poseidon_zk_login;
34+ use crate :: executor:: zk:: execute_vergrth16;
3335use crate :: stack:: Stack ;
3436use crate :: stack:: StackItem ;
3537use crate :: stack:: integer:: IntegerData ;
@@ -41,6 +43,30 @@ use crate::types::Status;
4143use crate :: utils:: pack_data_to_cell;
4244use crate :: utils:: unpack_data_from_cell;
4345
46+ use crate :: utils:: pack_string_to_cell;
47+ use crate :: utils:: unpack_string_from_cell;
48+
49+ use crate :: executor:: zk_stuff:: utils:: gen_address_seed;
50+ use crate :: executor:: zk_stuff:: utils:: get_zk_login_address;
51+
52+ use ed25519_dalek:: Signer ;
53+ use fastcrypto:: ed25519:: Ed25519KeyPair ;
54+ use fastcrypto:: traits:: KeyPair ;
55+ use fastcrypto:: traits:: ToFromBytes ;
56+
57+ use crate :: executor:: zk_stuff:: zk_login:: CanonicalSerialize ;
58+ use crate :: executor:: zk_stuff:: zk_login:: JWK ;
59+ use crate :: executor:: zk_stuff:: zk_login:: JwkId ;
60+ use crate :: executor:: zk_stuff:: zk_login:: OIDCProvider ;
61+ use crate :: executor:: zk_stuff:: zk_login:: ZkLoginInputs ;
62+ use crate :: executor:: zk_stuff:: curve_utils:: Bn254FrElement ;
63+ use crate :: executor:: zk_stuff:: error:: ZkCryptoError ;
64+
65+ use std:: collections:: HashMap ;
66+
67+ //use base64::decode;
68+ use base64ct:: Encoding as bEncoding;
69+
4470#[ allow( dead_code) ]
4571pub ( super ) fn split_to_chain_of_cells ( input : Vec < u8 > ) -> Result < Cell , failure:: Error > {
4672 // TODO: Cell size can maybe be increased up to 128?
@@ -1282,4 +1308,193 @@ fn test_tls_wasm_from_hash_for_4_args() {
12821308 // rejoin_chain_of_cells(engine.cc.stack.get(0).as_cell().unwrap()).
12831309 // unwrap().pop().unwrap() == 3u8
12841310 // );
1311+
12851312}
1313+
1314+ /**** VERGRTH16 TEST */
1315+
1316+ #[ test]
1317+ fn test_poseidon_and_vergrth16 ( ) {
1318+ let elector_code = load_boc ( "benches/elector-code.boc" ) ;
1319+ let elector_data = load_boc ( "benches/elector-data.boc" ) ;
1320+ let config_data = load_boc ( "benches/config-data.boc" ) ;
1321+ let mut ctrls = SaveList :: default ( ) ;
1322+ ctrls. put ( 4 , & mut StackItem :: Cell ( elector_data) ) . unwrap ( ) ;
1323+ let params = vec ! [
1324+ StackItem :: int( 0x76ef1ea ) ,
1325+ StackItem :: int( 0 ) ,
1326+ StackItem :: int( 0 ) ,
1327+ StackItem :: int( 1633458077 ) ,
1328+ StackItem :: int( 0 ) ,
1329+ StackItem :: int( 0 ) ,
1330+ StackItem :: int( 0 ) ,
1331+ StackItem :: tuple( vec![ StackItem :: int( 1000000000 ) , StackItem :: None ] ) ,
1332+ StackItem :: slice(
1333+ SliceData :: from_string(
1334+ "9fe0000000000000000000000000000000000000000000000000000000000000001_" ,
1335+ )
1336+ . unwrap( ) ,
1337+ ) ,
1338+ StackItem :: cell( config_data. reference( 0 ) . unwrap( ) ) ,
1339+ StackItem :: None ,
1340+ StackItem :: int( 0 ) ,
1341+ ] ;
1342+ ctrls. put ( 7 , & mut StackItem :: tuple ( vec ! [ StackItem :: tuple( params) ] ) ) . unwrap ( ) ;
1343+ let stack = Stack :: new ( ) ;
1344+ let mut engine = Engine :: with_capabilities ( DEFAULT_CAPABILITIES ) . setup_with_libraries (
1345+ SliceData :: load_cell_ref ( & elector_code) . unwrap ( ) ,
1346+ Some ( ctrls. clone ( ) ) ,
1347+ Some ( stack. clone ( ) ) ,
1348+ None ,
1349+ vec ! [ ] ,
1350+ ) ;
1351+
1352+
1353+ // password was 567890 in ascii 535455565748
1354+ let user_pass_salt = "535455565748" ;
1355+ let secret_key = [ 222 , 248 , 61 , 101 , 214 , 199 , 113 , 189 , 223 , 94 , 151 , 140 , 235 , 182 , 203 , 46 , 143 , 162 , 166 , 87 , 162 , 250 , 176 , 4 , 29 , 19 , 42 , 221 , 116 , 33 , 178 , 14 ,
1356+ ] ;
1357+ let ephemeral_kp = Ed25519KeyPair :: from_bytes ( & secret_key) . unwrap ( ) ; //
1358+ let mut eph_pubkey = Vec :: new ( ) ;
1359+ eph_pubkey. extend ( ephemeral_kp. public ( ) . as_ref ( ) ) ;
1360+ println ! ( "eph_pubkey: {:?}" , eph_pubkey) ;
1361+ println ! ( "len eph_pubkey: {:?}" , eph_pubkey. len( ) ) ;
1362+ let eph_pubkey_hex_number = "0x" . to_owned ( ) + & hex:: encode ( eph_pubkey. clone ( ) ) ;
1363+ println ! ( "eph_pubkey_hex_number: {:?}" , eph_pubkey_hex_number) ;
1364+ let zk_seed = gen_address_seed (
1365+ user_pass_salt,
1366+ "sub" ,
1367+ "112897468626716626103" ,
1368+ "232624085191-v1tq20fg1kdhhgvat6saj7jf0hd8233r.apps.googleusercontent.com" ,
1369+ )
1370+ . unwrap ( ) ;
1371+ println ! ( "zk_seed = {:?}" , zk_seed) ;
1372+ let proof_and_jwt = "{\" proofPoints\" :{\" a\" :[\" 2352077003566407045854435506409565889408960755152253285189640818725808263237\" ,\
1373+ \" 9548308350778027075240385782578683112366097953461273569343148999989145049123\" ,\" 1\" ],\
1374+ \" b\" :[[\" 2172697685172701179756462481453772004245591587568555358926512547679273443868\" ,\
1375+ \" 11300889616992175665271080883374830731684409375838395487979439153562369168807\" ],\
1376+ [\" 18769153619672444537277685186545610305405730219274884099876386487766026068190\" ,\
1377+ \" 12892936063156115176399929981646174277274895601746717550262309650970826515227\" ],[\" 1\" ,\" 0\" ]],\
1378+ \" c\" :[\" 21276833037675249246843718004583052134371270695679878402069223253610209272159\" ,\
1379+ \" 8637596258221986824049981569842218428861929142818091935707054543971817804456\" ,\" 1\" ]},\
1380+ \" issBase64Details\" :{\" value\" :\" yJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLC\" ,\" indexMod4\" :1},\
1381+ \" headerBase64\" :\" eyJhbGciOiJSUzI1NiIsImtpZCI6ImEzYjc2MmY4NzFjZGIzYmFlMDA0NGM2NDk2MjJmYzEzOTZlZGEzZTMiLCJ0eXAiOiJKV1QifQ\" }";
1382+ let len = proof_and_jwt. bytes ( ) . len ( ) ;
1383+ println ! ( " proof_and_jwt_bytes len (in bytes) = {:?}" , len) ;
1384+
1385+ println ! ( "proof_and_jwt: {}" , proof_and_jwt) ;
1386+
1387+ let iss_and_header_base64details = "{\" issBase64Details\" :{\" value\" :\" yJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLC\" ,\" indexMod4\" :1},\" headerBase64\" :\" eyJhbGciOiJSUzI1NiIsImtpZCI6ImEzYjc2MmY4NzFjZGIzYmFlMDA0NGM2NDk2MjJmYzEzOTZlZGEzZTMiLCJ0eXAiOiJKV1QifQ\" }" ;
1388+
1389+ println ! ( "iss_and_header_base64details: {}" , iss_and_header_base64details) ;
1390+
1391+ let header_base_64 = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImEzYjc2MmY4NzFjZGIzYmFlMDA0NGM2NDk2MjJmYzEzOTZlZGEzZTMiLCJ0eXAiOiJKV1QifQ" ;
1392+ let iss_base_64 = "yJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLC" ;
1393+
1394+
1395+ let zk_login_inputs = ZkLoginInputs :: from_json ( & * proof_and_jwt, & * zk_seed. to_string ( ) ) . unwrap ( ) ;
1396+ let content: JWK = JWK {
1397+ kty : "RSA" . to_string ( ) ,
1398+ e : "AQAB" . to_string ( ) ,
1399+ n : "uBHF-esPKiNlFaAvpdpejD4vpONW9FL0rgLDg1z8Q-x_CiHCvJCpiSehD41zmDOhzXP_fbMMSGpGL7R3duiz01nK5r_YmRw3RXeB0kcS7Z9H8MN6IJcde9MWbqkMabCDduFgdr6gvH0QbTipLB1qJK_oI_IBfRgjk6G0bGrKz3PniQw5TZ92r0u1LM-1XdBIb3aTYTGDW9KlOsrTTuKq0nj-anW5TXhecuxqSveFM4Hwlw7pw34ydBunFjFWDx4VVJqGNSqWCfcERxOulizIFruZIHJGkgunZnB4DF7mCZOttx2dwT9j7s3GfLJf0xoGumqpOMvecuipfTPeIdAzcQ" . to_string ( ) , // Alina's data
1400+ alg : "RS256" . to_string ( ) ,
1401+ } ;
1402+
1403+ let mut all_jwk = HashMap :: new ( ) ;
1404+ all_jwk. insert (
1405+ JwkId :: new (
1406+ OIDCProvider :: Google . get_config ( ) . iss ,
1407+ "a3b762f871cdb3bae0044c649622fc1396eda3e3" . to_string ( ) ,
1408+ ) ,
1409+ content,
1410+ ) ;
1411+
1412+ let ( iss, kid) =
1413+ ( zk_login_inputs. get_iss ( ) . to_string ( ) , zk_login_inputs. get_kid ( ) . to_string ( ) ) ;
1414+ let jwk = all_jwk. get ( & JwkId :: new ( iss. clone ( ) , kid. clone ( ) ) ) . ok_or_else ( || {
1415+ ZkCryptoError :: GeneralError ( format ! ( "JWK not found ({} - {})" , iss, kid) )
1416+ } ) . unwrap ( ) ;
1417+
1418+ let max_epoch = 142 ;
1419+
1420+ let modulus = base64ct:: Base64UrlUnpadded :: decode_vec ( & jwk. n )
1421+ . map_err ( |_| {
1422+ ZkCryptoError :: GeneralError ( "Invalid Base64 encoded jwk modulus" . to_string ( ) )
1423+ } )
1424+ . unwrap ( ) ;
1425+
1426+ let public_inputs = & [ zk_login_inputs. calculate_all_inputs_hash ( & eph_pubkey, & modulus, max_epoch) . unwrap ( ) ] ;
1427+
1428+ let mut public_inputs_as_bytes = vec ! [ ] ;
1429+ public_inputs. serialize_compressed ( & mut public_inputs_as_bytes) . unwrap ( ) ;
1430+ println ! ( "HERE public_inputs_as_bytes : {:?}" , public_inputs_as_bytes) ;
1431+ println ! ( "HERE public_inputs_as_bytes len : {:?}" , public_inputs_as_bytes. len( ) ) ;
1432+
1433+ let public_inputs_cell = pack_data_to_cell ( & public_inputs_as_bytes, & mut 0 ) . unwrap ( ) ;
1434+
1435+ println ! ( "====== Start Poseidon ========" ) ;
1436+
1437+ let index_mod_4 = 1 ;
1438+ engine. cc . stack . push ( StackItem :: int ( index_mod_4) ) ;
1439+ engine. cc . stack . push ( StackItem :: int ( max_epoch) ) ;
1440+ engine. cc . stack . push ( StackItem :: integer ( IntegerData :: from_unsigned_bytes_be ( & eph_pubkey. clone ( ) ) ) ) ;
1441+
1442+ let modulus_cell = pack_data_to_cell ( & modulus. clone ( ) , & mut 0 ) . unwrap ( ) ;
1443+ println ! ( "modulus_cell = {:?}" , modulus_cell) ;
1444+ engine. cc . stack . push ( StackItem :: cell ( modulus_cell. clone ( ) ) ) ;
1445+
1446+ let iss_base_64_cell = pack_string_to_cell ( & iss_base_64, & mut 0 ) . unwrap ( ) ;
1447+ println ! ( "iss_base_64_cell = {:?}" , iss_base_64_cell) ;
1448+ engine. cc . stack . push ( StackItem :: cell ( iss_base_64_cell. clone ( ) ) ) ;
1449+
1450+ let header_base_64_cell = pack_string_to_cell ( & header_base_64, & mut 0 ) . unwrap ( ) ;
1451+ println ! ( "header_base_64_cell = {:?}" , header_base_64_cell) ;
1452+ engine. cc . stack . push ( StackItem :: cell ( header_base_64_cell. clone ( ) ) ) ;
1453+
1454+ let zk_seed_cell = pack_string_to_cell ( & zk_seed. clone ( ) , & mut 0 ) . unwrap ( ) ;
1455+ println ! ( "zk_seed_cell = {:?}" , zk_seed_cell) ;
1456+ engine. cc . stack . push ( StackItem :: cell ( zk_seed_cell. clone ( ) ) ) ;
1457+
1458+ let start: Instant = Instant :: now ( ) ;
1459+ let status = execute_poseidon_zk_login ( & mut engine) . unwrap ( ) ;
1460+ let poseidon_elapsed = start. elapsed ( ) . as_micros ( ) ;
1461+
1462+ println ! ( "poseidon_elapsed in microsecond: {:?}" , poseidon_elapsed) ;
1463+
1464+ let poseidon_res = engine. cc . stack . get ( 0 ) . as_cell ( ) . unwrap ( ) ;
1465+ let slice = SliceData :: load_cell ( poseidon_res. clone ( ) ) . unwrap ( ) ;
1466+ let poseidon_res = unpack_data_from_cell ( slice, & mut engine) . unwrap ( ) ;
1467+ println ! ( "poseidon_res from stack: {:?}" , hex:: encode( poseidon_res. clone( ) ) ) ;
1468+
1469+ println ! ( "public_inputs hex (computed in test): {:?}" , hex:: encode( public_inputs_as_bytes. clone( ) ) ) ;
1470+ assert ! ( poseidon_res == public_inputs_as_bytes) ;
1471+
1472+ println ! ( "====== Start VERGRTH16 ========" ) ;
1473+ let proof = & zk_login_inputs. get_proof ( ) . as_arkworks ( ) . unwrap ( ) ;
1474+ let mut proof_as_bytes = vec ! [ ] ;
1475+ proof. serialize_compressed ( & mut proof_as_bytes) . unwrap ( ) ;
1476+ println ! ( "proof_as_bytes : {:?}" , proof_as_bytes) ;
1477+ println ! ( "proof_as_bytes len: {:?}" , proof_as_bytes. len( ) ) ;
1478+
1479+ let proof_cell = pack_data_to_cell ( & proof_as_bytes, & mut 0 ) . unwrap ( ) ;
1480+ engine. cc . stack . push ( StackItem :: cell ( proof_cell. clone ( ) ) ) ;
1481+
1482+ let public_inputs_cell = pack_data_to_cell ( & public_inputs_as_bytes. clone ( ) , & mut 0 ) . unwrap ( ) ;
1483+ engine. cc . stack . push ( StackItem :: cell ( public_inputs_cell. clone ( ) ) ) ;
1484+
1485+ let verification_key_id: u32 = 0 ; // valid key id
1486+ //let verification_key_id: u32 = 1; //invalid key id
1487+ engine. cc . stack . push ( StackItem :: int ( verification_key_id) ) ;
1488+
1489+ let start: Instant = Instant :: now ( ) ;
1490+ let status = execute_vergrth16 ( & mut engine) . unwrap ( ) ;
1491+ let vergrth16_elapsed = start. elapsed ( ) . as_micros ( ) ;
1492+
1493+ println ! ( "vergrth16_elapsed in microsecond: {:?}" , vergrth16_elapsed) ;
1494+
1495+ let res = engine. cc . stack . get ( 0 ) . as_integer ( ) . unwrap ( ) ;
1496+ println ! ( "res: {:?}" , res) ;
1497+ assert ! ( * res == IntegerData :: minus_one( ) ) ;
1498+
1499+
1500+ }
0 commit comments