69 Env env{*
this, features};
72 MPTTester mptAlice(env, alice, {.holders = {bob}});
76 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
82 mptAlice.pay(alice, bob, 100);
84 mptAlice.generateKeyPair(alice);
86 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
88 mptAlice.generateKeyPair(bob);
93 .holderPubKey = mptAlice.getPubKey(bob),
114 Env env{*
this, features};
117 MPTTester mptAlice(env, alice, {.holders = {bob}});
121 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
127 mptAlice.pay(alice, bob, 1);
129 mptAlice.generateKeyPair(alice);
130 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
132 mptAlice.generateKeyPair(bob);
136 .holderPubKey = mptAlice.getPubKey(bob),
149 Env env{*
this, features};
152 MPTTester mptAlice(env, alice, {.holders = {bob}});
156 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
164 mptAlice.generateKeyPair(alice);
165 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
167 mptAlice.generateKeyPair(bob);
173 .holderPubKey = mptAlice.getPubKey(bob),
178 auto const holderCiphertext =
180 auto const issuerCiphertext =
184 jv[jss::Account] = bob.human();
185 jv[jss::TransactionType] = jss::ConfidentialMPTConvert;
186 jv[sfMPTokenIssuanceID] =
to_string(mptAlice.issuanceID());
188 jv[sfHolderEncryptedAmount.jsonName] =
strHex(holderCiphertext);
189 jv[sfIssuerEncryptedAmount.jsonName] =
strHex(issuerCiphertext);
190 jv[sfBlindingFactor.jsonName] =
strHex(blindingFactor);
195 env.require(MptBalance(mptAlice, bob, 0));
263 Env env{*
this, features};
265 MPTTester mptAlice(env, alice);
268 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
270 mptAlice.generateKeyPair(alice);
275 .holderPubKey = mptAlice.getPubKey(alice),
281 Env env{*
this, features - featureConfidentialTransfer};
284 MPTTester mptAlice(env, alice, {.holders = {bob}});
288 .flags = tfMPTCanTransfer | tfMPTCanLock,
294 mptAlice.pay(alice, bob, 100);
296 mptAlice.generateKeyPair(alice);
297 mptAlice.generateKeyPair(bob);
301 .issuerPubKey = mptAlice.getPubKey(alice),
308 .holderPubKey = mptAlice.getPubKey(bob),
314 Env env{*
this, features};
317 MPTTester mptAlice(env, alice, {.holders = {bob}});
321 .flags = tfMPTCanTransfer | tfMPTCanLock,
327 mptAlice.pay(alice, bob, 100);
329 mptAlice.generateKeyPair(alice);
330 mptAlice.generateKeyPair(bob);
335 .holderPubKey = mptAlice.getPubKey(bob),
343 .holderPubKey = mptAlice.getPubKey(bob),
344 .holderEncryptedAmt =
Buffer{},
352 .holderPubKey = mptAlice.getPubKey(bob),
353 .issuerEncryptedAmt =
Buffer{},
361 .holderPubKey = mptAlice.getPubKey(bob),
362 .auditorEncryptedAmt = gMakeZeroBuffer(10),
370 .holderPubKey = mptAlice.getPubKey(bob),
379 .holderPubKey = mptAlice.getPubKey(bob),
387 .holderPubKey = mptAlice.getPubKey(bob),
397 .holderPubKey = mptAlice.getPubKey(bob),
422 Env env{*
this, features};
425 MPTTester mptAlice(env, alice, {.holders = {bob}});
429 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
435 mptAlice.pay(alice, bob, 100);
437 mptAlice.generateKeyPair(alice);
438 mptAlice.generateKeyPair(bob);
440 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
445 .fillSchnorrProof =
false,
446 .holderPubKey = mptAlice.getPubKey(bob),
453 .fillSchnorrProof =
false,
454 .holderPubKey = mptAlice.getPubKey(bob),
463 .holderPubKey = mptAlice.getPubKey(bob),
471 Env env{*
this, features};
474 MPTTester mptAlice(env, alice, {.holders = {bob}});
478 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
484 mptAlice.pay(alice, bob, 100);
486 mptAlice.generateKeyPair(alice);
487 mptAlice.generateKeyPair(bob);
489 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
496 .holderPubKey = mptAlice.getPubKey(bob),
503 .fillSchnorrProof =
true,
772 Env env{*
this, features};
774 MPTTester mptAlice(env, alice, {.holders = {}});
778 .flags = tfMPTCanTransfer | tfMPTCanLock,
781 mptAlice.generateKeyPair(alice);
785 .issuerPubKey = mptAlice.getPubKey(alice),
792 Env env{*
this, features};
795 MPTTester mptAlice(env, alice, {.holders = {bob}});
799 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
802 mptAlice.generateKeyPair(alice);
803 mptAlice.generateKeyPair(bob);
808 .issuerPubKey = mptAlice.getPubKey(alice),
814 .issuerPubKey = mptAlice.getPubKey(bob),
823 Env env{*
this, features};
826 Account const auditor(
"auditor");
827 MPTTester mptAlice(env, alice, {.holders = {bob}, .auditor = auditor});
831 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
834 mptAlice.generateKeyPair(alice);
835 mptAlice.generateKeyPair(bob);
836 mptAlice.generateKeyPair(auditor);
841 .issuerPubKey = mptAlice.getPubKey(alice),
842 .auditorPubKey = mptAlice.getPubKey(auditor),
848 .issuerPubKey = mptAlice.getPubKey(bob),
849 .auditorPubKey = mptAlice.getPubKey(alice),
856 Env env{*
this, features};
858 Account const auditor(
"auditor");
859 MPTTester mptAlice(env, alice, {.holders = {}, .auditor = auditor});
863 .flags = tfMPTCanTransfer | tfMPTCanLock,
866 mptAlice.generateKeyPair(alice);
867 mptAlice.generateKeyPair(auditor);
871 .issuerPubKey = mptAlice.getPubKey(alice),
872 .auditorPubKey = mptAlice.getPubKey(auditor),
879 Env env{*
this, features};
881 MPTTester mptAlice(env, alice, {.holders = {}});
886 .flags = tfMPTCanTransfer | tfMPTCanLock,
890 mptAlice.generateKeyPair(alice);
897 .issuerPubKey = mptAlice.getPubKey(alice),
904 Env env{*
this, features};
906 Account const auditor(
"auditor");
907 MPTTester mptAlice(env, alice, {.holders = {}, .auditor = auditor});
911 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
914 mptAlice.generateKeyPair(alice);
915 mptAlice.generateKeyPair(auditor);
920 .issuerPubKey = mptAlice.getPubKey(alice),
928 .issuerPubKey = mptAlice.getPubKey(alice),
929 .auditorPubKey = mptAlice.getPubKey(auditor),
1038 Env env{*
this, features};
1041 MPTTester mptAlice(env, alice, {.holders = {bob}});
1045 .flags = tfMPTCanTransfer | tfMPTCanLock,
1048 mptAlice.authorize({
1051 mptAlice.pay(alice, bob, 100);
1053 mptAlice.generateKeyPair(alice);
1054 mptAlice.generateKeyPair(bob);
1059 .holderPubKey = mptAlice.getPubKey(bob),
1066 Env env{*
this, features};
1069 MPTTester mptAlice(env, alice, {.holders = {bob}});
1073 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1076 mptAlice.authorize({
1079 mptAlice.pay(alice, bob, 100);
1081 mptAlice.generateKeyPair(alice);
1082 mptAlice.generateKeyPair(bob);
1087 .holderPubKey = mptAlice.getPubKey(bob),
1094 Env env{*
this, features};
1097 MPTTester mptAlice(env, alice, {.holders = {bob}});
1101 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1104 mptAlice.authorize({
1107 mptAlice.generateKeyPair(alice);
1109 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1112 mptAlice.generateKeyPair(bob);
1117 .holderPubKey = mptAlice.getPubKey(bob),
1124 Env env{*
this, features};
1127 MPTTester mptAlice(env, alice, {.holders = {bob}});
1131 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1134 mptAlice.generateKeyPair(alice);
1135 mptAlice.generateKeyPair(bob);
1137 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1142 .holderPubKey = mptAlice.getPubKey(bob),
1149 Env env{*
this, features};
1153 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1157 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1160 mptAlice.authorize({
1163 mptAlice.pay(alice, bob, 100);
1165 mptAlice.generateKeyPair(alice);
1166 mptAlice.generateKeyPair(bob);
1167 mptAlice.generateKeyPair(carol);
1169 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1174 .holderPubKey = mptAlice.getPubKey(bob),
1182 .holderPubKey = mptAlice.getPubKey(bob),
1189 Buffer const holderCiphertext = mptAlice.encryptAmount(bob, amount, blindingFactor);
1194 Buffer const wrongIssuerCiphertext =
1195 mptAlice.encryptAmount(carol, amount, blindingFactor);
1200 .holderPubKey = mptAlice.getPubKey(bob),
1201 .holderEncryptedAmt = holderCiphertext,
1202 .issuerEncryptedAmt = wrongIssuerCiphertext,
1203 .blindingFactor = blindingFactor,
1210 Env env{*
this, features};
1213 MPTTester mptAlice(env, alice, {.holders = {bob}});
1217 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1220 mptAlice.authorize({
1223 mptAlice.pay(alice, bob, 100);
1225 mptAlice.generateKeyPair(alice);
1227 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1229 mptAlice.generateKeyPair(bob);
1234 .holderPubKey = mptAlice.getPubKey(bob),
1241 Env env{*
this, features};
1244 MPTTester mptAlice(env, alice, {.holders = {bob}});
1248 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1251 mptAlice.authorize({
1254 mptAlice.pay(alice, bob, 100);
1256 mptAlice.generateKeyPair(alice);
1258 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1260 mptAlice.generateKeyPair(bob);
1262 mptAlice.convert({.account = bob, .amt = 10, .holderPubKey = mptAlice.getPubKey(bob)});
1268 .holderPubKey = mptAlice.getPubKey(bob),
1275 Env env{*
this, features};
1278 MPTTester mptAlice(env, alice, {.holders = {bob}});
1282 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1285 mptAlice.authorize({
1288 mptAlice.pay(alice, bob, 100);
1290 mptAlice.generateKeyPair(alice);
1292 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1300 mptAlice.generateKeyPair(bob);
1305 .holderPubKey = mptAlice.getPubKey(bob),
1312 .flags = tfMPTUnlock,
1318 .holderPubKey = mptAlice.getPubKey(bob),
1324 Env env{*
this, features};
1327 MPTTester mptAlice(env, alice, {.holders = {bob}});
1331 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTRequireAuth |
1332 tfMPTCanHoldConfidentialBalance,
1335 mptAlice.authorize({
1338 mptAlice.authorize({
1342 mptAlice.pay(alice, bob, 100);
1344 mptAlice.generateKeyPair(alice);
1346 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1348 mptAlice.generateKeyPair(bob);
1351 mptAlice.authorize({
1354 .flags = tfMPTUnauthorize,
1360 .holderPubKey = mptAlice.getPubKey(bob),
1365 mptAlice.authorize({
1373 .holderPubKey = mptAlice.getPubKey(bob),
1379 Env env{*
this, features};
1382 MPTTester mptAlice(env, alice, {.holders = {bob}});
1386 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1389 mptAlice.authorize({
1392 mptAlice.pay(alice, bob, 100);
1394 mptAlice.generateKeyPair(alice);
1396 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1405 mptAlice.generateKeyPair(bob);
1411 .holderPubKey = mptAlice.getPubKey(bob),
1418 Env env{*
this, features};
1421 MPTTester mptAlice(env, alice, {.holders = {bob}});
1425 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTRequireAuth |
1426 tfMPTCanHoldConfidentialBalance,
1429 mptAlice.authorize({
1432 mptAlice.authorize({
1436 mptAlice.pay(alice, bob, 100);
1438 mptAlice.generateKeyPair(alice);
1440 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1442 mptAlice.generateKeyPair(bob);
1445 mptAlice.authorize({
1448 .flags = tfMPTUnauthorize,
1455 .holderPubKey = mptAlice.getPubKey(bob),
1463 Env env{*
this, features};
1466 Account const auditor(
"auditor");
1477 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1480 mptAlice.authorize({
1483 mptAlice.pay(alice, bob, 100);
1485 mptAlice.generateKeyPair(alice);
1486 mptAlice.generateKeyPair(bob);
1487 mptAlice.generateKeyPair(auditor);
1491 .issuerPubKey = mptAlice.getPubKey(alice),
1492 .auditorPubKey = mptAlice.getPubKey(auditor)});
1498 .fillAuditorEncryptedAmt =
false,
1499 .holderPubKey = mptAlice.getPubKey(bob),
1507 Env env{*
this, features};
1510 MPTTester mptAlice(env, alice, {.holders = {bob}});
1514 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1517 mptAlice.authorize({
1520 mptAlice.pay(alice, bob, 100);
1522 mptAlice.generateKeyPair(alice);
1523 mptAlice.generateKeyPair(bob);
1526 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1531 .holderPubKey = mptAlice.getPubKey(bob),
1540 Env env{*
this, features};
1543 Account const auditor(
"auditor");
1553 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1556 mptAlice.authorize({
1559 mptAlice.pay(alice, bob, 100);
1561 mptAlice.generateKeyPair(alice);
1562 mptAlice.generateKeyPair(bob);
1563 mptAlice.generateKeyPair(auditor);
1567 .issuerPubKey = mptAlice.getPubKey(alice),
1568 .auditorPubKey = mptAlice.getPubKey(auditor)});
1573 .holderPubKey = mptAlice.getPubKey(bob),
1581 Env env{*
this, features};
1584 MPTTester mptAlice(env, alice, {.holders = {bob}});
1588 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1591 mptAlice.authorize({
1594 mptAlice.pay(alice, bob, 100);
1596 mptAlice.generateKeyPair(alice);
1597 mptAlice.generateKeyPair(bob);
1599 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1605 .holderPubKey = mptAlice.getPubKey(bob),
1612 Env env{*
this, features};
1615 MPTTester mptAlice(env, alice, {.holders = {bob}});
1619 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1622 mptAlice.authorize({
1625 mptAlice.pay(alice, bob, 100);
1627 mptAlice.generateKeyPair(alice);
1628 mptAlice.generateKeyPair(bob);
1630 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1642 Env env{*
this, features};
1645 MPTTester mptAlice(env, alice, {.holders = {bob}});
1649 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1652 mptAlice.authorize({
1655 mptAlice.pay(alice, bob, 100);
1657 mptAlice.generateKeyPair(alice);
1659 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1661 mptAlice.generateKeyPair(bob);
1667 .holderPubKey = mptAlice.getPubKey(bob),
1670 env.require(MptBalance(mptAlice, bob, 0));
1823 Env env{*
this, features};
1826 MPTTester mptAlice(env, alice, {.holders = {bob}});
1830 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1833 mptAlice.authorize({
1836 mptAlice.generateKeyPair(alice);
1838 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1841 mptAlice.generateKeyPair(bob);
1843 mptAlice.mergeInbox({
1851 Env env{*
this, features};
1854 MPTTester mptAlice(env, alice, {.holders = {bob}});
1858 .flags = tfMPTCanTransfer | tfMPTCanLock,
1861 mptAlice.authorize({
1864 mptAlice.pay(alice, bob, 100);
1866 mptAlice.generateKeyPair(alice);
1867 mptAlice.generateKeyPair(bob);
1869 mptAlice.mergeInbox({
1877 Env env{*
this, features};
1880 MPTTester mptAlice(env, alice, {.holders = {bob}});
1884 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1887 mptAlice.generateKeyPair(alice);
1889 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1891 mptAlice.mergeInbox({
1899 Env env{*
this, features};
1902 MPTTester mptAlice(env, alice, {.holders = {bob}});
1906 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1909 mptAlice.authorize({
1912 mptAlice.pay(alice, bob, 100);
1914 mptAlice.generateKeyPair(alice);
1916 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1918 mptAlice.generateKeyPair(bob);
1920 mptAlice.mergeInbox({
1928 Env env{*
this, features};
1931 MPTTester mptAlice(env, alice, {.holders = {bob}});
1935 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
1938 mptAlice.authorize({
1941 mptAlice.pay(alice, bob, 100);
1943 mptAlice.generateKeyPair(alice);
1944 mptAlice.generateKeyPair(bob);
1946 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1951 .holderPubKey = mptAlice.getPubKey(bob),
1961 mptAlice.mergeInbox({
1970 .flags = tfMPTUnlock,
1974 mptAlice.mergeInbox({
1981 Env env{*
this, features};
1984 MPTTester mptAlice(env, alice, {.holders = {bob}});
1988 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance |
1992 mptAlice.authorize({
1995 mptAlice.authorize({
1999 mptAlice.pay(alice, bob, 100);
2001 mptAlice.generateKeyPair(alice);
2002 mptAlice.generateKeyPair(bob);
2004 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
2009 .holderPubKey = mptAlice.getPubKey(bob),
2013 mptAlice.authorize({
2016 .flags = tfMPTUnauthorize,
2019 mptAlice.mergeInbox({
2025 mptAlice.authorize({
2031 mptAlice.mergeInbox({
2125 testcase(
"test ConfidentialMPTSend Preflight");
2130 Env env{*
this, features - featureConfidentialTransfer};
2134 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
2137 mptAlice.authorize({
2140 mptAlice.authorize({
2157 Env env{*
this, features};
2161 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
2165 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
2168 mptAlice.authorize({
2171 mptAlice.authorize({
2174 mptAlice.generateKeyPair(alice);
2175 mptAlice.generateKeyPair(bob);
2176 mptAlice.generateKeyPair(carol);
2177 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
2178 mptAlice.pay(alice, bob, 100);
2179 mptAlice.pay(alice, carol, 50);
2184 .holderPubKey = mptAlice.getPubKey(bob),
2190 .holderPubKey = mptAlice.getPubKey(carol),
2222 .senderEncryptedAmt = gMakeZeroBuffer(10),
2231 .destEncryptedAmt = gMakeZeroBuffer(10),
2240 .issuerEncryptedAmt = gMakeZeroBuffer(10),
2297 .amountCommitment = gMakeZeroBuffer(100),
2309 .balanceCommitment = gMakeZeroBuffer(100),
2338 Env env{*
this, features};
2342 Account const auditor(
"auditor");
2347 .holders = {bob, carol},
2353 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
2356 mptAlice.authorize({
2359 mptAlice.authorize({
2362 mptAlice.generateKeyPair(alice);
2363 mptAlice.generateKeyPair(bob);
2364 mptAlice.generateKeyPair(carol);
2365 mptAlice.generateKeyPair(auditor);
2369 .issuerPubKey = mptAlice.getPubKey(alice),
2370 .auditorPubKey = mptAlice.getPubKey(auditor)});
2371 mptAlice.pay(alice, bob, 100);
2372 mptAlice.pay(alice, carol, 50);
2377 .holderPubKey = mptAlice.getPubKey(bob),
2383 .holderPubKey = mptAlice.getPubKey(carol),
2392 .auditorEncryptedAmt = gMakeZeroBuffer(10),
2415 testcase(
"test ConfidentialMPTSend Preclaim");
2418 Env env{*
this, features};
2424 MPTTester mptAlice(env, alice, {.holders = {bob, carol, dave, eve}});
2428 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTRequireAuth |
2429 tfMPTCanHoldConfidentialBalance,
2431 mptAlice.authorize({
2434 mptAlice.authorize({
2438 mptAlice.authorize({
2441 mptAlice.authorize({
2445 mptAlice.authorize({
2448 mptAlice.authorize({
2454 mptAlice.pay(alice, bob, 100);
2455 mptAlice.pay(alice, carol, 50);
2457 mptAlice.generateKeyPair(alice);
2458 mptAlice.generateKeyPair(bob);
2459 mptAlice.generateKeyPair(carol);
2460 mptAlice.generateKeyPair(dave);
2461 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
2467 .holderPubKey = mptAlice.getPubKey(bob),
2473 .holderPubKey = mptAlice.getPubKey(carol),
2478 mptAlice.mergeInbox({
2481 mptAlice.mergeInbox({
2487 Env env{*
this, features};
2491 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
2494 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
2496 mptAlice.authorize({
2499 mptAlice.authorize({
2502 mptAlice.generateKeyPair(alice);
2503 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
2509 jv[jss::Account] = bob.human();
2510 jv[jss::Destination] = carol.human();
2511 jv[jss::TransactionType] = jss::ConfidentialMPTSend;
2512 jv[sfMPTokenIssuanceID] =
to_string(mptAlice.issuanceID());
2525 Account const unknown(
"unknown");
2542 env(fset(carol, asfRequireDest));
2558 env(fclear(carol, asfRequireDest));
2622 .flags = tfMPTUnlock,
2650 .flags = tfMPTUnlock,
2678 .flags = tfMPTUnlock,
2691 mptAlice.authorize({
2694 .flags = tfMPTUnauthorize,
2703 mptAlice.authorize({
2718 mptAlice.authorize({
2721 .flags = tfMPTUnauthorize,
2730 mptAlice.authorize({
2744 Env env{*
this, features};
2751 {{.account = bob, .payAmount = 100, .convertAmount = 60},
2752 {.account = carol, .payAmount = 50, .convertAmount = 20}},
2753 tfMPTCanLock | tfMPTCanHoldConfidentialBalance};
2754 auto& mptAlice = confEnv.
mpt;
2768 Env env{*
this, features};
2775 {{.account = bob, .payAmount = 100, .convertAmount = 60},
2776 {.account = carol, .payAmount = 50, .convertAmount = 20}}};
2777 auto& mptAlice = confEnv.
mpt;
2780 auto const issuance = std::const_pointer_cast<SLE>(
2781 view.read(keylet::mptokenIssuance(mptAlice.issuanceID())));
2785 issuance->setFieldU16(sfTransferFee, 1);
2786 view.rawReplace(issuance);
2801 Env env{*
this, features};
2808 {{.account = bob, .payAmount = 100, .convertAmount = 60},
2809 {.account = carol, .payAmount = 50, .convertAmount = 20}}};
2810 auto& mptAlice = confEnv.
mpt;
2835 Env env{*
this, features};
2839 Account const auditor(
"auditor");
2844 .holders = {bob, carol},
2850 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
2853 mptAlice.authorize({
2856 mptAlice.authorize({
2859 mptAlice.generateKeyPair(alice);
2860 mptAlice.generateKeyPair(bob);
2861 mptAlice.generateKeyPair(carol);
2862 mptAlice.generateKeyPair(auditor);
2866 .issuerPubKey = mptAlice.getPubKey(alice),
2867 .auditorPubKey = mptAlice.getPubKey(auditor)});
2868 mptAlice.pay(alice, bob, 100);
2869 mptAlice.pay(alice, carol, 50);
2874 .holderPubKey = mptAlice.getPubKey(bob),
2880 .holderPubKey = mptAlice.getPubKey(carol),
3092 Env env{*
this, features};
3095 MPTTester mptAlice(env, alice, {.holders = {bob}});
3099 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
3102 mptAlice.authorize({
3105 mptAlice.pay(alice, bob, 100);
3107 mptAlice.generateKeyPair(alice);
3109 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
3111 mptAlice.generateKeyPair(bob);
3116 .holderPubKey = mptAlice.getPubKey(bob),
3119 mptAlice.authorize({
3121 .flags = tfMPTUnauthorize,
3128 Env env{*
this, features};
3132 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
3136 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
3139 mptAlice.authorize({
3142 mptAlice.authorize({
3145 mptAlice.pay(alice, bob, 100);
3147 mptAlice.generateKeyPair(alice);
3149 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
3151 mptAlice.generateKeyPair(bob);
3152 mptAlice.generateKeyPair(carol);
3157 .holderPubKey = mptAlice.getPubKey(bob),
3163 .holderPubKey = mptAlice.getPubKey(carol),
3167 mptAlice.authorize({
3169 .flags = tfMPTUnauthorize,
3176 Env env{*
this, features};
3179 MPTTester mptAlice(env, alice, {.holders = {bob}});
3183 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
3186 mptAlice.authorize({
3189 mptAlice.generateKeyPair(alice);
3191 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
3193 mptAlice.generateKeyPair(bob);
3198 .holderPubKey = mptAlice.getPubKey(bob),
3201 mptAlice.authorize({
3203 .flags = tfMPTUnauthorize,
3210 Env env{*
this, features};
3213 MPTTester mptAlice(env, alice, {.holders = {bob}});
3217 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
3220 mptAlice.authorize({
3223 mptAlice.generateKeyPair(alice);
3225 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
3227 mptAlice.generateKeyPair(bob);
3232 .holderPubKey = mptAlice.getPubKey(bob),
3237 mptAlice.authorize({
3239 .flags = tfMPTUnauthorize,
3245 Env env{*
this, features};
3249 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 100}}};
3250 auto& mptAlice = confEnv.
mpt;
3257 mptAlice.pay(bob, alice, 100);
3260 mptAlice.authorize({
3262 .flags = tfMPTUnauthorize,
3269 Env env{*
this, features | featureSingleAssetVault};
3270 Account const issuer(
"issuer");
3272 Account const depositor(
"depositor");
3274 MPTTester mptt{env, issuer, {.holders = {owner, depositor}}};
3276 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanClawback,
3278 PrettyAsset
const asset = mptt.issuanceID();
3279 mptt.authorize({.account = owner});
3280 mptt.authorize({.account = depositor});
3281 env(pay(issuer, depositor, asset(1000)));
3285 auto [tx, vaultKeylet] = vault.create({.owner = owner, .asset = asset});
3290 auto const vaultSle = env.le(vaultKeylet);
3291 BEAST_EXPECT(vaultSle !=
nullptr);
3292 auto const share = vaultSle->at(sfShareMPTID);
3296 {.depositor = depositor, .id = vaultKeylet.key, .amount = asset(100)});
3302 BEAST_EXPECT(shareMpt !=
nullptr);
3314 issuance->setFlag(lsfMPTCanHoldConfidentialBalance);
3328 sle->setFieldVL(sfConfidentialBalanceSpending, dummyCiphertext);
3329 sle->setFieldVL(sfConfidentialBalanceInbox, dummyCiphertext);
3330 sle->setFieldVL(sfIssuerEncryptedBalance, dummyCiphertext);
3336 tx = vault.withdraw(
3337 {.depositor = depositor, .id = vaultKeylet.key, .amount = asset(100)});
3343 BEAST_EXPECT(shareMpt !=
nullptr);
3355 Env env{*
this, features};
3359 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
3360 auto& mptAlice = confEnv.
mpt;
3367 mptAlice.convertBack({
3375 Env env{*
this, features};
3379 env, alice, {{.account = bob, .payAmount = 2, .convertAmount = 2}}};
3380 auto& mptAlice = confEnv.
mpt;
3394 Env env{*
this, features};
3397 MPTTester mptAlice(env, alice, {.holders = {bob}});
3401 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
3404 mptAlice.authorize({
3409 mptAlice.generateKeyPair(alice);
3410 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
3412 mptAlice.generateKeyPair(bob);
3416 auto const convertHolderCiphertext =
3418 auto const convertIssuerCiphertext =
3420 auto const convertContextHash =
3423 mptAlice.getSchnorrProof(bob, convertContextHash),
"Missing schnorr proof");
3427 jv[jss::Account] = bob.human();
3428 jv[jss::TransactionType] = jss::ConfidentialMPTConvert;
3429 jv[sfMPTokenIssuanceID] =
to_string(mptAlice.issuanceID());
3431 jv[sfHolderEncryptionKey.jsonName] =
3433 jv[sfHolderEncryptedAmount.jsonName] =
strHex(convertHolderCiphertext);
3434 jv[sfIssuerEncryptedAmount.jsonName] =
strHex(convertIssuerCiphertext);
3435 jv[sfBlindingFactor.jsonName] =
strHex(convertBlindingFactor);
3436 jv[sfZKProof.jsonName] =
strHex(schnorrProof);
3444 jv[jss::Account] = bob.human();
3445 jv[jss::TransactionType] = jss::ConfidentialMPTMergeInbox;
3446 jv[sfMPTokenIssuanceID] =
to_string(mptAlice.issuanceID());
3457 auto const convertBackHolderCiphertext =
3458 mptAlice.encryptAmount(bob, convertBackAmt, convertBackBlindingFactor);
3459 auto const convertBackIssuerCiphertext =
3460 mptAlice.encryptAmount(alice, convertBackAmt, convertBackBlindingFactor);
3464 mptAlice.getEncryptedBalance(bob, MPTTester::holderEncryptedSpending),
3465 "Missing encrypted spending balance");
3469 Buffer const pedersenCommitment =
3473 auto const version = mptAlice.getMPTokenVersion(bob);
3474 uint256 const convertBackContextHash =
3477 Buffer const proof = mptAlice.getConvertBackProof(
3480 convertBackContextHash,
3482 .pedersenCommitment = pedersenCommitment,
3484 .encryptedAmt = encryptedSpendingBalance,
3485 .blindingFactor = pcBlindingFactor,
3490 jv[jss::Account] = bob.human();
3491 jv[jss::TransactionType] = jss::ConfidentialMPTConvertBack;
3492 jv[sfMPTokenIssuanceID] =
to_string(mptAlice.issuanceID());
3494 jv[sfHolderEncryptedAmount.jsonName] =
strHex(convertBackHolderCiphertext);
3495 jv[sfIssuerEncryptedAmount.jsonName] =
strHex(convertBackIssuerCiphertext);
3496 jv[sfBlindingFactor.jsonName] =
strHex(convertBackBlindingFactor);
3497 jv[sfBalanceCommitment.jsonName] =
strHex(pedersenCommitment);
3498 jv[sfZKProof.jsonName] =
strHex(proof);
3504 env.require(MptBalance(mptAlice, bob, convertBackAmt));
3665 Env env{*
this, features};
3668 MPTTester mptAlice(env, alice, {.holders = {bob}});
3672 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
3675 mptAlice.authorize({
3678 mptAlice.generateKeyPair(alice);
3680 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
3683 mptAlice.generateKeyPair(bob);
3685 mptAlice.convertBack({
3694 Env env{*
this, features};
3697 MPTTester mptAlice(env, alice, {.holders = {bob}});
3701 .flags = tfMPTCanTransfer | tfMPTCanLock,
3704 mptAlice.authorize({
3707 mptAlice.pay(alice, bob, 100);
3709 mptAlice.generateKeyPair(alice);
3710 mptAlice.generateKeyPair(bob);
3712 mptAlice.convertBack({
3721 Env env{*
this, features};
3724 MPTTester mptAlice(env, alice, {.holders = {bob}});
3728 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
3731 mptAlice.generateKeyPair(alice);
3732 mptAlice.generateKeyPair(bob);
3734 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
3736 mptAlice.convertBack({
3745 Env env{*
this, features};
3748 MPTTester mptAlice(env, alice, {.holders = {bob}});
3752 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
3755 mptAlice.authorize({
3759 mptAlice.pay(alice, bob, 100);
3760 mptAlice.generateKeyPair(alice);
3761 mptAlice.generateKeyPair(bob);
3762 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
3765 auto const sleBobMpt = env.le(
keylet::mptoken(mptAlice.issuanceID(), bob.id()));
3766 BEAST_EXPECT(sleBobMpt);
3767 BEAST_EXPECT(!sleBobMpt->isFieldPresent(sfHolderEncryptionKey));
3768 BEAST_EXPECT(!sleBobMpt->isFieldPresent(sfConfidentialBalanceSpending));
3769 BEAST_EXPECT(!sleBobMpt->isFieldPresent(sfIssuerEncryptedBalance));
3771 mptAlice.convertBack({
3780 Env env{*
this, features};
3784 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
3788 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
3791 mptAlice.authorize({
3794 mptAlice.authorize({
3797 mptAlice.pay(alice, bob, 100);
3798 mptAlice.pay(alice, carol, 100);
3800 mptAlice.generateKeyPair(alice);
3802 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
3804 mptAlice.generateKeyPair(bob);
3805 mptAlice.generateKeyPair(carol);
3810 .holderPubKey = mptAlice.getPubKey(bob),
3813 mptAlice.mergeInbox({
3820 .holderPubKey = mptAlice.getPubKey(carol),
3823 mptAlice.convertBack({
3832 Env env{*
this, features};
3835 MPTTester mptAlice(env, alice, {.holders = {bob}});
3839 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTRequireAuth |
3840 tfMPTCanHoldConfidentialBalance,
3843 mptAlice.authorize({
3846 mptAlice.authorize({
3850 mptAlice.pay(alice, bob, 100);
3852 mptAlice.generateKeyPair(alice);
3854 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
3856 mptAlice.generateKeyPair(bob);
3861 .holderPubKey = mptAlice.getPubKey(bob),
3864 mptAlice.mergeInbox({
3874 mptAlice.convertBack({
3883 .flags = tfMPTUnlock,
3886 mptAlice.convertBack({
3891 mptAlice.authorize({
3894 .flags = tfMPTUnauthorize,
3897 mptAlice.convertBack({
3903 mptAlice.authorize({
3908 mptAlice.convertBack({
3916 Env env{*
this, features};
3920 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 50}}};
3921 auto& mptAlice = confEnv.
mpt;
3934 mptAlice.convertBack({
3945 Env env{*
this, features};
3949 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 50}}};
3950 auto& mptAlice = confEnv.
mpt;
3963 Env env{*
this, features};
3966 Account const auditor(
"auditor");
3970 {{.account = bob, .payAmount = 100, .convertAmount = 50}},
3971 tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
3973 auto& mptAlice = confEnv.
mpt;
3979 .fillAuditorEncryptedAmt =
false,
3985 mptAlice.convertBack({
3997 testcase(
"test ConfidentialMPTClawback");
4000 Env env{*
this, features};
4005 MPTTester mptAlice(env, alice, {.holders = {bob, carol, dave}});
4008 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanClawback |
4009 tfMPTCanHoldConfidentialBalance,
4011 mptAlice.authorize({
4014 mptAlice.pay(alice, bob, 100);
4015 mptAlice.authorize({
4018 mptAlice.pay(alice, carol, 200);
4019 mptAlice.authorize({
4022 mptAlice.pay(alice, dave, 300);
4024 mptAlice.generateKeyPair(alice);
4025 mptAlice.generateKeyPair(bob);
4026 mptAlice.generateKeyPair(carol);
4027 mptAlice.generateKeyPair(dave);
4028 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
4034 mptAlice.convert({.account = bob, .amt = 60, .holderPubKey = mptAlice.getPubKey(bob)});
4037 mptAlice.mergeInbox({
4047 {.account = carol, .amt = 120, .holderPubKey = mptAlice.getPubKey(carol)});
4050 mptAlice.mergeInbox({
4058 mptAlice.convert({.account = dave, .amt = 200, .holderPubKey = mptAlice.getPubKey(dave)});
4072 auto const preBobPublicBalance = mptAlice.getBalance(bob);
4073 auto const preOutstandingAmount = mptAlice.getIssuanceOutstandingBalance();
4074 auto const preConfidentialOutstandingAmount = mptAlice.getIssuanceConfidentialBalance();
4075 BEAST_EXPECT(!env.le(
keylet::mptoken(mptAlice.issuanceID(), alice.id())));
4081 mptAlice.confidentialClaw({
4086 BEAST_EXPECT(mptAlice.getBalance(bob) == preBobPublicBalance);
4087 auto const postOutstandingAmount = mptAlice.getIssuanceOutstandingBalance();
4089 preOutstandingAmount && postOutstandingAmount &&
4090 *postOutstandingAmount == *preOutstandingAmount - 110);
4092 mptAlice.getIssuanceConfidentialBalance() == preConfidentialOutstandingAmount - 110);
4093 BEAST_EXPECT(!env.le(
keylet::mptoken(mptAlice.issuanceID(), alice.id())));
4097 mptAlice.confidentialClaw({
4105 mptAlice.confidentialClaw({
4419 testcase(
"Clawback Preclaim Errors");
4426 Env env{*
this, features};
4431 MPTTester mptAlice(env, alice, {.holders = {bob, carol, dave}});
4434 .flags = tfMPTCanTransfer | tfMPTCanClawback | tfMPTRequireAuth |
4435 tfMPTCanHoldConfidentialBalance,
4437 mptAlice.authorize({
4440 mptAlice.authorize({
4444 mptAlice.authorize({
4447 mptAlice.authorize({
4452 mptAlice.pay(alice, bob, 100);
4453 mptAlice.pay(alice, carol, 50);
4454 mptAlice.generateKeyPair(alice);
4455 mptAlice.generateKeyPair(bob);
4456 mptAlice.generateKeyPair(carol);
4457 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
4462 .holderPubKey = mptAlice.getPubKey(bob),
4464 mptAlice.mergeInbox({
4470 Account const unknown(
"unknown");
4471 mptAlice.confidentialClaw({
4481 mptAlice.confidentialClaw({
4491 mptAlice.confidentialClaw({
4502 Env env{*
this, features};
4505 MPTTester mptAlice(env, alice, {.holders = {bob}});
4508 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
4510 mptAlice.authorize({
4513 mptAlice.generateKeyPair(alice);
4514 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
4516 mptAlice.confidentialClaw({
4526 Env env{*
this, features};
4529 MPTTester mptAlice(env, alice, {.holders = {bob}});
4531 .flags = tfMPTCanClawback | tfMPTCanHoldConfidentialBalance,
4533 mptAlice.authorize({
4536 mptAlice.generateKeyPair(alice);
4538 mptAlice.confidentialClaw({
4548 Env env{*
this, features};
4551 MPTTester mptAlice(env, alice, {.holders = {bob}});
4553 .flags = tfMPTCanClawback | tfMPTCanHoldConfidentialBalance,
4555 mptAlice.authorize({
4558 mptAlice.generateKeyPair(alice);
4559 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
4565 jv[jss::Account] = alice.human();
4566 jv[sfHolder] = bob.human();
4567 jv[jss::TransactionType] = jss::ConfidentialMPTClawback;
4570 jv[sfZKProof] = dummyProof;
4571 jv[sfMPTokenIssuanceID] =
to_string(mptAlice.issuanceID());
4577 std::uint32_t const setupFlags = tfMPTCanTransfer | tfMPTCanClawback | tfMPTRequireAuth |
4578 tfMPTCanLock | tfMPTCanHoldConfidentialBalance;
4581 auto removeMPTokenField =
4582 [&](Env& env, MPTTester
const& mpt,
Account const& holder,
SField const& field) {
4584 auto const sle = std::const_pointer_cast<SLE>(
4585 view.read(keylet::mptoken(mpt.issuanceID(), holder.id())));
4589 sle->makeFieldAbsent(field);
4590 view.rawReplace(sle);
4599 Env env{*
this, features};
4603 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 60}}, setupFlags};
4604 auto& mptAlice = confEnv.
mpt;
4612 mptAlice.confidentialClaw({
4616 .proof = dummyClawbackProof,
4624 Env env{*
this, features};
4628 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 60}}, setupFlags};
4629 auto& mptAlice = confEnv.
mpt;
4631 removeMPTokenField(env, mptAlice, bob, sfIssuerEncryptedBalance);
4632 mptAlice.confidentialClaw({
4636 .proof = dummyClawbackProof,
4643 Env env{*
this, features};
4647 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 60}}, setupFlags};
4648 auto& mptAlice = confEnv.
mpt;
4650 removeMPTokenField(env, mptAlice, bob, sfHolderEncryptionKey);
4651 mptAlice.confidentialClaw({
4655 .proof = dummyClawbackProof,
4662 Env env{*
this, features};
4666 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 60}}, setupFlags};
4667 auto& mptAlice = confEnv.
mpt;
4675 mptAlice.confidentialClaw({
4684 Env env{*
this, features};
4688 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 60}}, setupFlags};
4689 auto& mptAlice = confEnv.
mpt;
4696 mptAlice.confidentialClaw({
4705 Env env{*
this, features};
4709 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 60}}, setupFlags};
4710 auto& mptAlice = confEnv.
mpt;
4716 .flags = tfMPTUnauthorize,
4719 mptAlice.confidentialClaw({
4729 Env env{*
this, features};
4733 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 60}}, setupFlags};
4734 auto& mptAlice = confEnv.
mpt;
4748 testcase(
"ConfidentialMPTClawback Proof");
4758 auto setupEnv = [&](Env& env) -> MPTTester {
4759 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
4762 .flags = tfMPTCanTransfer | tfMPTCanClawback | tfMPTCanHoldConfidentialBalance,
4765 for (
auto const& [acct, amt] : {
std::pair{bob, 1000}, {carol, 2000}})
4767 mptAlice.authorize({
4770 mptAlice.pay(alice, acct, amt);
4771 mptAlice.generateKeyPair(acct);
4774 mptAlice.generateKeyPair(alice);
4775 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
4782 auto checkBadProofs =
4784 for (
auto const badAmt : amts)
4786 mpt.confidentialClaw({
4800 Env env{*
this, features};
4801 auto mptAlice = setupEnv(env);
4804 mptAlice.convert({.account = bob, .amt = 500, .holderPubKey = mptAlice.getPubKey(bob)});
4805 mptAlice.mergeInbox({
4810 {.account = carol, .amt = 1000, .holderPubKey = mptAlice.getPubKey(carol)});
4846 mptAlice.confidentialClaw({
4851 mptAlice.confidentialClaw({
4865 Env env{*
this, features};
4866 auto mptAlice = setupEnv(env);
4868 mptAlice.convert({.account = bob, .amt = 300, .holderPubKey = mptAlice.getPubKey(bob)});
4869 mptAlice.mergeInbox({
4873 {.account = carol, .amt = 400, .holderPubKey = mptAlice.getPubKey(carol)});
4874 mptAlice.mergeInbox({
4921 mptAlice.confidentialClaw({
4926 mptAlice.confidentialClaw({
4938 Env env{*
this, features};
4939 auto mptAlice = setupEnv(env);
4941 mptAlice.convert({.account = bob, .amt = 500, .holderPubKey = mptAlice.getPubKey(bob)});
4942 mptAlice.mergeInbox({
4946 auto const privKey = mptAlice.getPrivKey(alice);
4947 if (!BEAST_EXPECT(privKey.has_value()))
4950 auto const proof = mptAlice.getClawbackProof(
4955 alice.id(), mptAlice.issuanceID(), env.seq(alice), bob.id()));
4956 if (!BEAST_EXPECT(proof.has_value()))
4962 auto const versionBefore = mptAlice.getMPTokenVersion(bob);
4963 mptAlice.mergeInbox({.account = bob});
4964 BEAST_EXPECT(mptAlice.getMPTokenVersion(bob) != versionBefore);
4967 mptAlice.confidentialClaw({
4979 testcase(
"Public transfers after clearing Confidential Flag");
4989 auto runPublicPayments = [&](MPTTester& mpt) {
4990 mpt.pay(bob, carol, 10);
4991 mpt.pay(carol, bob, 5);
4992 mpt.pay(alice, bob, 1);
4993 mpt.pay(carol, alice, 5);
4996 auto drainAndDeleteBobMPToken = [&](Env& env, MPTTester& mpt) {
4997 auto const bobBalance = mpt.getBalance(bob);
4998 BEAST_EXPECT(bobBalance > 0);
5000 mpt.pay(bob, alice, bobBalance);
5001 BEAST_EXPECT(mpt.getBalance(bob) == 0);
5003 mpt.authorize({.account = bob, .flags = tfMPTUnauthorize});
5010 Env env{*
this, features};
5014 {{.account = bob, .payAmount = 100, .convertAmount = 50}},
5015 tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance};
5017 env.fund(XRP(1'000), carol);
5019 ct.
mpt.
pay(alice, carol, 50);
5023 runPublicPayments(ct.
mpt);
5024 drainAndDeleteBobMPToken(env, ct.
mpt);
5029 Env env{*
this, features};
5030 Account const auditor(
"auditor");
5031 MPTTester mptAlice(env, alice, {.holders = {bob, carol}, .auditor = auditor});
5035 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
5038 mptAlice.authorize({.account = bob});
5039 mptAlice.authorize({.account = carol});
5040 mptAlice.pay(alice, bob, 100);
5041 mptAlice.pay(alice, carol, 50);
5043 mptAlice.generateKeyPair(alice);
5044 mptAlice.generateKeyPair(bob);
5045 mptAlice.generateKeyPair(auditor);
5048 .issuerPubKey = mptAlice.getPubKey(alice),
5049 .auditorPubKey = mptAlice.getPubKey(auditor)});
5054 .holderPubKey = mptAlice.getPubKey(bob),
5056 mptAlice.mergeInbox({.account = bob});
5057 mptAlice.convertBack({.account = bob, .amt = 50});
5059 runPublicPayments(mptAlice);
5060 drainAndDeleteBobMPToken(env, mptAlice);
5066 Env env{*
this, features};
5070 {{.account = bob, .payAmount = 100, .convertAmount = 50}},
5071 tfMPTCanTransfer | tfMPTCanClawback | tfMPTCanHoldConfidentialBalance};
5073 env.fund(XRP(1'000), carol);
5075 ct.
mpt.
pay(alice, carol, 50);
5079 runPublicPayments(ct.
mpt);
5080 drainAndDeleteBobMPToken(env, ct.
mpt);
5255 testcase(
"Convert back pedersen proof");
5258 Env env{*
this, features};
5262 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
5263 auto& mptAlice = confEnv.
mpt;
5267 uint64_t
const amt = 10;
5272 mptAlice.getDecryptedBalance(bob, MPTTester::holderEncryptedSpending),
5273 "Missing spending balance");
5275 mptAlice.getEncryptedBalance(bob, MPTTester::holderEncryptedSpending),
5276 "Missing encrypted spending balance");
5277 BEAST_EXPECT(!encryptedSpendingBalance.empty());
5279 Buffer const pedersenCommitment =
5280 mptAlice.getPedersenCommitment(spendingBalance, pcBlindingFactor);
5281 Buffer const issuerCiphertext = mptAlice.encryptAmount(alice, amt, blindingFactor);
5282 Buffer const bobCiphertext = mptAlice.encryptAmount(bob, amt, blindingFactor);
5283 auto const version = mptAlice.getMPTokenVersion(bob);
5296 Buffer const badPedersenCommitment =
5297 mptAlice.getPedersenCommitment(1, pcBlindingFactor);
5298 Buffer const proof = mptAlice.getConvertBackProof(
5303 .pedersenCommitment = badPedersenCommitment,
5304 .amt = spendingBalance,
5305 .encryptedAmt = encryptedSpendingBalance,
5306 .blindingFactor = pcBlindingFactor,
5309 mptAlice.convertBack({
5313 .holderEncryptedAmt = bobCiphertext,
5314 .issuerEncryptedAmt = issuerCiphertext,
5315 .blindingFactor = blindingFactor,
5316 .pedersenCommitment = pedersenCommitment,
5328 Buffer const proof = mptAlice.getConvertBackProof(
5333 .pedersenCommitment = pedersenCommitment,
5334 .amt = spendingBalance,
5335 .encryptedAmt = encryptedSpendingBalance,
5339 mptAlice.convertBack({
5343 .holderEncryptedAmt = bobCiphertext,
5344 .issuerEncryptedAmt = issuerCiphertext,
5345 .blindingFactor = blindingFactor,
5346 .pedersenCommitment = pedersenCommitment,
5358 Buffer const proof = mptAlice.getConvertBackProof(
5363 .pedersenCommitment = pedersenCommitment,
5365 .encryptedAmt = encryptedSpendingBalance,
5366 .blindingFactor = pcBlindingFactor,
5369 mptAlice.convertBack({
5373 .holderEncryptedAmt = bobCiphertext,
5374 .issuerEncryptedAmt = issuerCiphertext,
5375 .blindingFactor = blindingFactor,
5376 .pedersenCommitment = pedersenCommitment,
5388 Buffer const badPedersenCommitment =
5389 mptAlice.getPedersenCommitment(1, pcBlindingFactor);
5390 Buffer const proof = mptAlice.getConvertBackProof(
5395 .pedersenCommitment = pedersenCommitment,
5396 .amt = spendingBalance,
5397 .encryptedAmt = encryptedSpendingBalance,
5398 .blindingFactor = pcBlindingFactor,
5401 mptAlice.convertBack({
5405 .holderEncryptedAmt = bobCiphertext,
5406 .issuerEncryptedAmt = issuerCiphertext,
5407 .blindingFactor = blindingFactor,
5408 .pedersenCommitment = badPedersenCommitment,
5418 uint256 const badContextHash{1};
5420 Buffer const proof = mptAlice.getConvertBackProof(
5425 .pedersenCommitment = pedersenCommitment,
5426 .amt = spendingBalance,
5427 .encryptedAmt = encryptedSpendingBalance,
5428 .blindingFactor = pcBlindingFactor,
5431 mptAlice.convertBack({
5435 .holderEncryptedAmt = bobCiphertext,
5436 .issuerEncryptedAmt = issuerCiphertext,
5437 .blindingFactor = blindingFactor,
5438 .pedersenCommitment = pedersenCommitment,
5449 Buffer const proof = mptAlice.getConvertBackProof(
5454 .pedersenCommitment = pedersenCommitment,
5455 .amt = spendingBalance,
5456 .encryptedAmt = encryptedSpendingBalance,
5457 .blindingFactor = pcBlindingFactor,
5460 mptAlice.convertBack({
5464 .holderEncryptedAmt = bobCiphertext,
5465 .issuerEncryptedAmt = issuerCiphertext,
5466 .blindingFactor = blindingFactor,
5467 .pedersenCommitment = pedersenCommitment,
5475 testcase(
"Convert back bulletproof");
5478 Env env{*
this, features};
5482 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
5483 auto& mptAlice = confEnv.
mpt;
5487 uint64_t
const amt = 10;
5492 mptAlice.getDecryptedBalance(bob, MPTTester::holderEncryptedSpending),
5493 "Missing spending balance");
5495 mptAlice.getEncryptedBalance(bob, MPTTester::holderEncryptedSpending),
5496 "Missing encrypted spending balance");
5497 BEAST_EXPECT(!encryptedSpendingBalance.empty());
5499 Buffer const pedersenCommitment =
5500 mptAlice.getPedersenCommitment(spendingBalance, pcBlindingFactor);
5501 Buffer const issuerCiphertext = mptAlice.encryptAmount(alice, amt, blindingFactor);
5502 Buffer const bobCiphertext = mptAlice.encryptAmount(bob, amt, blindingFactor);
5503 auto const version = mptAlice.getMPTokenVersion(bob);
5517 Buffer const proof = mptAlice.getConvertBackProof(
5522 .pedersenCommitment = pedersenCommitment,
5524 .encryptedAmt = encryptedSpendingBalance,
5525 .blindingFactor = pcBlindingFactor,
5528 mptAlice.convertBack({
5532 .holderEncryptedAmt = bobCiphertext,
5533 .issuerEncryptedAmt = issuerCiphertext,
5534 .blindingFactor = blindingFactor,
5535 .pedersenCommitment = pedersenCommitment,
5548 Buffer const proof = mptAlice.getConvertBackProof(
5553 .pedersenCommitment = pedersenCommitment,
5554 .amt = spendingBalance,
5555 .encryptedAmt = encryptedSpendingBalance,
5559 mptAlice.convertBack({
5563 .holderEncryptedAmt = bobCiphertext,
5564 .issuerEncryptedAmt = issuerCiphertext,
5565 .blindingFactor = blindingFactor,
5566 .pedersenCommitment = pedersenCommitment,
5576 uint256 const badContextHash{1};
5577 Buffer const proof = mptAlice.getConvertBackProof(
5582 .pedersenCommitment = pedersenCommitment,
5583 .amt = spendingBalance,
5584 .encryptedAmt = encryptedSpendingBalance,
5585 .blindingFactor = pcBlindingFactor,
5588 mptAlice.convertBack({
5592 .holderEncryptedAmt = bobCiphertext,
5593 .issuerEncryptedAmt = issuerCiphertext,
5594 .blindingFactor = blindingFactor,
5595 .pedersenCommitment = pedersenCommitment,
5606 Buffer const proof = mptAlice.getConvertBackProof(
5611 .pedersenCommitment = pedersenCommitment,
5612 .amt = spendingBalance,
5613 .encryptedAmt = encryptedSpendingBalance,
5614 .blindingFactor = pcBlindingFactor,
5617 mptAlice.convertBack({
5621 .holderEncryptedAmt = bobCiphertext,
5622 .issuerEncryptedAmt = issuerCiphertext,
5623 .blindingFactor = blindingFactor,
5624 .pedersenCommitment = pedersenCommitment,
5636 testcase(
"ConvertBack proof context binding");
5639 auto runBadProof = [&](
auto makeContextHash) {
5640 Env env{*
this, features};
5645 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
5646 auto& mptAlice = confEnv.
mpt;
5652 auto const spendingBalance =
5653 mptAlice.getDecryptedBalance(bob, MPTTester::holderEncryptedSpending);
5654 auto const encryptedSpendingBalance =
5655 mptAlice.getEncryptedBalance(bob, MPTTester::holderEncryptedSpending);
5656 if (!BEAST_EXPECT(spendingBalance && encryptedSpendingBalance))
5659 Buffer const pedersenCommitment = mptAlice.getPedersenCommitment(
5660 requireOptional(spendingBalance,
"Missing spending balance"), pcBlindingFactor);
5661 Buffer const issuerCiphertext = mptAlice.encryptAmount(alice, amt, blindingFactor);
5662 Buffer const bobCiphertext = mptAlice.encryptAmount(bob, amt, blindingFactor);
5663 auto const version = mptAlice.getMPTokenVersion(bob);
5665 Buffer const proof = mptAlice.getConvertBackProof(
5668 makeContextHash(env, mptAlice, alice, bob, carol, version),
5670 .pedersenCommitment = pedersenCommitment,
5673 encryptedSpendingBalance,
"Missing encrypted spending balance"),
5674 .blindingFactor = pcBlindingFactor,
5677 mptAlice.convertBack({
5681 .holderEncryptedAmt = bobCiphertext,
5682 .issuerEncryptedAmt = issuerCiphertext,
5683 .blindingFactor = blindingFactor,
5684 .pedersenCommitment = pedersenCommitment,
5690 runBadProof([&](Env& env,
5691 MPTTester
const& mpt,
5700 runBadProof([&](Env& env,
5707 bob.id(),
makeMptID(env.seq(alice) + 100, alice), env.seq(bob), version);
5711 runBadProof([&](Env& env,
5712 MPTTester
const& mpt,
5721 runBadProof([&](Env& env,
5722 MPTTester
const& mpt,
6546 testcase(
"divergent C1 across participants in ConfidentialMPTSend");
6549 Env env{*
this, features};
6553 Account const auditor(
"auditor");
6557 {{.account = bob, .payAmount = 100, .convertAmount = 50},
6558 {.account = carol, .payAmount = 50, .convertAmount = 50}},
6559 tfMPTCanLock | tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer,
6561 auto& mptAlice = confEnv.
mpt;
6564 uint64_t
const amt = 10;
6566 enum class Participant { Sender, Dest, Issuer, Auditor };
6577 auto const proofOpt =
6591 case Participant::Sender:
6592 senderCt = mptAlice.encryptAmount(bob, amt, bfDivergent);
6594 case Participant::Dest:
6595 destCt = mptAlice.encryptAmount(carol, amt, bfDivergent);
6597 case Participant::Issuer:
6598 issuerCt = mptAlice.encryptAmount(alice, amt, bfDivergent);
6600 case Participant::Auditor:
6601 auditorCt = mptAlice.encryptAmount(auditor, amt, bfDivergent);
6612 .proof =
strHex(proofOpt),
6613 .senderEncryptedAmt = senderCt,
6614 .destEncryptedAmt = destCt,
6615 .issuerEncryptedAmt = issuerCt,
6616 .auditorEncryptedAmt = auditorCt,
6624 auto const spendingAfter =
6625 mptAlice.getDecryptedBalance(bob, MPTTester::holderEncryptedSpending);
6632 BEAST_EXPECT(spendingAfter == setup.
prevSpending - amt);
6638 submitWithDivergentC1(std::nullopt);
6641 submitWithDivergentC1(Participant::Sender);
6642 submitWithDivergentC1(Participant::Dest);
6643 submitWithDivergentC1(Participant::Issuer);
6644 submitWithDivergentC1(Participant::Auditor);
6650 testcase(
"test confidential transactions fee");
6657 .flags = tfMPTCanLock | tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer |
6660 mpt.authorize({.account = bob});
6661 mpt.authorize({.account = carol});
6662 mpt.pay(alice, bob, 100);
6663 mpt.pay(alice, carol, 50);
6664 mpt.generateKeyPair(alice);
6665 mpt.generateKeyPair(bob);
6666 mpt.generateKeyPair(carol);
6667 mpt.set({.account = alice, .issuerPubKey = mpt.getPubKey(alice)});
6672 Env env{*
this, features};
6673 Account const alice(
"alice"), bob(
"bob"), carol(
"carol");
6674 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
6675 setup(mptAlice, alice, bob, carol);
6677 auto const baseFee = env.current()->fees().base;
6682 auto checkFee = [&](
Account const& acct,
auto&& submitFn) {
6683 auto const before = env.balance(acct);
6685 auto const after = env.balance(acct);
6686 BEAST_EXPECT(before -
after == expectedFee);
6689 checkFee(bob, [&]() {
6693 .holderPubKey = mptAlice.getPubKey(bob),
6694 .fee = expectedFee});
6696 checkFee(carol, [&]() {
6700 .holderPubKey = mptAlice.getPubKey(carol),
6701 .fee = expectedFee});
6703 checkFee(bob, [&]() { mptAlice.mergeInbox({.account = bob, .fee = expectedFee}); });
6704 checkFee(carol, [&]() { mptAlice.mergeInbox({.account = carol, .fee = expectedFee}); });
6705 checkFee(bob, [&]() {
6706 mptAlice.send({.account = bob, .dest = carol, .amt = 5, .fee = expectedFee});
6708 checkFee(bob, [&]() {
6709 mptAlice.convertBack({.account = bob, .amt = 5, .fee = expectedFee});
6711 checkFee(alice, [&]() {
6712 mptAlice.confidentialClaw(
6713 {.account = alice, .holder = carol, .amt = 15, .fee = expectedFee});
6719 Env env{*
this, features};
6720 Account const alice(
"alice"), bob(
"bob"), carol(
"carol");
6721 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
6722 setup(mptAlice, alice, bob, carol);
6723 auto const baseFee = env.current()->fees().base;
6729 .holderPubKey = mptAlice.getPubKey(bob),
6730 .fee = expectedFee - 1,
6732 mptAlice.mergeInbox({.account = bob, .fee = baseFee, .err =
telINSUF_FEE_P});
6739 mptAlice.convertBack({.account = bob, .amt = 1, .fee = baseFee, .err =
telINSUF_FEE_P});
6740 mptAlice.confidentialClaw(
6750 Env env{*
this, features};
6751 Account const alice(
"alice"), bob(
"bob"), carol(
"carol");
6752 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
6753 setup(mptAlice, alice, bob, carol);
6755 auto const baseFee = env.current()->fees().base;
6757 auto const bobBefore = env.balance(bob);
6761 .holderPubKey = mptAlice.getPubKey(bob),
6763 BEAST_EXPECT(env.balance(bob) == bobBefore - highFee);
7182 testcase(
"Send: special witness values");
7185 Env env{*
this, features};
7186 Account const alice(
"alice"), bob(
"bob"), carol(
"carol");
7190 {{.account = bob}, {.account = carol, .payAmount = 1000, .convertAmount = 50}}};
7191 auto& mptAlice = confEnv.
mpt;
7197 auto const proof = setup.
generateProof(mptAlice, env, bob, carol);
7198 if (!BEAST_EXPECT(proof.has_value()))
7203 static constexpr size_t kSigmaScalarSize = 32;
7204 static constexpr size_t kChallengeOffset = 0;
7205 static constexpr size_t kResponseOffset = kChallengeOffset + kSigmaScalarSize;
7206 static constexpr size_t kResponseSize = 5 * kSigmaScalarSize;
7214 auto const proof = setup.
generateProof(mptAlice, env, bob, carol);
7215 if (!BEAST_EXPECT(proof.has_value()))
7224 mptAlice.send(args);
7229 auto const proof = setup.
generateProof(mptAlice, env, bob, carol);
7230 if (!BEAST_EXPECT(proof.has_value()))
7239 mptAlice.send(args);
7244 auto const proof = setup.
generateProof(mptAlice, env, bob, carol);
7245 if (!BEAST_EXPECT(proof.has_value()))
7250 static constexpr unsigned char kCurveOrder[32] = {
7251 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
7252 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
7253 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
7254 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41
7264 auto const proof = setup.
generateProof(mptAlice, env, bob, carol);
7265 if (!BEAST_EXPECT(proof.has_value()))
7270 static constexpr unsigned char kOverflowScalar[32] = {
7271 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
7272 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
7273 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
7274 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x42
7286 testcase(
"Send: cross-statement proof substitution");
7293 Env env{*
this, features};
7294 Account const alice(
"alice"), bob(
"bob"), carol(
"carol");
7298 {{.account = bob}, {.account = carol, .payAmount = 1000, .convertAmount = 50}},
7299 tfMPTCanLock | tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer | tfMPTCanClawback};
7300 auto& mptAlice = confEnv.
mpt;
7302 uint64_t
const sendAmount = 10;
7319 mptAlice.getDecryptedBalance(bob, MPTTester::holderEncryptedSpending),
7320 "Missing spending balance");
7322 mptAlice.getEncryptedBalance(bob, MPTTester::holderEncryptedSpending),
7323 "Missing encrypted spending balance");
7326 Buffer const pedersenCommitment =
7327 mptAlice.getPedersenCommitment(spendingBalance, pcBlindingFactor);
7329 auto const version = mptAlice.getMPTokenVersion(bob);
7330 uint256 const convertBackCtxHash =
7333 Buffer const convertBackProof = mptAlice.getConvertBackProof(
7338 .pedersenCommitment = pedersenCommitment,
7339 .amt = spendingBalance,
7340 .encryptedAmt = encryptedSpending,
7341 .blindingFactor = pcBlindingFactor,
7348 Buffer resizedProof(expectedSendSize);
7349 auto const copyLen =
std::min(convertBackProof.
size(), expectedSendSize);
7352 if (copyLen < expectedSendSize)
7353 std::memset(resizedProof.
data() + copyLen, 0, expectedSendSize - copyLen);
7369 uint192 const fakeIssuanceID{1};
7371 bob.id(), fakeIssuanceID, env.seq(bob), carol.id(), setup.
version);
7374 auto const wrongProof = mptAlice.getConfidentialSendProof(
7381 .pedersenCommitment = setup.amountCommitment,
7383 .encryptedAmt = setup.senderAmt,
7384 .blindingFactor = setup.amountBlindingFactor,
7387 .pedersenCommitment = setup.balanceCommitment,
7388 .amt = setup.prevSpending,
7389 .encryptedAmt = setup.prevEncryptedSpending,
7390 .blindingFactor = setup.balanceBlindingFactor,
7393 if (!BEAST_EXPECT(wrongProof.has_value()))
7936 testcase(
"Send: recipient inbox rerandomization prevents merge cancellation");
7942 auto getCanonicalZeroBlindingFactor = [](
AccountID const& account,
MPTID const& mptID) {
7963 if (secp256k1_ec_seckey_verify(mpt_secp256k1_context(), scalar.data()))
7972 auto negateScalarSum = [](
Buffer const& lhs,
Buffer const& rhs) {
7975 secp256k1_mpt_scalar_add(
sum.data(), lhs.
data(), rhs.data());
7976 secp256k1_mpt_scalar_negate(negated.
data(),
sum.data());
7984 Env env{*
this, features};
7985 Account const alice(
"alice"), bob(
"bob"), carol(
"carol");
7986 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
7990 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
7993 mptAlice.authorize({.account = bob});
7994 mptAlice.authorize({.account = carol});
7995 mptAlice.pay(alice, bob, 100);
7996 mptAlice.pay(alice, carol, 100);
7998 mptAlice.generateKeyPair(alice);
7999 mptAlice.generateKeyPair(bob);
8000 mptAlice.generateKeyPair(carol);
8001 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
8006 .holderPubKey = mptAlice.getPubKey(carol),
8008 mptAlice.mergeInbox({.account = carol});
8014 .holderPubKey = mptAlice.getPubKey(bob),
8015 .blindingFactor = convertBlindingFactor,
8018 Buffer const canonicalZeroBlindingFactor =
8019 getCanonicalZeroBlindingFactor(bob.id(), mptAlice.issuanceID());
8023 Buffer const maliciousSendBlindingFactor =
8024 negateScalarSum(canonicalZeroBlindingFactor, convertBlindingFactor);
8030 .blindingFactor = maliciousSendBlindingFactor,
8033 mptAlice.mergeInbox({.account = bob});
8035 auto const bobSpending =
8036 mptAlice.getDecryptedBalance(bob, MPTTester::holderEncryptedSpending);
8037 BEAST_EXPECT(bobSpending && *bobSpending == 25);
8045 Env env{*
this, features};
8046 Account const alice(
"alice"), bob(
"bob"), carol(
"carol"), auditor(
"auditor");
8047 MPTTester mptAlice(env, alice, {.holders = {bob, carol}, .auditor = auditor});
8051 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
8054 mptAlice.authorize({.account = bob});
8055 mptAlice.authorize({.account = carol});
8056 mptAlice.pay(alice, bob, 100);
8057 mptAlice.pay(alice, carol, 100);
8059 mptAlice.generateKeyPair(alice);
8060 mptAlice.generateKeyPair(bob);
8061 mptAlice.generateKeyPair(carol);
8062 mptAlice.generateKeyPair(auditor);
8065 .issuerPubKey = mptAlice.getPubKey(alice),
8066 .auditorPubKey = mptAlice.getPubKey(auditor),
8072 .holderPubKey = mptAlice.getPubKey(carol),
8074 mptAlice.mergeInbox({.account = carol});
8080 .holderPubKey = mptAlice.getPubKey(bob),
8081 .blindingFactor = convertBlindingFactor,
8085 Buffer const maliciousSendBlindingFactor =
8092 .blindingFactor = maliciousSendBlindingFactor,
8095 auto const bobAuditor =
8096 mptAlice.getDecryptedBalance(bob, MPTTester::auditorEncryptedBalance);
8097 BEAST_EXPECT(bobAuditor && *bobAuditor == 25);