95 testcase(
"MPTokenIssuanceSet rotate both issuer and auditor keys");
98 Env env{*
this, features};
101 Account const auditor(
"auditor");
102 MPTTester mptAlice(env, alice, {.holders = {bob}});
106 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
109 mptAlice.generateKeyPair(alice);
110 mptAlice.generateKeyPair(bob);
111 mptAlice.generateKeyPair(auditor);
116 .issuerPubKey = mptAlice.getPubKey(alice),
117 .auditorPubKey = mptAlice.getPubKey(auditor),
121 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt, std::nullopt));
124 bool const rotationEnabled = features[featureConfidentialMPTKeyRotation];
127 .issuerPubKey = mptAlice.getPubKey(bob),
128 .auditorPubKey = mptAlice.getPubKey(alice),
134 BEAST_EXPECT(mptAlice.checkEncryptionKeys(bob, alice));
135 BEAST_EXPECT(mptAlice.checkKeyEpochs(1u, 1u));
139 BEAST_EXPECT(mptAlice.checkEncryptionKeys(alice, auditor));
140 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt, std::nullopt));
149 .issuerPubKey = mptAlice.getPubKey(bob),
157 .auditorPubKey = mptAlice.getPubKey(alice),
166 .issuerPubKey = mptAlice.getPubKey(bob),
167 .auditorPubKey = mptAlice.getPubKey(auditor),
174 .issuerPubKey = mptAlice.getPubKey(auditor),
175 .auditorPubKey = mptAlice.getPubKey(alice),
180 BEAST_EXPECT(mptAlice.checkKeyEpochs(1u, 1u));
185 .issuerPubKey = mptAlice.getPubKey(alice),
186 .auditorPubKey = mptAlice.getPubKey(auditor),
189 BEAST_EXPECT(mptAlice.checkKeyEpochs(2u, 2u));
300 testcase(
"MPTokenIssuanceSet register auditor key later with circulating supply");
303 Env env{*
this, features};
306 Account const auditor(
"auditor");
307 MPTTester mptAlice(env, alice, {.holders = {bob}});
311 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
314 mptAlice.authorize({.account = bob});
315 mptAlice.pay(alice, bob, 100);
317 mptAlice.generateKeyPair(alice);
318 mptAlice.generateKeyPair(bob);
319 mptAlice.generateKeyPair(auditor);
323 .issuerPubKey = mptAlice.getPubKey(alice),
330 .holderPubKey = mptAlice.getPubKey(bob),
334 if (!BEAST_EXPECT(sleIssuanceBefore))
336 auto const coaBefore = (*sleIssuanceBefore)[~sfConfidentialOutstandingAmount].value_or(0);
337 BEAST_EXPECT(coaBefore > 0);
343 bool const rotationEnabled = features[featureConfidentialMPTKeyRotation];
346 .auditorPubKey = mptAlice.getPubKey(auditor),
351 if (!BEAST_EXPECT(sleIssuance))
353 BEAST_EXPECT(mptAlice.checkEncryptionKeys(
355 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt, std::nullopt));
358 BEAST_EXPECT((*sleIssuance)[~sfConfidentialOutstandingAmount].value_or(0) == coaBefore);
397 testcase(
"MPTokenIssuanceSet rotate with circulating confidential supply");
400 Env env{*
this, features};
404 MPTTester mptAlice(env, alice, {.holders = {bob}});
408 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
411 mptAlice.authorize({.account = bob});
412 mptAlice.pay(alice, bob, 100);
414 mptAlice.generateKeyPair(alice);
415 mptAlice.generateKeyPair(bob);
416 mptAlice.generateKeyPair(carol);
420 .issuerPubKey = mptAlice.getPubKey(alice),
428 .holderPubKey = mptAlice.getPubKey(bob),
431 auto const sleIssuanceBeforeRotation =
433 if (!BEAST_EXPECT(sleIssuanceBeforeRotation))
435 auto const coaBeforeRotation =
436 (*sleIssuanceBeforeRotation)[~sfConfidentialOutstandingAmount].value_or(0);
437 BEAST_EXPECT(coaBeforeRotation > 0);
441 bool const rotationEnabled = features[featureConfidentialMPTKeyRotation];
444 .issuerPubKey = mptAlice.getPubKey(carol),
449 if (!BEAST_EXPECT(sleIssuance))
453 BEAST_EXPECT(mptAlice.checkEncryptionKeys(carol, std::nullopt));
454 BEAST_EXPECT(mptAlice.checkKeyEpochs(1u, std::nullopt));
458 BEAST_EXPECT(mptAlice.checkEncryptionKeys(alice, std::nullopt));
459 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt, std::nullopt));
464 (*sleIssuance)[~sfConfidentialOutstandingAmount].value_or(0) == coaBeforeRotation);
470 .flags = tfMPTSetCanHoldConfidentialBalance,
479 if (!features[featureConfidentialMPTKeyRotation])
482 testcase(
"MPTokenIssuanceSet key epoch cannot wrap");
484 Env env{*
this, features};
488 Account const auditor(
"auditor");
491 MPTTester mptAlice(env, alice, {.holders = {bob}, .close =
false});
495 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
498 mptAlice.generateKeyPair(alice);
499 mptAlice.generateKeyPair(bob);
500 mptAlice.generateKeyPair(carol);
501 mptAlice.generateKeyPair(auditor);
505 .issuerPubKey = mptAlice.getPubKey(alice),
506 .auditorPubKey = mptAlice.getPubKey(auditor),
517 auto const sle = view.
read(issuanceKeylet);
523 (*replacement)[sfIssuerKeyEpoch] = *issuerKeyEpoch;
525 (*replacement)[sfAuditorKeyEpoch] = *auditorKeyEpoch;
531 BEAST_EXPECT(mptAlice.checkEncryptionKeys(alice, auditor));
532 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt, std::nullopt));
536 BEAST_EXPECT(mptAlice.checkEncryptionKeys(alice, auditor));
537 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt,
kMaxKeyEpoch - 1));
542 .auditorPubKey = mptAlice.getPubKey(carol),
545 BEAST_EXPECT(mptAlice.checkEncryptionKeys(alice, carol));
546 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt,
kMaxKeyEpoch));
551 .auditorPubKey = mptAlice.getPubKey(bob),
559 .issuerPubKey = mptAlice.getPubKey(auditor),
560 .auditorPubKey = mptAlice.getPubKey(bob),
565 BEAST_EXPECT(mptAlice.checkEncryptionKeys(alice, carol));
566 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt,
kMaxKeyEpoch));
571 .issuerPubKey = mptAlice.getPubKey(bob),
574 BEAST_EXPECT(mptAlice.checkEncryptionKeys(bob, carol));
575 BEAST_EXPECT(mptAlice.checkKeyEpochs(1u,
kMaxKeyEpoch));
579 BEAST_EXPECT(mptAlice.checkEncryptionKeys(bob, carol));
585 .issuerPubKey = mptAlice.getPubKey(auditor),
588 BEAST_EXPECT(mptAlice.checkEncryptionKeys(auditor, carol));
594 .issuerPubKey = mptAlice.getPubKey(alice),
599 .auditorPubKey = mptAlice.getPubKey(bob),
604 .issuerPubKey = mptAlice.getPubKey(alice),
605 .auditorPubKey = mptAlice.getPubKey(bob),
609 BEAST_EXPECT(mptAlice.checkEncryptionKeys(auditor, carol));
616 testcase(
"ConfidentialMPTConvert mirror epoch");
622 Account const auditor(
"auditor");
627 Env env{*
this, features};
628 MPTTester mptAlice(env, alice, {.holders = {bob}, .auditor = auditor});
633 .issuerPubKey = mptAlice.getPubKey(alice),
634 .auditorPubKey = mptAlice.getPubKey(auditor),
637 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt, std::nullopt));
642 .holderPubKey = mptAlice.getPubKey(bob),
645 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, std::nullopt, std::nullopt));
654 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, std::nullopt, std::nullopt));
658 if (!features[featureConfidentialMPTKeyRotation])
664 Env env{*
this, features};
665 MPTTester mptAlice(env, alice, {.holders = {bob, carol}, .auditor = auditor});
670 .issuerPubKey = mptAlice.getPubKey(alice),
671 .auditorPubKey = mptAlice.getPubKey(auditor),
675 for (
int i = 0; i < 10; ++i)
677 mptAlice.generateKeyPair(alice);
678 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
681 BEAST_EXPECT(mptAlice.checkKeyEpochs(10u, std::nullopt));
682 BEAST_EXPECT(mptAlice.checkEncryptionKeys(alice, auditor));
689 .holderPubKey = mptAlice.getPubKey(carol),
692 BEAST_EXPECT(mptAlice.checkMirrorEpochs(carol, 10u, std::nullopt));
698 Env env{*
this, features};
699 MPTTester mptAlice(env, alice, {.holders = {bob, carol}, .auditor = auditor});
704 .issuerPubKey = mptAlice.getPubKey(alice),
705 .auditorPubKey = mptAlice.getPubKey(auditor),
709 for (
int i = 0; i < 100; ++i)
711 mptAlice.generateKeyPair(alice);
712 mptAlice.generateKeyPair(auditor);
715 .issuerPubKey = mptAlice.getPubKey(alice),
716 .auditorPubKey = mptAlice.getPubKey(auditor),
721 for (
int i = 0; i < 5; ++i)
723 mptAlice.generateKeyPair(auditor);
724 mptAlice.set({.account = alice, .auditorPubKey = mptAlice.getPubKey(auditor)});
727 BEAST_EXPECT(mptAlice.checkKeyEpochs(100u, 105u));
728 BEAST_EXPECT(mptAlice.checkEncryptionKeys(alice, auditor));
735 .holderPubKey = mptAlice.getPubKey(carol),
738 BEAST_EXPECT(mptAlice.checkMirrorEpochs(carol, 100u, 105u));
744 Env env{*
this, features};
745 MPTTester mptAlice(env, alice, {.holders = {bob, carol}, .auditor = auditor});
750 .issuerPubKey = mptAlice.getPubKey(alice),
751 .auditorPubKey = mptAlice.getPubKey(auditor),
759 .holderPubKey = mptAlice.getPubKey(carol),
762 BEAST_EXPECT(mptAlice.checkMirrorEpochs(carol, std::nullopt, std::nullopt));
765 mptAlice.generateKeyPair(alice);
766 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
768 BEAST_EXPECT(mptAlice.checkKeyEpochs(1u, std::nullopt));
774 .holderPubKey = mptAlice.getPubKey(bob),
777 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, 1u, std::nullopt));
786 BEAST_EXPECT(mptAlice.checkMirrorEpochs(carol, std::nullopt, std::nullopt));
789 mptAlice.generateKeyPair(alice);
790 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
792 BEAST_EXPECT(mptAlice.checkKeyEpochs(2u, std::nullopt));
803 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, 1u, std::nullopt));
812 BEAST_EXPECT(mptAlice.checkMirrorEpochs(carol, std::nullopt, std::nullopt));
819 Env env{*
this, features};
820 MPTTester mptAlice(env, alice, {.holders = {bob, carol}, .auditor = auditor});
825 .issuerPubKey = mptAlice.getPubKey(alice),
826 .auditorPubKey = mptAlice.getPubKey(auditor),
834 .holderPubKey = mptAlice.getPubKey(bob),
837 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, std::nullopt, std::nullopt));
841 mptAlice.generateKeyPair(auditor);
842 mptAlice.set({.account = alice, .auditorPubKey = mptAlice.getPubKey(auditor)});
844 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt, 1u));
845 BEAST_EXPECT(mptAlice.checkEncryptionKeys(alice, auditor));
853 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, std::nullopt, std::nullopt));
860 .holderPubKey = mptAlice.getPubKey(carol),
863 BEAST_EXPECT(mptAlice.checkMirrorEpochs(carol, std::nullopt, 1u));
870 Env env{*
this, features};
871 MPTTester mptAlice(env, alice, {.holders = {bob}, .auditor = auditor});
877 .issuerPubKey = mptAlice.getPubKey(alice),
884 .fillAuditorEncryptedAmt =
false,
885 .holderPubKey = mptAlice.getPubKey(bob),
888 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, std::nullopt, std::nullopt));
893 .auditorPubKey = mptAlice.getPubKey(auditor),
896 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt, std::nullopt));
905 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, std::nullopt, std::nullopt));
912 testcase(
"ConfidentialMPTSend mirror epoch");
918 Account const auditor(
"auditor");
923 Env env{*
this, features};
924 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
926 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
930 mptAlice.generateKeyPair(alice);
931 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
933 BEAST_EXPECT(mptAlice.checkKeyEpochs(1u, std::nullopt));
935 for (
auto const& holder : {bob, carol})
940 .holderPubKey = mptAlice.getPubKey(holder),
942 mptAlice.mergeInbox({.account = holder});
945 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, 1u, std::nullopt));
946 BEAST_EXPECT(mptAlice.checkMirrorEpochs(carol, 1u, std::nullopt));
948 mptAlice.send({.account = bob, .dest = carol, .amt = 10});
951 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, 1u, std::nullopt));
952 BEAST_EXPECT(mptAlice.checkMirrorEpochs(carol, 1u, std::nullopt));
957 Env env{*
this, features};
958 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
960 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
966 .holderPubKey = mptAlice.getPubKey(carol),
968 mptAlice.mergeInbox({.account = carol});
971 mptAlice.generateKeyPair(alice);
972 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
978 .holderPubKey = mptAlice.getPubKey(bob),
980 mptAlice.mergeInbox({.account = bob});
982 BEAST_EXPECT(mptAlice.checkMirrorEpochs(carol, std::nullopt, std::nullopt));
983 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, 1u, std::nullopt));
1004 BEAST_EXPECT(mptAlice.checkMirrorEpochs(carol, std::nullopt, std::nullopt));
1005 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, 1u, std::nullopt));
1010 Env env{*
this, features};
1011 MPTTester mptAlice(env, alice, {.holders = {bob, carol}, .auditor = auditor});
1015 .issuerPubKey = mptAlice.getPubKey(alice),
1016 .auditorPubKey = mptAlice.getPubKey(auditor),
1019 for (
auto const& holder : {bob, carol})
1024 .holderPubKey = mptAlice.getPubKey(holder),
1026 mptAlice.mergeInbox({.account = holder});
1030 mptAlice.generateKeyPair(auditor);
1031 mptAlice.set({.account = alice, .auditorPubKey = mptAlice.getPubKey(auditor)});
1033 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt, 1u));
1049 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, std::nullopt, std::nullopt));
1050 BEAST_EXPECT(mptAlice.checkMirrorEpochs(carol, std::nullopt, std::nullopt));
1057 testcase(
"ConfidentialMPTConvertBack mirror epoch");
1062 Account const auditor(
"auditor");
1067 Env env{*
this, features};
1068 MPTTester mptAlice(env, alice, {.holders = {bob}});
1070 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1074 mptAlice.generateKeyPair(alice);
1075 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1077 BEAST_EXPECT(mptAlice.checkKeyEpochs(1u, std::nullopt));
1082 .holderPubKey = mptAlice.getPubKey(bob),
1084 mptAlice.mergeInbox({.account = bob});
1086 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, 1u, std::nullopt));
1088 mptAlice.convertBack({.account = bob, .amt = 20});
1090 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, 1u, std::nullopt));
1095 Env env{*
this, features};
1096 MPTTester mptAlice(env, alice, {.holders = {bob}});
1098 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1104 .holderPubKey = mptAlice.getPubKey(bob),
1106 mptAlice.mergeInbox({.account = bob});
1109 mptAlice.convertBack({.account = bob, .amt = 20});
1112 mptAlice.generateKeyPair(alice);
1113 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1115 mptAlice.convertBack({
1122 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, std::nullopt, std::nullopt));
1128 Env env{*
this, features};
1129 MPTTester mptAlice(env, alice, {.holders = {bob}, .auditor = auditor});
1133 .issuerPubKey = mptAlice.getPubKey(alice),
1134 .auditorPubKey = mptAlice.getPubKey(auditor),
1140 .holderPubKey = mptAlice.getPubKey(bob),
1142 mptAlice.mergeInbox({.account = bob});
1145 mptAlice.generateKeyPair(auditor);
1146 mptAlice.set({.account = alice, .auditorPubKey = mptAlice.getPubKey(auditor)});
1148 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt, 1u));
1150 mptAlice.convertBack({
1156 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, std::nullopt, std::nullopt));
1163 testcase(
"ConfidentialMPTClawback mirror epoch");
1168 Account const auditor(
"auditor");
1171 tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance | tfMPTCanClawback;
1176 Env env{*
this, features};
1177 MPTTester mptAlice(env, alice, {.holders = {bob}, .auditor = auditor});
1181 .issuerPubKey = mptAlice.getPubKey(alice),
1182 .auditorPubKey = mptAlice.getPubKey(auditor),
1189 .holderPubKey = mptAlice.getPubKey(bob),
1193 for (
int i = 0; i < 2; ++i)
1195 mptAlice.generateKeyPair(auditor);
1196 mptAlice.set({.account = alice, .auditorPubKey = mptAlice.getPubKey(auditor)});
1199 BEAST_EXPECT(mptAlice.checkKeyEpochs(std::nullopt, 2u));
1200 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, std::nullopt, std::nullopt));
1202 mptAlice.confidentialClaw({.account = alice, .holder = bob, .amt = 50});
1203 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, std::nullopt, 2u));
1209 Env env{*
this, features};
1210 MPTTester mptAlice(env, alice, {.holders = {bob}});
1212 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1215 for (
int i = 0; i < 5; ++i)
1217 mptAlice.generateKeyPair(alice);
1218 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1224 .holderPubKey = mptAlice.getPubKey(bob),
1226 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, 5u, std::nullopt));
1228 mptAlice.confidentialClaw({.account = alice, .holder = bob, .amt = 50});
1229 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, 5u, std::nullopt));
1238 Env env{*
this, features};
1239 MPTTester mptAlice(env, alice, {.holders = {bob}});
1241 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1247 .holderPubKey = mptAlice.getPubKey(bob),
1251 mptAlice.generateKeyPair(alice);
1252 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1254 BEAST_EXPECT(mptAlice.checkKeyEpochs(1u, std::nullopt));
1256 mptAlice.confidentialClaw({
1263 BEAST_EXPECT(mptAlice.checkMirrorEpochs(bob, std::nullopt, std::nullopt));
1374 testcase(
"ConfidentialMPTMirrorUpdate preclaim");
1381 Env env{*
this, features};
1384 MPTTester mptAlice(env, alice, {.holders = {bob}});
1387 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
1392 mptAlice.mirrorUpdate({
1394 .issuerEncryptedAmount = validCipher,
1401 Env env{*
this, features};
1404 MPTTester mptAlice(env, alice, {.holders = {bob}});
1405 mptAlice.create({.ownerCount = 1, .flags = tfMPTCanTransfer});
1407 mptAlice.mirrorUpdate({
1410 .issuerEncryptedAmount = validCipher,
1417 Env env{*
this, features};
1420 MPTTester mptAlice(env, alice, {.holders = {bob}});
1422 {.ownerCount = 1, .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance});
1423 mptAlice.authorize({.account = bob});
1425 mptAlice.mirrorUpdate({
1428 .issuerEncryptedAmount = validCipher,
1435 Env env{*
this, features};
1438 MPTTester mptAlice(env, alice);
1440 {.ownerCount = 1, .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance});
1441 mptAlice.generateKeyPair(alice);
1442 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1445 mptAlice.mirrorUpdate({
1448 .issuerEncryptedAmount = validCipher,
1455 Env env{*
this, features};
1458 MPTTester mptAlice(env, alice, {.holders = {bob}});
1460 {.ownerCount = 1, .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance});
1461 mptAlice.generateKeyPair(alice);
1462 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1464 mptAlice.mirrorUpdate({
1467 .issuerEncryptedAmount = validCipher,
1474 Env env{*
this, features};
1477 MPTTester mptAlice(env, alice, {.holders = {bob}});
1479 {.ownerCount = 1, .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance});
1480 mptAlice.authorize({.account = bob});
1481 mptAlice.generateKeyPair(alice);
1482 mptAlice.set({.account = alice, .issuerPubKey = mptAlice.getPubKey(alice)});
1484 mptAlice.mirrorUpdate({
1487 .issuerEncryptedAmount = validCipher,
1494 Env env{*
this, features};
1504 .auditorEncryptedAmount = validCipher,
1512 Env env{*
this, features};
1520 .issuerEncryptedAmount = validCipher,
1529 Env env{*
this, features};
1532 Account const auditor(
"auditor");
1533 Account const newIssuerKey(
"newIssuerKey");
1541 tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer,
1552 .auditorEncryptedAmount = validCipher,
1560 Env env{*
this, features};
1563 Account const auditor(
"auditor");
1570 tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer,
1578 .auditorEncryptedAmount = validCipher,
1586 Env env{*
this, features};
1589 Account const auditor(
"auditor");
1590 Account const newIssuerKey(
"newIssuerKey");
1596 tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer,
1608 .issuerEncryptedAmount = validCipher,
1609 .auditorEncryptedAmount = validCipher,
1618 Env env{*
this, features};
1621 Account const auditor(
"auditor");
1622 Account const newAuditorKey(
"newAuditorKey");
1628 tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer,
1640 .issuerEncryptedAmount = validCipher,
1641 .auditorEncryptedAmount = validCipher,
1650 Env env{*
this, features};
1657 .issuerEncryptedAmount = validCipher,
1666 Env env{*
this, features};
1669 Account const auditor(
"auditor");
1670 Account const newIssuerKey(
"newIssuerKey");
1676 tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer,
1687 .issuerEncryptedAmount = validCipher,
1688 .auditorEncryptedAmount = validCipher,
1697 Env env{*
this, features};
1700 Account const auditor(
"auditor");
1701 Account const newAuditorKey(
"newAuditorKey");
1707 tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer,
1718 .issuerEncryptedAmount = validCipher,
1719 .auditorEncryptedAmount = validCipher,
1729 Env env{*
this, features};
1733 Account const newIssuerKey(
"newIssuerKey");
1735 ConfidentialEnv ct{env, alice, {{.account = bob}, {.account = carol}}};
1739 ct.
mpt.
send({.account = carol, .dest = bob, .amt = 10});
1748 .issuerEncryptedAmount = validCipher,
1756 .issuerEncryptedAmount = validCipher,
1763 Env env{*
this, features};
1767 Account const newIssuerKey(
"newIssuerKey");
1768 Account const newerIssuerKey(
"newerIssuerKey");
1770 ConfidentialEnv ct{env, alice, {{.account = bob}, {.account = carol}}};
1771 ct.
mpt.
set({.account = alice, .holder = bob, .flags = tfMPTLock});
1772 ct.
mpt.
set({.account = alice, .holder = carol, .flags = tfMPTLock});
1782 .issuerEncryptedAmount = validCipher,
1789 .issuerEncryptedAmount = validCipher,
1795 ct.
mpt.
set({.account = alice, .holder = bob, .flags = tfMPTUnlock});
1796 ct.
mpt.
set({.account = alice, .holder = carol, .flags = tfMPTUnlock});
1797 ct.
mpt.
set({.account = alice, .flags = tfMPTLock});
1804 .issuerEncryptedAmount = validCipher,
1810 .issuerEncryptedAmount = validCipher,
1819 testcase(
"ConfidentialMPTMirrorUpdate doApply");
1829 Env env{*
this, features};
1832 Account const newIssuerKey(
"newIssuerKey");
1840 Buffer const newIssuerCipher =
1848 .issuerEncryptedAmount = newIssuerCipher,
1852 if (!BEAST_EXPECT(sle))
1855 BEAST_EXPECT(
strHex((*sle)[sfIssuerEncryptedBalance]) ==
strHex(newIssuerCipher));
1856 BEAST_EXPECT((*sle)[~sfIssuerKeyMirrorEpoch] == 1u);
1862 .issuerEncryptedAmount = newIssuerCipher,
1870 Env env{*
this, features};
1873 Account const auditor(
"auditor");
1874 Account const newAuditorKey(
"newAuditorKey");
1879 tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer,
1887 Buffer const newAuditorCipher =
1893 .auditorEncryptedAmount = newAuditorCipher,
1897 if (!BEAST_EXPECT(sle))
1900 BEAST_EXPECT(
strHex((*sle)[sfAuditorEncryptedBalance]) ==
strHex(newAuditorCipher));
1901 BEAST_EXPECT((*sle)[~sfAuditorKeyMirrorEpoch] == 1u);
1907 Env env{*
this, features};
1910 Account const auditor(
"auditor");
1911 Account const newIssuerKey(
"newIssuerKey");
1912 Account const newAuditorKey(
"newAuditorKey");
1917 tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer,
1937 .issuerEncryptedAmount = newIssuerCipher,
1938 .auditorEncryptedAmount = newAuditorCipher,
1942 if (!BEAST_EXPECT(sle))
1945 BEAST_EXPECT(
strHex((*sle)[sfIssuerEncryptedBalance]) ==
strHex(newIssuerCipher));
1946 BEAST_EXPECT(
strHex((*sle)[sfAuditorEncryptedBalance]) ==
strHex(newAuditorCipher));
1947 BEAST_EXPECT((*sle)[~sfIssuerKeyMirrorEpoch] == 1u);
1948 BEAST_EXPECT((*sle)[~sfAuditorKeyMirrorEpoch] == 1u);
1955 Env env{*
this, features};
1958 Account const auditor(
"auditor");
1968 Buffer const auditorCipher =
1974 .auditorEncryptedAmount = auditorCipher,
1978 if (!BEAST_EXPECT(sle))
1980 BEAST_EXPECT(
strHex((*sle)[sfAuditorEncryptedBalance]) ==
strHex(auditorCipher));
1982 BEAST_EXPECT(!sle->isFieldPresent(sfAuditorKeyMirrorEpoch));
1992 Env env{*
this, features};
1995 Account const newIssuerKey(
"newIssuerKey");
2002 Buffer const newIssuerCipher =
2007 .issuerEncryptedAmount = newIssuerCipher,
2011 if (!BEAST_EXPECT(sle))
2013 BEAST_EXPECT(
strHex((*sle)[sfIssuerEncryptedBalance]) ==
strHex(newIssuerCipher));
2014 BEAST_EXPECT((*sle)[~sfIssuerKeyMirrorEpoch] == 1u);
2019 Env env{*
this, features};
2022 Account const auditor(
"auditor");
2023 Account const newAuditorKey(
"newAuditorKey");
2028 tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer,
2035 Buffer const newAuditorCipher =
2040 .auditorEncryptedAmount = newAuditorCipher,
2044 if (!BEAST_EXPECT(sle))
2046 BEAST_EXPECT(
strHex((*sle)[sfAuditorEncryptedBalance]) ==
strHex(newAuditorCipher));
2047 BEAST_EXPECT((*sle)[~sfAuditorKeyMirrorEpoch] == 1u);
2052 Env env{*
this, features};
2055 Account const auditor(
"auditor");
2056 Account const newIssuerKey(
"newIssuerKey");
2057 Account const newAuditorKey(
"newAuditorKey");
2062 tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer,
2080 .issuerEncryptedAmount = newIssuerCipher,
2081 .auditorEncryptedAmount = newAuditorCipher,
2085 if (!BEAST_EXPECT(sle))
2087 BEAST_EXPECT(
strHex((*sle)[sfIssuerEncryptedBalance]) ==
strHex(newIssuerCipher));
2088 BEAST_EXPECT(
strHex((*sle)[sfAuditorEncryptedBalance]) ==
strHex(newAuditorCipher));
2089 BEAST_EXPECT((*sle)[~sfIssuerKeyMirrorEpoch] == 1u);
2090 BEAST_EXPECT((*sle)[~sfAuditorKeyMirrorEpoch] == 1u);
2097 Env env{*
this, features};
2100 Account const auditor(
"auditor");
2110 Buffer const auditorCipher =
2115 .auditorEncryptedAmount = auditorCipher,
2119 if (!BEAST_EXPECT(sle))
2121 BEAST_EXPECT(
strHex((*sle)[sfAuditorEncryptedBalance]) ==
strHex(auditorCipher));
2123 BEAST_EXPECT(!sle->isFieldPresent(sfAuditorKeyMirrorEpoch));
2130 testcase(
"ConfidentialMPTMirrorUpdate issuer migrates after several rotations");
2135 Env env{*
this, features};
2138 Account const auditor(
"auditor");
2139 Account const issuerKey1(
"issuerKey1");
2140 Account const issuerKey2(
"issuerKey2");
2141 Account const issuerKey3(
"issuerKey3");
2142 Account const issuerKey4(
"issuerKey4");
2143 Account const issuerKey5(
"issuerKey5");
2144 Account const auditorKey1(
"auditorKey1");
2145 Account const auditorKey2(
"auditorKey2");
2146 Account const auditorKey3(
"auditorKey3");
2147 Account const auditorKey4(
"auditorKey4");
2152 tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer,
2167 BEAST_EXPECT(sleIssuance && (*sleIssuance)[~sfIssuerKeyEpoch] == 3u);
2175 Buffer const newIssuerCipher =
2181 .issuerEncryptedAmount = newIssuerCipher,
2186 if (!BEAST_EXPECT(sle))
2188 BEAST_EXPECT(
strHex((*sle)[sfIssuerEncryptedBalance]) ==
strHex(newIssuerCipher));
2189 BEAST_EXPECT((*sle)[~sfIssuerKeyMirrorEpoch] == 3u);
2197 .issuerEncryptedAmount = newIssuerCipher,
2211 BEAST_EXPECT(sleIssuance && (*sleIssuance)[~sfAuditorKeyEpoch] == 2u);
2212 BEAST_EXPECT(sleIssuance && (*sleIssuance)[~sfIssuerKeyEpoch] == 3u);
2220 Buffer const newAuditorCipher =
2226 .auditorEncryptedAmount = newAuditorCipher,
2231 if (!BEAST_EXPECT(sle))
2233 BEAST_EXPECT(
strHex((*sle)[sfAuditorEncryptedBalance]) ==
strHex(newAuditorCipher));
2234 BEAST_EXPECT((*sle)[~sfAuditorKeyMirrorEpoch] == 2u);
2237 BEAST_EXPECT(
strHex((*sle)[sfIssuerEncryptedBalance]) ==
strHex(newIssuerCipher));
2238 BEAST_EXPECT((*sle)[~sfIssuerKeyMirrorEpoch] == 3u);
2246 .auditorEncryptedAmount = newAuditorCipher,
2269 BEAST_EXPECT(sleIssuance && (*sleIssuance)[~sfIssuerKeyEpoch] == 5u);
2270 BEAST_EXPECT(sleIssuance && (*sleIssuance)[~sfAuditorKeyEpoch] == 4u);
2278 Buffer const bothIssuerCipher =
2280 Buffer const bothAuditorCipher =
2286 .issuerEncryptedAmount = bothIssuerCipher,
2287 .auditorEncryptedAmount = bothAuditorCipher,
2292 if (!BEAST_EXPECT(sle))
2294 BEAST_EXPECT(
strHex((*sle)[sfIssuerEncryptedBalance]) ==
strHex(bothIssuerCipher));
2295 BEAST_EXPECT(
strHex((*sle)[sfAuditorEncryptedBalance]) ==
strHex(bothAuditorCipher));
2296 BEAST_EXPECT((*sle)[~sfIssuerKeyMirrorEpoch] == 5u);
2297 BEAST_EXPECT((*sle)[~sfAuditorKeyMirrorEpoch] == 4u);
2305 .issuerEncryptedAmount = bothIssuerCipher,
2306 .auditorEncryptedAmount = bothAuditorCipher,
2314 testcase(
"ConfidentialMPTMirrorUpdate holder migrates after several rotations");
2319 Env env{*
this, features};
2322 Account const auditor(
"auditor");
2323 Account const issuerKey1(
"issuerKey1");
2324 Account const issuerKey2(
"issuerKey2");
2325 Account const issuerKey3(
"issuerKey3");
2326 Account const issuerKey4(
"issuerKey4");
2327 Account const issuerKey5(
"issuerKey5");
2328 Account const auditorKey1(
"auditorKey1");
2329 Account const auditorKey2(
"auditorKey2");
2330 Account const auditorKey3(
"auditorKey3");
2331 Account const auditorKey4(
"auditorKey4");
2336 tfMPTCanHoldConfidentialBalance | tfMPTCanTransfer,
2352 Buffer const newIssuerCipher =
2357 .issuerEncryptedAmount = newIssuerCipher,
2362 if (!BEAST_EXPECT(sle))
2364 BEAST_EXPECT(
strHex((*sle)[sfIssuerEncryptedBalance]) ==
strHex(newIssuerCipher));
2365 BEAST_EXPECT((*sle)[~sfIssuerKeyMirrorEpoch] == 3u);
2372 .issuerEncryptedAmount = newIssuerCipher,
2383 Buffer const newAuditorCipher =
2388 .auditorEncryptedAmount = newAuditorCipher,
2393 if (!BEAST_EXPECT(sle))
2395 BEAST_EXPECT(
strHex((*sle)[sfAuditorEncryptedBalance]) ==
strHex(newAuditorCipher));
2396 BEAST_EXPECT((*sle)[~sfAuditorKeyMirrorEpoch] == 2u);
2398 BEAST_EXPECT(
strHex((*sle)[sfIssuerEncryptedBalance]) ==
strHex(newIssuerCipher));
2399 BEAST_EXPECT((*sle)[~sfIssuerKeyMirrorEpoch] == 3u);
2406 .auditorEncryptedAmount = newAuditorCipher,
2429 Buffer const bothIssuerCipher =
2431 Buffer const bothAuditorCipher =
2436 .issuerEncryptedAmount = bothIssuerCipher,
2437 .auditorEncryptedAmount = bothAuditorCipher,
2442 if (!BEAST_EXPECT(sle))
2444 BEAST_EXPECT(
strHex((*sle)[sfIssuerEncryptedBalance]) ==
strHex(bothIssuerCipher));
2445 BEAST_EXPECT(
strHex((*sle)[sfAuditorEncryptedBalance]) ==
strHex(bothAuditorCipher));
2446 BEAST_EXPECT((*sle)[~sfIssuerKeyMirrorEpoch] == 5u);
2447 BEAST_EXPECT((*sle)[~sfAuditorKeyMirrorEpoch] == 4u);
2453 .issuerEncryptedAmount = bothIssuerCipher,
2454 .auditorEncryptedAmount = bothAuditorCipher,
2462 testcase(
"ConfidentialMPTHolderKeyUpdate preflight");
2465 Env env{*
this, features};
2470 if (!features[featureConfidentialMPTKeyRotation] || !features[featureConfidentialTransfer])
2472 MPTTester mptAlice(env, alice, {.holders = {bob}});
2473 mptAlice.create({.ownerCount = 1, .flags = tfMPTCanTransfer});
2474 mptAlice.holderKeyUpdate({
2477 .flags = tfHolderKeyRecovery,
2483 ConfidentialEnv ct{env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
2485 Account const bobNewKey(
"bobNewKey");
2490 for (
auto const flags : {0x00080000u, 0x00080000u | tfHolderKeyRecovery, 0x00100000u})
2495 .proof = gMakeZeroBuffer(1),
2502 for (
auto const flags :
2504 tfHolderKeyRotation | tfHolderKeyRecovery,
2505 tfHolderKeyRotation | tfCancelRecovery,
2506 tfHolderKeyRecovery | tfCancelRecovery,
2507 tfHolderKeyRotation | tfHolderKeyRecovery | tfCancelRecovery})
2512 .proof = gMakeZeroBuffer(1),
2519 Account const aliceNewKey(
"aliceNewKey");
2524 .proof = gMakeZeroBuffer(1),
2525 .flags = tfHolderKeyRecovery,
2533 .proof = gMakeZeroBuffer(1),
2534 .flags = tfHolderKeyRecovery,
2543 .proof = gMakeZeroBuffer(1),
2544 .flags = tfHolderKeyRecovery,
2552 .proof = gMakeZeroBuffer(1),
2553 .flags = tfHolderKeyRecovery,
2561 for (
auto const& [spending, inbox] :
2567 .spendingCiphertext = spending,
2568 .inboxCiphertext = inbox,
2569 .proof = gMakeZeroBuffer(1),
2570 .flags = tfHolderKeyRotation,
2576 for (
auto const& [spending, inbox] :
2582 .spendingCiphertext = spending,
2583 .inboxCiphertext = inbox,
2584 .proof = gMakeZeroBuffer(1),
2585 .flags = tfHolderKeyRecovery,
2590 for (
auto const& [spending, inbox] :
2595 .spendingCiphertext = spending,
2596 .inboxCiphertext = inbox,
2597 .flags = tfCancelRecovery,
2608 .proof = gMakeZeroBuffer(1),
2609 .flags = tfHolderKeyRotation,
2619 .proof = gMakeZeroBuffer(1),
2620 .flags = tfHolderKeyRotation,
2631 .proof = gMakeZeroBuffer(1),
2632 .flags = tfHolderKeyRotation,
2643 .proof = gMakeZeroBuffer(1),
2644 .flags = tfHolderKeyRotation,
2652 .flags = tfHolderKeyRecovery,
2660 .flags = tfCancelRecovery,
2667 .proof = gMakeZeroBuffer(1),
2668 .flags = tfCancelRecovery,
2676 testcase(
"ConfidentialMPTHolderKeyUpdate preclaim");
2681 Env env{*
this, features};
2684 MPTTester mptAlice(env, alice, {.holders = {bob}});
2688 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
2693 mptAlice.holderKeyUpdate({
2695 .flags = tfCancelRecovery,
2704 Env env{*
this, features};
2707 MPTTester mptAlice(env, alice, {.holders = {bob}});
2708 mptAlice.create({.ownerCount = 1, .flags = tfMPTCanTransfer});
2709 mptAlice.authorize({.account = bob});
2711 mptAlice.holderKeyUpdate({
2713 .flags = tfCancelRecovery,
2721 Env env{*
this, features};
2724 MPTTester mptAlice(env, alice);
2727 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
2729 env.fund(XRP(1000), carol);
2732 Account const carolNewKey(
"carolNewKey");
2733 mptAlice.generateKeyPair(carolNewKey);
2735 mptAlice.holderKeyUpdate({
2737 .holderPubKey = mptAlice.getPubKey(carolNewKey),
2738 .proof = gMakeZeroBuffer(1),
2739 .flags = tfHolderKeyRecovery,
2747 Env env{*
this, features};
2750 MPTTester mptAlice(env, alice, {.holders = {bob}});
2753 .flags = tfMPTCanTransfer | tfMPTCanHoldConfidentialBalance,
2755 mptAlice.authorize({.account = bob});
2756 mptAlice.pay(alice, bob, 100);
2758 Account const bobNewKey(
"bobNewKey");
2759 mptAlice.generateKeyPair(bobNewKey);
2761 mptAlice.holderKeyUpdate({
2763 .holderPubKey = mptAlice.getPubKey(bobNewKey),
2764 .proof = gMakeZeroBuffer(1),
2765 .flags = tfHolderKeyRecovery,
2772 Env env{*
this, features};
2776 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
2781 .proof = gMakeZeroBuffer(1),
2782 .flags = tfHolderKeyRecovery,
2790 Env env{*
this, features};
2794 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
2796 Account const bobRecoveryKey(
"bobRecoveryKey");
2801 .proof = gMakeZeroBuffer(1),
2802 .flags = tfHolderKeyRecovery,
2805 Account const bobRecoveryKey2(
"bobRecoveryKey2");
2810 .proof = gMakeZeroBuffer(1),
2811 .flags = tfHolderKeyRecovery,
2819 Env env{*
this, features};
2823 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
2827 .flags = tfCancelRecovery,
2835 Account const bobNewKey(
"bobNewKey");
2839 BEAST_EXPECT(reEnc.has_value());
2846 .spendingCiphertext = reEnc->first,
2847 .inboxCiphertext = reEnc->second,
2848 .proof = gMakeZeroBuffer(1),
2849 .flags = tfHolderKeyRotation,
2852 Account const bobRecoveryKey(
"bobRecoveryKey");
2857 .proof = gMakeZeroBuffer(1),
2858 .flags = tfHolderKeyRecovery,
2863 .flags = tfCancelRecovery,
2869 Env env{*
this, features};
2873 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
2874 ct.
mpt.
set({.account = alice, .holder = bob, .flags = tfMPTLock});
2876 allModesSucceed(ct, bob);
2881 Env env{*
this, features};
2885 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
2886 ct.
mpt.
set({.account = alice, .flags = tfMPTLock});
2888 allModesSucceed(ct, bob);
2893 Env env{*
this, features};
2897 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
2901 Account const aliceNewIssuerKey(
"aliceNewIssuerKey");
2907 allModesSucceed(ct, bob);
2914 testcase(
"ConfidentialMPTHolderKeyUpdate doApply");
2920 Env env{*
this, features};
2924 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
2928 Account const bobNewKey(
"bobNewKey");
2932 BEAST_EXPECT(reEnc.has_value());
2939 .spendingCiphertext = reEnc->first,
2940 .inboxCiphertext = reEnc->second,
2941 .proof = gMakeZeroBuffer(1),
2942 .flags = tfHolderKeyRotation,
2946 if (!BEAST_EXPECT(sleMptoken))
2951 newPubKey &&
strHex((*sleMptoken)[sfHolderEncryptionKey]) ==
strHex(*newPubKey));
2952 BEAST_EXPECT(!sleMptoken->isFieldPresent(sfRecoveryKey));
2957 auto const spendingCt =
2960 BEAST_EXPECT(spendingCt.has_value());
2961 BEAST_EXPECT(inboxCt.has_value());
2962 if (!spendingCt || !inboxCt)
2967 BEAST_EXPECT(spendingAmt && *spendingAmt == 40);
2968 BEAST_EXPECT(inboxAmt && *inboxAmt == 0);
2974 Env env{*
this, features};
2981 {{.account = bob, .payAmount = 100, .convertAmount = 40},
2982 {.account = carol, .payAmount = 100, .convertAmount = 50}}};
2986 ct.
mpt.
send({.account = carol, .dest = bob, .amt = 15});
2988 Account const bobNewKey(
"bobNewKey");
2992 BEAST_EXPECT(reEnc.has_value());
2999 .spendingCiphertext = reEnc->first,
3000 .inboxCiphertext = reEnc->second,
3001 .proof = gMakeZeroBuffer(1),
3002 .flags = tfHolderKeyRotation,
3005 auto const spendingCt =
3008 BEAST_EXPECT(spendingCt.has_value());
3009 BEAST_EXPECT(inboxCt.has_value());
3010 if (!spendingCt || !inboxCt)
3015 BEAST_EXPECT(spendingAmt && *spendingAmt == 40);
3016 BEAST_EXPECT(inboxAmt && *inboxAmt == 15);
3022 Env env{*
this, features};
3026 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
3029 auto const prevSpending =
3034 Account const bobRecoveryKey(
"bobRecoveryKey");
3040 .proof = gMakeZeroBuffer(1),
3041 .flags = tfHolderKeyRecovery,
3045 if (!BEAST_EXPECT(sleMptoken))
3048 auto const recoveryKey = ct.
mpt.
getPubKey(bobRecoveryKey);
3050 sleMptoken->isFieldPresent(sfRecoveryKey) && recoveryKey &&
3051 strHex((*sleMptoken)[sfRecoveryKey]) ==
strHex(*recoveryKey));
3054 prevKey &&
strHex((*sleMptoken)[sfHolderEncryptionKey]) ==
strHex(*prevKey));
3066 Env env{*
this, features};
3070 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
3072 Account const bobRecoveryKey(
"bobRecoveryKey");
3078 .proof = gMakeZeroBuffer(1),
3079 .flags = tfHolderKeyRecovery,
3083 auto const prevSpending =
3090 .flags = tfCancelRecovery,
3094 if (!BEAST_EXPECT(sleMptoken))
3097 BEAST_EXPECT(!sleMptoken->isFieldPresent(sfRecoveryKey));
3099 prevKey &&
strHex((*sleMptoken)[sfHolderEncryptionKey]) ==
strHex(*prevKey));
3110 Env env{*
this, features};
3114 env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 40}}};
3116 Account const bobRecoveryKey(
"bobRecoveryKey");
3121 .proof = gMakeZeroBuffer(1),
3122 .flags = tfHolderKeyRecovery,
3127 if (!BEAST_EXPECT(sleMptoken))
3129 BEAST_EXPECT(sleMptoken->isFieldPresent(sfRecoveryKey));
3132 Account const bobNewKey(
"bobNewKey");
3136 BEAST_EXPECT(reEnc.has_value());
3143 .spendingCiphertext = reEnc->first,
3144 .inboxCiphertext = reEnc->second,
3145 .proof = gMakeZeroBuffer(1),
3146 .flags = tfHolderKeyRotation,
3150 if (!BEAST_EXPECT(sleMptoken))
3152 BEAST_EXPECT(!sleMptoken->isFieldPresent(sfRecoveryKey));