Skip to content

Commit aa5c20a

Browse files
committed
Merge branch 'develop' into fix-innerobj-templ
2 parents 034b98e + 828bb64 commit aa5c20a

File tree

10 files changed

+418
-41
lines changed

10 files changed

+418
-41
lines changed

.github/workflows/windows.yml

+1-5
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,7 @@ jobs:
9191
# Hard code for now. Move to the matrix if varied options are needed
9292
cmake-args: '-Dassert=ON -Dreporting=OFF -Dunity=ON'
9393
cmake-target: install
94-
- name: test (permitted to silently fail)
94+
- name: test
9595
shell: bash
96-
# Github runners are resource limited, which causes unit tests to fail
97-
# (e.g. OOM). To allow forward progress until self-hosted runners are
98-
# up and running reliably, allow the job to succeed even if tests fail.
99-
continue-on-error: true
10096
run: |
10197
${build_dir}/${{ matrix.configuration }}/rippled --unittest --unittest-jobs $(nproc)

conanfile.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,9 @@ def package(self):
147147
def package_info(self):
148148
libxrpl = self.cpp_info.components['libxrpl']
149149
libxrpl.libs = [
150-
'libxrpl_core.a',
151-
'libed25519.a',
152-
'libsecp256k1.a',
150+
'xrpl_core',
151+
'ed25519',
152+
'secp256k1',
153153
]
154154
# TODO: Fix the protobufs to include each other relative to
155155
# `include/`, not `include/ripple/proto/`.

src/ripple/app/tx/impl/NFTokenAcceptOffer.cpp

+57-22
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,60 @@ NFTokenAcceptOffer::pay(
301301
return tesSUCCESS;
302302
}
303303

304+
TER
305+
NFTokenAcceptOffer::transferNFToken(
306+
AccountID const& buyer,
307+
AccountID const& seller,
308+
uint256 const& nftokenID)
309+
{
310+
auto tokenAndPage = nft::findTokenAndPage(view(), seller, nftokenID);
311+
312+
if (!tokenAndPage)
313+
return tecINTERNAL;
314+
315+
if (auto const ret = nft::removeToken(
316+
view(), seller, nftokenID, std::move(tokenAndPage->page));
317+
!isTesSuccess(ret))
318+
return ret;
319+
320+
auto const sleBuyer = view().read(keylet::account(buyer));
321+
if (!sleBuyer)
322+
return tecINTERNAL;
323+
324+
std::uint32_t const buyerOwnerCountBefore =
325+
sleBuyer->getFieldU32(sfOwnerCount);
326+
327+
auto const insertRet =
328+
nft::insertToken(view(), buyer, std::move(tokenAndPage->token));
329+
330+
// if fixNFTokenReserve is enabled, check if the buyer has sufficient
331+
// reserve to own a new object, if their OwnerCount changed.
332+
//
333+
// There was an issue where the buyer accepts a sell offer, the ledger
334+
// didn't check if the buyer has enough reserve, meaning that buyer can get
335+
// NFTs free of reserve.
336+
if (view().rules().enabled(fixNFTokenReserve))
337+
{
338+
// To check if there is sufficient reserve, we cannot use mPriorBalance
339+
// because NFT is sold for a price. So we must use the balance after
340+
// the deduction of the potential offer price. A small caveat here is
341+
// that the balance has already deducted the transaction fee, meaning
342+
// that the reserve requirement is a few drops higher.
343+
auto const buyerBalance = sleBuyer->getFieldAmount(sfBalance);
344+
345+
auto const buyerOwnerCountAfter = sleBuyer->getFieldU32(sfOwnerCount);
346+
if (buyerOwnerCountAfter > buyerOwnerCountBefore)
347+
{
348+
if (auto const reserve =
349+
view().fees().accountReserve(buyerOwnerCountAfter);
350+
buyerBalance < reserve)
351+
return tecINSUFFICIENT_RESERVE;
352+
}
353+
}
354+
355+
return insertRet;
356+
}
357+
304358
TER
305359
NFTokenAcceptOffer::acceptOffer(std::shared_ptr<SLE> const& offer)
306360
{
@@ -333,17 +387,7 @@ NFTokenAcceptOffer::acceptOffer(std::shared_ptr<SLE> const& offer)
333387
}
334388

335389
// Now transfer the NFT:
336-
auto tokenAndPage = nft::findTokenAndPage(view(), seller, nftokenID);
337-
338-
if (!tokenAndPage)
339-
return tecINTERNAL;
340-
341-
if (auto const ret = nft::removeToken(
342-
view(), seller, nftokenID, std::move(tokenAndPage->page));
343-
!isTesSuccess(ret))
344-
return ret;
345-
346-
return nft::insertToken(view(), buyer, std::move(tokenAndPage->token));
390+
return transferNFToken(buyer, seller, nftokenID);
347391
}
348392

