Merge branch 'bthomee/rename_definitions' into bthomee/rename_copyright

This commit is contained in:
Bart Thomee
2025-11-01 12:53:00 -04:00
150 changed files with 1143 additions and 1061 deletions

View File

@@ -17,7 +17,7 @@ Loop: xrpld.app xrpld.rpc
xrpld.rpc > xrpld.app
Loop: xrpld.app xrpld.shamap
xrpld.app > xrpld.shamap
xrpld.shamap ~= xrpld.app
Loop: xrpld.core xrpld.perflog
xrpld.perflog == xrpld.core

View File

@@ -8,6 +8,10 @@ libxrpl.ledger > xrpl.ledger
libxrpl.ledger > xrpl.protocol
libxrpl.net > xrpl.basics
libxrpl.net > xrpl.net
libxrpl.nodestore > xrpl.basics
libxrpl.nodestore > xrpl.json
libxrpl.nodestore > xrpl.nodestore
libxrpl.nodestore > xrpl.protocol
libxrpl.protocol > xrpl.basics
libxrpl.protocol > xrpl.json
libxrpl.protocol > xrpl.protocol
@@ -18,6 +22,9 @@ libxrpl.server > xrpl.basics
libxrpl.server > xrpl.json
libxrpl.server > xrpl.protocol
libxrpl.server > xrpl.server
libxrpl.shamap > xrpl.basics
libxrpl.shamap > xrpl.protocol
libxrpl.shamap > xrpl.shamap
test.app > test.jtx
test.app > test.rpc
test.app > test.toplevel
@@ -25,11 +32,11 @@ test.app > test.unit_test
test.app > xrpl.basics
test.app > xrpld.app
test.app > xrpld.core
test.app > xrpld.nodestore
test.app > xrpld.overlay
test.app > xrpld.rpc
test.app > xrpl.json
test.app > xrpl.ledger
test.app > xrpl.nodestore
test.app > xrpl.protocol
test.app > xrpl.resource
test.basics > test.jtx
@@ -86,8 +93,7 @@ test.nodestore > test.toplevel
test.nodestore > test.unit_test
test.nodestore > xrpl.basics
test.nodestore > xrpld.core
test.nodestore > xrpld.nodestore
test.nodestore > xrpld.unity
test.nodestore > xrpl.nodestore
test.overlay > test.jtx
test.overlay > test.toplevel
test.overlay > test.unit_test
@@ -95,8 +101,8 @@ test.overlay > xrpl.basics
test.overlay > xrpld.app
test.overlay > xrpld.overlay
test.overlay > xrpld.peerfinder
test.overlay > xrpld.shamap
test.overlay > xrpl.protocol
test.overlay > xrpl.shamap
test.peerfinder > test.beast
test.peerfinder > test.unit_test
test.peerfinder > xrpl.basics
@@ -131,9 +137,9 @@ test.server > xrpl.json
test.server > xrpl.server
test.shamap > test.unit_test
test.shamap > xrpl.basics
test.shamap > xrpld.nodestore
test.shamap > xrpld.shamap
test.shamap > xrpl.nodestore
test.shamap > xrpl.protocol
test.shamap > xrpl.shamap
test.toplevel > test.csf
test.toplevel > xrpl.json
test.unit_test > xrpl.basics
@@ -144,6 +150,8 @@ xrpl.json > xrpl.basics
xrpl.ledger > xrpl.basics
xrpl.ledger > xrpl.protocol
xrpl.net > xrpl.basics
xrpl.nodestore > xrpl.basics
xrpl.nodestore > xrpl.protocol
xrpl.protocol > xrpl.basics
xrpl.protocol > xrpl.json
xrpl.resource > xrpl.basics
@@ -152,17 +160,21 @@ xrpl.resource > xrpl.protocol
xrpl.server > xrpl.basics
xrpl.server > xrpl.json
xrpl.server > xrpl.protocol
xrpl.shamap > xrpl.basics
xrpl.shamap > xrpl.nodestore
xrpl.shamap > xrpl.protocol
xrpld.app > test.unit_test
xrpld.app > xrpl.basics
xrpld.app > xrpld.conditions
xrpld.app > xrpld.consensus
xrpld.app > xrpld.nodestore
xrpld.app > xrpld.perflog
xrpld.app > xrpl.json
xrpld.app > xrpl.ledger
xrpld.app > xrpl.net
xrpld.app > xrpl.nodestore
xrpld.app > xrpl.protocol
xrpld.app > xrpl.resource
xrpld.app > xrpl.shamap
xrpld.conditions > xrpl.basics
xrpld.conditions > xrpl.protocol
xrpld.consensus > xrpl.basics
@@ -172,11 +184,6 @@ xrpld.core > xrpl.basics
xrpld.core > xrpl.json
xrpld.core > xrpl.net
xrpld.core > xrpl.protocol
xrpld.nodestore > xrpl.basics
xrpld.nodestore > xrpld.core
xrpld.nodestore > xrpld.unity
xrpld.nodestore > xrpl.json
xrpld.nodestore > xrpl.protocol
xrpld.overlay > xrpl.basics
xrpld.overlay > xrpld.core
xrpld.overlay > xrpld.peerfinder
@@ -192,13 +199,11 @@ xrpld.perflog > xrpl.basics
xrpld.perflog > xrpl.json
xrpld.rpc > xrpl.basics
xrpld.rpc > xrpld.core
xrpld.rpc > xrpld.nodestore
xrpld.rpc > xrpl.json
xrpld.rpc > xrpl.ledger
xrpld.rpc > xrpl.net
xrpld.rpc > xrpl.nodestore
xrpld.rpc > xrpl.protocol
xrpld.rpc > xrpl.resource
xrpld.rpc > xrpl.server
xrpld.shamap > xrpl.basics
xrpld.shamap > xrpld.nodestore
xrpld.shamap > xrpl.protocol
xrpld.shamap > xrpl.shamap

View File

@@ -18,10 +18,10 @@ fi
# XRPLF, and certain individual contributors upon mutual agreement, so the one
# in the LICENSE.md file applies throughout. Copyright notices referencing
# external contributions, e.g. from Bitcoin, remain as-is.
# Usage: .github/scripts/rename/copyright.sh <directory>
# Usage: .github/scripts/rename/copyright.sh <repository directory>
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <directory>"
echo "Usage: $0 <repository directory>"
exit 1
fi

View File

@@ -17,10 +17,10 @@ fi
# Specifically, it renames "RIPPLED_XXX" and "RIPPLE_XXX" to "XRPL_XXX" by
# scanning all cmake, header, and source files in the specified directory and
# its subdirectories.
# Usage: .github/scripts/rename/definitions.sh <directory>
# Usage: .github/scripts/rename/definitions.sh <repository directory>
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <directory>"
echo "Usage: $0 <repository directory>"
exit 1
fi

View File

