mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-25 08:00:22 +00:00
ConfidentialConvert tests (#5911)
This commit is contained in:
@@ -31,7 +31,7 @@ class ConfidentialTransfer_test : public beast::unit_test::suite
|
||||
void
|
||||
testConvert(FeatureBitset features)
|
||||
{
|
||||
testcase("test convert");
|
||||
testcase("Convert");
|
||||
using namespace test::jtx;
|
||||
Env env{*this, features};
|
||||
Account const alice("alice");
|
||||
@@ -85,7 +85,7 @@ class ConfidentialTransfer_test : public beast::unit_test::suite
|
||||
void
|
||||
testConvertPreflight(FeatureBitset features)
|
||||
{
|
||||
testcase("test convert");
|
||||
testcase("Convert preflight");
|
||||
using namespace test::jtx;
|
||||
|
||||
Env env{*this, features - featureConfidentialTransfer};
|
||||
@@ -146,6 +146,13 @@ class ConfidentialTransfer_test : public beast::unit_test::suite
|
||||
.issuerEncryptedAmt = Buffer{},
|
||||
.err = temMALFORMED});
|
||||
|
||||
mptAlice.convert(
|
||||
{.account = bob,
|
||||
.amt = maxMPTokenAmount + 1,
|
||||
.proof = "123",
|
||||
.holderPubKey = mptAlice.getPubKey(bob),
|
||||
.err = temMALFORMED});
|
||||
|
||||
// todo: change to to check proof size
|
||||
// mptAlice.convert(
|
||||
// {.account = bob,
|
||||
@@ -161,28 +168,249 @@ class ConfidentialTransfer_test : public beast::unit_test::suite
|
||||
testcase("Set preflight");
|
||||
using namespace test::jtx;
|
||||
|
||||
Env env{*this, features - featureConfidentialTransfer};
|
||||
Account const alice("alice");
|
||||
Account const bob("bob");
|
||||
MPTTester mptAlice(env, alice, {.holders = {bob}});
|
||||
{
|
||||
Env env{*this, features - featureConfidentialTransfer};
|
||||
Account const alice("alice");
|
||||
Account const bob("bob");
|
||||
MPTTester mptAlice(env, alice, {.holders = {bob}});
|
||||
|
||||
mptAlice.create(
|
||||
{.ownerCount = 1,
|
||||
.holderCount = 0,
|
||||
.flags = tfMPTCanTransfer | tfMPTCanLock});
|
||||
mptAlice.create(
|
||||
{.ownerCount = 1,
|
||||
.holderCount = 0,
|
||||
.flags = tfMPTCanTransfer | tfMPTCanLock});
|
||||
|
||||
mptAlice.authorize({.account = bob});
|
||||
env.close();
|
||||
mptAlice.pay(alice, bob, 100);
|
||||
env.close();
|
||||
mptAlice.authorize({.account = bob});
|
||||
env.close();
|
||||
mptAlice.pay(alice, bob, 100);
|
||||
env.close();
|
||||
|
||||
mptAlice.generateKeyPair(alice);
|
||||
mptAlice.generateKeyPair(bob);
|
||||
mptAlice.generateKeyPair(alice);
|
||||
mptAlice.generateKeyPair(bob);
|
||||
|
||||
mptAlice.set(
|
||||
{.account = alice,
|
||||
.pubKey = mptAlice.getPubKey(alice),
|
||||
.err = temDISABLED});
|
||||
mptAlice.set(
|
||||
{.account = alice,
|
||||
.pubKey = mptAlice.getPubKey(alice),
|
||||
.err = temDISABLED});
|
||||
}
|
||||
|
||||
// issuance has disabled confidential transfer
|
||||
{
|
||||
Env env{*this, features};
|
||||
Account const alice("alice");
|
||||
Account const bob("bob");
|
||||
MPTTester mptAlice(env, alice, {.holders = {bob}});
|
||||
|
||||
mptAlice.create(
|
||||
{.ownerCount = 1,
|
||||
.holderCount = 0,
|
||||
.flags = tfMPTCanTransfer | tfMPTCanLock |
|
||||
tfMPTNoConfidentialTransfer});
|
||||
|
||||
mptAlice.authorize({.account = bob});
|
||||
env.close();
|
||||
mptAlice.pay(alice, bob, 100);
|
||||
env.close();
|
||||
|
||||
mptAlice.generateKeyPair(alice);
|
||||
mptAlice.generateKeyPair(bob);
|
||||
|
||||
mptAlice.set(
|
||||
{.account = alice,
|
||||
.pubKey = mptAlice.getPubKey(alice),
|
||||
.err = tecNO_PERMISSION});
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testConvertPreclaim(FeatureBitset features)
|
||||
{
|
||||
testcase("Convert preclaim");
|
||||
using namespace test::jtx;
|
||||
|
||||
// tfMPTNoConfidentialTransfer is set on issuance
|
||||
{
|
||||
Env env{*this, features};
|
||||
Account const alice("alice");
|
||||
Account const bob("bob");
|
||||
MPTTester mptAlice(env, alice, {.holders = {bob}});
|
||||
|
||||
mptAlice.create(
|
||||
{.ownerCount = 1,
|
||||
.holderCount = 0,
|
||||
.flags = tfMPTCanTransfer | tfMPTCanLock |
|
||||
tfMPTNoConfidentialTransfer});
|
||||
|
||||
mptAlice.authorize({.account = bob});
|
||||
env.close();
|
||||
mptAlice.pay(alice, bob, 100);
|
||||
env.close();
|
||||
|
||||
mptAlice.generateKeyPair(alice);
|
||||
mptAlice.generateKeyPair(bob);
|
||||
|
||||
mptAlice.convert(
|
||||
{.account = bob,
|
||||
.amt = 10,
|
||||
.proof = "123",
|
||||
.holderPubKey = mptAlice.getPubKey(bob),
|
||||
.err = tecNO_PERMISSION});
|
||||
}
|
||||
|
||||
// issuer has not uploaded their sfIssuerElGamalPublicKey
|
||||
{
|
||||
Env env{*this, features};
|
||||
Account const alice("alice");
|
||||
Account const bob("bob");
|
||||
MPTTester mptAlice(env, alice, {.holders = {bob}});
|
||||
|
||||
mptAlice.create(
|
||||
{.ownerCount = 1,
|
||||
.holderCount = 0,
|
||||
.flags = tfMPTCanTransfer | tfMPTCanLock});
|
||||
|
||||
mptAlice.authorize({.account = bob});
|
||||
env.close();
|
||||
mptAlice.pay(alice, bob, 100);
|
||||
env.close();
|
||||
|
||||
mptAlice.generateKeyPair(alice);
|
||||
mptAlice.generateKeyPair(bob);
|
||||
|
||||
mptAlice.convert(
|
||||
{.account = bob,
|
||||
.amt = 10,
|
||||
.proof = "123",
|
||||
.holderPubKey = mptAlice.getPubKey(bob),
|
||||
.err = tecNO_PERMISSION});
|
||||
}
|
||||
|
||||
// issuance does not exist
|
||||
{
|
||||
Env env{*this, features};
|
||||
Account const alice("alice");
|
||||
Account const bob("bob");
|
||||
MPTTester mptAlice(env, alice, {.holders = {bob}});
|
||||
|
||||
mptAlice.create(
|
||||
{.ownerCount = 1,
|
||||
.holderCount = 0,
|
||||
.flags = tfMPTCanTransfer | tfMPTCanLock});
|
||||
|
||||
mptAlice.authorize({.account = bob});
|
||||
mptAlice.generateKeyPair(alice);
|
||||
|
||||
mptAlice.set(
|
||||
{.account = alice, .pubKey = mptAlice.getPubKey(alice)});
|
||||
|
||||
mptAlice.destroy();
|
||||
mptAlice.generateKeyPair(bob);
|
||||
|
||||
mptAlice.convert(
|
||||
{.account = bob,
|
||||
.amt = 10,
|
||||
.proof = "123",
|
||||
.holderPubKey = mptAlice.getPubKey(bob),
|
||||
.err = tecOBJECT_NOT_FOUND});
|
||||
}
|
||||
|
||||
// bob has not created MPToken
|
||||
{
|
||||
Env env{*this, features};
|
||||
Account const alice("alice");
|
||||
Account const bob("bob");
|
||||
MPTTester mptAlice(env, alice, {.holders = {bob}});
|
||||
|
||||
mptAlice.create(
|
||||
{.ownerCount = 1,
|
||||
.holderCount = 0,
|
||||
.flags = tfMPTCanTransfer | tfMPTCanLock});
|
||||
|
||||
mptAlice.generateKeyPair(alice);
|
||||
mptAlice.generateKeyPair(bob);
|
||||
|
||||
mptAlice.set(
|
||||
{.account = alice, .pubKey = mptAlice.getPubKey(alice)});
|
||||
|
||||
mptAlice.convert(
|
||||
{.account = bob,
|
||||
.amt = 10,
|
||||
.proof = "123",
|
||||
.holderPubKey = mptAlice.getPubKey(bob),
|
||||
.err = tecOBJECT_NOT_FOUND});
|
||||
}
|
||||
|
||||
// trying to convert more than what bob has
|
||||
{
|
||||
Env env{*this, features};
|
||||
Account const alice("alice");
|
||||
Account const bob("bob");
|
||||
MPTTester mptAlice(env, alice, {.holders = {bob}});
|
||||
|
||||
mptAlice.create(
|
||||
{.ownerCount = 1,
|
||||
.holderCount = 0,
|
||||
.flags = tfMPTCanTransfer | tfMPTCanLock});
|
||||
|
||||
mptAlice.authorize({.account = bob});
|
||||
env.close();
|
||||
mptAlice.pay(alice, bob, 100);
|
||||
env.close();
|
||||
|
||||
mptAlice.generateKeyPair(alice);
|
||||
|
||||
mptAlice.set(
|
||||
{.account = alice, .pubKey = mptAlice.getPubKey(alice)});
|
||||
|
||||
mptAlice.generateKeyPair(bob);
|
||||
|
||||
mptAlice.convert(
|
||||
{.account = bob,
|
||||
.amt = 200,
|
||||
.proof = "123",
|
||||
.holderPubKey = mptAlice.getPubKey(bob),
|
||||
.err = tecINSUFFICIENT_FUNDS});
|
||||
}
|
||||
|
||||
// holder cannot upload pk again
|
||||
{
|
||||
Env env{*this, features};
|
||||
Account const alice("alice");
|
||||
Account const bob("bob");
|
||||
MPTTester mptAlice(env, alice, {.holders = {bob}});
|
||||
|
||||
mptAlice.create(
|
||||
{.ownerCount = 1,
|
||||
.holderCount = 0,
|
||||
.flags = tfMPTCanTransfer | tfMPTCanLock});
|
||||
|
||||
mptAlice.authorize({.account = bob});
|
||||
env.close();
|
||||
mptAlice.pay(alice, bob, 100);
|
||||
env.close();
|
||||
|
||||
mptAlice.generateKeyPair(alice);
|
||||
|
||||
mptAlice.set(
|
||||
{.account = alice, .pubKey = mptAlice.getPubKey(alice)});
|
||||
|
||||
mptAlice.generateKeyPair(bob);
|
||||
|
||||
mptAlice.convert(
|
||||
{.account = bob,
|
||||
.amt = 10,
|
||||
.proof = "123",
|
||||
.holderPubKey = mptAlice.getPubKey(bob)});
|
||||
|
||||
// cannot upload pk again
|
||||
mptAlice.convert(
|
||||
{.account = bob,
|
||||
.amt = 10,
|
||||
.proof = "123",
|
||||
.holderPubKey = mptAlice.getPubKey(bob),
|
||||
.err = tecDUPLICATE});
|
||||
}
|
||||
|
||||
// todo: test well formed proof
|
||||
}
|
||||
|
||||
void
|
||||
@@ -190,6 +418,8 @@ class ConfidentialTransfer_test : public beast::unit_test::suite
|
||||
{
|
||||
testConvert(features);
|
||||
testConvertPreflight(features);
|
||||
testConvertPreclaim(features);
|
||||
|
||||
testSetPreflight(features);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,9 @@ ConfidentialConvert::preflight(PreflightContext const& ctx)
|
||||
ctx.tx[sfIssuerEncryptedAmount].length() != ecGamalEncryptedTotalLength)
|
||||
return temMALFORMED;
|
||||
|
||||
if (ctx.tx[sfMPTAmount] > maxMPTokenAmount)
|
||||
return temMALFORMED;
|
||||
|
||||
// if (ctx.tx[sfZKProof].length() != ecEqualityProofLength)
|
||||
// return temMALFORMED;
|
||||
|
||||
@@ -83,7 +86,7 @@ ConfidentialConvert::preclaim(PreclaimContext const& ctx)
|
||||
// can't update if there's already a pk
|
||||
if (sleMptoken->isFieldPresent(sfHolderElGamalPublicKey) &&
|
||||
ctx.tx.isFieldPresent(sfHolderElGamalPublicKey))
|
||||
return tecNO_PERMISSION;
|
||||
return tecDUPLICATE;
|
||||
|
||||
auto const holderPubKey = ctx.tx.isFieldPresent(sfHolderElGamalPublicKey)
|
||||
? ctx.tx[sfHolderElGamalPublicKey]
|
||||
@@ -180,18 +183,17 @@ ConfidentialConvert::doApply()
|
||||
(*sleMptoken)[sfIssuerEncryptedBalance] = issuerEc;
|
||||
(*sleMptoken)[sfConfidentialBalanceVersion] = 0;
|
||||
|
||||
// encrypt sfConfidentialBalanceSpending with zero balance
|
||||
Buffer out;
|
||||
try
|
||||
{
|
||||
// encrypt sfConfidentialBalanceSpending with zero balance
|
||||
Buffer out;
|
||||
out = encryptAmount(0, (*sleMptoken)[sfHolderElGamalPublicKey]);
|
||||
(*sleMptoken)[sfConfidentialBalanceSpending] = out;
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
return tecINTERNAL;
|
||||
}
|
||||
|
||||
(*sleMptoken)[sfConfidentialBalanceSpending] = out;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user