mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Increased fees for multisigned transactions (RIPD-182):
Multisigned transactions place a higher load on the network than non-multisigned transactions, requiring a higher fee. - A non-multisigned transaction always has a minimum fee - the network base fee. - A multisigned transaction has a minimum fee equal to the number of multisigners plus one times the network base fee.
This commit is contained in:
committed by
Nik Bougalis
parent
aeebfeab10
commit
b8e192e058
@@ -142,38 +142,41 @@ public:
|
|||||||
env.require (owners (alice, 4));
|
env.require (owners (alice, 4));
|
||||||
|
|
||||||
// This should work.
|
// This should work.
|
||||||
|
auto const baseFee = env.config.FEE_DEFAULT;
|
||||||
std::uint32_t aliceSeq = env.seq (alice);
|
std::uint32_t aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(bogie, demon));
|
env(noop(alice), msig(bogie, demon), fee(3 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
// Either signer alone should work.
|
// Either signer alone should work.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(bogie));
|
env(noop(alice), msig(bogie), fee(2 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(demon));
|
env(noop(alice), msig(demon), fee(2 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
// Duplicate signers should fail.
|
// Duplicate signers should fail.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(demon, demon), ter(temINVALID));
|
env(noop(alice), msig(demon, demon), fee(3 * baseFee), ter(temINVALID));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq);
|
expect (env.seq(alice) == aliceSeq);
|
||||||
|
|
||||||
// A non-signer should fail.
|
// A non-signer should fail.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(bogie, spook), ter(tefBAD_SIGNATURE));
|
env(noop(alice),
|
||||||
|
msig(bogie, spook), fee(3 * baseFee), ter(tefBAD_SIGNATURE));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq);
|
expect (env.seq(alice) == aliceSeq);
|
||||||
|
|
||||||
// Multisign, but leave a nonempty sfSigners. Should fail.
|
// Multisign, but leave a nonempty sfSigners. Should fail.
|
||||||
{
|
{
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
Json::Value multiSig = env.json (noop (alice), msig(bogie));
|
Json::Value multiSig =
|
||||||
|
env.json (noop (alice), msig(bogie), fee(2 * baseFee));
|
||||||
|
|
||||||
env (env.jt (multiSig), ter (temINVALID));
|
env (env.jt (multiSig), ter (temINVALID));
|
||||||
env.close();
|
env.close();
|
||||||
@@ -183,17 +186,101 @@ public:
|
|||||||
// Don't meet the quorum. Should fail.
|
// Don't meet the quorum. Should fail.
|
||||||
env(signers(alice, 2, {{bogie, 1}, {demon, 1}}));
|
env(signers(alice, 2, {{bogie, 1}, {demon, 1}}));
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(bogie), ter(tefBAD_QUORUM));
|
env(noop(alice), msig(bogie), fee(2 * baseFee), ter(tefBAD_QUORUM));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq);
|
expect (env.seq(alice) == aliceSeq);
|
||||||
|
|
||||||
// Meet the quorum. Should succeed.
|
// Meet the quorum. Should succeed.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(bogie, demon));
|
env(noop(alice), msig(bogie, demon), fee(3 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_enablement()
|
||||||
|
{
|
||||||
|
using namespace jtx;
|
||||||
|
Env env(*this);
|
||||||
|
Account const alice {"alice", KeyType::ed25519};
|
||||||
|
env.fund(XRP(1000), alice);
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
// Add a signer list to alice. Should succeed.
|
||||||
|
env(signers(alice, 1, {{bogie, 1}}));
|
||||||
|
env.close();
|
||||||
|
env.require (owners (alice, 3));
|
||||||
|
|
||||||
|
// alice multisigns a transaction. Should succeed.
|
||||||
|
std::uint32_t aliceSeq = env.seq (alice);
|
||||||
|
auto const baseFee = env.config.FEE_DEFAULT;
|
||||||
|
env(noop(alice), msig(bogie), fee(2 * baseFee));
|
||||||
|
env.close();
|
||||||
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
|
// Make sure multisign is disabled in production.
|
||||||
|
// NOTE: THESE FOUR TESTS FAIL IF RIPPLE_ENABLE_MULTI_SIGN != 0
|
||||||
|
env.disable_testing();
|
||||||
|
aliceSeq = env.seq (alice);
|
||||||
|
env(noop(alice), msig(bogie), fee(2 * baseFee), ter(temINVALID));
|
||||||
|
env.close();
|
||||||
|
expect (env.seq(alice) == aliceSeq);
|
||||||
|
|
||||||
|
env(signers(alice, 1, {{bogie, 1}, {demon,1}}), ter(temDISABLED));
|
||||||
|
env.close();
|
||||||
|
expect (env.seq(alice) == aliceSeq);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_fee ()
|
||||||
|
{
|
||||||
|
using namespace jtx;
|
||||||
|
Env env(*this);
|
||||||
|
Account const alice {"alice", KeyType::ed25519};
|
||||||
|
env.fund(XRP(1000), alice);
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
// Attach maximum possible number of signers to alice.
|
||||||
|
env(signers(alice, 1, {{bogie, 1}, {demon, 1}, {ghost, 1}, {haunt, 1},
|
||||||
|
{jinni, 1}, {phase, 1}, {shade, 1}, {spook, 1}}));
|
||||||
|
env.close();
|
||||||
|
env.require (owners (alice, 10));
|
||||||
|
|
||||||
|
// This should work.
|
||||||
|
auto const baseFee = env.config.FEE_DEFAULT;
|
||||||
|
std::uint32_t aliceSeq = env.seq (alice);
|
||||||
|
env(noop(alice), msig(bogie), fee(2 * baseFee));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
|
// This should fail because the fee is too small.
|
||||||
|
aliceSeq = env.seq (alice);
|
||||||
|
env(noop(alice),
|
||||||
|
msig(bogie), fee((2 * baseFee) - 1), ter(telINSUF_FEE_P));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
expect (env.seq(alice) == aliceSeq);
|
||||||
|
|
||||||
|
// This should work.
|
||||||
|
aliceSeq = env.seq (alice);
|
||||||
|
env(noop(alice),
|
||||||
|
msig(bogie, demon, ghost, haunt, jinni, phase, shade, spook),
|
||||||
|
fee(9 * baseFee));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
|
// This should fail because the fee is too small.
|
||||||
|
aliceSeq = env.seq (alice);
|
||||||
|
env(noop(alice),
|
||||||
|
msig(bogie, demon, ghost, haunt, jinni, phase, shade, spook),
|
||||||
|
fee((9 * baseFee) - 1),
|
||||||
|
ter(telINSUF_FEE_P));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
expect (env.seq(alice) == aliceSeq);
|
||||||
|
}
|
||||||
|
|
||||||
void test_misorderedSigners()
|
void test_misorderedSigners()
|
||||||
{
|
{
|
||||||
using namespace jtx;
|
using namespace jtx;
|
||||||
@@ -242,14 +329,15 @@ public:
|
|||||||
env.require (owners (alice, 4));
|
env.require (owners (alice, 4));
|
||||||
|
|
||||||
// Attempt a multisigned transaction that meets the quorum.
|
// Attempt a multisigned transaction that meets the quorum.
|
||||||
|
auto const baseFee = env.config.FEE_DEFAULT;
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(cheri));
|
env(noop(alice), msig(cheri), fee(2 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
// If we don't meet the quorum the transaction should fail.
|
// If we don't meet the quorum the transaction should fail.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(becky), ter(tefBAD_QUORUM));
|
env(noop(alice), msig(becky), fee(2 * baseFee), ter(tefBAD_QUORUM));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq);
|
expect (env.seq(alice) == aliceSeq);
|
||||||
|
|
||||||
@@ -262,7 +350,7 @@ public:
|
|||||||
|
|
||||||
// becky's and cheri's master keys should still work.
|
// becky's and cheri's master keys should still work.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(becky, cheri));
|
env(noop(alice), msig(becky, cheri), fee(3 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
}
|
}
|
||||||
@@ -294,31 +382,32 @@ public:
|
|||||||
env.close();
|
env.close();
|
||||||
|
|
||||||
// Attempt a multisigned transaction that meets the quorum.
|
// Attempt a multisigned transaction that meets the quorum.
|
||||||
|
auto const baseFee = env.config.FEE_DEFAULT;
|
||||||
std::uint32_t aliceSeq = env.seq (alice);
|
std::uint32_t aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(msig::Reg{cheri, cher}));
|
env(noop(alice), msig(msig::Reg{cheri, cher}), fee(2 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
// cheri should not be able to multisign using her master key.
|
// cheri should not be able to multisign using her master key.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(cheri), ter(tefMASTER_DISABLED));
|
env(noop(alice), msig(cheri), fee(2 * baseFee), ter(tefMASTER_DISABLED));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq);
|
expect (env.seq(alice) == aliceSeq);
|
||||||
|
|
||||||
// becky should be able to multisign using either of her keys.
|
// becky should be able to multisign using either of her keys.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(becky));
|
env(noop(alice), msig(becky), fee(2 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(msig::Reg{becky, beck}));
|
env(noop(alice), msig(msig::Reg{becky, beck}), fee(2 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
// Both becky and cheri should be able to sign using regular keys.
|
// Both becky and cheri should be able to sign using regular keys.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice),
|
env(noop(alice), fee(3 * baseFee),
|
||||||
msig(msig::Reg{becky, beck}, msig::Reg{cheri, cher}));
|
msig(msig::Reg{becky, beck}, msig::Reg{cheri, cher}));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
@@ -360,34 +449,35 @@ public:
|
|||||||
env.require (owners (alice, 6));
|
env.require (owners (alice, 6));
|
||||||
|
|
||||||
// Each type of signer should succeed individually.
|
// Each type of signer should succeed individually.
|
||||||
|
auto const baseFee = env.config.FEE_DEFAULT;
|
||||||
std::uint32_t aliceSeq = env.seq (alice);
|
std::uint32_t aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(becky));
|
env(noop(alice), msig(becky), fee(2 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(cheri));
|
env(noop(alice), msig(cheri), fee(2 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(msig::Reg{cheri, cher}));
|
env(noop(alice), msig(msig::Reg{cheri, cher}), fee(2 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(msig::Reg{daria, dari}));
|
env(noop(alice), msig(msig::Reg{daria, dari}), fee(2 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(jinni));
|
env(noop(alice), msig(jinni), fee(2 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
// Should also work if all signers sign.
|
// Should also work if all signers sign.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice),
|
env(noop(alice), fee(5 * baseFee),
|
||||||
msig(becky, msig::Reg{cheri, cher}, msig::Reg{daria, dari}, jinni));
|
msig(becky, msig::Reg{cheri, cher}, msig::Reg{daria, dari}, jinni));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
@@ -399,14 +489,15 @@ public:
|
|||||||
env.require (owners (alice, 6));
|
env.require (owners (alice, 6));
|
||||||
|
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice),
|
env(noop(alice), fee(9 * baseFee),
|
||||||
msig(becky, msig::Reg{cheri, cher}, msig::Reg{daria, dari}, jinni));
|
msig(becky, msig::Reg{cheri, cher}, msig::Reg{daria, dari}, jinni));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
// Try cheri with both key types.
|
// Try cheri with both key types.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(becky, cheri, msig::Reg{daria, dari}, jinni));
|
env(noop(alice), fee(5 * baseFee),
|
||||||
|
msig(becky, cheri, msig::Reg{daria, dari}, jinni));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
@@ -418,7 +509,7 @@ public:
|
|||||||
env.require (owners (alice, 10));
|
env.require (owners (alice, 10));
|
||||||
|
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(becky, msig::Reg{cheri, cher},
|
env(noop(alice), fee(9 * baseFee), msig(becky, msig::Reg{cheri, cher},
|
||||||
msig::Reg{daria, dari}, haunt, jinni, phase, shade, spook));
|
msig::Reg{daria, dari}, haunt, jinni, phase, shade, spook));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
@@ -426,7 +517,7 @@ public:
|
|||||||
// One signer short should fail.
|
// One signer short should fail.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(becky, cheri, haunt, jinni, phase, shade, spook),
|
env(noop(alice), msig(becky, cheri, haunt, jinni, phase, shade, spook),
|
||||||
ter (tefBAD_QUORUM));
|
fee(8 * baseFee), ter (tefBAD_QUORUM));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq);
|
expect (env.seq(alice) == aliceSeq);
|
||||||
|
|
||||||
@@ -460,27 +551,29 @@ public:
|
|||||||
env.require (owners (alice, 4));
|
env.require (owners (alice, 4));
|
||||||
|
|
||||||
// Multisign a ttPAYMENT.
|
// Multisign a ttPAYMENT.
|
||||||
|
auto const baseFee = env.config.FEE_DEFAULT;
|
||||||
std::uint32_t aliceSeq = env.seq (alice);
|
std::uint32_t aliceSeq = env.seq (alice);
|
||||||
env(pay(alice, env.master, XRP(1)), msig(becky, bogie));
|
env(pay(alice, env.master, XRP(1)),
|
||||||
|
msig(becky, bogie), fee(3 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
// Multisign a ttACCOUNT_SET.
|
// Multisign a ttACCOUNT_SET.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
env(noop(alice), msig(becky, bogie));
|
env(noop(alice), msig(becky, bogie), fee(3 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
// Multisign a ttREGULAR_KEY_SET.
|
// Multisign a ttREGULAR_KEY_SET.
|
||||||
aliceSeq = env.seq (alice);
|
aliceSeq = env.seq (alice);
|
||||||
Account const ace {"ace", KeyType::secp256k1};
|
Account const ace {"ace", KeyType::secp256k1};
|
||||||
env(regkey (alice, ace), msig(becky, bogie));
|
env(regkey (alice, ace), msig(becky, bogie), fee(3 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
|
|
||||||
// Multisign a ttTRUST_SET
|
// Multisign a ttTRUST_SET
|
||||||
env(trust("alice", USD(100)),
|
env(trust("alice", USD(100)),
|
||||||
msig(becky, bogie), require (lines("alice", 1)));
|
msig(becky, bogie), fee(3 * baseFee), require (lines("alice", 1)));
|
||||||
env.close();
|
env.close();
|
||||||
env.require (owners (alice, 5));
|
env.require (owners (alice, 5));
|
||||||
|
|
||||||
@@ -491,7 +584,8 @@ public:
|
|||||||
env.require(balance(gw, alice["USD"](-50)));
|
env.require(balance(gw, alice["USD"](-50)));
|
||||||
|
|
||||||
std::uint32_t const offerSeq = env.seq (alice);
|
std::uint32_t const offerSeq = env.seq (alice);
|
||||||
env(offer(alice, XRP(50), USD(50)), msig (becky, bogie));
|
env(offer(alice, XRP(50), USD(50)),
|
||||||
|
msig (becky, bogie), fee(3 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
env.require(owners(alice, 6));
|
env.require(owners(alice, 6));
|
||||||
|
|
||||||
@@ -502,7 +596,8 @@ public:
|
|||||||
cancelOffer[jss::Account] = alice.human();
|
cancelOffer[jss::Account] = alice.human();
|
||||||
cancelOffer[jss::OfferSequence] = offerSeq;
|
cancelOffer[jss::OfferSequence] = offerSeq;
|
||||||
cancelOffer[jss::TransactionType] = "OfferCancel";
|
cancelOffer[jss::TransactionType] = "OfferCancel";
|
||||||
env (cancelOffer, seq (aliceSeq), msig (becky, bogie));
|
env (cancelOffer, seq (aliceSeq),
|
||||||
|
msig (becky, bogie), fee(3 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
expect (env.seq(alice) == aliceSeq + 1);
|
expect (env.seq(alice) == aliceSeq + 1);
|
||||||
env.require(owners(alice, 5));
|
env.require(owners(alice, 5));
|
||||||
@@ -510,7 +605,7 @@ public:
|
|||||||
|
|
||||||
// Multisign a ttSIGNER_LIST_SET.
|
// Multisign a ttSIGNER_LIST_SET.
|
||||||
env(signers(alice, 3, {{becky, 1}, {bogie, 1}, {demon, 1}}),
|
env(signers(alice, 3, {{becky, 1}, {bogie, 1}, {demon, 1}}),
|
||||||
msig (becky, bogie));
|
msig (becky, bogie), fee(3 * baseFee));
|
||||||
env.close();
|
env.close();
|
||||||
env.require (owners (alice, 6));
|
env.require (owners (alice, 6));
|
||||||
}
|
}
|
||||||
@@ -520,6 +615,8 @@ public:
|
|||||||
test_noReserve();
|
test_noReserve();
|
||||||
test_signerListSet();
|
test_signerListSet();
|
||||||
test_phantomSigners();
|
test_phantomSigners();
|
||||||
|
test_enablement();
|
||||||
|
test_fee();
|
||||||
test_misorderedSigners();
|
test_misorderedSigners();
|
||||||
test_masterSigners();
|
test_masterSigners();
|
||||||
test_regularSigners();
|
test_regularSigners();
|
||||||
|
|||||||
@@ -98,8 +98,20 @@ Transactor::Transactor(
|
|||||||
|
|
||||||
std::uint64_t Transactor::calculateBaseFee ()
|
std::uint64_t Transactor::calculateBaseFee ()
|
||||||
{
|
{
|
||||||
// Returns the fee in fee units
|
// Returns the fee in fee units.
|
||||||
return ctx_.config.TRANSACTION_FEE_BASE;
|
|
||||||
|
// The computation has two parts:
|
||||||
|
// * The base fee, which is the same for most transactions.
|
||||||
|
// * The additional cost of each multisignature on the transaction.
|
||||||
|
std::uint64_t baseFee = view().fees().units;
|
||||||
|
|
||||||
|
// Each signer adds one more baseFee to the minimum required fee
|
||||||
|
// for the transaction.
|
||||||
|
std::uint32_t signerCount = 0;
|
||||||
|
if (tx().isFieldPresent (sfSigners))
|
||||||
|
signerCount = tx().getFieldArray (sfSigners).size();
|
||||||
|
|
||||||
|
return baseFee + (signerCount * baseFee);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER Transactor::payFee ()
|
TER Transactor::payFee ()
|
||||||
@@ -216,9 +228,9 @@ TER Transactor::apply ()
|
|||||||
return terNO_ACCOUNT;
|
return terNO_ACCOUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto const& fees = view().fees();
|
||||||
mFeeDue = STAmount (getApp().getFeeTrack().scaleFeeLoad(
|
mFeeDue = STAmount (getApp().getFeeTrack().scaleFeeLoad(
|
||||||
calculateBaseFee(), view().fees().base,
|
calculateBaseFee(), fees.base, fees.units, view().flags() & tapADMIN));
|
||||||
view().fees().units, view().flags() & tapADMIN));
|
|
||||||
|
|
||||||
if (sle)
|
if (sle)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ protected:
|
|||||||
explicit
|
explicit
|
||||||
Transactor (ApplyContext& ctx);
|
Transactor (ApplyContext& ctx);
|
||||||
|
|
||||||
// Returns the fee, not scaled for load (Should be in fee units. FIXME)
|
// Returns the fee in fee units, not scaled for load.
|
||||||
virtual std::uint64_t calculateBaseFee ();
|
virtual std::uint64_t calculateBaseFee ();
|
||||||
|
|
||||||
virtual void preCompute();
|
virtual void preCompute();
|
||||||
|
|||||||
@@ -360,10 +360,12 @@ public:
|
|||||||
{ { "bob", 1 }, { "carol", 2 } }));
|
{ { "bob", 1 }, { "carol", 2 } }));
|
||||||
env(noop("alice"));
|
env(noop("alice"));
|
||||||
|
|
||||||
env(noop("alice"), msig("bob"));
|
auto const baseFee = env.config.FEE_DEFAULT;
|
||||||
env(noop("alice"), msig("carol"));
|
env(noop("alice"), msig("bob"), fee(2 * baseFee));
|
||||||
env(noop("alice"), msig("bob", "carol"));
|
env(noop("alice"), msig("carol"), fee(2 * baseFee));
|
||||||
env(noop("alice"), msig("bob", "carol", "dilbert"), ter(tefBAD_SIGNATURE));
|
env(noop("alice"), msig("bob", "carol"), fee(3 * baseFee));
|
||||||
|
env(noop("alice"), msig("bob", "carol", "dilbert"),
|
||||||
|
fee(4 * baseFee), ter(tefBAD_SIGNATURE));
|
||||||
|
|
||||||
env(signers("alice", none));
|
env(signers("alice", none));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user