349393
TER
@@ -431,17 +475,8 @@ NFTokenAcceptOffer::doApply()
431475
return r;
432476
}
433477

434-
auto tokenAndPage = nft::findTokenAndPage(view(), seller, nftokenID);
435-
436-
if (!tokenAndPage)
437-
return tecINTERNAL;
438-
439-
if (auto const ret = nft::removeToken(
440-
view(), seller, nftokenID, std::move(tokenAndPage->page));
441-
!isTesSuccess(ret))
442-
return ret;
443-
444-
return nft::insertToken(view(), buyer, std::move(tokenAndPage->token));
478+
// Now transfer the NFT:
479+
return transferNFToken(buyer, seller, nftokenID);
445480
}
446481

447482
if (bo)

src/ripple/app/tx/impl/NFTokenAcceptOffer.h

+6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ class NFTokenAcceptOffer : public Transactor
3838
std::shared_ptr<SLE> const& buy,
3939
std::shared_ptr<SLE> const& sell);
4040

41+
TER
42+
transferNFToken(
43+
AccountID const& buyer,
44+
AccountID const& seller,
45+
uint256 const& nfTokenID);
46+
4147
public:
4248
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
4349

src/ripple/protocol/Feature.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ namespace detail {
7474
// Feature.cpp. Because it's only used to reserve storage, and determine how
7575
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
7676
// the actual number of amendments. A LogicError on startup will verify this.
77-
static constexpr std::size_t numFeatures = 66;
77+
static constexpr std::size_t numFeatures = 67;
7878

7979
/** Amendments that this server supports and the default voting behavior.
8080
Whether they are enabled depends on the Rules defined in the validated
@@ -352,6 +352,7 @@ extern uint256 const featureXChainBridge;
352352
extern uint256 const fixDisallowIncomingV1;
353353
extern uint256 const featureDID;
354354
extern uint256 const fixFillOrKill;
355+
extern uint256 const fixNFTokenReserve;
355356
extern uint256 const fixInnerObjTemplate;
356357

357358
} // namespace ripple

src/ripple/protocol/impl/BuildInfo.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ namespace BuildInfo {
3333
// and follow the format described at http://semver.org/
3434
//------------------------------------------------------------------------------
3535
// clang-format off
36-
char const* const versionString = "2.0.1-rc1"
36+
char const* const versionString = "2.0.1"
3737
// clang-format on
3838

3939
#if defined(DEBUG) || defined(SANITIZER)

src/ripple/protocol/impl/Feature.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ REGISTER_FEATURE(XChainBridge, Supported::yes, VoteBehavior::De
459459
REGISTER_FIX (fixDisallowIncomingV1, Supported::yes, VoteBehavior::DefaultNo);
460460
REGISTER_FEATURE(DID, Supported::yes, VoteBehavior::DefaultNo);
461461
REGISTER_FIX(fixFillOrKill, Supported::yes, VoteBehavior::DefaultNo);
462+
REGISTER_FIX (fixNFTokenReserve, Supported::yes, VoteBehavior::DefaultNo);
462463
REGISTER_FIX(fixInnerObjTemplate, Supported::yes, VoteBehavior::DefaultNo);
463464

464465
// The following amendments are obsolete, but must remain supported

src/secp256k1/src/CMakeLists.txt

+10-3
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,16 @@ elseif(APPLE)
6464
endif()
6565
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
6666
set(${PROJECT_NAME}_windows "secp256k1")
67-
if(MSVC)
68-
set(${PROJECT_NAME}_windows "${PROJECT_NAME}")
69-
endif()
67+
# This step is commented out from the original. It is bad practice to change
68+
# the binary base name depending on the platform. CMake already manipulates
69+
# the base name into a final name that fits the conventions of the platform.
70+
# Linkers accept base names on the command line and then look for
71+
# conventional names on disk. This way, developers can use base names
72+
# everywhere (in the CMake and Conan they write) and the tools will do the
73+
# right thing.
74+
# if(MSVC)
75+
# set(${PROJECT_NAME}_windows "${PROJECT_NAME}")
76+
# endif()
7077
set_target_properties(secp256k1 PROPERTIES
7178
ARCHIVE_OUTPUT_NAME "${${PROJECT_NAME}_windows}"
7279
RUNTIME_OUTPUT_NAME "${${PROJECT_NAME}_windows}-${${PROJECT_NAME}_soversion}"

0 commit comments

Comments
 (0)