mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-03 08:46:46 +00:00
Increase confidential transactions fee (#7063)
This commit is contained in:
@@ -348,6 +348,9 @@ std::size_t constexpr kEC_CONVERT_BACK_PROOF_LENGTH = 816;
|
||||
/** Length of the ZKProof for ConfidentialMPTClawback. */
|
||||
std::size_t constexpr kEC_CLAWBACK_PROOF_LENGTH = 64;
|
||||
|
||||
/** Extra base fee multiplier charged to confidential MPT transactions. */
|
||||
std::uint32_t constexpr kCONFIDENTIAL_FEE_MULTIPLIER = 9;
|
||||
|
||||
/** Compressed EC point prefix for even y-coordinate */
|
||||
std::uint8_t constexpr kEC_COMPRESSED_PREFIX_EVEN_Y = 0x02;
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@ public:
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@ public:
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
|
||||
@@ -35,6 +35,9 @@ public:
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
|
||||
@@ -36,6 +36,9 @@ public:
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
|
||||
@@ -45,6 +45,9 @@ public:
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/ConfidentialTransfer.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
@@ -45,6 +47,15 @@ ConfidentialMPTClawback::preflight(PreflightContext const& ctx)
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
XRPAmount
|
||||
ConfidentialMPTClawback::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
{
|
||||
// Transactor::calculateBaseFee = baseFee + (signerCount * baseFee).
|
||||
// We charge kCONFIDENTIAL_FEE_MULTIPLIER extra base fees so the total is
|
||||
// 10 * baseFee + (signerCount * baseFee).
|
||||
return Transactor::calculateBaseFee(view, tx) + view.fees().base * kCONFIDENTIAL_FEE_MULTIPLIER;
|
||||
}
|
||||
|
||||
TER
|
||||
ConfidentialMPTClawback::preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/protocol/ConfidentialTransfer.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
@@ -63,6 +65,15 @@ ConfidentialMPTConvert::preflight(PreflightContext const& ctx)
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
XRPAmount
|
||||
ConfidentialMPTConvert::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
{
|
||||
// Transactor::calculateBaseFee = baseFee + (signerCount * baseFee).
|
||||
// We charge kCONFIDENTIAL_FEE_MULTIPLIER extra base fees so the total is
|
||||
// 10 * baseFee + (signerCount * baseFee).
|
||||
return Transactor::calculateBaseFee(view, tx) + view.fees().base * kCONFIDENTIAL_FEE_MULTIPLIER;
|
||||
}
|
||||
|
||||
TER
|
||||
ConfidentialMPTConvert::preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/protocol/ConfidentialTransfer.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
@@ -48,6 +49,15 @@ ConfidentialMPTConvertBack::preflight(PreflightContext const& ctx)
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
XRPAmount
|
||||
ConfidentialMPTConvertBack::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
{
|
||||
// Transactor::calculateBaseFee = baseFee + (signerCount * baseFee).
|
||||
// We charge kCONFIDENTIAL_FEE_MULTIPLIER extra base fees so the total is
|
||||
// 10 * baseFee + (signerCount * baseFee).
|
||||
return Transactor::calculateBaseFee(view, tx) + view.fees().base * kCONFIDENTIAL_FEE_MULTIPLIER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the cryptographic proofs for a ConvertBack transaction.
|
||||
*
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/protocol/ConfidentialTransfer.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
@@ -31,6 +33,15 @@ ConfidentialMPTMergeInbox::preflight(PreflightContext const& ctx)
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
XRPAmount
|
||||
ConfidentialMPTMergeInbox::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
{
|
||||
// Transactor::calculateBaseFee = baseFee + (signerCount * baseFee).
|
||||
// We charge kCONFIDENTIAL_FEE_MULTIPLIER extra base fees so the total is
|
||||
// 10 * baseFee + (signerCount * baseFee).
|
||||
return Transactor::calculateBaseFee(view, tx) + view.fees().base * kCONFIDENTIAL_FEE_MULTIPLIER;
|
||||
}
|
||||
|
||||
TER
|
||||
ConfidentialMPTMergeInbox::preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <xrpl/tx/transactors/token/ConfidentialMPTSend.h>
|
||||
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/helpers/CredentialHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/protocol/ConfidentialTransfer.h>
|
||||
@@ -88,6 +89,15 @@ ConfidentialMPTSend::preflight(PreflightContext const& ctx)
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
XRPAmount
|
||||
ConfidentialMPTSend::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
{
|
||||
// Transactor::calculateBaseFee = baseFee + (signerCount * baseFee).
|
||||
// We charge kCONFIDENTIAL_FEE_MULTIPLIER extra base fees so the total is
|
||||
// 10 * baseFee + (signerCount * baseFee).
|
||||
return Transactor::calculateBaseFee(view, tx) + view.fees().base * kCONFIDENTIAL_FEE_MULTIPLIER;
|
||||
}
|
||||
|
||||
TER
|
||||
verifySendProofs(
|
||||
PreclaimContext const& ctx,
|
||||
|
||||
@@ -2900,7 +2900,8 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
ConfidentialEnv confEnv{
|
||||
env,
|
||||
alice,
|
||||
{{.account = bob, .payAmount = 1000, .convertAmount = 60}, {carol, 1000, 50}}};
|
||||
{{.account = bob, .payAmount = 1000, .convertAmount = 60},
|
||||
{.account = carol, .payAmount = 1000, .convertAmount = 50}}};
|
||||
auto& mptAlice = confEnv.mpt;
|
||||
|
||||
{
|
||||
@@ -2972,7 +2973,8 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
ConfidentialEnv zeroEnv{
|
||||
env2,
|
||||
alice2,
|
||||
{{.account = bob2, .payAmount = 100, .convertAmount = 0}, {carol2, 50, 0}}};
|
||||
{{.account = bob2, .payAmount = 100, .convertAmount = 0},
|
||||
{.account = carol2, .payAmount = 50, .convertAmount = 0}}};
|
||||
auto& mptAlice2 = zeroEnv.mpt;
|
||||
|
||||
// Trying to send any amount with 0 spending balance must fail:
|
||||
@@ -6057,7 +6059,8 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
ConfidentialEnv confEnv{
|
||||
env,
|
||||
alice,
|
||||
{{.account = bob, .payAmount = 100, .convertAmount = 100}, {carol, 50, 50}}};
|
||||
{{.account = bob, .payAmount = 100, .convertAmount = 100},
|
||||
{.account = carol, .payAmount = 50, .convertAmount = 50}}};
|
||||
auto& mptAlice = confEnv.mpt;
|
||||
|
||||
// Bob sends 10 to carol. The send amount (10) and Bob's remaining balance
|
||||
@@ -6205,7 +6208,8 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
ConfidentialEnv confEnv{
|
||||
env,
|
||||
alice,
|
||||
{{.account = bob, .payAmount = 100, .convertAmount = 60}, {carol, 50, 30}}};
|
||||
{{.account = bob, .payAmount = 100, .convertAmount = 60},
|
||||
{.account = carol, .payAmount = 50, .convertAmount = 30}}};
|
||||
auto& mptAlice = confEnv.mpt;
|
||||
|
||||
// sender's encrypted amount has an invalid coordinate
|
||||
@@ -6284,7 +6288,8 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
ConfidentialEnv confEnv{
|
||||
env,
|
||||
alice,
|
||||
{{.account = bob, .payAmount = 100, .convertAmount = 60}, {carol, 50, 30}}};
|
||||
{{.account = bob, .payAmount = 100, .convertAmount = 60},
|
||||
{.account = carol, .payAmount = 50, .convertAmount = 30}}};
|
||||
auto& mptAlice = confEnv.mpt;
|
||||
|
||||
Buffer badProof(kEC_SEND_PROOF_LENGTH);
|
||||
@@ -6310,7 +6315,8 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
ConfidentialEnv confEnv{
|
||||
env,
|
||||
alice,
|
||||
{{.account = bob, .payAmount = 100, .convertAmount = 60}, {carol, 50, 30}}};
|
||||
{{.account = bob, .payAmount = 100, .convertAmount = 60},
|
||||
{.account = carol, .payAmount = 50, .convertAmount = 30}}};
|
||||
auto& mptAlice = confEnv.mpt;
|
||||
|
||||
// getTrivialCiphertext() has both C1 and C2 as valid (but trivial)
|
||||
@@ -6402,7 +6408,10 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
Env env{*this, features};
|
||||
Account const alice("alice"), bob("bob"), carol("carol");
|
||||
ConfidentialEnv confEnv{
|
||||
env, alice, {{.account = bob, .payAmount = 100, .convertAmount = 60}, {carol, 50, 30}}};
|
||||
env,
|
||||
alice,
|
||||
{{.account = bob, .payAmount = 100, .convertAmount = 60},
|
||||
{.account = carol, .payAmount = 50, .convertAmount = 30}}};
|
||||
auto& mptAlice = confEnv.mpt;
|
||||
|
||||
// The x-coordinate of the NIST P-256 generator point — a real,
|
||||
@@ -6586,7 +6595,8 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
ConfidentialEnv confEnv{
|
||||
env,
|
||||
alice,
|
||||
{{.account = bob, .payAmount = 100, .convertAmount = 100}, {carol, 50, 50}}};
|
||||
{{.account = bob, .payAmount = 100, .convertAmount = 100},
|
||||
{.account = carol, .payAmount = 50, .convertAmount = 50}}};
|
||||
auto& mptAlice = confEnv.mpt;
|
||||
|
||||
auto const bobSpendingBefore =
|
||||
@@ -6733,6 +6743,125 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
submitWithDivergentC1(Participant::Auditor);
|
||||
}
|
||||
|
||||
void
|
||||
testConfidentialMPTBaseFee(FeatureBitset features)
|
||||
{
|
||||
testcase("test confidential transactions fee");
|
||||
using namespace test::jtx;
|
||||
|
||||
auto setup =
|
||||
[&](MPTTester& mpt, Account const& alice, Account const& bob, Account const& carol) {
|
||||
mpt.create({
|
||||
.ownerCount = 1,
|
||||
.flags = tfMPTCanLock | tfMPTCanConfidentialAmount | tfMPTCanTransfer |
|
||||
tfMPTCanClawback,
|
||||
});
|
||||
mpt.authorize({.account = bob});
|
||||
mpt.authorize({.account = carol});
|
||||
mpt.pay(alice, bob, 100);
|
||||
mpt.pay(alice, carol, 50);
|
||||
mpt.generateKeyPair(alice);
|
||||
mpt.generateKeyPair(bob);
|
||||
mpt.generateKeyPair(carol);
|
||||
mpt.set({.account = alice, .issuerPubKey = mpt.getPubKey(alice)});
|
||||
};
|
||||
|
||||
// test expected base fee for confidential transactions
|
||||
{
|
||||
Env env{*this, features};
|
||||
Account const alice("alice"), bob("bob"), carol("carol");
|
||||
MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
|
||||
setup(mptAlice, alice, bob, carol);
|
||||
|
||||
auto const baseFee = env.current()->fees().base;
|
||||
auto const expectedFee = baseFee * 10;
|
||||
|
||||
// lambda function to submit confidential transaction and check fee charged to the
|
||||
// account
|
||||
auto checkFee = [&](Account const& acct, auto&& submitFn) {
|
||||
auto const before = env.balance(acct);
|
||||
submitFn();
|
||||
auto const after = env.balance(acct);
|
||||
BEAST_EXPECT(before - after == expectedFee);
|
||||
};
|
||||
|
||||
checkFee(bob, [&]() {
|
||||
mptAlice.convert(
|
||||
{.account = bob,
|
||||
.amt = 50,
|
||||
.holderPubKey = mptAlice.getPubKey(bob),
|
||||
.fee = expectedFee});
|
||||
});
|
||||
checkFee(carol, [&]() {
|
||||
mptAlice.convert(
|
||||
{.account = carol,
|
||||
.amt = 10,
|
||||
.holderPubKey = mptAlice.getPubKey(carol),
|
||||
.fee = expectedFee});
|
||||
});
|
||||
checkFee(bob, [&]() { mptAlice.mergeInbox({.account = bob, .fee = expectedFee}); });
|
||||
checkFee(carol, [&]() { mptAlice.mergeInbox({.account = carol, .fee = expectedFee}); });
|
||||
checkFee(bob, [&]() {
|
||||
mptAlice.send({.account = bob, .dest = carol, .amt = 5, .fee = expectedFee});
|
||||
});
|
||||
checkFee(bob, [&]() {
|
||||
mptAlice.convertBack({.account = bob, .amt = 5, .fee = expectedFee});
|
||||
});
|
||||
checkFee(alice, [&]() {
|
||||
mptAlice.confidentialClaw(
|
||||
{.account = alice, .holder = carol, .amt = 15, .fee = expectedFee});
|
||||
});
|
||||
}
|
||||
|
||||
// test insufficient fee for confidential transactions
|
||||
{
|
||||
Env env{*this, features};
|
||||
Account const alice("alice"), bob("bob"), carol("carol");
|
||||
MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
|
||||
setup(mptAlice, alice, bob, carol);
|
||||
auto const baseFee = env.current()->fees().base;
|
||||
|
||||
mptAlice.convert(
|
||||
{.account = bob,
|
||||
.amt = 1,
|
||||
.holderPubKey = mptAlice.getPubKey(bob),
|
||||
.fee = baseFee * 10 - 1,
|
||||
.err = telINSUF_FEE_P});
|
||||
mptAlice.mergeInbox({.account = bob, .fee = baseFee, .err = telINSUF_FEE_P});
|
||||
mptAlice.send(
|
||||
{.account = bob,
|
||||
.dest = carol,
|
||||
.amt = 1,
|
||||
.fee = baseFee * 9,
|
||||
.err = telINSUF_FEE_P});
|
||||
mptAlice.convertBack({.account = bob, .amt = 1, .fee = baseFee, .err = telINSUF_FEE_P});
|
||||
mptAlice.confidentialClaw(
|
||||
{.account = alice,
|
||||
.holder = carol,
|
||||
.amt = 1,
|
||||
.fee = baseFee,
|
||||
.err = telINSUF_FEE_P});
|
||||
}
|
||||
|
||||
// test excessive fee for confidential transactions
|
||||
{
|
||||
Env env{*this, features};
|
||||
Account const alice("alice"), bob("bob"), carol("carol");
|
||||
MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
|
||||
setup(mptAlice, alice, bob, carol);
|
||||
|
||||
auto const baseFee = env.current()->fees().base;
|
||||
auto const highFee = baseFee * 20;
|
||||
auto const bobBefore = env.balance(bob);
|
||||
mptAlice.convert(
|
||||
{.account = bob,
|
||||
.amt = 1,
|
||||
.holderPubKey = mptAlice.getPubKey(bob),
|
||||
.fee = highFee});
|
||||
BEAST_EXPECT(env.balance(bob) == bobBefore - highFee);
|
||||
}
|
||||
}
|
||||
|
||||
// Exercises every Confidential Transfer transaction type (MPTokenIssuanceSet,
|
||||
// Convert, MergeInbox, Send, ConvertBack) using tickets instead of regular account
|
||||
// sequence numbers.
|
||||
@@ -7082,7 +7211,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const carolSeq = env.seq(carol);
|
||||
// 3 signers, Bob, Carol, Dave
|
||||
auto const batchFee = batch::calcBatchFee(env, 1, 3);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 1, 3);
|
||||
|
||||
auto const jv1 = mpt.sendJV({.account = bob, .dest = carol, .amt = 100}, bobSeq + 1);
|
||||
auto const jv2 = mpt.mergeInboxJV({.account = carol});
|
||||
@@ -7119,7 +7248,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
// tfAllOrNothing — rejects the whole batch as 2nd txn proof is incorrect
|
||||
{
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const batchFee = batch::calcBatchFee(env, 0, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 0, 2);
|
||||
|
||||
auto const jv1 = mpt.sendJV({.account = bob, .dest = carol, .amt = 50}, bobSeq + 1);
|
||||
auto const jv2 = mpt.sendJV({.account = bob, .dest = dave, .amt = 60}, bobSeq + 2);
|
||||
@@ -7140,7 +7269,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
// If we change batch mode to be tfIndependent — txn 1 applies, inner 2 fails.
|
||||
{
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const batchFee = batch::calcBatchFee(env, 0, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 0, 2);
|
||||
|
||||
auto const jv1 = mpt.sendJV({.account = bob, .dest = carol, .amt = 50}, bobSeq + 1);
|
||||
auto const jv2 = mpt.sendJV({.account = bob, .dest = dave, .amt = 60}, bobSeq + 2);
|
||||
@@ -7176,7 +7305,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
|
||||
{
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const batchFee = batch::calcBatchFee(env, 0, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 0, 2);
|
||||
|
||||
// jv1 is built against the current ledger state (spending=200).
|
||||
auto const jv1 =
|
||||
@@ -7215,7 +7344,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
setupBatchEnv(mpt2, alice2, bob2, carol2, dave2, 150, 0);
|
||||
|
||||
auto const bobSeq = env2.seq(bob2);
|
||||
auto const batchFee = batch::calcBatchFee(env2, 0, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env2, 0, 2);
|
||||
|
||||
auto const jv1 =
|
||||
mpt2.sendJV({.account = bob2, .dest = carol2, .amt = 100}, bobSeq + 1);
|
||||
@@ -7261,7 +7390,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
{
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const carolSeq = env.seq(carol);
|
||||
auto const batchFee = batch::calcBatchFee(env, 1, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 1, 2);
|
||||
|
||||
auto const jv1 = mpt.sendJV({.account = bob, .dest = dave, .amt = 10}, bobSeq + 1);
|
||||
auto const jv2 = mpt.sendJV({.account = carol, .dest = dave, .amt = 5}, carolSeq);
|
||||
@@ -7300,7 +7429,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
{
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const carolSeq = env.seq(carol);
|
||||
auto const batchFee = batch::calcBatchFee(env, 1, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 1, 2);
|
||||
|
||||
// Both proofs fail range check (amount > balance)
|
||||
auto const jv1 = mpt.sendJV({.account = bob, .dest = dave, .amt = 200}, bobSeq + 1);
|
||||
@@ -7323,7 +7452,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
{
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const carolSeq = env.seq(carol);
|
||||
auto const batchFee = batch::calcBatchFee(env, 1, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 1, 2);
|
||||
|
||||
auto jv1 = mpt.sendJV({.account = bob, .dest = dave, .amt = 200}, bobSeq + 1);
|
||||
auto jv2 = mpt.sendJV({.account = carol, .dest = dave, .amt = 5}, carolSeq);
|
||||
@@ -7363,7 +7492,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
{
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const carolSeq = env.seq(carol);
|
||||
auto const batchFee = batch::calcBatchFee(env, 1, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 1, 2);
|
||||
|
||||
auto const jv1 = mpt.sendJV({.account = bob, .dest = dave, .amt = 200}, bobSeq + 1);
|
||||
auto const jv2 = mpt.sendJV({.account = carol, .dest = dave, .amt = 5}, carolSeq);
|
||||
@@ -7383,7 +7512,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
{
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const carolSeq = env.seq(carol);
|
||||
auto const batchFee = batch::calcBatchFee(env, 1, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 1, 2);
|
||||
|
||||
auto const jv1 = mpt.sendJV({.account = bob, .dest = dave, .amt = 10}, bobSeq + 1);
|
||||
auto const jv2 = mpt.sendJV({.account = carol, .dest = dave, .amt = 5}, carolSeq);
|
||||
@@ -7424,7 +7553,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
{
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const carolSeq = env.seq(carol);
|
||||
auto const batchFee = batch::calcBatchFee(env, 1, 3);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 1, 3);
|
||||
|
||||
auto const jv1 = mpt.sendJV({.account = bob, .dest = dave, .amt = 10}, bobSeq + 1);
|
||||
|
||||
@@ -7482,7 +7611,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
mpt.pay(alice, bob, 50);
|
||||
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const batchFee = batch::calcBatchFee(env, 0, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 0, 2);
|
||||
|
||||
// jv1: convert 50 regular MPT into confidential inbox
|
||||
auto const jv1 = mpt.convertJV({.account = bob, .amt = 50}, bobSeq + 1);
|
||||
@@ -7523,7 +7652,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
mpt.pay(alice, bob, 50);
|
||||
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const batchFee = batch::calcBatchFee(env, 0, 3);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 0, 3);
|
||||
|
||||
auto const jv1 = mpt.convertJV({.account = bob, .amt = 50}, bobSeq + 1);
|
||||
auto const jv2 = mpt.mergeInboxJV({.account = bob});
|
||||
@@ -7586,7 +7715,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
auto const carolSeq = env.seq(carol);
|
||||
auto const daveSeq = env.seq(dave);
|
||||
// 2 extra signers (carol, dave), 4 inner txns
|
||||
auto const batchFee = batch::calcBatchFee(env, 2, 4);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 2, 4);
|
||||
|
||||
// jv1: bob sends 30 to carol
|
||||
auto const jv1 = mpt.sendJV({.account = bob, .dest = carol, .amt = 30}, bobSeq + 1);
|
||||
@@ -7633,7 +7762,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
setupBatchEnv(mpt, alice, bob, carol, dave, 100, 0);
|
||||
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const batchFee = batch::calcBatchFee(env, 0, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 0, 2);
|
||||
|
||||
// jv1: bob sends 30 to carol (spending 100->70, version V->V+1)
|
||||
auto const jv1 = mpt.sendJV({.account = bob, .dest = carol, .amt = 30}, bobSeq + 1);
|
||||
@@ -7679,7 +7808,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
|
||||
auto const bobSeq = env.seq(bob);
|
||||
// 0 extra signers: all inner txns are from bob;
|
||||
auto const batchFee = batch::calcBatchFee(env, 0, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 0, 2);
|
||||
|
||||
// When the outer uses a ticket (seq=0), inner txns start from bobSeq, bobSeq+1.
|
||||
// jv2 must use chain state predicted after jv1 since both sends are from bob.
|
||||
@@ -7721,7 +7850,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
env.close();
|
||||
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const batchFee = batch::calcBatchFee(env, 0, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 0, 2);
|
||||
|
||||
// jv1: proof bound to ticketSeq1.
|
||||
auto const jv1 = mpt.sendJV({.account = bob, .dest = carol, .amt = 40}, ticketSeq1);
|
||||
@@ -7758,7 +7887,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
env.close();
|
||||
|
||||
auto const bobSeq = env.seq(bob);
|
||||
auto const batchFee = batch::calcBatchFee(env, 0, 2);
|
||||
auto const batchFee = batch::calcConfidentialBatchFee(env, 0, 2);
|
||||
|
||||
// Proof intentionally built with account seq (bobSeq+1) instead of ticketSeq.
|
||||
auto const badJV = mpt.sendJV({.account = bob, .dest = carol, .amt = 40}, bobSeq + 1);
|
||||
@@ -8501,7 +8630,8 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
ConfidentialEnv confEnv{
|
||||
env,
|
||||
alice,
|
||||
{{.account = bob, .payAmount = 1000, .convertAmount = 10}, {carol, 1000, 50}}};
|
||||
{{.account = bob, .payAmount = 1000, .convertAmount = 10},
|
||||
{.account = carol, .payAmount = 1000, .convertAmount = 50}}};
|
||||
auto& mptAlice = confEnv.mpt;
|
||||
|
||||
uint64_t const sendAmount = 10;
|
||||
@@ -8683,7 +8813,7 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
alice,
|
||||
{{.account = bob},
|
||||
{.account = carol, .payAmount = 1000, .convertAmount = 50},
|
||||
{dan, 1000, 50}}};
|
||||
{.account = dan, .payAmount = 1000, .convertAmount = 50}}};
|
||||
auto& mptAlice = confEnv.mpt;
|
||||
|
||||
uint64_t const sendAmount = 10;
|
||||
@@ -9768,6 +9898,9 @@ class ConfidentialTransfer_test : public beast::unit_test::Suite
|
||||
// Crafted-proof Tests
|
||||
testSendSharedRandomnessViolation(features);
|
||||
|
||||
// Fee Tests
|
||||
testConfidentialMPTBaseFee(features);
|
||||
|
||||
// Ticket Tests
|
||||
testWithTickets(features);
|
||||
testConvertTicketProofBinding(features);
|
||||
|
||||
@@ -21,6 +21,10 @@ namespace xrpl::test::jtx::batch {
|
||||
XRPAmount
|
||||
calcBatchFee(jtx::Env const& env, uint32_t const& numSigners, uint32_t const& txns = 0);
|
||||
|
||||
/** Calculate Batch Fee with Confidential MPT inner transactions. */
|
||||
XRPAmount
|
||||
calcConfidentialBatchFee(jtx::Env const& env, uint32_t const& numSigners, uint32_t const& txns = 0);
|
||||
|
||||
/** Batch. */
|
||||
json::Value
|
||||
outer(jtx::Account const& account, uint32_t seq, STAmount const& fee, std::uint32_t flags);
|
||||
|
||||
@@ -37,6 +37,16 @@ calcBatchFee(test::jtx::Env const& env, uint32_t const& numSigners, uint32_t con
|
||||
return ((numSigners + 2) * feeDrops) + feeDrops * txns;
|
||||
}
|
||||
|
||||
XRPAmount
|
||||
calcConfidentialBatchFee(
|
||||
test::jtx::Env const& env,
|
||||
uint32_t const& numSigners,
|
||||
uint32_t const& txns)
|
||||
{
|
||||
XRPAmount const feeDrops = env.current()->fees().base;
|
||||
return ((numSigners + 2) * feeDrops) + feeDrops * 10 * txns;
|
||||
}
|
||||
|
||||
// Batch.
|
||||
json::Value
|
||||
outer(jtx::Account const& account, uint32_t seq, STAmount const& fee, std::uint32_t flags)
|
||||
|
||||
@@ -57,7 +57,22 @@ fillFee(json::Value& jv, ReadView const& view)
|
||||
{
|
||||
if (jv.isMember(jss::Fee))
|
||||
return;
|
||||
jv[jss::Fee] = to_string(view.fees().base);
|
||||
|
||||
auto const base = view.fees().base;
|
||||
|
||||
// For confidential transactions, the fee higher because confidential
|
||||
// transaction processing is more expensive.
|
||||
auto const txType = jv[jss::TransactionType].asString();
|
||||
if (txType == jss::ConfidentialMPTConvert || txType == jss::ConfidentialMPTConvertBack ||
|
||||
txType == jss::ConfidentialMPTSend || txType == jss::ConfidentialMPTMergeInbox ||
|
||||
txType == jss::ConfidentialMPTClawback)
|
||||
{
|
||||
jv[jss::Fee] = to_string(base * 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
jv[jss::Fee] = to_string(base);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <xrpl/protocol/ConfidentialTransfer.h>
|
||||
#include <xrpl/protocol/TxFlags.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@@ -208,6 +209,7 @@ struct MPTConvert
|
||||
std::optional<std::uint32_t> ownerCount = std::nullopt;
|
||||
std::optional<std::uint32_t> holderCount = std::nullopt;
|
||||
std::optional<std::uint32_t> flags = std::nullopt;
|
||||
std::optional<XRPAmount> fee = std::nullopt;
|
||||
std::optional<TER> err = std::nullopt;
|
||||
};
|
||||
|
||||
@@ -220,6 +222,7 @@ struct MPTMergeInbox
|
||||
std::optional<std::uint32_t> ownerCount = std::nullopt;
|
||||
std::optional<std::uint32_t> holderCount = std::nullopt;
|
||||
std::optional<std::uint32_t> flags = std::nullopt;
|
||||
std::optional<XRPAmount> fee = std::nullopt;
|
||||
std::optional<TER> err = std::nullopt;
|
||||
};
|
||||
|
||||
@@ -247,6 +250,7 @@ struct MPTConfidentialSend
|
||||
std::optional<std::uint32_t> ownerCount = std::nullopt;
|
||||
std::optional<std::uint32_t> holderCount = std::nullopt;
|
||||
std::optional<std::uint32_t> flags = std::nullopt;
|
||||
std::optional<XRPAmount> fee = std::nullopt;
|
||||
std::optional<TER> err = std::nullopt;
|
||||
};
|
||||
|
||||
@@ -268,6 +272,7 @@ struct MPTConvertBack
|
||||
std::optional<std::uint32_t> ownerCount = std::nullopt;
|
||||
std::optional<std::uint32_t> holderCount = std::nullopt;
|
||||
std::optional<std::uint32_t> flags = std::nullopt;
|
||||
std::optional<XRPAmount> fee = std::nullopt;
|
||||
std::optional<TER> err = std::nullopt;
|
||||
};
|
||||
|
||||
@@ -283,6 +288,7 @@ struct MPTConfidentialClawback
|
||||
std::optional<std::uint32_t> ownerCount = std::nullopt;
|
||||
std::optional<std::uint32_t> holderCount = std::nullopt;
|
||||
std::optional<std::uint32_t> flags = std::nullopt;
|
||||
std::optional<XRPAmount> fee = std::nullopt;
|
||||
std::optional<TER> err = std::nullopt;
|
||||
};
|
||||
|
||||
@@ -599,11 +605,17 @@ private:
|
||||
|
||||
template <typename A>
|
||||
TER
|
||||
submit(A const& arg, json::Value const& jv)
|
||||
submit(A const& arg, json::Value jv)
|
||||
{
|
||||
auto const expectedFlags = Txflags(arg.flags.value_or(0));
|
||||
auto const expectedTer = Ter(arg.err.value_or(tesSUCCESS));
|
||||
|
||||
if constexpr (requires { arg.fee; })
|
||||
{
|
||||
if (arg.fee)
|
||||
jv[jss::Fee] = to_string(*arg.fee);
|
||||
}
|
||||
|
||||
std::optional<std::uint32_t> ticketSeq;
|
||||
if constexpr (requires { arg.ticketSeq; })
|
||||
ticketSeq = arg.ticketSeq;
|
||||
|
||||
Reference in New Issue
Block a user