mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge remote-tracking branch 'origin/develop' into a1q123456/optimise-xxhash
This commit is contained in:
28
docs/build/environment.md
vendored
28
docs/build/environment.md
vendored
@@ -53,6 +53,34 @@ minimum required (see [BUILD.md][]).
|
||||
clang --version
|
||||
```
|
||||
|
||||
### Install Xcode Specific Version (Optional)
|
||||
|
||||
If you develop other applications using XCode you might be consistently updating to the newest version of Apple Clang.
|
||||
This will likely cause issues building rippled. You may want to install a specific version of Xcode:
|
||||
|
||||
1. **Download Xcode**
|
||||
|
||||
- Visit [Apple Developer Downloads](https://developer.apple.com/download/more/)
|
||||
- Sign in with your Apple Developer account
|
||||
- Search for an Xcode version that includes **Apple Clang (Expected Version)**
|
||||
- Download the `.xip` file
|
||||
|
||||
2. **Install and Configure Xcode**
|
||||
|
||||
```bash
|
||||
# Extract the .xip file and rename for version management
|
||||
# Example: Xcode_16.2.app
|
||||
|
||||
# Move to Applications directory
|
||||
sudo mv Xcode_16.2.app /Applications/
|
||||
|
||||
# Set as default toolchain (persistent)
|
||||
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
|
||||
|
||||
# Set as environment variable (temporary)
|
||||
export DEVELOPER_DIR=/Applications/Xcode_16.2.app/Contents/Developer
|
||||
```
|
||||
|
||||
The command line developer tools should include Git too:
|
||||
|
||||
```
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
// If you add an amendment here, then do not forget to increment `numFeatures`
|
||||
// in include/xrpl/protocol/Feature.h.
|
||||
|
||||
XRPL_FIX (MPTDeliveredAmount, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (AMMClawbackRounding, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(TokenEscrow, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <test/jtx/WSClient.h>
|
||||
|
||||
#include <xrpl/beast/unit_test.h>
|
||||
#include <xrpl/beast/unit_test/suite.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
namespace ripple {
|
||||
@@ -329,12 +330,95 @@ class DeliveredAmount_test : public beast::unit_test::suite
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testMPTDeliveredAmountRPC(FeatureBitset features)
|
||||
{
|
||||
testcase("MPT DeliveredAmount");
|
||||
|
||||
using namespace jtx;
|
||||
Account const alice("alice");
|
||||
Account const carol("carol");
|
||||
Account const bob("bob");
|
||||
Env env{*this, features};
|
||||
|
||||
MPTTester mptAlice(
|
||||
env, alice, {.holders = {bob, carol}, .close = false});
|
||||
|
||||
mptAlice.create(
|
||||
{.transferFee = 25000,
|
||||
.ownerCount = 1,
|
||||
.holderCount = 0,
|
||||
.flags = tfMPTCanTransfer});
|
||||
auto const MPT = mptAlice["MPT"];
|
||||
|
||||
mptAlice.authorize({.account = bob});
|
||||
mptAlice.authorize({.account = carol});
|
||||
|
||||
// issuer to holder
|
||||
mptAlice.pay(alice, bob, 10000);
|
||||
|
||||
// holder to holder
|
||||
env(pay(bob, carol, mptAlice.mpt(1000)), txflags(tfPartialPayment));
|
||||
env.close();
|
||||
|
||||
// Get the hash for the most recent transaction.
|
||||
std::string txHash{
|
||||
env.tx()->getJson(JsonOptions::none)[jss::hash].asString()};
|
||||
Json::Value meta = env.rpc("tx", txHash)[jss::result][jss::meta];
|
||||
|
||||
if (features[fixMPTDeliveredAmount])
|
||||
{
|
||||
BEAST_EXPECT(
|
||||
meta[sfDeliveredAmount.jsonName] ==
|
||||
STAmount{MPT(800)}.getJson(JsonOptions::none));
|
||||
BEAST_EXPECT(
|
||||
meta[jss::delivered_amount] ==
|
||||
STAmount{MPT(800)}.getJson(JsonOptions::none));
|
||||
}
|
||||
else
|
||||
{
|
||||
BEAST_EXPECT(!meta.isMember(sfDeliveredAmount.jsonName));
|
||||
BEAST_EXPECT(
|
||||
meta[jss::delivered_amount] = Json::Value("unavailable"));
|
||||
}
|
||||
|
||||
env(pay(bob, carol, MPT(1000)),
|
||||
sendmax(MPT(1200)),
|
||||
txflags(tfPartialPayment));
|
||||
env.close();
|
||||
|
||||
txHash = env.tx()->getJson(JsonOptions::none)[jss::hash].asString();
|
||||
meta = env.rpc("tx", txHash)[jss::result][jss::meta];
|
||||
|
||||
if (features[fixMPTDeliveredAmount])
|
||||
{
|
||||
BEAST_EXPECT(
|
||||
meta[sfDeliveredAmount.jsonName] ==
|
||||
STAmount{MPT(960)}.getJson(JsonOptions::none));
|
||||
BEAST_EXPECT(
|
||||
meta[jss::delivered_amount] ==
|
||||
STAmount{MPT(960)}.getJson(JsonOptions::none));
|
||||
}
|
||||
else
|
||||
{
|
||||
BEAST_EXPECT(!meta.isMember(sfDeliveredAmount.jsonName));
|
||||
BEAST_EXPECT(
|
||||
meta[jss::delivered_amount] = Json::Value("unavailable"));
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void
|
||||
run() override
|
||||
{
|
||||
using namespace test::jtx;
|
||||
FeatureBitset const all{testable_amendments()};
|
||||
|
||||
testTxDeliveredAmountRPC();
|
||||
testAccountDeliveredAmountSubscribe();
|
||||
|
||||
testMPTDeliveredAmountRPC(all - fixMPTDeliveredAmount);
|
||||
testMPTDeliveredAmountRPC(all);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -175,126 +175,18 @@ MPTokenAuthorize::createMPToken(
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
MPTokenAuthorize::authorize(
|
||||
ApplyView& view,
|
||||
beast::Journal journal,
|
||||
MPTAuthorizeArgs const& args)
|
||||
{
|
||||
auto const sleAcct = view.peek(keylet::account(args.account));
|
||||
if (!sleAcct)
|
||||
return tecINTERNAL;
|
||||
|
||||
// If the account that submitted the tx is a holder
|
||||
// Note: `account_` is holder's account
|
||||
// `holderID` is NOT used
|
||||
if (!args.holderID)
|
||||
{
|
||||
// When a holder wants to unauthorize/delete a MPT, the ledger must
|
||||
// - delete mptokenKey from owner directory
|
||||
// - delete the MPToken
|
||||
if (args.flags & tfMPTUnauthorize)
|
||||
{
|
||||
auto const mptokenKey =
|
||||
keylet::mptoken(args.mptIssuanceID, args.account);
|
||||
auto const sleMpt = view.peek(mptokenKey);
|
||||
if (!sleMpt || (*sleMpt)[sfMPTAmount] != 0)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
if (!view.dirRemove(
|
||||
keylet::ownerDir(args.account),
|
||||
(*sleMpt)[sfOwnerNode],
|
||||
sleMpt->key(),
|
||||
false))
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
adjustOwnerCount(view, sleAcct, -1, journal);
|
||||
|
||||
view.erase(sleMpt);
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
// A potential holder wants to authorize/hold a mpt, the ledger must:
|
||||
// - add the new mptokenKey to the owner directory
|
||||
// - create the MPToken object for the holder
|
||||
|
||||
// The reserve that is required to create the MPToken. Note
|
||||
// that although the reserve increases with every item
|
||||
// an account owns, in the case of MPTokens we only
|
||||
// *enforce* a reserve if the user owns more than two
|
||||
// items. This is similar to the reserve requirements of trust lines.
|
||||
std::uint32_t const uOwnerCount = sleAcct->getFieldU32(sfOwnerCount);
|
||||
XRPAmount const reserveCreate(
|
||||
(uOwnerCount < 2) ? XRPAmount(beast::zero)
|
||||
: view.fees().accountReserve(uOwnerCount + 1));
|
||||
|
||||
if (args.priorBalance < reserveCreate)
|
||||
return tecINSUFFICIENT_RESERVE;
|
||||
|
||||
auto const mptokenKey =
|
||||
keylet::mptoken(args.mptIssuanceID, args.account);
|
||||
auto mptoken = std::make_shared<SLE>(mptokenKey);
|
||||
if (auto ter = dirLink(view, args.account, mptoken))
|
||||
return ter; // LCOV_EXCL_LINE
|
||||
|
||||
(*mptoken)[sfAccount] = args.account;
|
||||
(*mptoken)[sfMPTokenIssuanceID] = args.mptIssuanceID;
|
||||
(*mptoken)[sfFlags] = 0;
|
||||
view.insert(mptoken);
|
||||
|
||||
// Update owner count.
|
||||
adjustOwnerCount(view, sleAcct, 1, journal);
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
auto const sleMptIssuance =
|
||||
view.read(keylet::mptIssuance(args.mptIssuanceID));
|
||||
if (!sleMptIssuance)
|
||||
return tecINTERNAL;
|
||||
|
||||
// If the account that submitted this tx is the issuer of the MPT
|
||||
// Note: `account_` is issuer's account
|
||||
// `holderID` is holder's account
|
||||
if (args.account != (*sleMptIssuance)[sfIssuer])
|
||||
return tecINTERNAL;
|
||||
|
||||
auto const sleMpt =
|
||||
view.peek(keylet::mptoken(args.mptIssuanceID, *args.holderID));
|
||||
if (!sleMpt)
|
||||
return tecINTERNAL;
|
||||
|
||||
std::uint32_t const flagsIn = sleMpt->getFieldU32(sfFlags);
|
||||
std::uint32_t flagsOut = flagsIn;
|
||||
|
||||
// Issuer wants to unauthorize the holder, unset lsfMPTAuthorized on
|
||||
// their MPToken
|
||||
if (args.flags & tfMPTUnauthorize)
|
||||
flagsOut &= ~lsfMPTAuthorized;
|
||||
// Issuer wants to authorize a holder, set lsfMPTAuthorized on their
|
||||
// MPToken
|
||||
else
|
||||
flagsOut |= lsfMPTAuthorized;
|
||||
|
||||
if (flagsIn != flagsOut)
|
||||
sleMpt->setFieldU32(sfFlags, flagsOut);
|
||||
|
||||
view.update(sleMpt);
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
MPTokenAuthorize::doApply()
|
||||
{
|
||||
auto const& tx = ctx_.tx;
|
||||
return authorize(
|
||||
return authorizeMPToken(
|
||||
ctx_.view(),
|
||||
mPriorBalance,
|
||||
tx[sfMPTokenIssuanceID],
|
||||
account_,
|
||||
ctx_.journal,
|
||||
{.priorBalance = mPriorBalance,
|
||||
.mptIssuanceID = tx[sfMPTokenIssuanceID],
|
||||
.account = account_,
|
||||
.flags = tx.getFlags(),
|
||||
.holderID = tx[~sfHolder]});
|
||||
tx.getFlags(),
|
||||
tx[~sfHolder]);
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -48,12 +48,6 @@ public:
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
static TER
|
||||
authorize(
|
||||
ApplyView& view,
|
||||
beast::Journal journal,
|
||||
MPTAuthorizeArgs const& args);
|
||||
|
||||
static TER
|
||||
createMPToken(
|
||||
ApplyView& view,
|
||||
|
||||
@@ -580,7 +580,16 @@ Payment::doApply()
|
||||
auto res = accountSend(
|
||||
pv, account_, dstAccountID, amountDeliver, ctx_.journal);
|
||||
if (res == tesSUCCESS)
|
||||
{
|
||||
pv.apply(ctx_.rawView());
|
||||
|
||||
// If the actual amount delivered is different from the original
|
||||
// amount due to partial payment or transfer fee, we need to update
|
||||
// DelieveredAmount using the actual delivered amount
|
||||
if (view().rules().enabled(fixMPTDeliveredAmount) &&
|
||||
amountDeliver != dstAmount)
|
||||
ctx_.deliver(amountDeliver);
|
||||
}
|
||||
else if (res == tecINSUFFICIENT_FUNDS || res == tecPATH_DRY)
|
||||
res = tecPATH_PARTIAL;
|
||||
|
||||
|
||||
@@ -210,12 +210,12 @@ VaultDeposit::doApply()
|
||||
auto sleMpt = view().read(keylet::mptoken(mptIssuanceID, account_));
|
||||
if (!sleMpt)
|
||||
{
|
||||
if (auto const err = MPTokenAuthorize::authorize(
|
||||
if (auto const err = authorizeMPToken(
|
||||
view(),
|
||||
ctx_.journal,
|
||||
{.priorBalance = mPriorBalance,
|
||||
.mptIssuanceID = mptIssuanceID->value(),
|
||||
.account = account_});
|
||||
mPriorBalance,
|
||||
mptIssuanceID->value(),
|
||||
account_,
|
||||
ctx_.journal);
|
||||
!isTesSuccess(err))
|
||||
return err;
|
||||
}
|
||||
@@ -223,15 +223,15 @@ VaultDeposit::doApply()
|
||||
// If the vault is private, set the authorized flag for the vault owner
|
||||
if (vault->isFlag(tfVaultPrivate))
|
||||
{
|
||||
if (auto const err = MPTokenAuthorize::authorize(
|
||||
if (auto const err = authorizeMPToken(
|
||||
view(),
|
||||
mPriorBalance, // priorBalance
|
||||
mptIssuanceID->value(), // mptIssuanceID
|
||||
sleIssuance->at(sfIssuer), // account
|
||||
ctx_.journal,
|
||||
{
|
||||
.priorBalance = mPriorBalance,
|
||||
.mptIssuanceID = mptIssuanceID->value(),
|
||||
.account = sleIssuance->at(sfIssuer),
|
||||
.holderID = account_,
|
||||
});
|
||||
{}, // flags
|
||||
account_ // holderID
|
||||
);
|
||||
!isTesSuccess(err))
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -600,6 +600,16 @@ addEmptyHolding(
|
||||
asset.value());
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
authorizeMPToken(
|
||||
ApplyView& view,
|
||||
XRPAmount const& priorBalance,
|
||||
MPTID const& mptIssuanceID,
|
||||
AccountID const& account,
|
||||
beast::Journal journal,
|
||||
std::uint32_t flags = 0,
|
||||
std::optional<AccountID> holderID = std::nullopt);
|
||||
|
||||
// VFALCO NOTE Both STAmount parameters should just
|
||||
// be "Amount", a unit-less number.
|
||||
//
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <xrpld/app/misc/CredentialHelpers.h>
|
||||
#include <xrpld/app/tx/detail/MPTokenAuthorize.h>
|
||||
#include <xrpld/ledger/ReadView.h>
|
||||
#include <xrpld/ledger/View.h>
|
||||
|
||||
@@ -1215,12 +1214,115 @@ addEmptyHolding(
|
||||
if (view.peek(keylet::mptoken(mptID, accountID)))
|
||||
return tecDUPLICATE;
|
||||
|
||||
return MPTokenAuthorize::authorize(
|
||||
view,
|
||||
journal,
|
||||
{.priorBalance = priorBalance,
|
||||
.mptIssuanceID = mptID,
|
||||
.account = accountID});
|
||||
return authorizeMPToken(view, priorBalance, mptID, accountID, journal);
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
authorizeMPToken(
|
||||
ApplyView& view,
|
||||
XRPAmount const& priorBalance,
|
||||
MPTID const& mptIssuanceID,
|
||||
AccountID const& account,
|
||||
beast::Journal journal,
|
||||
std::uint32_t flags,
|
||||
std::optional<AccountID> holderID)
|
||||
{
|
||||
auto const sleAcct = view.peek(keylet::account(account));
|
||||
if (!sleAcct)
|
||||
return tecINTERNAL;
|
||||
|
||||
// If the account that submitted the tx is a holder
|
||||
// Note: `account_` is holder's account
|
||||
// `holderID` is NOT used
|
||||
if (!holderID)
|
||||
{
|
||||
// When a holder wants to unauthorize/delete a MPT, the ledger must
|
||||
// - delete mptokenKey from owner directory
|
||||
// - delete the MPToken
|
||||
if (flags & tfMPTUnauthorize)
|
||||
{
|
||||
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
|
||||
auto const sleMpt = view.peek(mptokenKey);
|
||||
if (!sleMpt || (*sleMpt)[sfMPTAmount] != 0)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
if (!view.dirRemove(
|
||||
keylet::ownerDir(account),
|
||||
(*sleMpt)[sfOwnerNode],
|
||||
sleMpt->key(),
|
||||
false))
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
adjustOwnerCount(view, sleAcct, -1, journal);
|
||||
|
||||
view.erase(sleMpt);
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
// A potential holder wants to authorize/hold a mpt, the ledger must:
|
||||
// - add the new mptokenKey to the owner directory
|
||||
// - create the MPToken object for the holder
|
||||
|
||||
// The reserve that is required to create the MPToken. Note
|
||||
// that although the reserve increases with every item
|
||||
// an account owns, in the case of MPTokens we only
|
||||
// *enforce* a reserve if the user owns more than two
|
||||
// items. This is similar to the reserve requirements of trust lines.
|
||||
std::uint32_t const uOwnerCount = sleAcct->getFieldU32(sfOwnerCount);
|
||||
XRPAmount const reserveCreate(
|
||||
(uOwnerCount < 2) ? XRPAmount(beast::zero)
|
||||
: view.fees().accountReserve(uOwnerCount + 1));
|
||||
|
||||
if (priorBalance < reserveCreate)
|
||||
return tecINSUFFICIENT_RESERVE;
|
||||
|
||||
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
|
||||
auto mptoken = std::make_shared<SLE>(mptokenKey);
|
||||
if (auto ter = dirLink(view, account, mptoken))
|
||||
return ter; // LCOV_EXCL_LINE
|
||||
|
||||
(*mptoken)[sfAccount] = account;
|
||||
(*mptoken)[sfMPTokenIssuanceID] = mptIssuanceID;
|
||||
(*mptoken)[sfFlags] = 0;
|
||||
view.insert(mptoken);
|
||||
|
||||
// Update owner count.
|
||||
adjustOwnerCount(view, sleAcct, 1, journal);
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
auto const sleMptIssuance = view.read(keylet::mptIssuance(mptIssuanceID));
|
||||
if (!sleMptIssuance)
|
||||
return tecINTERNAL;
|
||||
|
||||
// If the account that submitted this tx is the issuer of the MPT
|
||||
// Note: `account_` is issuer's account
|
||||
// `holderID` is holder's account
|
||||
if (account != (*sleMptIssuance)[sfIssuer])
|
||||
return tecINTERNAL;
|
||||
|
||||
auto const sleMpt = view.peek(keylet::mptoken(mptIssuanceID, *holderID));
|
||||
if (!sleMpt)
|
||||
return tecINTERNAL;
|
||||
|
||||
std::uint32_t const flagsIn = sleMpt->getFieldU32(sfFlags);
|
||||
std::uint32_t flagsOut = flagsIn;
|
||||
|
||||
// Issuer wants to unauthorize the holder, unset lsfMPTAuthorized on
|
||||
// their MPToken
|
||||
if (flags & tfMPTUnauthorize)
|
||||
flagsOut &= ~lsfMPTAuthorized;
|
||||
// Issuer wants to authorize a holder, set lsfMPTAuthorized on their
|
||||
// MPToken
|
||||
else
|
||||
flagsOut |= lsfMPTAuthorized;
|
||||
|
||||
if (flagsIn != flagsOut)
|
||||
sleMpt->setFieldU32(sfFlags, flagsOut);
|
||||
|
||||
view.update(sleMpt);
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
@@ -1418,13 +1520,14 @@ removeEmptyHolding(
|
||||
if (mptoken->at(sfMPTAmount) != 0)
|
||||
return tecHAS_OBLIGATIONS;
|
||||
|
||||
return MPTokenAuthorize::authorize(
|
||||
return authorizeMPToken(
|
||||
view,
|
||||
{}, // priorBalance
|
||||
mptID,
|
||||
accountID,
|
||||
journal,
|
||||
{.priorBalance = {},
|
||||
.mptIssuanceID = mptID,
|
||||
.account = accountID,
|
||||
.flags = tfMPTUnauthorize});
|
||||
tfMPTUnauthorize // flags
|
||||
);
|
||||
}
|
||||
|
||||
TER
|
||||
@@ -2497,15 +2600,12 @@ enforceMPTokenAuthorization(
|
||||
XRPL_ASSERT(
|
||||
maybeDomainID.has_value() && sleToken == nullptr,
|
||||
"ripple::enforceMPTokenAuthorization : new MPToken for domain");
|
||||
if (auto const err = MPTokenAuthorize::authorize(
|
||||
if (auto const err = authorizeMPToken(
|
||||
view,
|
||||
j,
|
||||
{
|
||||
.priorBalance = priorBalance,
|
||||
.mptIssuanceID = mptIssuanceID,
|
||||
.account = account,
|
||||
.flags = 0,
|
||||
});
|
||||
priorBalance, // priorBalance
|
||||
mptIssuanceID, // mptIssuanceID
|
||||
account, // account
|
||||
j);
|
||||
!isTesSuccess(err))
|
||||
return err;
|
||||
|
||||
|
||||
@@ -446,6 +446,8 @@ Slot<clock_type>::deletePeer(PublicKey const& validator, id_t id, bool erase)
|
||||
auto it = peers_.find(id);
|
||||
if (it != peers_.end())
|
||||
{
|
||||
std::vector<Peer::id_t> toUnsquelch;
|
||||
|
||||
JLOG(journal_.trace())
|
||||
<< "deletePeer: " << Slice(validator) << " " << id << " selected "
|
||||
<< (it->second.state == PeerState::Selected) << " considered "
|
||||
@@ -457,7 +459,7 @@ Slot<clock_type>::deletePeer(PublicKey const& validator, id_t id, bool erase)
|
||||
for (auto& [k, v] : peers_)
|
||||
{
|
||||
if (v.state == PeerState::Squelched)
|
||||
handler_.unsquelch(validator, k);
|
||||
toUnsquelch.push_back(k);
|
||||
v.state = PeerState::Counting;
|
||||
v.count = 0;
|
||||
v.expire = now;
|
||||
@@ -479,6 +481,10 @@ Slot<clock_type>::deletePeer(PublicKey const& validator, id_t id, bool erase)
|
||||
|
||||
if (erase)
|
||||
peers_.erase(it);
|
||||
|
||||
// Must be after peers_.erase(it)
|
||||
for (auto const& k : toUnsquelch)
|
||||
handler_.unsquelch(validator, k);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1423,7 +1423,12 @@ OverlayImpl::updateSlotAndSquelch(
|
||||
if (!strand_.running_in_this_thread())
|
||||
return post(
|
||||
strand_,
|
||||
[this, key, validator, peers = std::move(peers), type]() mutable {
|
||||
// Must capture copies of reference parameters (i.e. key, validator)
|
||||
[this,
|
||||
key = key,
|
||||
validator = validator,
|
||||
peers = std::move(peers),
|
||||
type]() mutable {
|
||||
updateSlotAndSquelch(key, validator, std::move(peers), type);
|
||||
});
|
||||
|
||||
@@ -1444,7 +1449,10 @@ OverlayImpl::updateSlotAndSquelch(
|
||||
return;
|
||||
|
||||
if (!strand_.running_in_this_thread())
|
||||
return post(strand_, [this, key, validator, peer, type]() {
|
||||
return post(
|
||||
strand_,
|
||||
// Must capture copies of reference parameters (i.e. key, validator)
|
||||
[this, key = key, validator = validator, peer, type]() {
|
||||
updateSlotAndSquelch(key, validator, peer, type);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user