mirror of
				https://github.com/Xahau/xahaud.git
				synced 2025-11-04 10:45:50 +00:00 
			
		
		
		
	fixReduceImport (#398)
Co-authored-by: Denis Angell <dangell@transia.co>
This commit is contained in:
		@@ -889,6 +889,45 @@ Import::preclaim(PreclaimContext const& ctx)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto const& sle = ctx.view.read(keylet::account(ctx.tx[sfAccount]));
 | 
			
		||||
 | 
			
		||||
    auto const tt = stpTrans->getTxnType();
 | 
			
		||||
    if ((tt == ttSIGNER_LIST_SET || tt == ttREGULAR_KEY_SET) &&
 | 
			
		||||
        ctx.view.rules().enabled(fixReduceImport) && sle)
 | 
			
		||||
    {
 | 
			
		||||
        // blackhole check
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            // if master key is not set then it is not blackholed
 | 
			
		||||
            if (!(sle->getFlags() & lsfDisableMaster))
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            // if a regular key is set then it must be acc 0, 1, or 2 otherwise
 | 
			
		||||
            // not blackholed
 | 
			
		||||
            if (sle->isFieldPresent(sfRegularKey))
 | 
			
		||||
            {
 | 
			
		||||
                AccountID rk = sle->getAccountID(sfRegularKey);
 | 
			
		||||
                static const AccountID ACCOUNT_ZERO(0);
 | 
			
		||||
                static const AccountID ACCOUNT_ONE(1);
 | 
			
		||||
                static const AccountID ACCOUNT_TWO(2);
 | 
			
		||||
 | 
			
		||||
                if (rk != ACCOUNT_ZERO && rk != ACCOUNT_ONE &&
 | 
			
		||||
                    rk != ACCOUNT_TWO)
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // if a signer list is set then it's not blackholed
 | 
			
		||||
            auto const signerListKeylet = keylet::signers(ctx.tx[sfAccount]);
 | 
			
		||||
            if (ctx.view.exists(signerListKeylet))
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            // execution to here means it's blackholed
 | 
			
		||||
            JLOG(ctx.j.warn())
 | 
			
		||||
                << "Import: during preclaim target account is blackholed "
 | 
			
		||||
                << ctx.tx[sfAccount] << ", bailing.";
 | 
			
		||||
            return tefIMPORT_BLACKHOLED;
 | 
			
		||||
        } while (0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sle && sle->isFieldPresent(sfImportSequence))
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t sleImportSequence = sle->getFieldU32(sfImportSequence);
 | 
			
		||||
 
 | 
			
		||||
@@ -74,7 +74,7 @@ namespace detail {
 | 
			
		||||
// Feature.cpp. Because it's only used to reserve storage, and determine how
 | 
			
		||||
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
 | 
			
		||||
// the actual number of amendments. A LogicError on startup will verify this.
 | 
			
		||||
static constexpr std::size_t numFeatures = 74;
 | 
			
		||||
static constexpr std::size_t numFeatures = 75;
 | 
			
		||||
 | 
			
		||||
/** Amendments that this server supports and the default voting behavior.
 | 
			
		||||
   Whether they are enabled depends on the Rules defined in the validated
 | 
			
		||||
@@ -362,6 +362,7 @@ extern uint256 const fix240819;
 | 
			
		||||
extern uint256 const fixPageCap;
 | 
			
		||||
extern uint256 const fix240911;
 | 
			
		||||
extern uint256 const fixFloatDivide;
 | 
			
		||||
extern uint256 const fixReduceImport;
 | 
			
		||||
 | 
			
		||||
}  // namespace ripple
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -184,6 +184,7 @@ enum TEFcodes : TERUnderlyingType {
 | 
			
		||||
    tefPAST_IMPORT_SEQ,
 | 
			
		||||
    tefPAST_IMPORT_VL_SEQ,
 | 
			
		||||
    tefNONDIR_EMIT,
 | 
			
		||||
    tefIMPORT_BLACKHOLED,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 
 | 
			
		||||
@@ -468,6 +468,7 @@ REGISTER_FIX    (fix240819,                     Supported::yes, VoteBehavior::De
 | 
			
		||||
REGISTER_FIX    (fixPageCap,                    Supported::yes, VoteBehavior::DefaultYes);
 | 
			
		||||
REGISTER_FIX    (fix240911,                     Supported::yes, VoteBehavior::DefaultYes);
 | 
			
		||||
REGISTER_FIX    (fixFloatDivide,                Supported::yes, VoteBehavior::DefaultYes);
 | 
			
		||||
REGISTER_FIX    (fixReduceImport,               Supported::yes, VoteBehavior::DefaultYes);
 | 
			
		||||
 | 
			
		||||
// The following amendments are obsolete, but must remain supported
 | 
			
		||||
// because they could potentially get enabled.
 | 
			
		||||
 
 | 
			
		||||
@@ -116,6 +116,7 @@ transResults()
 | 
			
		||||
        MAKE_ERROR(tefNO_TICKET,                   "Ticket is not in ledger."),
 | 
			
		||||
        MAKE_ERROR(tefNFTOKEN_IS_NOT_TRANSFERABLE, "The specified NFToken is not transferable."),
 | 
			
		||||
        MAKE_ERROR(tefNONDIR_EMIT,                 "An emitted txn was injected into the ledger without a corresponding directory entry."),
 | 
			
		||||
        MAKE_ERROR(tefIMPORT_BLACKHOLED,           "Cannot import keying because target account is blackholed."),
 | 
			
		||||
 | 
			
		||||
        MAKE_ERROR(telLOCAL_ERROR,            "Local failure."),
 | 
			
		||||
        MAKE_ERROR(telBAD_DOMAIN,             "Domain too long."),
 | 
			
		||||
 
 | 
			
		||||
@@ -79,7 +79,7 @@ class Import_test : public beast::unit_test::suite
 | 
			
		||||
    importVLSequence(jtx::Env const& env, PublicKey const& pk)
 | 
			
		||||
    {
 | 
			
		||||
        auto const sle = env.le(keylet::import_vlseq(pk));
 | 
			
		||||
        if (sle->isFieldPresent(sfImportSequence))
 | 
			
		||||
        if (sle && sle->isFieldPresent(sfImportSequence))
 | 
			
		||||
            return (*sle)[sfImportSequence];
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
@@ -2672,6 +2672,134 @@ class Import_test : public beast::unit_test::suite
 | 
			
		||||
            env(import::import(alice, tmpXpop), ter(temMALFORMED));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // tefIMPORT_BLACKHOLED - SetRegularKey (w/seed) AccountZero
 | 
			
		||||
        {
 | 
			
		||||
            test::jtx::Env env{
 | 
			
		||||
                *this, network::makeNetworkVLConfig(21337, keys)};
 | 
			
		||||
            auto const feeDrops = env.current()->fees().base;
 | 
			
		||||
 | 
			
		||||
            auto const alice = Account("alice");
 | 
			
		||||
            env.fund(XRP(1000), alice);
 | 
			
		||||
            env.close();
 | 
			
		||||
 | 
			
		||||
            // Set Regular Key
 | 
			
		||||
            Json::Value jv;
 | 
			
		||||
            jv[jss::Account] = alice.human();
 | 
			
		||||
            const AccountID ACCOUNT_ZERO(0);
 | 
			
		||||
            jv["RegularKey"] = to_string(ACCOUNT_ZERO);
 | 
			
		||||
            jv[jss::TransactionType] = jss::SetRegularKey;
 | 
			
		||||
            env(jv, alice);
 | 
			
		||||
 | 
			
		||||
            // Disable Master Key
 | 
			
		||||
            env(fset(alice, asfDisableMaster), sig(alice));
 | 
			
		||||
            env.close();
 | 
			
		||||
 | 
			
		||||
            // Import with Master Key
 | 
			
		||||
            Json::Value tmpXpop =
 | 
			
		||||
                import::loadXpop(ImportTCSetRegularKey::w_seed);
 | 
			
		||||
            env(import::import(alice, tmpXpop),
 | 
			
		||||
                ter(tefIMPORT_BLACKHOLED),
 | 
			
		||||
                fee(feeDrops * 10),
 | 
			
		||||
                sig(alice));
 | 
			
		||||
            env.close();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // tefIMPORT_BLACKHOLED - SetRegularKey (w/seed) AccountOne
 | 
			
		||||
        {
 | 
			
		||||
            test::jtx::Env env{
 | 
			
		||||
                *this, network::makeNetworkVLConfig(21337, keys)};
 | 
			
		||||
            auto const feeDrops = env.current()->fees().base;
 | 
			
		||||
 | 
			
		||||
            auto const alice = Account("alice");
 | 
			
		||||
            env.fund(XRP(1000), alice);
 | 
			
		||||
            env.close();
 | 
			
		||||
 | 
			
		||||
            // Set Regular Key
 | 
			
		||||
            Json::Value jv;
 | 
			
		||||
            jv[jss::Account] = alice.human();
 | 
			
		||||
            const AccountID ACCOUNT_ONE(1);
 | 
			
		||||
            jv["RegularKey"] = to_string(ACCOUNT_ONE);
 | 
			
		||||
            jv[jss::TransactionType] = jss::SetRegularKey;
 | 
			
		||||
            env(jv, alice);
 | 
			
		||||
 | 
			
		||||
            // Disable Master Key
 | 
			
		||||
            env(fset(alice, asfDisableMaster), sig(alice));
 | 
			
		||||
            env.close();
 | 
			
		||||
 | 
			
		||||
            // Import with Master Key
 | 
			
		||||
            Json::Value tmpXpop =
 | 
			
		||||
                import::loadXpop(ImportTCSetRegularKey::w_seed);
 | 
			
		||||
            env(import::import(alice, tmpXpop),
 | 
			
		||||
                ter(tefIMPORT_BLACKHOLED),
 | 
			
		||||
                fee(feeDrops * 10),
 | 
			
		||||
                sig(alice));
 | 
			
		||||
            env.close();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // tefIMPORT_BLACKHOLED - SetRegularKey (w/seed) AccountTwo
 | 
			
		||||
        {
 | 
			
		||||
            test::jtx::Env env{
 | 
			
		||||
                *this, network::makeNetworkVLConfig(21337, keys)};
 | 
			
		||||
            auto const feeDrops = env.current()->fees().base;
 | 
			
		||||
 | 
			
		||||
            auto const alice = Account("alice");
 | 
			
		||||
            env.fund(XRP(1000), alice);
 | 
			
		||||
            env.close();
 | 
			
		||||
 | 
			
		||||
            // Set Regular Key
 | 
			
		||||
            Json::Value jv;
 | 
			
		||||
            jv[jss::Account] = alice.human();
 | 
			
		||||
            const AccountID ACCOUNT_TWO(2);
 | 
			
		||||
            jv["RegularKey"] = to_string(ACCOUNT_TWO);
 | 
			
		||||
            jv[jss::TransactionType] = jss::SetRegularKey;
 | 
			
		||||
            env(jv, alice);
 | 
			
		||||
 | 
			
		||||
            // Disable Master Key
 | 
			
		||||
            env(fset(alice, asfDisableMaster), sig(alice));
 | 
			
		||||
            env.close();
 | 
			
		||||
 | 
			
		||||
            // Import with Master Key
 | 
			
		||||
            Json::Value tmpXpop =
 | 
			
		||||
                import::loadXpop(ImportTCSetRegularKey::w_seed);
 | 
			
		||||
            env(import::import(alice, tmpXpop),
 | 
			
		||||
                ter(tefIMPORT_BLACKHOLED),
 | 
			
		||||
                fee(feeDrops * 10),
 | 
			
		||||
                sig(alice));
 | 
			
		||||
            env.close();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // tefIMPORT_BLACKHOLED - SignersListSet (w/seed)
 | 
			
		||||
        {
 | 
			
		||||
            test::jtx::Env env{
 | 
			
		||||
                *this, network::makeNetworkVLConfig(21337, keys)};
 | 
			
		||||
            auto const feeDrops = env.current()->fees().base;
 | 
			
		||||
 | 
			
		||||
            auto const alice = Account("alice");
 | 
			
		||||
            env.fund(XRP(1000), alice);
 | 
			
		||||
            env.close();
 | 
			
		||||
 | 
			
		||||
            // Set Regular Key
 | 
			
		||||
            Json::Value jv;
 | 
			
		||||
            jv[jss::Account] = alice.human();
 | 
			
		||||
            const AccountID ACCOUNT_ZERO(0);
 | 
			
		||||
            jv["RegularKey"] = to_string(ACCOUNT_ZERO);
 | 
			
		||||
            jv[jss::TransactionType] = jss::SetRegularKey;
 | 
			
		||||
            env(jv, alice);
 | 
			
		||||
 | 
			
		||||
            // Disable Master Key
 | 
			
		||||
            env(fset(alice, asfDisableMaster), sig(alice));
 | 
			
		||||
            env.close();
 | 
			
		||||
 | 
			
		||||
            // Import with Master Key
 | 
			
		||||
            Json::Value tmpXpop =
 | 
			
		||||
                import::loadXpop(ImportTCSignersListSet::w_seed);
 | 
			
		||||
            env(import::import(alice, tmpXpop),
 | 
			
		||||
                ter(tefIMPORT_BLACKHOLED),
 | 
			
		||||
                fee(feeDrops * 10),
 | 
			
		||||
                sig(alice));
 | 
			
		||||
            env.close();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // tefPAST_IMPORT_SEQ
 | 
			
		||||
        {
 | 
			
		||||
            test::jtx::Env env{
 | 
			
		||||
@@ -4580,14 +4708,22 @@ class Import_test : public beast::unit_test::suite
 | 
			
		||||
            // confirm signers set
 | 
			
		||||
            auto const [signers, signersSle] =
 | 
			
		||||
                signersKeyAndSle(*env.current(), alice);
 | 
			
		||||
            auto const signerEntries =
 | 
			
		||||
                signersSle->getFieldArray(sfSignerEntries);
 | 
			
		||||
            BEAST_EXPECT(signerEntries.size() == 2);
 | 
			
		||||
            BEAST_EXPECT(signerEntries[0u].getFieldU16(sfSignerWeight) == 1);
 | 
			
		||||
            BEAST_EXPECT(
 | 
			
		||||
                signerEntries[0u].getAccountID(sfAccount) == carol.id());
 | 
			
		||||
            BEAST_EXPECT(signerEntries[1u].getFieldU16(sfSignerWeight) == 1);
 | 
			
		||||
            BEAST_EXPECT(signerEntries[1u].getAccountID(sfAccount) == bob.id());
 | 
			
		||||
                signersSle && signersSle->isFieldPresent(sfSignerEntries));
 | 
			
		||||
            if (signersSle && signersSle->isFieldPresent(sfSignerEntries))
 | 
			
		||||
            {
 | 
			
		||||
                auto const signerEntries =
 | 
			
		||||
                    signersSle->getFieldArray(sfSignerEntries);
 | 
			
		||||
                BEAST_EXPECT(signerEntries.size() == 2);
 | 
			
		||||
                BEAST_EXPECT(
 | 
			
		||||
                    signerEntries[0u].getFieldU16(sfSignerWeight) == 1);
 | 
			
		||||
                BEAST_EXPECT(
 | 
			
		||||
                    signerEntries[0u].getAccountID(sfAccount) == carol.id());
 | 
			
		||||
                BEAST_EXPECT(
 | 
			
		||||
                    signerEntries[1u].getFieldU16(sfSignerWeight) == 1);
 | 
			
		||||
                BEAST_EXPECT(
 | 
			
		||||
                    signerEntries[1u].getAccountID(sfAccount) == bob.id());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // confirm multisign tx
 | 
			
		||||
            env.close();
 | 
			
		||||
@@ -5986,6 +6122,69 @@ class Import_test : public beast::unit_test::suite
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void
 | 
			
		||||
    testBlackhole(FeatureBitset features)
 | 
			
		||||
    {
 | 
			
		||||
        testcase("blackhole");
 | 
			
		||||
 | 
			
		||||
        using namespace test::jtx;
 | 
			
		||||
        using namespace std::literals;
 | 
			
		||||
 | 
			
		||||
        auto blackholeAccount = [&](Env& env, Account const& acct) {
 | 
			
		||||
            // Set Regular Key
 | 
			
		||||
            Json::Value jv;
 | 
			
		||||
            jv[jss::Account] = acct.human();
 | 
			
		||||
            const AccountID ACCOUNT_ZERO(0);
 | 
			
		||||
            jv["RegularKey"] = to_string(ACCOUNT_ZERO);
 | 
			
		||||
            jv[jss::TransactionType] = jss::SetRegularKey;
 | 
			
		||||
            env(jv, acct);
 | 
			
		||||
 | 
			
		||||
            // Disable Master Key
 | 
			
		||||
            env(fset(acct, asfDisableMaster), sig(acct));
 | 
			
		||||
            env.close();
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        auto burnHeader = [&](Env& env) {
 | 
			
		||||
            // confirm total coins header
 | 
			
		||||
            auto const initCoins = env.current()->info().drops;
 | 
			
		||||
            BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
 | 
			
		||||
 | 
			
		||||
            // burn 10'000 xrp
 | 
			
		||||
            auto const master = Account("masterpassphrase");
 | 
			
		||||
            env(noop(master), fee(100'000'000'000'000), ter(tesSUCCESS));
 | 
			
		||||
            env.close();
 | 
			
		||||
 | 
			
		||||
            // confirm total coins header
 | 
			
		||||
            auto const burnCoins = env.current()->info().drops;
 | 
			
		||||
            BEAST_EXPECT(burnCoins == initCoins - 100'000'000'000'000);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // AccountSet (w/seed)
 | 
			
		||||
        {
 | 
			
		||||
            test::jtx::Env env{
 | 
			
		||||
                *this, network::makeNetworkVLConfig(21337, keys)};
 | 
			
		||||
            auto const feeDrops = env.current()->fees().base;
 | 
			
		||||
 | 
			
		||||
            // Burn Header
 | 
			
		||||
            burnHeader(env);
 | 
			
		||||
 | 
			
		||||
            auto const alice = Account("alice");
 | 
			
		||||
            env.fund(XRP(1000), alice);
 | 
			
		||||
            env.close();
 | 
			
		||||
 | 
			
		||||
            // Blackhole Account
 | 
			
		||||
            blackholeAccount(env, alice);
 | 
			
		||||
 | 
			
		||||
            // Import with Master Key
 | 
			
		||||
            Json::Value tmpXpop = import::loadXpop(ImportTCAccountSet::w_seed);
 | 
			
		||||
            env(import::import(alice, tmpXpop),
 | 
			
		||||
                ter(tesSUCCESS),
 | 
			
		||||
                fee(feeDrops * 10),
 | 
			
		||||
                sig(alice));
 | 
			
		||||
            env.close();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    void
 | 
			
		||||
    run() override
 | 
			
		||||
@@ -6026,6 +6225,7 @@ public:
 | 
			
		||||
        testMaxSupply(features);
 | 
			
		||||
        testMinMax(features);
 | 
			
		||||
        testHalving(features - featureOwnerPaysFee);
 | 
			
		||||
        testBlackhole(features);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user