@@ -53,14 +53,15 @@ add_library(xrpl.imports.main INTERFACE)
target_link_libraries(xrpl.imports.main
INTERFACE
LibArchive::LibArchive
OpenSSL::Crypto
Ripple::boost
Ripple::opts
Ripple::syslibs
absl::random_random
date::date
ed25519::ed25519
LibArchive::LibArchive
OpenSSL::Crypto
Ripple::boost
Ripple::libs
Ripple::opts
Ripple::syslibs
secp256k1::secp256k1
xrpl.libpb
xxHash::xxhash
@@ -111,6 +112,21 @@ target_link_libraries(xrpl.libxrpl.net PUBLIC
add_module(xrpl server)
target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol)
add_module(xrpl nodestore)
target_link_libraries(xrpl.libxrpl.nodestore PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.json
xrpl.libxrpl.protocol
)
add_module(xrpl shamap)
target_link_libraries(xrpl.libxrpl.shamap PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.crypto
xrpl.libxrpl.protocol
xrpl.libxrpl.nodestore
)
add_module(xrpl ledger)
target_link_libraries(xrpl.libxrpl.ledger PUBLIC
xrpl.libxrpl.basics
@@ -136,6 +152,8 @@ target_link_modules(xrpl PUBLIC
protocol
resource
server
nodestore
shamap
net
ledger
)

View File

@@ -8,20 +8,23 @@ install (
TARGETS
common
opts
ripple_syslibs
ripple_boost
ripple_libs
ripple_syslibs
xrpl.imports.main
xrpl.libpb
xrpl.libxrpl
xrpl.libxrpl.basics
xrpl.libxrpl.beast
xrpl.libxrpl.crypto
xrpl.libxrpl.json
xrpl.libxrpl.ledger
xrpl.libxrpl.net
xrpl.libxrpl.nodestore
xrpl.libxrpl.protocol
xrpl.libxrpl.resource
xrpl.libxrpl.ledger
xrpl.libxrpl.server
xrpl.libxrpl.net
xrpl.libxrpl
xrpl.libxrpl.shamap
antithesis-sdk-cpp
EXPORT RippleExports
LIBRARY DESTINATION lib

View File

@@ -1,7 +1,7 @@
#ifndef XRPL_NODESTORE_BACKEND_H_INCLUDED
#define XRPL_NODESTORE_BACKEND_H_INCLUDED
#include <xrpld/nodestore/Types.h>
#include <xrpl/nodestore/Types.h>
#include <cstdint>

View File

@@ -1,13 +1,12 @@
#ifndef XRPL_NODESTORE_DATABASE_H_INCLUDED
#define XRPL_NODESTORE_DATABASE_H_INCLUDED
#include <xrpld/nodestore/Backend.h>
#include <xrpld/nodestore/NodeObject.h>
#include <xrpld/nodestore/Scheduler.h>
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/TaggedCache.ipp>
#include <xrpl/nodestore/Backend.h>
#include <xrpl/nodestore/NodeObject.h>
#include <xrpl/nodestore/Scheduler.h>
#include <xrpl/protocol/SystemParameters.h>
#include <condition_variable>

View File

@@ -1,7 +1,7 @@
#ifndef XRPL_NODESTORE_DATABASEROTATING_H_INCLUDED
#define XRPL_NODESTORE_DATABASEROTATING_H_INCLUDED
#include <xrpld/nodestore/Database.h>
#include <xrpl/nodestore/Database.h>
namespace ripple {
namespace NodeStore {

View File

@@ -1,7 +1,7 @@
#ifndef XRPL_NODESTORE_DUMMYSCHEDULER_H_INCLUDED
#define XRPL_NODESTORE_DUMMYSCHEDULER_H_INCLUDED
#include <xrpld/nodestore/Scheduler.h>
#include <xrpl/nodestore/Scheduler.h>
namespace ripple {
namespace NodeStore {

View File

@@ -1,11 +1,10 @@
#ifndef XRPL_NODESTORE_FACTORY_H_INCLUDED
#define XRPL_NODESTORE_FACTORY_H_INCLUDED
#include <xrpld/nodestore/Backend.h>
#include <xrpld/nodestore/Scheduler.h>
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/nodestore/Backend.h>
#include <xrpl/nodestore/Scheduler.h>
#include <nudb/store.hpp>

View File

@@ -1,8 +1,8 @@
#ifndef XRPL_NODESTORE_MANAGER_H_INCLUDED
#define XRPL_NODESTORE_MANAGER_H_INCLUDED
#include <xrpld/nodestore/DatabaseRotating.h>
#include <xrpld/nodestore/Factory.h>
#include <xrpl/nodestore/DatabaseRotating.h>
#include <xrpl/nodestore/Factory.h>
namespace ripple {

View File

@@ -1,7 +1,7 @@
#ifndef XRPL_NODESTORE_SCHEDULER_H_INCLUDED
#define XRPL_NODESTORE_SCHEDULER_H_INCLUDED
#include <xrpld/nodestore/Task.h>
#include <xrpl/nodestore/Task.h>
#include <chrono>

View File

@@ -1,7 +1,7 @@
#ifndef XRPL_NODESTORE_TYPES_H_INCLUDED
#define XRPL_NODESTORE_TYPES_H_INCLUDED
#include <xrpld/nodestore/NodeObject.h>
#include <xrpl/nodestore/NodeObject.h>
#include <vector>

View File

@@ -1,9 +1,9 @@
#ifndef XRPL_NODESTORE_BATCHWRITER_H_INCLUDED
#define XRPL_NODESTORE_BATCHWRITER_H_INCLUDED
#include <xrpld/nodestore/Scheduler.h>
#include <xrpld/nodestore/Task.h>
#include <xrpld/nodestore/Types.h>
#include <xrpl/nodestore/Scheduler.h>
#include <xrpl/nodestore/Task.h>
#include <xrpl/nodestore/Types.h>
#include <condition_variable>
#include <mutex>

View File

@@ -1,10 +1,9 @@
#ifndef XRPL_NODESTORE_DATABASENODEIMP_H_INCLUDED
#define XRPL_NODESTORE_DATABASENODEIMP_H_INCLUDED
#include <xrpld/nodestore/Database.h>
#include <xrpl/basics/TaggedCache.h>
#include <xrpl/basics/chrono.h>
#include <xrpl/nodestore/Database.h>
namespace ripple {
namespace NodeStore {

View File

@@ -1,7 +1,7 @@
#ifndef XRPL_NODESTORE_DATABASEROTATINGIMP_H_INCLUDED
#define XRPL_NODESTORE_DATABASEROTATINGIMP_H_INCLUDED
#include <xrpld/nodestore/DatabaseRotating.h>
#include <xrpl/nodestore/DatabaseRotating.h>
#include <mutex>

View File

@@ -1,7 +1,7 @@
#ifndef XRPL_NODESTORE_DECODEDBLOB_H_INCLUDED
#define XRPL_NODESTORE_DECODEDBLOB_H_INCLUDED
#include <xrpld/nodestore/NodeObject.h>
#include <xrpl/nodestore/NodeObject.h>
namespace ripple {
namespace NodeStore {

View File

@@ -1,9 +1,8 @@
#ifndef XRPL_NODESTORE_ENCODEDBLOB_H_INCLUDED
#define XRPL_NODESTORE_ENCODEDBLOB_H_INCLUDED
#include <xrpld/nodestore/NodeObject.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/nodestore/NodeObject.h>
#include <boost/align/align_up.hpp>

View File

@@ -1,7 +1,7 @@
#ifndef XRPL_NODESTORE_MANAGERIMP_H_INCLUDED
#define XRPL_NODESTORE_MANAGERIMP_H_INCLUDED
#include <xrpld/nodestore/Manager.h>
#include <xrpl/nodestore/Manager.h>
namespace ripple {
@@ -20,7 +20,7 @@ public:
static void
missing_backend();
ManagerImp() = default;
ManagerImp();
~ManagerImp() = default;

View File

@@ -4,11 +4,10 @@
// Disable lz4 deprecation warning due to incompatibility with clang attributes
#define LZ4_DISABLE_DEPRECATE_WARNINGS
#include <xrpld/nodestore/NodeObject.h>
#include <xrpld/nodestore/detail/varint.h>
#include <xrpl/basics/contract.h>
#include <xrpl/basics/safe_cast.h>
#include <xrpl/nodestore/NodeObject.h>
#include <xrpl/nodestore/detail/varint.h>
#include <xrpl/protocol/HashPrefix.h>
#include <nudb/detail/field.hpp>

View File

@@ -36,7 +36,10 @@ std::size_t constexpr oversizeMetaDataCap = 5200;
/** The maximum number of entries per directory page */
std::size_t constexpr dirNodeMaxEntries = 32;
/** The maximum number of pages allowed in a directory */
/** The maximum number of pages allowed in a directory
Made obsolete by fixDirectoryLimit amendment.
*/
std::uint64_t constexpr dirNodeMaxPages = 262144;
/** The maximum number of items in an NFT page */

View File

@@ -54,14 +54,8 @@ static constexpr std::uint32_t XRP_LEDGER_EARLIEST_SEQ{32570u};
* used in asserts and tests. */
static constexpr std::uint32_t XRP_LEDGER_EARLIEST_FEES{562177u};
/** The minimum amount of support an amendment should have.
@note This value is used by legacy code and will become obsolete
once the fixAmendmentMajorityCalc amendment activates.
*/
constexpr std::ratio<204, 256> preFixAmendmentMajorityCalcThreshold;
constexpr std::ratio<80, 100> postFixAmendmentMajorityCalcThreshold;
/** The minimum amount of support an amendment should have. */
constexpr std::ratio<80, 100> amendmentMajorityCalcThreshold;
/** The minimum amount of time an amendment must hold a majority */
constexpr std::chrono::seconds const defaultAmendmentMajorityTime = weeks{2};

View File

@@ -208,6 +208,7 @@ enum TERcodes : TERUnderlyingType {
terNO_AMM, // AMM doesn't exist for the asset pair
terADDRESS_COLLISION, // Failed to allocate AccountID when trying to
// create a pseudo-account
terNO_DELEGATE_PERMISSION, // Delegate does not have permission
};
//------------------------------------------------------------------------------
@@ -342,6 +343,9 @@ enum TECcodes : TERUnderlyingType {
tecLIMIT_EXCEEDED = 195,
tecPSEUDO_ACCOUNT = 196,
tecPRECISION_LOSS = 197,
// DEPRECATED: This error code tecNO_DELEGATE_PERMISSION is reserved for
// backward compatibility with historical data on non-prod networks, can be
// reclaimed after those networks reset.
tecNO_DELEGATE_PERMISSION = 198,
};

View File

@@ -14,51 +14,35 @@ namespace ripple {
class TxMeta
{
private:
struct CtorHelper
{
explicit CtorHelper() = default;
};
template <class T>
TxMeta(
uint256 const& txID,
std::uint32_t ledger,
T const& data,
CtorHelper);
public:
TxMeta(
uint256 const& transactionID,
std::uint32_t ledger,
std::optional<uint256> parentBatchId = std::nullopt);
TxMeta(uint256 const& transactionID, std::uint32_t ledger);
TxMeta(uint256 const& txID, std::uint32_t ledger, Blob const&);
TxMeta(uint256 const& txID, std::uint32_t ledger, std::string const&);
TxMeta(uint256 const& txID, std::uint32_t ledger, STObject const&);
uint256 const&
getTxID() const
{
return mTransactionID;
return transactionID_;
}
std::uint32_t
getLgrSeq() const
{
return mLedger;
return ledgerSeq_;
}
int
getResult() const
{
return mResult;
return result_;
}
TER
getResultTER() const
{
return TER::fromInt(mResult);
return TER::fromInt(result_);
}
std::uint32_t
getIndex() const
{
return mIndex;
return index_;
}
void
@@ -85,66 +69,52 @@ public:
STArray&
getNodes()
{
return (mNodes);
return nodes_;
}
STArray const&
getNodes() const
{
return (mNodes);
return nodes_;
}
void
setDeliveredAmount(STAmount const& delivered)
setAdditionalFields(STObject const& obj)
{
mDelivered = delivered;
if (obj.isFieldPresent(sfDeliveredAmount))
deliveredAmount_ = obj.getFieldAmount(sfDeliveredAmount);
if (obj.isFieldPresent(sfParentBatchID))
parentBatchID_ = obj.getFieldH256(sfParentBatchID);
}
STAmount
std::optional<STAmount> const&
getDeliveredAmount() const
{
XRPL_ASSERT(
hasDeliveredAmount(),
"ripple::TxMeta::getDeliveredAmount : non-null delivered amount");
return *mDelivered;
}
bool
hasDeliveredAmount() const
{
return static_cast<bool>(mDelivered);
return deliveredAmount_;
}
void
setParentBatchId(uint256 const& parentBatchId)
setDeliveredAmount(std::optional<STAmount> const& amount)
{
mParentBatchId = parentBatchId;
deliveredAmount_ = amount;
}
uint256
getParentBatchId() const
void
setParentBatchID(std::optional<uint256> const& id)
{
XRPL_ASSERT(
hasParentBatchId(),
"ripple::TxMeta::getParentBatchId : non-null batch id");
return *mParentBatchId;
}
bool
hasParentBatchId() const
{
return static_cast<bool>(mParentBatchId);
parentBatchID_ = id;
}
private:
uint256 mTransactionID;
std::uint32_t mLedger;
std::uint32_t mIndex;
int mResult;
uint256 transactionID_;
std::uint32_t ledgerSeq_;
std::uint32_t index_;
int result_;
std::optional<STAmount> mDelivered;
std::optional<uint256> mParentBatchId;
std::optional<STAmount> deliveredAmount_;
std::optional<uint256> parentBatchID_;
STArray mNodes;
STArray nodes_;
};
} // namespace ripple

View File

@@ -10,13 +10,12 @@
// Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order.
// If you add an amendment here, then do not forget to increment `numFeatures`
// in include/xrpl/protocol/Feature.h.
XRPL_FEATURE(PermissionDelegationV1_1, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (DirectoryLimit, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (IncludeKeyletFields, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(DynamicMPT, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (TokenEscrowV1, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (DelegateV1_1, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (PriceOracleOrder, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (MPTDeliveredAmount, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (AMMClawbackRounding, Supported::yes, VoteBehavior::DefaultNo)
@@ -26,7 +25,6 @@ XRPL_FIX (AMMv1_3, Supported::yes, VoteBehavior::DefaultNo
XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(SingleAssetVault, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(PermissionDelegation, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo)
// Check flags in Credential transactions
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo)
@@ -60,7 +58,6 @@ XRPL_FIX (DisallowIncomingV1, Supported::yes, VoteBehavior::DefaultNo
XRPL_FEATURE(XChainBridge, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(AMM, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(Clawback, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (ReducedOffersV1, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (NFTokenRemint, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (NonFungibleTokensV1_2, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (UniversalNumber, Supported::yes, VoteBehavior::DefaultNo)
@@ -75,12 +72,10 @@ XRPL_FEATURE(CheckCashMakesTrustLine, Supported::yes, VoteBehavior::DefaultNo
XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(TicketBatch, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(NegativeUNL, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (AmendmentMajorityCalc, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(HardenedValidations, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(RequireFullyCanonicalSig, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(DeletableAccounts, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (PayChanRecipientOwnerDir, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (MasterKeyAsRegularKey, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(MultiSignReserve, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(DepositPreauth, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(Checks, Supported::yes, VoteBehavior::DefaultYes)
@@ -122,8 +117,11 @@ XRPL_RETIRE(fix1571)
XRPL_RETIRE(fix1578)
XRPL_RETIRE(fix1623)
XRPL_RETIRE(fix1781)
XRPL_RETIRE(fixAmendmentMajorityCalc)
XRPL_RETIRE(fixCheckThreading)
XRPL_RETIRE(fixMasterKeyAsRegularKey)
XRPL_RETIRE(fixQualityUpperBound)
XRPL_RETIRE(fixReducedOffersV1)
XRPL_RETIRE(fixRmSmallIncreasedQOffers)
XRPL_RETIRE(fixSTAmountCanonicalize)
XRPL_RETIRE(fixTakerDryOfferRemoval)

View File

@@ -438,7 +438,7 @@ LEDGER_ENTRY(ltCREDENTIAL, 0x0081, Credential, credential, ({
{sfExpiration, soeOPTIONAL},
{sfURI, soeOPTIONAL},
{sfIssuerNode, soeREQUIRED},
{sfSubjectNode, soeREQUIRED},
{sfSubjectNode, soeOPTIONAL},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
}))

View File

@@ -297,7 +297,7 @@ TRANSACTION(ttTRUST_SET, 20, TrustSet,
#endif
TRANSACTION(ttACCOUNT_DELETE, 21, AccountDelete,
Delegation::notDelegatable,
uint256{},
featureDeletableAccounts,
mustDeleteAcct,
({
{sfDestination, soeREQUIRED},
@@ -818,7 +818,7 @@ TRANSACTION(ttPERMISSIONED_DOMAIN_DELETE, 63, PermissionedDomainDelete,
#endif
TRANSACTION(ttDELEGATE_SET, 64, DelegateSet,
Delegation::notDelegatable,
featurePermissionDelegation,
featurePermissionDelegationV1_1,
noPriv,
({
{sfAuthorize, soeREQUIRED},

View File

@@ -1,11 +1,10 @@
#ifndef XRPL_SHAMAP_FAMILY_H_INCLUDED
#define XRPL_SHAMAP_FAMILY_H_INCLUDED
#include <xrpld/nodestore/Database.h>
#include <xrpld/shamap/FullBelowCache.h>
#include <xrpld/shamap/TreeNodeCache.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/nodestore/Database.h>
#include <xrpl/shamap/FullBelowCache.h>
#include <xrpl/shamap/TreeNodeCache.h>
#include <cstdint>

View File

@@ -1,21 +1,19 @@
#ifndef XRPL_SHAMAP_SHAMAP_H_INCLUDED
#define XRPL_SHAMAP_SHAMAP_H_INCLUDED
#include <xrpld/nodestore/Database.h>
#include <xrpld/nodestore/NodeObject.h>
#include <xrpld/shamap/Family.h>
#include <xrpld/shamap/SHAMapAddNode.h>
#include <xrpld/shamap/SHAMapInnerNode.h>
#include <xrpld/shamap/SHAMapItem.h>
#include <xrpld/shamap/SHAMapLeafNode.h>
#include <xrpld/shamap/SHAMapMissingNode.h>
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpld/shamap/TreeNodeCache.h>
#include <xrpl/basics/IntrusivePointer.h>
#include <xrpl/basics/UnorderedContainers.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/nodestore/Database.h>
#include <xrpl/nodestore/NodeObject.h>
#include <xrpl/shamap/Family.h>
#include <xrpl/shamap/SHAMapAddNode.h>
#include <xrpl/shamap/SHAMapInnerNode.h>
#include <xrpl/shamap/SHAMapItem.h>
#include <xrpl/shamap/SHAMapLeafNode.h>
#include <xrpl/shamap/SHAMapMissingNode.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <set>
#include <stack>

View File

@@ -1,12 +1,11 @@
#ifndef XRPL_SHAMAP_SHAMAPACCOUNTSTATELEAFNODE_H_INCLUDED
#define XRPL_SHAMAP_SHAMAPACCOUNTSTATELEAFNODE_H_INCLUDED
#include <xrpld/shamap/SHAMapItem.h>
#include <xrpld/shamap/SHAMapLeafNode.h>
#include <xrpl/basics/CountedObject.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/digest.h>
#include <xrpl/shamap/SHAMapItem.h>
#include <xrpl/shamap/SHAMapLeafNode.h>
namespace ripple {

View File

@@ -1,10 +1,9 @@
#ifndef XRPL_SHAMAP_SHAMAPINNERNODE_H_INCLUDED
#define XRPL_SHAMAP_SHAMAPINNERNODE_H_INCLUDED
#include <xrpld/shamap/SHAMapNodeID.h>
#include <xrpld/shamap/detail/TaggedPointer.h>
#include <xrpl/basics/IntrusivePointer.h>
#include <xrpl/shamap/SHAMapNodeID.h>
#include <xrpl/shamap/detail/TaggedPointer.h>
#include <atomic>
#include <cstdint>

View File

@@ -1,8 +1,8 @@
#ifndef XRPL_SHAMAP_SHAMAPLEAFNODE_H_INCLUDED
#define XRPL_SHAMAP_SHAMAPLEAFNODE_H_INCLUDED
#include <xrpld/shamap/SHAMapItem.h>
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpl/shamap/SHAMapItem.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <cstdint>

View File

@@ -1,9 +1,8 @@
#ifndef XRPL_SHAMAP_SHAMAPMISSINGNODE_H_INCLUDED
#define XRPL_SHAMAP_SHAMAPMISSINGNODE_H_INCLUDED
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <iosfwd>
#include <stdexcept>

View File

@@ -1,7 +1,7 @@
#ifndef XRPL_SHAMAP_SHAMAPSYNCFILTER_H_INCLUDED
#define XRPL_SHAMAP_SHAMAPSYNCFILTER_H_INCLUDED
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <optional>

View File

@@ -1,13 +1,12 @@
#ifndef XRPL_SHAMAP_SHAMAPTREENODE_H_INCLUDED
#define XRPL_SHAMAP_SHAMAPTREENODE_H_INCLUDED
#include <xrpld/shamap/SHAMapItem.h>
#include <xrpld/shamap/SHAMapNodeID.h>
#include <xrpl/basics/IntrusivePointer.h>
#include <xrpl/basics/IntrusiveRefCounts.h>
#include <xrpl/basics/SHAMapHash.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/shamap/SHAMapItem.h>
#include <xrpl/shamap/SHAMapNodeID.h>
#include <cstdint>
#include <string>

View File

@@ -1,12 +1,11 @@
#ifndef XRPL_SHAMAP_SHAMAPTXLEAFNODE_H_INCLUDED
#define XRPL_SHAMAP_SHAMAPTXLEAFNODE_H_INCLUDED
#include <xrpld/shamap/SHAMapItem.h>
#include <xrpld/shamap/SHAMapLeafNode.h>
#include <xrpl/basics/CountedObject.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/digest.h>
#include <xrpl/shamap/SHAMapItem.h>
#include <xrpl/shamap/SHAMapLeafNode.h>
namespace ripple {

View File

@@ -1,12 +1,11 @@
#ifndef XRPL_SHAMAP_SHAMAPLEAFTXPLUSMETANODE_H_INCLUDED
#define XRPL_SHAMAP_SHAMAPLEAFTXPLUSMETANODE_H_INCLUDED
#include <xrpld/shamap/SHAMapItem.h>
#include <xrpld/shamap/SHAMapLeafNode.h>
#include <xrpl/basics/CountedObject.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/digest.h>
#include <xrpl/shamap/SHAMapItem.h>
#include <xrpl/shamap/SHAMapLeafNode.h>
namespace ripple {

View File

@@ -1,10 +1,9 @@
#ifndef XRPL_SHAMAP_TREENODECACHE_H_INCLUDED
#define XRPL_SHAMAP_TREENODECACHE_H_INCLUDED
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpl/basics/IntrusivePointer.h>
#include <xrpl/basics/TaggedCache.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
namespace ripple {

View File

@@ -1,9 +1,8 @@
#ifndef XRPL_SHAMAP_TAGGEDPOINTER_H_INCLUDED
#define XRPL_SHAMAP_TAGGEDPOINTER_H_INCLUDED
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpl/basics/IntrusivePointer.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <array>
#include <cstdint>

View File

@@ -1,7 +1,6 @@
#include <xrpld/shamap/SHAMapInnerNode.h>
#include <xrpld/shamap/detail/TaggedPointer.h>
#include <xrpl/basics/ByteUtilities.h>
#include <xrpl/shamap/SHAMapInnerNode.h>
#include <xrpl/shamap/detail/TaggedPointer.h>
#include <boost/pool/pool_alloc.hpp>

View File

@@ -107,10 +107,10 @@ ApplyStateTable::apply(
std::optional<TxMeta> metadata;
if (!to.open() || isDryRun)
{
TxMeta meta(tx.getTransactionID(), to.seq(), parentBatchId);
TxMeta meta(tx.getTransactionID(), to.seq());
if (deliver)
meta.setDeliveredAmount(*deliver);
meta.setDeliveredAmount(deliver);
meta.setParentBatchID(parentBatchId);
Mods newMod;
for (auto& item : items_)

View File

@@ -3,6 +3,9 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/protocol/Protocol.h>
#include <limits>
#include <type_traits>
namespace ripple {
std::optional<std::uint64_t>
@@ -72,8 +75,21 @@ ApplyView::dirAdd(
return page;
}
// We rely on modulo arithmetic of unsigned integers (guaranteed in
// [basic.fundamental] paragraph 2) to detect page representation overflow.
// For signed integers this would be UB, hence static_assert here.
static_assert(std::is_unsigned_v<decltype(page)>);
// Defensive check against breaking changes in compiler.
static_assert([]<typename T>(std::type_identity<T>) constexpr -> T {
T tmp = std::numeric_limits<T>::max();
return ++tmp;
}(std::type_identity<decltype(page)>{}) == 0);
++page;
// Check whether we're out of pages.
if (++page >= dirNodeMaxPages)
if (page == 0)
return std::nullopt;
if (!rules().enabled(fixDirectoryLimit) &&
page >= dirNodeMaxPages) // Old pages limit
return std::nullopt;
// We are about to create a new node; we'll link it to

View File

@@ -1,4 +1,4 @@
#include <xrpld/nodestore/detail/BatchWriter.h>
#include <xrpl/nodestore/detail/BatchWriter.h>
namespace ripple {
namespace NodeStore {

View File

@@ -1,8 +1,7 @@
#include <xrpld/nodestore/Database.h>
#include <xrpl/basics/chrono.h>
#include <xrpl/beast/core/CurrentThreadName.h>
#include <xrpl/json/json_value.h>
#include <xrpl/nodestore/Database.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/jss.h>

View File

@@ -1,4 +1,4 @@
#include <xrpld/nodestore/detail/DatabaseNodeImp.h>
#include <xrpl/nodestore/detail/DatabaseNodeImp.h>
namespace ripple {
namespace NodeStore {

View File

@@ -1,4 +1,4 @@
#include <xrpld/nodestore/detail/DatabaseRotatingImp.h>
#include <xrpl/nodestore/detail/DatabaseRotatingImp.h>
namespace ripple {
namespace NodeStore {

View File

@@ -1,7 +1,6 @@
#include <xrpld/nodestore/detail/DecodedBlob.h>
#include <xrpl/basics/safe_cast.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/nodestore/detail/DecodedBlob.h>
#include <algorithm>

View File

@@ -1,4 +1,4 @@
#include <xrpld/nodestore/DummyScheduler.h>
#include <xrpl/nodestore/DummyScheduler.h>
namespace ripple {
namespace NodeStore {

View File

@@ -1,5 +1,5 @@
#include <xrpld/nodestore/detail/DatabaseNodeImp.h>
#include <xrpld/nodestore/detail/ManagerImp.h>
#include <xrpl/nodestore/detail/DatabaseNodeImp.h>
#include <xrpl/nodestore/detail/ManagerImp.h>
#include <boost/algorithm/string/predicate.hpp>
@@ -22,6 +22,27 @@ ManagerImp::missing_backend()
"please see the rippled-example.cfg file!");
}
// We shouldn't rely on global variables for lifetime management because their
// lifetime is not well-defined. ManagerImp may get destroyed before the Factory
// classes, and then, calling Manager::instance().erase() in the destructors of
// the Factory classes is an undefined behaviour.
void
registerNuDBFactory(Manager& manager);
void
registerRocksDBFactory(Manager& manager);
void
registerNullFactory(Manager& manager);
void
registerMemoryFactory(Manager& manager);
ManagerImp::ManagerImp()
{
registerNuDBFactory(*this);
registerRocksDBFactory(*this);
registerNullFactory(*this);
registerMemoryFactory(*this);
}
std::unique_ptr<Backend>
ManagerImp::make_Backend(
Section const& parameters,

View File

@@ -1,4 +1,4 @@
#include <xrpld/nodestore/NodeObject.h>
#include <xrpl/nodestore/NodeObject.h>
#include <memory>

View File

@@ -1,7 +1,6 @@
#include <xrpld/nodestore/Factory.h>
#include <xrpld/nodestore/Manager.h>
#include <xrpl/basics/contract.h>
#include <xrpl/nodestore/Factory.h>
#include <xrpl/nodestore/Manager.h>
#include <boost/beast/core/string.hpp>
#include <boost/core/ignore_unused.hpp>
@@ -27,10 +26,10 @@ class MemoryFactory : public Factory
private:
std::mutex mutex_;
std::map<std::string, MemoryDB, boost::beast::iless> map_;
Manager& manager_;
public:
MemoryFactory();
~MemoryFactory() override;
explicit MemoryFactory(Manager& manager);
std::string
getName() const override;
@@ -56,7 +55,14 @@ public:
}
};
static MemoryFactory memoryFactory;
MemoryFactory* memoryFactory = nullptr;
void
registerMemoryFactory(Manager& manager)
{
static MemoryFactory instance{manager};
memoryFactory = &instance;
}
//------------------------------------------------------------------------------
@@ -93,9 +99,9 @@ public:
}
void
open(bool createIfMissing) override
open(bool) override
{
db_ = &memoryFactory.open(name_);
db_ = &memoryFactory->open(name_);
}
bool
@@ -200,14 +206,9 @@ public:
//------------------------------------------------------------------------------
MemoryFactory::MemoryFactory()
MemoryFactory::MemoryFactory(Manager& manager) : manager_(manager)
{
Manager::instance().insert(*this);
}
MemoryFactory::~MemoryFactory()
{
Manager::instance().erase(*this);
manager_.insert(*this);
}
std::string

View File

@@ -1,12 +1,11 @@
#include <xrpld/nodestore/Factory.h>
#include <xrpld/nodestore/Manager.h>
#include <xrpld/nodestore/detail/DecodedBlob.h>
#include <xrpld/nodestore/detail/EncodedBlob.h>
#include <xrpld/nodestore/detail/codec.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/core/LexicalCast.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/nodestore/Factory.h>
#include <xrpl/nodestore/Manager.h>
#include <xrpl/nodestore/detail/DecodedBlob.h>
#include <xrpl/nodestore/detail/EncodedBlob.h>
#include <xrpl/nodestore/detail/codec.h>
#include <boost/filesystem.hpp>
@@ -408,15 +407,13 @@ private:
class NuDBFactory : public Factory
{
public:
NuDBFactory()
{
Manager::instance().insert(*this);
}
private:
Manager& manager_;
~NuDBFactory() override
public:
explicit NuDBFactory(Manager& manager) : manager_(manager)
{
Manager::instance().erase(*this);
manager_.insert(*this);
}
std::string
@@ -451,7 +448,11 @@ public:
}
};
static NuDBFactory nuDBFactory;
void
registerNuDBFactory(Manager& manager)
{
static NuDBFactory instance{manager};
}
} // namespace NodeStore
} // namespace ripple

View File

@@ -1,5 +1,5 @@
#include <xrpld/nodestore/Factory.h>
#include <xrpld/nodestore/Manager.h>
#include <xrpl/nodestore/Factory.h>
#include <xrpl/nodestore/Manager.h>
#include <memory>
@@ -92,15 +92,13 @@ private:
class NullFactory : public Factory
{
public:
NullFactory()
{
Manager::instance().insert(*this);
}
private:
Manager& manager_;
~NullFactory() override
public:
explicit NullFactory(Manager& manager) : manager_(manager)
{
Manager::instance().erase(*this);
manager_.insert(*this);
}
std::string
@@ -121,7 +119,11 @@ public:
}
};
static NullFactory nullFactory;
void
registerNullFactory(Manager& manager)
{
static NullFactory instance{manager};
}
} // namespace NodeStore
} // namespace ripple

View File

@@ -1,17 +1,15 @@
#include <xrpld/unity/rocksdb.h>
#include <xrpl/basics/rocksdb.h>
#if XRPL_ROCKSDB_AVAILABLE
#include <xrpld/core/Config.h> // VFALCO Bad dependency
#include <xrpld/nodestore/Factory.h>
#include <xrpld/nodestore/Manager.h>
#include <xrpld/nodestore/detail/BatchWriter.h>
#include <xrpld/nodestore/detail/DecodedBlob.h>
#include <xrpld/nodestore/detail/EncodedBlob.h>
#include <xrpl/basics/ByteUtilities.h>
#include <xrpl/basics/contract.h>
#include <xrpl/basics/safe_cast.h>
#include <xrpl/beast/core/CurrentThreadName.h>
#include <xrpl/nodestore/Factory.h>
#include <xrpl/nodestore/Manager.h>
#include <xrpl/nodestore/detail/BatchWriter.h>
#include <xrpl/nodestore/detail/DecodedBlob.h>
#include <xrpl/nodestore/detail/EncodedBlob.h>
#include <atomic>
#include <memory>
@@ -474,7 +472,11 @@ public:
}
};
static RocksDBFactory rocksDBFactory;
void
registerRocksDBFactory(Manager& manager)
{
static RocksDBFactory instance{manager};
}
} // namespace NodeStore
} // namespace ripple

View File

@@ -155,21 +155,22 @@ Permission::isDelegatable(
auto const txType = permissionToTxType(permissionValue);
auto const it = delegatableTx_.find(txType);
if (rules.enabled(fixDelegateV1_1))
{
if (it == delegatableTx_.end())
return false;
auto const feature = getTxFeature(txType);
auto const txFeaturesIt = txFeatureMap_.find(txType);
XRPL_ASSERT(
txFeaturesIt != txFeatureMap_.end(),
"ripple::Permissions::isDelegatable : tx exists in txFeatureMap_");
// fixDelegateV1_1: Delegation is only allowed if the required amendment
// for the transaction is enabled. For transactions that do not require
// an amendment, delegation is always allowed.
if (feature && !rules.enabled(*feature))
// Delegation is only allowed if the required amendment for the transaction
// is enabled. For transactions that do not require an amendment, delegation
// is always allowed.
if (txFeaturesIt->second != uint256{} &&
!rules.enabled(txFeaturesIt->second))
return false;
}
if (it != delegatableTx_.end() && it->second == Delegation::notDelegatable)
if (it->second == Delegation::notDelegatable)
return false;
return true;

View File

@@ -108,7 +108,6 @@ transResults()
MAKE_ERROR(tecLIMIT_EXCEEDED, "Limit exceeded."),
MAKE_ERROR(tecPSEUDO_ACCOUNT, "This operation is not allowed against a pseudo-account."),
MAKE_ERROR(tecPRECISION_LOSS, "The amounts used by the transaction cannot interact."),
MAKE_ERROR(tecNO_DELEGATE_PERMISSION, "Delegated account lacks permission to perform this transaction."),
MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),
@@ -216,6 +215,7 @@ transResults()
MAKE_ERROR(terPRE_TICKET, "Ticket is not yet in ledger."),
MAKE_ERROR(terNO_AMM, "AMM doesn't exist for the asset pair."),
MAKE_ERROR(terADDRESS_COLLISION, "Failed to allocate an unique account address."),
MAKE_ERROR(terNO_DELEGATE_PERMISSION, "Delegated account lacks permission to perform this transaction."),
MAKE_ERROR(tesSUCCESS, "The transaction was applied. Only final in a validated ledger."),
};

View File

@@ -20,35 +20,13 @@
namespace ripple {
template <class T>
TxMeta::TxMeta(
uint256 const& txid,
std::uint32_t ledger,
T const& data,
CtorHelper)
: mTransactionID(txid), mLedger(ledger), mNodes(sfAffectedNodes, 32)
{
SerialIter sit(makeSlice(data));
STObject obj(sit, sfMetadata);
mResult = obj.getFieldU8(sfTransactionResult);
mIndex = obj.getFieldU32(sfTransactionIndex);
mNodes = *dynamic_cast<STArray*>(&obj.getField(sfAffectedNodes));
if (obj.isFieldPresent(sfDeliveredAmount))
setDeliveredAmount(obj.getFieldAmount(sfDeliveredAmount));
if (obj.isFieldPresent(sfParentBatchID))
setParentBatchId(obj.getFieldH256(sfParentBatchID));
}
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
: mTransactionID(txid)
, mLedger(ledger)
, mNodes(obj.getFieldArray(sfAffectedNodes))
: transactionID_(txid)
, ledgerSeq_(ledger)
, nodes_(obj.getFieldArray(sfAffectedNodes))
{
mResult = obj.getFieldU8(sfTransactionResult);
mIndex = obj.getFieldU32(sfTransactionIndex);
result_ = obj.getFieldU8(sfTransactionResult);
index_ = obj.getFieldU32(sfTransactionIndex);
auto affectedNodes =
dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes));
@@ -56,40 +34,32 @@ TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
affectedNodes,
"ripple::TxMeta::TxMeta(STObject) : type cast succeeded");
if (affectedNodes)
mNodes = *affectedNodes;
nodes_ = *affectedNodes;
if (obj.isFieldPresent(sfDeliveredAmount))
setDeliveredAmount(obj.getFieldAmount(sfDeliveredAmount));
if (obj.isFieldPresent(sfParentBatchID))
setParentBatchId(obj.getFieldH256(sfParentBatchID));
setAdditionalFields(obj);
}
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, Blob const& vec)
: TxMeta(txid, ledger, vec, CtorHelper())
: transactionID_(txid), ledgerSeq_(ledger), nodes_(sfAffectedNodes, 32)
{
SerialIter sit(makeSlice(vec));
STObject obj(sit, sfMetadata);
result_ = obj.getFieldU8(sfTransactionResult);
index_ = obj.getFieldU32(sfTransactionIndex);
nodes_ = obj.getFieldArray(sfAffectedNodes);
setAdditionalFields(obj);
}
TxMeta::TxMeta(
uint256 const& txid,
std::uint32_t ledger,
std::string const& data)
: TxMeta(txid, ledger, data, CtorHelper())
TxMeta::TxMeta(uint256 const& transactionID, std::uint32_t ledger)
: transactionID_(transactionID)
, ledgerSeq_(ledger)
, index_(std::numeric_limits<std::uint32_t>::max())
, result_(255)
, nodes_(sfAffectedNodes)
{
}
TxMeta::TxMeta(
uint256 const& transactionID,
std::uint32_t ledger,
std::optional<uint256> parentBatchId)
: mTransactionID(transactionID)
, mLedger(ledger)
, mIndex(static_cast<std::uint32_t>(-1))
, mResult(255)
, mParentBatchId(parentBatchId)
, mNodes(sfAffectedNodes)
{
mNodes.reserve(32);
nodes_.reserve(32);
}
void
@@ -99,7 +69,7 @@ TxMeta::setAffectedNode(
std::uint16_t nodeType)
{
// make sure the node exists and force its type
for (auto& n : mNodes)
for (auto& n : nodes_)
{
if (n.getFieldH256(sfLedgerIndex) == node)
{
@@ -109,8 +79,8 @@ TxMeta::setAffectedNode(
}
}
mNodes.push_back(STObject(type));
STObject& obj = mNodes.back();
nodes_.push_back(STObject(type));
STObject& obj = nodes_.back();
XRPL_ASSERT(
obj.getFName() == type,
@@ -127,14 +97,15 @@ TxMeta::getAffectedAccounts() const
// This code should match the behavior of the JS method:
// Meta#getAffectedAccounts
for (auto const& it : mNodes)
for (auto const& node : nodes_)
{
int index = it.getFieldIndex(
(it.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
int index = node.getFieldIndex(
(node.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
if (index != -1)
{
auto inner = dynamic_cast<STObject const*>(&it.peekAtIndex(index));
auto const* inner =
dynamic_cast<STObject const*>(&node.peekAtIndex(index));
XRPL_ASSERT(
inner,
"ripple::getAffectedAccounts : STObject type cast succeeded");
@@ -194,13 +165,13 @@ STObject&
TxMeta::getAffectedNode(SLE::ref node, SField const& type)
{
uint256 index = node->key();
for (auto& n : mNodes)
for (auto& n : nodes_)
{
if (n.getFieldH256(sfLedgerIndex) == index)
return n;
}
mNodes.push_back(STObject(type));
STObject& obj = mNodes.back();
nodes_.push_back(STObject(type));
STObject& obj = nodes_.back();
XRPL_ASSERT(
obj.getFName() == type,
@@ -214,7 +185,7 @@ TxMeta::getAffectedNode(SLE::ref node, SField const& type)
STObject&
TxMeta::getAffectedNode(uint256 const& node)
{
for (auto& n : mNodes)
for (auto& n : nodes_)
{
if (n.getFieldH256(sfLedgerIndex) == node)
return n;
@@ -222,7 +193,7 @@ TxMeta::getAffectedNode(uint256 const& node)
// LCOV_EXCL_START
UNREACHABLE("ripple::TxMeta::getAffectedNode(uint256) : node not found");
Throw<std::runtime_error>("Affected node not found");
return *(mNodes.begin()); // Silence compiler warning.
return *(nodes_.begin()); // Silence compiler warning.
// LCOV_EXCL_STOP
}
@@ -230,15 +201,15 @@ STObject
TxMeta::getAsObject() const
{
STObject metaData(sfTransactionMetaData);
XRPL_ASSERT(mResult != 255, "ripple::TxMeta::getAsObject : result is set");
metaData.setFieldU8(sfTransactionResult, mResult);
metaData.setFieldU32(sfTransactionIndex, mIndex);
metaData.emplace_back(mNodes);
if (hasDeliveredAmount())
metaData.setFieldAmount(sfDeliveredAmount, getDeliveredAmount());
XRPL_ASSERT(result_ != 255, "ripple::TxMeta::getAsObject : result_ is set");
metaData.setFieldU8(sfTransactionResult, result_);
metaData.setFieldU32(sfTransactionIndex, index_);
metaData.emplace_back(nodes_);
if (deliveredAmount_.has_value())
metaData.setFieldAmount(sfDeliveredAmount, *deliveredAmount_);
if (hasParentBatchId())
metaData.setFieldH256(sfParentBatchID, getParentBatchId());
if (parentBatchID_.has_value())
metaData.setFieldH256(sfParentBatchID, *parentBatchID_);
return metaData;
}
@@ -246,13 +217,13 @@ TxMeta::getAsObject() const
void
TxMeta::addRaw(Serializer& s, TER result, std::uint32_t index)
{
mResult = TERtoInt(result);
mIndex = index;
result_ = TERtoInt(result);
index_ = index;
XRPL_ASSERT(
(mResult == 0) || ((mResult > 100) && (mResult <= 255)),
(result_ == 0) || ((result_ > 100) && (result_ <= 255)),
"ripple::TxMeta::addRaw : valid TER input");
mNodes.sort([](STObject const& o1, STObject const& o2) {
nodes_.sort([](STObject const& o1, STObject const& o2) {
return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex);
});

View File

@@ -1,12 +1,11 @@
#include <xrpld/shamap/SHAMap.h>
#include <xrpld/shamap/SHAMapAccountStateLeafNode.h>
#include <xrpld/shamap/SHAMapNodeID.h>
#include <xrpld/shamap/SHAMapSyncFilter.h>
#include <xrpld/shamap/SHAMapTxLeafNode.h>
#include <xrpld/shamap/SHAMapTxPlusMetaLeafNode.h>
#include <xrpl/basics/TaggedCache.ipp>
#include <xrpl/basics/contract.h>
#include <xrpl/shamap/SHAMap.h>
#include <xrpl/shamap/SHAMapAccountStateLeafNode.h>
#include <xrpl/shamap/SHAMapNodeID.h>
#include <xrpl/shamap/SHAMapSyncFilter.h>
#include <xrpl/shamap/SHAMapTxLeafNode.h>
#include <xrpl/shamap/SHAMapTxPlusMetaLeafNode.h>
namespace ripple {

View File

@@ -1,7 +1,6 @@
#include <xrpld/shamap/SHAMap.h>
#include <xrpl/basics/IntrusivePointer.ipp>
#include <xrpl/basics/contract.h>
#include <xrpl/shamap/SHAMap.h>
#include <array>
#include <stack>

View File

@@ -1,13 +1,12 @@
#include <xrpld/shamap/SHAMapInnerNode.h>
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpld/shamap/detail/TaggedPointer.ipp>
#include <xrpl/basics/IntrusivePointer.ipp>
#include <xrpl/basics/Slice.h>
#include <xrpl/basics/contract.h>
#include <xrpl/basics/spinlock.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/digest.h>
#include <xrpl/shamap/SHAMapInnerNode.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <xrpl/shamap/detail/TaggedPointer.ipp>
namespace ripple {

View File

@@ -1,4 +1,4 @@
#include <xrpld/shamap/SHAMapLeafNode.h>
#include <xrpl/shamap/SHAMapLeafNode.h>
namespace ripple {

View File

@@ -1,9 +1,8 @@
#include <xrpld/shamap/SHAMap.h>
#include <xrpld/shamap/SHAMapNodeID.h>
#include <xrpl/beast/core/LexicalCast.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/shamap/SHAMap.h>
#include <xrpl/shamap/SHAMapNodeID.h>
namespace ripple {

View File

@@ -1,7 +1,7 @@
#include <xrpld/shamap/SHAMap.h>
#include <xrpld/shamap/SHAMapSyncFilter.h>
#include <xrpl/basics/random.h>
#include <xrpl/shamap/SHAMap.h>
#include <xrpl/shamap/SHAMapLeafNode.h>
#include <xrpl/shamap/SHAMapSyncFilter.h>
namespace ripple {
@@ -572,16 +572,16 @@ SHAMap::addKnownNode(
}
auto const generation = f_.getFullBelowCache()->getGeneration();
SHAMapNodeID iNodeID;
auto iNode = root_.get();
SHAMapNodeID currNodeID;
auto currNode = root_.get();
while (iNode->isInner() &&
!static_cast<SHAMapInnerNode*>(iNode)->isFullBelow(generation) &&
(iNodeID.getDepth() < node.getDepth()))
while (currNode->isInner() &&
!static_cast<SHAMapInnerNode*>(currNode)->isFullBelow(generation) &&
(currNodeID.getDepth() < node.getDepth()))
{
int branch = selectBranch(iNodeID, node.getNodeID());
int const branch = selectBranch(currNodeID, node.getNodeID());
XRPL_ASSERT(branch >= 0, "ripple::SHAMap::addKnownNode : valid branch");
auto inner = static_cast<SHAMapInnerNode*>(iNode);
auto inner = static_cast<SHAMapInnerNode*>(currNode);
if (inner->isEmptyBranch(branch))
{
JLOG(journal_.warn()) << "Add known node for empty branch" << node;
@@ -595,10 +595,12 @@ SHAMap::addKnownNode(
}
auto prevNode = inner;
std::tie(iNode, iNodeID) = descend(inner, iNodeID, branch, filter);
std::tie(currNode, currNodeID) =
descend(inner, currNodeID, branch, filter);
if (currNode != nullptr)
continue;
if (iNode == nullptr)
{
auto newNode = SHAMapTreeNode::makeFromWire(rawNode);
if (!newNode || childHash != newNode->getHash())
@@ -607,24 +609,49 @@ SHAMap::addKnownNode(
return SHAMapAddNode::invalid();
}
// In rare cases, a node can still be corrupt even after hash
// validation. For leaf nodes, we perform an additional check to
// ensure the node's position in the tree is consistent with its
// content to prevent inconsistencies that could
// propagate further down the line.
if (newNode->isLeaf())
{
auto const& actualKey =
static_cast<SHAMapLeafNode const*>(newNode.get())
->peekItem()
->key();
// Validate that this leaf belongs at the target position
auto const expectedNodeID =
SHAMapNodeID::createID(node.getDepth(), actualKey);
if (expectedNodeID.getNodeID() != node.getNodeID())
{
JLOG(journal_.debug())
<< "Leaf node position mismatch: "
<< "expected=" << expectedNodeID.getNodeID()
<< ", actual=" << node.getNodeID();
return SHAMapAddNode::invalid();
}
}
// Inner nodes must be at a level strictly less than 64
// but leaf nodes (while notionally at level 64) can be
// at any depth up to and including 64:
if ((iNodeID.getDepth() > leafDepth) ||
(newNode->isInner() && iNodeID.getDepth() == leafDepth))
if ((currNodeID.getDepth() > leafDepth) ||
(newNode->isInner() && currNodeID.getDepth() == leafDepth))
{
// Map is provably invalid
state_ = SHAMapState::Invalid;
return SHAMapAddNode::useful();
}
if (iNodeID != node)
if (currNodeID != node)
{
// Either this node is broken or we didn't request it (yet)
JLOG(journal_.warn()) << "unable to hook node " << node;
JLOG(journal_.info()) << " stuck at " << iNodeID;
JLOG(journal_.info()) << " stuck at " << currNodeID;
JLOG(journal_.info()) << "got depth=" << node.getDepth()
<< ", walked to= " << iNodeID.getDepth();
<< ", walked to= " << currNodeID.getDepth();
return SHAMapAddNode::useful();
}
@@ -647,7 +674,6 @@ SHAMap::addKnownNode(
return SHAMapAddNode::useful();
}
}
JLOG(journal_.trace()) << "got node, already had it (late)";
return SHAMapAddNode::duplicate();

View File

@@ -1,15 +1,14 @@
#include <xrpld/shamap/SHAMapAccountStateLeafNode.h>
#include <xrpld/shamap/SHAMapInnerNode.h>
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpld/shamap/SHAMapTxLeafNode.h>
#include <xrpld/shamap/SHAMapTxPlusMetaLeafNode.h>
#include <xrpl/basics/IntrusivePointer.ipp>
#include <xrpl/basics/Slice.h>
#include <xrpl/basics/contract.h>
#include <xrpl/basics/safe_cast.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/digest.h>
#include <xrpl/shamap/SHAMapAccountStateLeafNode.h>
#include <xrpl/shamap/SHAMapInnerNode.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <xrpl/shamap/SHAMapTxLeafNode.h>
#include <xrpl/shamap/SHAMapTxPlusMetaLeafNode.h>
namespace ripple {

View File

@@ -526,8 +526,7 @@ public:
for (auto const& [hash, nVotes] : votes)
{
if (rules.enabled(fixAmendmentMajorityCalc) ? nVotes >= i
: nVotes > i)
if (nVotes >= i)
{
// We vote yes on this amendment
field.push_back(hash);
@@ -963,10 +962,6 @@ public:
void
testChangedUNL(FeatureBitset const& feat)
{
// This test doesn't work without fixAmendmentMajorityCalc enabled.
if (!feat[fixAmendmentMajorityCalc])
return;
testcase("changedUNL");
auto const testAmendment = amendmentId("changedUNL");
@@ -1124,10 +1119,6 @@ public:
void
testValidatorFlapping(FeatureBitset const& feat)
{
// This test doesn't work without fixAmendmentMajorityCalc enabled.
if (!feat[fixAmendmentMajorityCalc])
return;
testcase("validatorFlapping");
// We run a test where a validator flaps on and off every 23 hours
@@ -1270,14 +1261,12 @@ public:
run() override
{
FeatureBitset const all{test::jtx::testable_amendments()};
FeatureBitset const fixMajorityCalc{fixAmendmentMajorityCalc};
testConstruct();
testGet();
testBadConfig();
testEnableVeto();
testHasUnsupported();
testFeature(all - fixMajorityCalc);
testFeature(all);
}
};

View File

@@ -3927,14 +3927,13 @@ class Batch_test : public beast::unit_test::suite
tesSUCCESS,
batch::outer(gw, seq, batchFee, tfIndependent),
batch::inner(jv1, seq + 1),
// tecNO_DELEGATE_PERMISSION: not authorized to clear freeze
// terNO_DELEGATE_PERMISSION: not authorized to clear freeze
batch::inner(jv2, seq + 2));
env.close();
std::vector<TestLedgerData> testCases = {
{0, "Batch", "tesSUCCESS", batchID, std::nullopt},
{1, "TrustSet", "tesSUCCESS", txIDs[0], batchID},
{2, "TrustSet", "tecNO_DELEGATE_PERMISSION", txIDs[1], batchID},
};
validateClosedLedger(env, testCases);
}

View File

@@ -539,6 +539,39 @@ struct Credentials_test : public beast::unit_test::suite
jle[jss::result][jss::node]["CredentialType"] ==
strHex(std::string_view(credType)));
}
{
testcase("Credentials fail, directory full");
std::uint32_t const issuerSeq{env.seq(issuer) + 1};
env(ticket::create(issuer, 63));
env.close();
// Everything below can only be tested on open ledger.
auto const res1 = directory::bumpLastPage(
env,
directory::maximumPageIndex(env),
keylet::ownerDir(issuer.id()),
directory::adjustOwnerNode);
BEAST_EXPECT(res1);
auto const jv = credentials::create(issuer, subject, credType);
env(jv, ter(tecDIR_FULL));
// Free one directory entry by using a ticket
env(noop(issuer), ticket::use(issuerSeq + 40));
// Fill subject directory
env(ticket::create(subject, 63));
auto const res2 = directory::bumpLastPage(
env,
directory::maximumPageIndex(env),
keylet::ownerDir(subject.id()),
directory::adjustOwnerNode);
BEAST_EXPECT(res2);
env(jv, ter(tecDIR_FULL));
// End test
env.close();
}
}
{
@@ -1065,6 +1098,7 @@ struct Credentials_test : public beast::unit_test::suite
testSuccessful(all);
testCredentialsDelete(all);
testCreateFailed(all);
testCreateFailed(all - fixDirectoryLimit);
testAcceptFailed(all);
testDeleteFailed(all);
testFeatureFailed(all - featureCredentials);

View File

@@ -10,23 +10,27 @@ namespace test {
class Delegate_test : public beast::unit_test::suite
{
void
testFeatureDisabled()
testFeatureDisabled(FeatureBitset features)
{
testcase("test featurePermissionDelegation not enabled");
testcase("test feature not enabled");
using namespace jtx;
Env env{*this, testable_amendments() - featurePermissionDelegation};
Env env{*this, features};
Account gw{"gateway"};
Account alice{"alice"};
Account bob{"bob"};
env.fund(XRP(1000000), gw, alice, bob);
env.close();
auto res = features[featurePermissionDelegationV1_1] ? ter(tesSUCCESS)
: ter(temDISABLED);
// can not set Delegate when feature disabled
env(delegate::set(gw, alice, {"Payment"}), ter(temDISABLED));
env(delegate::set(gw, alice, {"Payment"}), res);
env.close();
// can not send delegating transaction when feature disabled
env(pay(alice, bob, XRP(100)), delegate::as(bob), ter(temDISABLED));
env(pay(gw, bob, XRP(100)), delegate::as(alice), res);
}
void
@@ -200,17 +204,16 @@ class Delegate_test : public beast::unit_test::suite
}
// non-delegatable transaction
auto const res = features[fixDelegateV1_1] ? ter(temMALFORMED)
: ter(tecNO_PERMISSION);
{
env(delegate::set(gw, alice, {"SetRegularKey"}), res);
env(delegate::set(gw, alice, {"AccountSet"}), res);
env(delegate::set(gw, alice, {"SignerListSet"}), res);
env(delegate::set(gw, alice, {"DelegateSet"}), res);
env(delegate::set(gw, alice, {"EnableAmendment"}), res);
env(delegate::set(gw, alice, {"UNLModify"}), res);
env(delegate::set(gw, alice, {"SetFee"}), res);
env(delegate::set(gw, alice, {"Batch"}), res);
env(delegate::set(gw, alice, {"SetRegularKey"}), ter(temMALFORMED));
env(delegate::set(gw, alice, {"AccountSet"}), ter(temMALFORMED));
env(delegate::set(gw, alice, {"SignerListSet"}), ter(temMALFORMED));
env(delegate::set(gw, alice, {"DelegateSet"}), ter(temMALFORMED));
env(delegate::set(gw, alice, {"EnableAmendment"}),
ter(temMALFORMED));
env(delegate::set(gw, alice, {"UNLModify"}), ter(temMALFORMED));
env(delegate::set(gw, alice, {"SetFee"}), ter(temMALFORMED));
env(delegate::set(gw, alice, {"Batch"}), ter(temMALFORMED));
}
}
@@ -288,10 +291,6 @@ class Delegate_test : public beast::unit_test::suite
env.close();
{
// Fee should be checked before permission check,
// otherwise tecNO_DELEGATE_PERMISSION returned when permission
// check fails could cause context reset to pay fee because it is
// tec error
auto aliceBalance = env.balance(alice);
auto bobBalance = env.balance(bob);
auto carolBalance = env.balance(carol);
@@ -299,7 +298,7 @@ class Delegate_test : public beast::unit_test::suite
env(pay(alice, carol, XRP(100)),
fee(XRP(2000)),
delegate::as(bob),
ter(terINSUF_FEE_B));
ter(terNO_DELEGATE_PERMISSION));
env.close();
BEAST_EXPECT(env.balance(alice) == aliceBalance);
BEAST_EXPECT(env.balance(bob) == bobBalance);
@@ -506,12 +505,12 @@ class Delegate_test : public beast::unit_test::suite
// bob does not have permission to create check
env(check::create(alice, bob, XRP(10)),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
// carol does not have permission to create check
env(check::create(alice, bob, XRP(10)),
delegate::as(carol),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
}
void
@@ -546,9 +545,8 @@ class Delegate_test : public beast::unit_test::suite
// delegate ledger object is not created yet
env(pay(gw, alice, USD(50)),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
env.require(balance(bob, bobBalance - drops(baseFee)));
bobBalance = env.balance(bob, XRP);
ter(terNO_DELEGATE_PERMISSION));
env.require(balance(bob, bobBalance));
// gw gives bob burn permission
env(delegate::set(gw, bob, {"PaymentBurn"}));
@@ -559,10 +557,9 @@ class Delegate_test : public beast::unit_test::suite
// bob sends a payment transaction on behalf of gw
env(pay(gw, alice, USD(50)),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env.close();
env.require(balance(bob, bobBalance - drops(baseFee)));
bobBalance = env.balance(bob, XRP);
env.require(balance(bob, bobBalance));
// gw gives bob mint permission, alice gives bob burn permission
env(delegate::set(gw, bob, {"PaymentMint"}));
@@ -576,10 +573,9 @@ class Delegate_test : public beast::unit_test::suite
// can not send XRP
env(pay(gw, alice, XRP(50)),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env.close();
env.require(balance(bob, bobBalance - drops(baseFee)));
bobBalance = env.balance(bob, XRP);
env.require(balance(bob, bobBalance));
// mint 50 USD
env(pay(gw, alice, USD(50)), delegate::as(bob));
@@ -664,10 +660,9 @@ class Delegate_test : public beast::unit_test::suite
// permission
env(pay(gw, alice, USD(50)),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env.close();
env.require(balance(bob, bobBalance - drops(baseFee)));
bobBalance = env.balance(bob, XRP);
env.require(balance(bob, bobBalance));
// gw gives bob Payment permission as well
env(delegate::set(gw, bob, {"PaymentBurn", "Payment"}));
@@ -706,11 +701,6 @@ class Delegate_test : public beast::unit_test::suite
env(pay(gw, carol, USD(10000)));
env.close();
auto const result = features[fixDelegateV1_1]
? static_cast<TER>(tecNO_DELEGATE_PERMISSION)
: static_cast<TER>(tesSUCCESS);
auto const offerCount = features[fixDelegateV1_1] ? 1 : 0;
// PaymentMint
{
env(offer(carol, XRP(100), USD(501)));
@@ -718,16 +708,21 @@ class Delegate_test : public beast::unit_test::suite
env(delegate::set(gw, bob, {"PaymentMint"}));
env.close();
// post-amendment: fixDelegateV1_1
// bob can not send cross currency payment on behalf of the gw,
// even with PaymentMint permission and gw being the issuer.
env(pay(gw, alice, USD(5000)),
path(~USD),
sendmax(XRP(1001)),
txflags(tfPartialPayment),
delegate::as(bob),
ter(result));
BEAST_EXPECT(expectOffers(env, carol, offerCount));
ter(terNO_DELEGATE_PERMISSION));
BEAST_EXPECT(expectOffers(env, carol, 1));
env(pay(gw, alice, USD(5000)),
path(~XRP),
txflags(tfPartialPayment),
delegate::as(bob),
ter(terNO_DELEGATE_PERMISSION));
BEAST_EXPECT(expectOffers(env, carol, 1));
// succeed with direct payment
env(pay(gw, alice, USD(100)), delegate::as(bob));
@@ -741,16 +736,21 @@ class Delegate_test : public beast::unit_test::suite
env(delegate::set(alice, bob, {"PaymentBurn"}));
env.close();
// post-amendment: fixDelegateV1_1
// bob can not send cross currency payment on behalf of alice,
// even with PaymentBurn permission and gw being the issuer.
env(pay(alice, gw, USD(5000)),
path(~USD),
sendmax(XRP(1001)),
txflags(tfPartialPayment),
delegate::as(bob),
ter(result));
BEAST_EXPECT(expectOffers(env, bob, offerCount));
ter(terNO_DELEGATE_PERMISSION));
BEAST_EXPECT(expectOffers(env, bob, 1));
env(pay(alice, gw, USD(5000)),
path(~XRP),
txflags(tfPartialPayment),
delegate::as(bob),
ter(terNO_DELEGATE_PERMISSION));
BEAST_EXPECT(expectOffers(env, bob, 1));
// succeed with direct payment
env(pay(alice, gw, USD(100)), delegate::as(bob));
@@ -785,45 +785,24 @@ class Delegate_test : public beast::unit_test::suite
env(delegate::set(gw, bob, {"PaymentMint"}));
env.close();
if (!features[fixDelegateV1_1])
{
// pre-amendment: PaymentMint is not supported for MPT
env(pay(gw, alice, MPT(50)),
delegate::as(bob),
ter(tefEXCEPTION));
}
else
{
env(pay(gw, alice, MPT(50)), delegate::as(bob));
BEAST_EXPECT(env.balance(alice, MPT) == aliceMPT + MPT(50));
BEAST_EXPECT(env.balance(bob, MPT) == bobMPT);
aliceMPT = env.balance(alice, MPT);
}
}
// PaymentBurn
{
env(delegate::set(alice, bob, {"PaymentBurn"}));
env.close();
if (!features[fixDelegateV1_1])
{
// pre-amendment: PaymentBurn is not supported for MPT
env(pay(alice, gw, MPT(50)),
delegate::as(bob),
ter(tefEXCEPTION));
}
else
{
env(pay(alice, gw, MPT(50)), delegate::as(bob));
BEAST_EXPECT(env.balance(alice, MPT) == aliceMPT - MPT(50));
BEAST_EXPECT(env.balance(bob, MPT) == bobMPT);
aliceMPT = env.balance(alice, MPT);
}
}
// Payment transaction for MPT is allowed for both pre and post
// amendment
// Grant both granular permissions and tx level permission.
{
env(delegate::set(
alice, bob, {"PaymentBurn", "PaymentMint", "Payment"}));
@@ -861,7 +840,7 @@ class Delegate_test : public beast::unit_test::suite
// has unfreeze permission
env(trust(alice, gw["USD"](50)),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env.close();
// alice creates trustline by herself
@@ -875,38 +854,38 @@ class Delegate_test : public beast::unit_test::suite
// unsupported flags
env(trust(alice, gw["USD"](50), tfSetNoRipple),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env(trust(alice, gw["USD"](50), tfClearNoRipple),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env(trust(gw, gw["USD"](0), alice, tfSetDeepFreeze),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env(trust(gw, gw["USD"](0), alice, tfClearDeepFreeze),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env.close();
// supported flags with wrong permission
env(trust(gw, gw["USD"](0), alice, tfSetfAuth),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env(trust(gw, gw["USD"](0), alice, tfSetFreeze),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env.close();
env(delegate::set(gw, bob, {"TrustlineAuthorize"}));
env.close();
env(trust(gw, gw["USD"](0), alice, tfClearFreeze),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env.close();
// although trustline authorize is granted, bob can not change the
// limit number
env(trust(gw, gw["USD"](50), alice, tfSetfAuth),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env.close();
// supported flags with correct permission
@@ -927,30 +906,30 @@ class Delegate_test : public beast::unit_test::suite
// permission
env(trust(gw, gw["USD"](0), alice, tfSetFreeze),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
// cannot update LimitAmount with granular permission, both high and
// low account
env(trust(alice, gw["USD"](100)),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env(trust(gw, alice["USD"](100)),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
// can not set QualityIn or QualityOut
auto tx = trust(alice, gw["USD"](50));
tx["QualityIn"] = "1000";
env(tx, delegate::as(bob), ter(tecNO_DELEGATE_PERMISSION));
env(tx, delegate::as(bob), ter(terNO_DELEGATE_PERMISSION));
auto tx2 = trust(alice, gw["USD"](50));
tx2["QualityOut"] = "1000";
env(tx2, delegate::as(bob), ter(tecNO_DELEGATE_PERMISSION));
env(tx2, delegate::as(bob), ter(terNO_DELEGATE_PERMISSION));
auto tx3 = trust(gw, alice["USD"](50));
tx3["QualityIn"] = "1000";
env(tx3, delegate::as(bob), ter(tecNO_DELEGATE_PERMISSION));
env(tx3, delegate::as(bob), ter(terNO_DELEGATE_PERMISSION));
auto tx4 = trust(gw, alice["USD"](50));
tx4["QualityOut"] = "1000";
env(tx4, delegate::as(bob), ter(tecNO_DELEGATE_PERMISSION));
env(tx4, delegate::as(bob), ter(terNO_DELEGATE_PERMISSION));
// granting TrustSet can make it work
env(delegate::set(gw, bob, {"TrustSet"}));
@@ -960,7 +939,7 @@ class Delegate_test : public beast::unit_test::suite
env(tx5, delegate::as(bob));
auto tx6 = trust(alice, gw["USD"](50));
tx6["QualityOut"] = "1000";
env(tx6, delegate::as(bob), ter(tecNO_DELEGATE_PERMISSION));
env(tx6, delegate::as(bob), ter(terNO_DELEGATE_PERMISSION));
env(delegate::set(alice, bob, {"TrustSet"}));
env.close();
env(tx6, delegate::as(bob));
@@ -979,14 +958,14 @@ class Delegate_test : public beast::unit_test::suite
// bob does not have permission
env(trust(alice, gw["USD"](50)),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env(delegate::set(
alice, bob, {"TrustlineUnfreeze", "NFTokenCreateOffer"}));
env.close();
// bob still does not have permission
env(trust(alice, gw["USD"](50)),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
// add TrustSet permission and some unrelated permission
env(delegate::set(
@@ -1079,7 +1058,7 @@ class Delegate_test : public beast::unit_test::suite
env(delegate::set(
alice, bob, {"TrustlineUnfreeze", "AccountEmailHashSet"}));
env.close();
env(jt, ter(tecNO_DELEGATE_PERMISSION));
env(jt, ter(terNO_DELEGATE_PERMISSION));
// alice give granular permission of AccountDomainSet to bob
env(delegate::set(alice, bob, {"AccountDomainSet"}));
@@ -1098,7 +1077,7 @@ class Delegate_test : public beast::unit_test::suite
std::string const failDomain = "fail_domain_update";
jt[sfFlags] = tfRequireAuth;
jt[sfDomain] = strHex(failDomain);
env(jt, ter(tecNO_DELEGATE_PERMISSION));
env(jt, ter(terNO_DELEGATE_PERMISSION));
// reset flag number
jt[sfFlags] = 0;
@@ -1107,7 +1086,7 @@ class Delegate_test : public beast::unit_test::suite
jt[sfDomain] = strHex(domain);
std::string const mh("5F31A79367DC3137FADA860C05742EE6");
jt[sfEmailHash] = mh;
env(jt, ter(tecNO_DELEGATE_PERMISSION));
env(jt, ter(terNO_DELEGATE_PERMISSION));
// alice give granular permission of AccountEmailHashSet to bob
env(delegate::set(
@@ -1120,7 +1099,7 @@ class Delegate_test : public beast::unit_test::suite
// bob does not have permission to set message key for alice
auto const rkp = randomKeyPair(KeyType::ed25519);
jt[sfMessageKey] = strHex(rkp.first.slice());
env(jt, ter(tecNO_DELEGATE_PERMISSION));
env(jt, ter(terNO_DELEGATE_PERMISSION));
// alice give granular permission of AccountMessageKeySet to bob
env(delegate::set(
@@ -1143,7 +1122,7 @@ class Delegate_test : public beast::unit_test::suite
// bob does not have permission to set transfer rate for alice
env(rate(alice, 2.0),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
// alice give granular permission of AccountTransferRateSet to bob
env(delegate::set(
@@ -1161,7 +1140,7 @@ class Delegate_test : public beast::unit_test::suite
// bob does not have permission to set ticksize for alice
jt[sfTickSize] = 8;
env(jt, ter(tecNO_DELEGATE_PERMISSION));
env(jt, ter(terNO_DELEGATE_PERMISSION));
// alice give granular permission of AccountTickSizeSet to bob
env(delegate::set(
@@ -1179,7 +1158,7 @@ class Delegate_test : public beast::unit_test::suite
// can not set asfRequireAuth flag for alice
env(fset(alice, asfRequireAuth),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
// reset Delegate will delete the Delegate
// object
@@ -1188,7 +1167,7 @@ class Delegate_test : public beast::unit_test::suite
// alice
env(fset(alice, asfRequireAuth),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
// alice can set for herself
env(fset(alice, asfRequireAuth));
env.require(flags(alice, asfRequireAuth));
@@ -1196,7 +1175,7 @@ class Delegate_test : public beast::unit_test::suite
// can not update tick size because bob no longer has permission
jt[sfTickSize] = 7;
env(jt, ter(tecNO_DELEGATE_PERMISSION));
env(jt, ter(terNO_DELEGATE_PERMISSION));
env(delegate::set(
alice,
@@ -1214,7 +1193,7 @@ class Delegate_test : public beast::unit_test::suite
jv2[sfDomain] = strHex(domain);
jv2[sfDelegate] = bob.human();
jv2[sfWalletLocator] = locator;
env(jv2, ter(tecNO_DELEGATE_PERMISSION));
env(jv2, ter(terNO_DELEGATE_PERMISSION));
}
// can not set AccountSet flags on behalf of other account
@@ -1229,7 +1208,7 @@ class Delegate_test : public beast::unit_test::suite
// bob can not set flag on behalf of alice
env(fset(alice, flag),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
// alice set by herself
env(fset(alice, flag));
env.close();
@@ -1237,7 +1216,7 @@ class Delegate_test : public beast::unit_test::suite
// bob can not clear on behalf of alice
env(fclear(alice, flag),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
};
// testSetClearFlag(asfNoFreeze);
@@ -1266,19 +1245,19 @@ class Delegate_test : public beast::unit_test::suite
// bob can not set asfAccountTxnID on behalf of alice
env(fset(alice, asfAccountTxnID),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env(fset(alice, asfAccountTxnID));
env.close();
BEAST_EXPECT(env.le(alice)->isFieldPresent(sfAccountTxnID));
env(fclear(alice, asfAccountTxnID),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
// bob can not set asfAuthorizedNFTokenMinter on behalf of alice
Json::Value jt = fset(alice, asfAuthorizedNFTokenMinter);
jt[sfDelegate] = bob.human();
jt[sfNFTokenMinter] = bob.human();
env(jt, ter(tecNO_DELEGATE_PERMISSION));
env(jt, ter(terNO_DELEGATE_PERMISSION));
// bob gives alice some permissions
env(delegate::set(
@@ -1294,14 +1273,14 @@ class Delegate_test : public beast::unit_test::suite
// behalf of bob.
env(fset(alice, asfNoFreeze),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
env(fset(bob, asfNoFreeze));
env.close();
env.require(flags(bob, asfNoFreeze));
// alice can not clear on behalf of bob
env(fclear(alice, asfNoFreeze),
delegate::as(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
// bob can not set asfDisableMaster on behalf of alice
Account const bobKey{"bobKey", KeyType::secp256k1};
@@ -1310,7 +1289,7 @@ class Delegate_test : public beast::unit_test::suite
env(fset(alice, asfDisableMaster),
delegate::as(bob),
sig(bob),
ter(tecNO_DELEGATE_PERMISSION));
ter(terNO_DELEGATE_PERMISSION));
}
// tfFullyCanonicalSig won't block delegated transaction
@@ -1360,7 +1339,7 @@ class Delegate_test : public beast::unit_test::suite
{.account = alice,
.flags = tfMPTLock,
.delegate = bob,
.err = tecNO_DELEGATE_PERMISSION});
.err = terNO_DELEGATE_PERMISSION});
// alice gives granular permission to bob of MPTokenIssuanceUnlock
env(delegate::set(alice, bob, {"MPTokenIssuanceUnlock"}));
@@ -1370,7 +1349,7 @@ class Delegate_test : public beast::unit_test::suite
{.account = alice,
.flags = tfMPTLock,
.delegate = bob,
.err = tecNO_DELEGATE_PERMISSION});
.err = terNO_DELEGATE_PERMISSION});
// bob now has lock permission, but does not have unlock permission
env(delegate::set(alice, bob, {"MPTokenIssuanceLock"}));
env.close();
@@ -1379,7 +1358,7 @@ class Delegate_test : public beast::unit_test::suite
{.account = alice,
.flags = tfMPTUnlock,
.delegate = bob,
.err = tecNO_DELEGATE_PERMISSION});
.err = terNO_DELEGATE_PERMISSION});
// now bob can lock and unlock
env(delegate::set(
@@ -1412,7 +1391,7 @@ class Delegate_test : public beast::unit_test::suite
{.account = alice,
.flags = tfMPTUnlock,
.delegate = bob,
.err = tecNO_DELEGATE_PERMISSION});
.err = terNO_DELEGATE_PERMISSION});
// alice gives bob some unrelated permission with
// MPTokenIssuanceLock
@@ -1426,7 +1405,7 @@ class Delegate_test : public beast::unit_test::suite
{.account = alice,
.flags = tfMPTUnlock,
.delegate = bob,
.err = tecNO_DELEGATE_PERMISSION});
.err = terNO_DELEGATE_PERMISSION});
// alice add MPTokenIssuanceSet to permissions
env(delegate::set(
@@ -1502,6 +1481,7 @@ class Delegate_test : public beast::unit_test::suite
testcase("test single sign with bad secret");
using namespace jtx;
{
Env env(*this);
Account alice{"alice"};
Account bob{"bob"};
@@ -1527,6 +1507,72 @@ class Delegate_test : public beast::unit_test::suite
BEAST_EXPECT(env.balance(carol) == carolBalance);
}
{
Env env(*this);
Account alice{"alice"}, bob{"bob"}, carol{"carol"};
env.fund(XRP(100000), alice, bob, carol);
env.close();
env(delegate::set(alice, bob, {"TrustSet"}));
env.close();
auto aliceBalance = env.balance(alice);
auto bobBalance = env.balance(bob);
auto carolBalance = env.balance(carol);
env(pay(alice, carol, XRP(100)),
fee(XRP(10)),
delegate::as(bob),
sig(carol),
ter(terNO_DELEGATE_PERMISSION));
env.close();
BEAST_EXPECT(env.balance(alice) == aliceBalance);
BEAST_EXPECT(env.balance(bob) == bobBalance);
BEAST_EXPECT(env.balance(carol) == carolBalance);
env(pay(alice, carol, XRP(100)),
fee(XRP(10)),
delegate::as(bob),
sig(alice),
ter(terNO_DELEGATE_PERMISSION));
env.close();
BEAST_EXPECT(env.balance(alice) == aliceBalance);
BEAST_EXPECT(env.balance(bob) == bobBalance);
BEAST_EXPECT(env.balance(carol) == carolBalance);
}
{
Env env(*this);
Account alice{"alice"}, bob{"bob"}, carol{"carol"};
env.fund(XRP(100000), alice, bob, carol);
env.close();
auto aliceBalance = env.balance(alice);
auto bobBalance = env.balance(bob);
auto carolBalance = env.balance(carol);
env(pay(alice, carol, XRP(100)),
fee(XRP(10)),
delegate::as(bob),
sig(alice),
ter(terNO_DELEGATE_PERMISSION));
env.close();
BEAST_EXPECT(env.balance(alice) == aliceBalance);
BEAST_EXPECT(env.balance(bob) == bobBalance);
BEAST_EXPECT(env.balance(carol) == carolBalance);
env(pay(alice, carol, XRP(100)),
fee(XRP(10)),
delegate::as(bob),
sig(carol),
ter(terNO_DELEGATE_PERMISSION));
env.close();
BEAST_EXPECT(env.balance(alice) == aliceBalance);
BEAST_EXPECT(env.balance(bob) == bobBalance);
BEAST_EXPECT(env.balance(carol) == carolBalance);
}
}
void
testMultiSign()
{
@@ -1642,9 +1688,6 @@ class Delegate_test : public beast::unit_test::suite
for (auto value : {0, 100000, 54321})
{
auto jv = buildRequest(value);
if (!features[fixDelegateV1_1])
env(jv);
else
env(jv, ter(temMALFORMED));
}
}
@@ -1703,8 +1746,7 @@ class Delegate_test : public beast::unit_test::suite
{"VaultWithdraw", featureSingleAssetVault},
{"VaultClawback", featureSingleAssetVault}};
// fixDelegateV1_1 post-amendment: can not delegate tx if any
// required feature disabled.
// Can not delegate tx if any required feature disabled.
{
auto txAmendmentDisabled = [&](FeatureBitset features,
std::string const& tx) {
@@ -1717,9 +1759,6 @@ class Delegate_test : public beast::unit_test::suite
env.fund(XRP(100000), alice, bob);
env.close();
if (!features[fixDelegateV1_1])
env(delegate::set(alice, bob, {tx}));
else
env(delegate::set(alice, bob, {tx}), ter(temMALFORMED));
};
@@ -1769,9 +1808,6 @@ class Delegate_test : public beast::unit_test::suite
"NFTokenCancelOffer",
"NFTokenAcceptOffer"})
{
if (!features[fixDelegateV1_1])
env(delegate::set(alice, bob, {tx}));
else
env(delegate::set(alice, bob, {tx}), ter(temMALFORMED));
}
}
@@ -1806,17 +1842,16 @@ class Delegate_test : public beast::unit_test::suite
{
FeatureBitset const all = jtx::testable_amendments();
testFeatureDisabled();
testFeatureDisabled(all - featurePermissionDelegationV1_1);
testFeatureDisabled(all);
testDelegateSet();
testInvalidRequest(all);
testInvalidRequest(all - fixDelegateV1_1);
testReserve();
testFee();
testSequence();
testAccountDelete();
testDelegateTransaction();
testPaymentGranular(all);
testPaymentGranular(all - fixDelegateV1_1);
testTrustSetGranular();
testAccountSetGranular();
testMPTokenIssuanceSetGranular();
@@ -1825,9 +1860,7 @@ class Delegate_test : public beast::unit_test::suite
testMultiSign();
testMultiSignQuorumNotMet();
testPermissionValue(all);
testPermissionValue(all - fixDelegateV1_1);
testTxReqireFeatures(all);
testTxReqireFeatures(all - fixDelegateV1_1);
}
};
BEAST_DEFINE_TESTSUITE(Delegate, app, ripple);

View File

@@ -61,12 +61,8 @@ public:
auto const bob = Account{"bob"};
auto const USD = gw["USD"];
// Make one test run without fixReducedOffersV1 and one with.
for (FeatureBitset features :
{testable_amendments() - fixReducedOffersV1,
testable_amendments() | fixReducedOffersV1})
{
Env env{*this, features};
Env env{*this, testable_amendments()};
// Make sure none of the offers we generate are under funded.
env.fund(XRP(10'000'000), gw, alice, bob);
@@ -189,20 +185,10 @@ public:
blockedCount += exerciseOfferPair(alicesOffer, bobsOffer);
}
// If fixReducedOffersV1 is enabled, then none of the test cases
// should produce a potentially blocking rate.
//
// Also verify that if fixReducedOffersV1 is not enabled then
// some of the test cases produced a potentially blocking rate.
if (features[fixReducedOffersV1])
{
// None of the test cases should produce a potentially blocking
// rate.
BEAST_EXPECT(blockedCount == 0);
}
else
{
BEAST_EXPECT(blockedCount >= 170);
}
}
}
void
@@ -217,13 +203,9 @@ public:
auto const bob = Account{"bob"};
auto const USD = gw["USD"];
// Make one test run without fixReducedOffersV1 and one with.
for (FeatureBitset features :
{testable_amendments() - fixReducedOffersV1,
testable_amendments() | fixReducedOffersV1})
{
// Make sure none of the offers we generate are under funded.
Env env{*this, features};
Env env{*this, testable_amendments()};
env.fund(XRP(10'000'000), gw, alice, bob);
env.close();
@@ -348,20 +330,10 @@ public:
blockedCount += exerciseOfferPair(aliceOffer, bobsOffer);
}
// If fixReducedOffersV1 is enabled, then none of the test cases
// should produce a potentially blocking rate.
//
// Also verify that if fixReducedOffersV1 is not enabled then
// some of the test cases produced a potentially blocking rate.
if (features[fixReducedOffersV1])
{
// None of the test cases should produce a potentially blocking
// rate.
BEAST_EXPECT(blockedCount == 0);
}
else
{
BEAST_EXPECT(blockedCount > 10);
}
}
}
void
@@ -370,9 +342,6 @@ public:
testcase("exercise underfunded XRP/IOU offer Q change");
// Bob places an offer that is not fully funded.
//
// This unit test compares the behavior of this situation before and
// after applying the fixReducedOffersV1 amendment.
using namespace jtx;
auto const alice = Account{"alice"};
@@ -380,12 +349,8 @@ public:
auto const gw = Account{"gw"};
auto const USD = gw["USD"];
// Make one test run without fixReducedOffersV1 and one with.
for (FeatureBitset features :
{testable_amendments() - fixReducedOffersV1,
testable_amendments() | fixReducedOffersV1})
{
Env env{*this, features};
Env env{*this, testable_amendments()};
env.fund(XRP(10000), alice, bob, gw);
env.close();
@@ -451,20 +416,10 @@ public:
}
}
// If fixReducedOffersV1 is enabled, then none of the test cases
// should produce a potentially blocking rate.
//
// Also verify that if fixReducedOffersV1 is not enabled then
// some of the test cases produced a potentially blocking rate.
if (features[fixReducedOffersV1])
{
// None of the test cases should produce a potentially blocking
// rate.
BEAST_EXPECT(blockedOrderBookCount == 0);
}
else
{
BEAST_EXPECT(blockedOrderBookCount > 15);
}
}
}
void
@@ -473,9 +428,6 @@ public:
testcase("exercise underfunded IOU/IOU offer Q change");
// Bob places an IOU/IOU offer that is not fully funded.
//
// This unit test compares the behavior of this situation before and
// after applying the fixReducedOffersV1 amendment.
using namespace jtx;
using namespace std::chrono_literals;
@@ -488,12 +440,8 @@ public:
STAmount const tinyUSD(USD.issue(), /*mantissa*/ 1, /*exponent*/ -81);
// Make one test run without fixReducedOffersV1 and one with.
for (FeatureBitset features :
{testable_amendments() - fixReducedOffersV1,
testable_amendments() | fixReducedOffersV1})
{
Env env{*this, features};
Env env{*this, testable_amendments()};
env.fund(XRP(10000), alice, bob, gw);
env.close();
@@ -575,20 +523,10 @@ public:
env.close();
}
// If fixReducedOffersV1 is enabled, then none of the test cases
// should produce a potentially blocking rate.
//
// Also verify that if fixReducedOffersV1 is not enabled then
// some of the test cases produced a potentially blocking rate.
if (features[fixReducedOffersV1])
{
// None of the test cases should produce a potentially blocking
// rate.
BEAST_EXPECT(blockedOrderBookCount == 0);
}
else
{
BEAST_EXPECT(blockedOrderBookCount > 20);
}
}
}
Amounts

View File

@@ -6,8 +6,8 @@
#include <xrpld/app/misc/SHAMapStore.h>
#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
#include <xrpld/core/ConfigSections.h>
#include <xrpld/nodestore/detail/DatabaseRotatingImp.h>
#include <xrpl/nodestore/detail/DatabaseRotatingImp.h>
#include <xrpl/protocol/jss.h>
namespace ripple {

View File

@@ -8,52 +8,12 @@ class SetRegularKey_test : public beast::unit_test::suite
{
public:
void
testDisableMasterKey()
testDisabledMasterKey()
{
using namespace test::jtx;
testcase("Set regular key");
Env env{*this, testable_amendments() - fixMasterKeyAsRegularKey};
Account const alice("alice");
Account const bob("bob");
env.fund(XRP(10000), alice, bob);
env(regkey(alice, bob));
auto const ar = env.le(alice);
BEAST_EXPECT(
ar->isFieldPresent(sfRegularKey) &&
(ar->getAccountID(sfRegularKey) == bob.id()));
env(noop(alice), sig(bob));
env(noop(alice), sig(alice));
testcase("Disable master key");
env(fset(alice, asfDisableMaster), sig(alice));
env(noop(alice), sig(bob));
env(noop(alice), sig(alice), ter(tefMASTER_DISABLED));
testcase("Re-enable master key");
env(fclear(alice, asfDisableMaster),
sig(alice),
ter(tefMASTER_DISABLED));
env(fclear(alice, asfDisableMaster), sig(bob));
env(noop(alice), sig(bob));
env(noop(alice), sig(alice));
testcase("Revoke regular key");
env(regkey(alice, disabled));
env(noop(alice), sig(bob), ter(tefBAD_AUTH_MASTER));
env(noop(alice), sig(alice));
}
void
testDisableMasterKeyAfterFix()
{
using namespace test::jtx;
testcase("Set regular key");
Env env{*this, testable_amendments() | fixMasterKeyAsRegularKey};
Env env{*this, testable_amendments()};
Account const alice("alice");
Account const bob("bob");
env.fund(XRP(10000), alice, bob);
@@ -87,44 +47,11 @@ public:
{
using namespace test::jtx;
// See https://ripplelabs.atlassian.net/browse/RIPD-1721.
testcase(
"Set regular key to master key (before fixMasterKeyAsRegularKey)");
Env env{*this, testable_amendments() - fixMasterKeyAsRegularKey};
testcase("Set regular key to master key");
Env env{*this, testable_amendments()};
Account const alice("alice");
env.fund(XRP(10000), alice);
// Must be possible unless amendment `fixMasterKeyAsRegularKey` enabled.
env(regkey(alice, alice), sig(alice));
env(fset(alice, asfDisableMaster), sig(alice));
// No way to sign...
env(noop(alice), ter(tefMASTER_DISABLED));
env(noop(alice), sig(alice), ter(tefMASTER_DISABLED));
// ... until now.
env.enableFeature(fixMasterKeyAsRegularKey);
env(noop(alice));
env(noop(alice), sig(alice));
env(regkey(alice, disabled), ter(tecNO_ALTERNATIVE_KEY));
env(fclear(alice, asfDisableMaster));
env(regkey(alice, disabled));
env(fset(alice, asfDisableMaster), ter(tecNO_ALTERNATIVE_KEY));
}
void
testDisableRegularKeyAfterFix()
{
using namespace test::jtx;
testcase(
"Set regular key to master key (after fixMasterKeyAsRegularKey)");
Env env{*this, testable_amendments() | fixMasterKeyAsRegularKey};
Account const alice("alice");
env.fund(XRP(10000), alice);
// Must be possible unless amendment `fixMasterKeyAsRegularKey` enabled.
env(regkey(alice, alice), ter(temBAD_REGKEY));
}
@@ -234,10 +161,8 @@ public:
void
run() override
{
testDisableMasterKey();
testDisableMasterKeyAfterFix();
testDisabledMasterKey();
testDisabledRegularKey();
testDisableRegularKeyAfterFix();
testPasswordSpent();
testUniversalMask();
testTicketRegularKey();

View File

@@ -20,6 +20,7 @@
#include <test/jtx/delivermin.h>
#include <test/jtx/deposit.h>
#include <test/jtx/did.h>
#include <test/jtx/directory.h>
#include <test/jtx/domain.h>
#include <test/jtx/escrow.h>
#include <test/jtx/fee.h>

View File

@@ -246,7 +246,7 @@ public:
{
using namespace jtx;
Env env{*this, testable_amendments() | fixMasterKeyAsRegularKey};
Env env{*this, testable_amendments()};
Account const alice("alice", KeyType::ed25519);
Account const bob("bob", KeyType::secp256k1);
Account const carol("carol");

62
src/test/jtx/directory.h Normal file
View File

@@ -0,0 +1,62 @@
#ifndef XRPL_TEST_JTX_DIRECTORY_H_INCLUDED
#define XRPL_TEST_JTX_DIRECTORY_H_INCLUDED
#include <test/jtx/Env.h>
#include <xrpl/basics/Expected.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <cstdint>
#include <limits>
namespace ripple::test::jtx {
/** Directory operations. */
namespace directory {
enum Error {
DirectoryRootNotFound,
DirectoryTooSmall,
DirectoryPageDuplicate,
DirectoryPageNotFound,
InvalidLastPage,
AdjustmentError
};
/// Move the position of the last page in the user's directory on open ledger to
/// newLastPage. Requirements:
/// - directory must have at least two pages (root and one more)
/// - adjust should be used to update owner nodes of the objects affected
/// - newLastPage must be greater than index of the last page in the directory
///
/// Use this to test tecDIR_FULL errors in open ledger.
/// NOTE: effects will be DISCARDED on env.close()
auto
bumpLastPage(
Env& env,
std::uint64_t newLastPage,
Keylet directory,
std::function<bool(ApplyView&, uint256, std::uint64_t)> adjust)
-> Expected<void, Error>;
/// Implementation of adjust for the most common ledger entry, i.e. one where
/// page index is stored in sfOwnerNode (and only there). Pass this function
/// to bumpLastPage if the last page of directory has only objects
/// of this kind (e.g. ticket, DID, offer, deposit preauth, MPToken etc.)
bool
adjustOwnerNode(ApplyView& view, uint256 key, std::uint64_t page);
inline auto
maximumPageIndex(Env const& env) -> std::uint64_t
{
if (env.enabled(fixDirectoryLimit))
return std::numeric_limits<std::uint64_t>::max();
return dirNodeMaxPages - 1;
}
} // namespace directory
} // namespace ripple::test::jtx
#endif

View File

@@ -0,0 +1,126 @@
#include <test/jtx/directory.h>
#include <xrpl/ledger/Sandbox.h>
namespace ripple::test::jtx {
/** Directory operations. */
namespace directory {
auto
bumpLastPage(
Env& env,
std::uint64_t newLastPage,
Keylet directory,
std::function<bool(ApplyView&, uint256, std::uint64_t)> adjust)
-> Expected<void, Error>
{
Expected<void, Error> res{};
env.app().openLedger().modify(
[&](OpenView& view, beast::Journal j) -> bool {
Sandbox sb(&view, tapNONE);
// Find the root page
auto sleRoot = sb.peek(directory);
if (!sleRoot)
{
res = Unexpected<Error>(DirectoryRootNotFound);
return false;
}
// Find last page
auto const lastIndex = sleRoot->getFieldU64(sfIndexPrevious);
if (lastIndex == 0)
{
res = Unexpected<Error>(DirectoryTooSmall);
return false;
}
if (sb.exists(keylet::page(directory, newLastPage)))
{
res = Unexpected<Error>(DirectoryPageDuplicate);
return false;
}
if (lastIndex >= newLastPage)
{
res = Unexpected<Error>(InvalidLastPage);
return false;
}
auto slePage = sb.peek(keylet::page(directory, lastIndex));
if (!slePage)
{
res = Unexpected<Error>(DirectoryPageNotFound);
return false;
}
// Copy its data and delete the page
auto indexes = slePage->getFieldV256(sfIndexes);
auto prevIndex = slePage->at(~sfIndexPrevious);
auto owner = slePage->at(~sfOwner);
sb.erase(slePage);
// Create new page to replace slePage
auto sleNew =
std::make_shared<SLE>(keylet::page(directory, newLastPage));
sleNew->setFieldH256(sfRootIndex, directory.key);
sleNew->setFieldV256(sfIndexes, indexes);
if (owner)
sleNew->setAccountID(sfOwner, *owner);
if (prevIndex)
sleNew->setFieldU64(sfIndexPrevious, *prevIndex);
sb.insert(sleNew);
// Adjust root previous and previous node's next
sleRoot->setFieldU64(sfIndexPrevious, newLastPage);
if (prevIndex.value_or(0) == 0)
sleRoot->setFieldU64(sfIndexNext, newLastPage);
else
{
auto slePrev = sb.peek(keylet::page(directory, *prevIndex));
if (!slePrev)
{
res = Unexpected<Error>(DirectoryPageNotFound);
return false;
}
slePrev->setFieldU64(sfIndexNext, newLastPage);
sb.update(slePrev);
}
sb.update(sleRoot);
// Fixup page numbers in the objects referred by indexes
if (adjust)
for (auto const key : indexes)
{
if (!adjust(sb, key, newLastPage))
{
res = Unexpected<Error>(AdjustmentError);
return false;
}
}
sb.apply(view);
return true;
});
return res;
}
bool
adjustOwnerNode(ApplyView& view, uint256 key, std::uint64_t page)
{
auto sle = view.peek({ltANY, key});
if (sle && sle->isFieldPresent(sfOwnerNode))
{
sle->setFieldU64(sfOwnerNode, page);
view.update(sle);
return true;
}
return false;
}
} // namespace directory
} // namespace ripple::test::jtx

View File

@@ -5,9 +5,11 @@
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/jss.h>
#include <algorithm>
#include <limits>
namespace ripple {
namespace test {
@@ -472,6 +474,91 @@ struct Directory_test : public beast::unit_test::suite
}
}
void
testDirectoryFull()
{
using namespace test::jtx;
Account alice("alice");
auto const testCase = [&, this](FeatureBitset features, auto setup) {
using namespace test::jtx;
Env env(*this, features);
env.fund(XRP(20000), alice);
env.close();
auto const [lastPage, full] = setup(env);
// Populate root page and last page
for (int i = 0; i < 63; ++i)
env(credentials::create(alice, alice, std::to_string(i)));
env.close();
// NOTE, everything below can only be tested on open ledger because
// there is no transaction type to express what bumpLastPage does.
// Bump position of last page from 1 to highest possible
auto const res = directory::bumpLastPage(
env,
lastPage,
keylet::ownerDir(alice.id()),
[lastPage, this](
ApplyView& view, uint256 key, std::uint64_t page) {
auto sle = view.peek({ltCREDENTIAL, key});
if (!BEAST_EXPECT(sle))
return false;
BEAST_EXPECT(page == lastPage);
sle->setFieldU64(sfIssuerNode, page);
// sfSubjectNode is not set in self-issued credentials
view.update(sle);
return true;
});
BEAST_EXPECT(res);
// Create one more credential
env(credentials::create(alice, alice, std::to_string(63)));
// Not enough space for another object if full
auto const expected = full ? ter{tecDIR_FULL} : ter{tesSUCCESS};
env(credentials::create(alice, alice, "foo"), expected);
// Destroy all objects in directory
for (int i = 0; i < 64; ++i)
env(credentials::deleteCred(
alice, alice, alice, std::to_string(i)));
if (!full)
env(credentials::deleteCred(alice, alice, alice, "foo"));
// Verify directory is empty.
auto const sle = env.le(keylet::ownerDir(alice.id()));
BEAST_EXPECT(sle == nullptr);
// Test completed
env.close();
};
testCase(
testable_amendments() - fixDirectoryLimit,
[this](Env&) -> std::tuple<std::uint64_t, bool> {
testcase("directory full without fixDirectoryLimit");
return {dirNodeMaxPages - 1, true};
});
testCase(
testable_amendments(), //
[this](Env&) -> std::tuple<std::uint64_t, bool> {
testcase("directory not full with fixDirectoryLimit");
return {dirNodeMaxPages - 1, false};
});
testCase(
testable_amendments(), //
[this](Env&) -> std::tuple<std::uint64_t, bool> {
testcase("directory full with fixDirectoryLimit");
return {std::numeric_limits<std::uint64_t>::max(), true};
});
}
void
run() override
{
@@ -480,6 +567,7 @@ struct Directory_test : public beast::unit_test::suite
testRipd1353();
testEmptyChain();
testPreviousTxnID();
testDirectoryFull();
}
};

View File

@@ -1,12 +1,11 @@
#include <test/nodestore/TestBase.h>
#include <test/unit_test/SuiteJournal.h>
#include <xrpld/nodestore/DummyScheduler.h>
#include <xrpld/nodestore/Manager.h>
#include <xrpld/unity/rocksdb.h>
#include <xrpl/basics/ByteUtilities.h>
#include <xrpl/basics/rocksdb.h>
#include <xrpl/beast/utility/temp_dir.h>
#include <xrpl/nodestore/DummyScheduler.h>
#include <xrpl/nodestore/Manager.h>
#include <algorithm>

View File

@@ -1,7 +1,7 @@
#include <test/nodestore/TestBase.h>
#include <xrpld/nodestore/detail/DecodedBlob.h>
#include <xrpld/nodestore/detail/EncodedBlob.h>
#include <xrpl/nodestore/detail/DecodedBlob.h>
#include <xrpl/nodestore/detail/EncodedBlob.h>
namespace ripple {
namespace NodeStore {

View File

@@ -5,10 +5,10 @@
#include <test/unit_test/SuiteJournal.h>
#include <xrpld/core/DatabaseCon.h>
#include <xrpld/nodestore/DummyScheduler.h>
#include <xrpld/nodestore/Manager.h>
#include <xrpl/beast/utility/temp_dir.h>
#include <xrpl/nodestore/DummyScheduler.h>
#include <xrpl/nodestore/Manager.h>
namespace ripple {

View File

@@ -1,12 +1,11 @@
#include <test/nodestore/TestBase.h>
#include <test/unit_test/SuiteJournal.h>
#include <xrpld/nodestore/DummyScheduler.h>
#include <xrpld/nodestore/Manager.h>
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/basics/ByteUtilities.h>
#include <xrpl/beast/utility/temp_dir.h>
#include <xrpl/nodestore/DummyScheduler.h>
#include <xrpl/nodestore/Manager.h>
#include <memory>
#include <sstream>

View File

@@ -1,15 +1,14 @@
#ifndef XRPL_NODESTORE_BASE_H_INCLUDED
#define XRPL_NODESTORE_BASE_H_INCLUDED
#include <xrpld/nodestore/Backend.h>
#include <xrpld/nodestore/Database.h>
#include <xrpld/nodestore/Types.h>
#include <xrpl/basics/StringUtilities.h>
#include <xrpl/basics/random.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/beast/utility/rngfill.h>
#include <xrpl/beast/xor_shift_engine.h>
#include <xrpl/nodestore/Backend.h>
#include <xrpl/nodestore/Database.h>
#include <xrpl/nodestore/Types.h>
#include <boost/algorithm/string.hpp>

View File

@@ -1,9 +1,6 @@
#include <test/nodestore/TestBase.h>
#include <test/unit_test/SuiteJournal.h>
#include <xrpld/nodestore/DummyScheduler.h>
#include <xrpld/nodestore/Manager.h>
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/basics/ByteUtilities.h>
#include <xrpl/basics/safe_cast.h>
@@ -11,6 +8,8 @@
#include <xrpl/beast/unit_test/thread.h>
#include <xrpl/beast/utility/temp_dir.h>
#include <xrpl/beast/xor_shift_engine.h>
#include <xrpl/nodestore/DummyScheduler.h>
#include <xrpl/nodestore/Manager.h>
#include <boost/algorithm/string.hpp>

View File

@@ -1,11 +1,10 @@
#include <xrpld/nodestore/detail/codec.h>
#include <xrpld/unity/rocksdb.h>
#include <xrpl/basics/contract.h>
#include <xrpl/basics/rocksdb.h>
#include <xrpl/beast/clock/basic_seconds_clock.h>
#include <xrpl/beast/core/LexicalCast.h>
#include <xrpl/beast/rfc2616.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/nodestore/detail/codec.h>
#include <boost/beast/core/string.hpp>
#include <boost/regex.hpp>

View File

@@ -1,6 +1,5 @@
#include <xrpld/nodestore/detail/varint.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/nodestore/detail/varint.h>
#include <array>
#include <vector>

View File

@@ -11,7 +11,6 @@
#include <xrpld/overlay/detail/Handshake.h>
#include <xrpld/overlay/detail/ProtocolMessage.h>
#include <xrpld/overlay/detail/ZeroCopyStream.h>
#include <xrpld/shamap/SHAMapNodeID.h>
#include <xrpl/basics/random.h>
#include <xrpl/beast/unit_test.h>
@@ -23,6 +22,7 @@
#include <xrpl/protocol/digest.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/protocol/messages.h>
#include <xrpl/shamap/SHAMapNodeID.h>
#include <boost/asio/ip/address_v4.hpp>
#include <boost/beast/core/multi_buffer.hpp>

View File

@@ -313,23 +313,6 @@ class Feature_test : public beast::unit_test::suite
result[jss::error_message] ==
"You don't have permission for this command.");
}
{
std::string const feature =
"C4483A1896170C66C098DEA5B0E024309C60DC960DE5F01CD7AF986AA3D9AD"
"37";
Json::Value params;
params[jss::feature] = feature;
auto const result =
env.rpc("json", "feature", to_string(params))[jss::result];
BEAST_EXPECT(result.isMember(feature));
auto const amendmentResult = result[feature];
BEAST_EXPECT(amendmentResult[jss::enabled].asBool() == false);
BEAST_EXPECT(amendmentResult[jss::supported].asBool() == true);
BEAST_EXPECT(
amendmentResult[jss::name].asString() ==
"fixMasterKeyAsRegularKey");
}
}
void

View File

@@ -1,15 +1,14 @@
#include <test/shamap/common.h>
#include <test/unit_test/SuiteJournal.h>
#include <xrpld/shamap/SHAMap.h>
#include <xrpld/shamap/SHAMapSyncFilter.h>
#include <xrpl/basics/UnorderedContainers.h>
#include <xrpl/basics/contract.h>
#include <xrpl/basics/random.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/beast/xor_shift_engine.h>
#include <xrpl/protocol/digest.h>
#include <xrpl/shamap/SHAMap.h>
#include <xrpl/shamap/SHAMapSyncFilter.h>
#include <functional>
#include <stdexcept>

View File

@@ -1,12 +1,11 @@
#include <test/shamap/common.h>
#include <test/unit_test/SuiteJournal.h>
#include <xrpld/shamap/SHAMap.h>
#include <xrpld/shamap/SHAMapItem.h>
#include <xrpl/basics/random.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/beast/xor_shift_engine.h>
#include <xrpl/shamap/SHAMap.h>
#include <xrpl/shamap/SHAMapItem.h>
namespace ripple {
namespace tests {

View File

@@ -1,12 +1,11 @@
#include <test/shamap/common.h>
#include <test/unit_test/SuiteJournal.h>
#include <xrpld/shamap/SHAMap.h>
#include <xrpl/basics/Blob.h>
#include <xrpl/basics/Buffer.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/shamap/SHAMap.h>
namespace ripple {
namespace tests {

Some files were not shown because too many files have changed in this diff Show More