Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
thejohnfreeman committed Oct 8, 2024
1 parent ea727bf commit 884e20e
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 49 deletions.
4 changes: 4 additions & 0 deletions include/xrpl/protocol/STTx.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ class STTx final : public STObject, public CountedObject<STTx>
SeqProxy
getSeqProxy() const;

/** Returns the first non-zero value of (Sequence, TicketSequence). */
std::uint32_t
getSequence() const;

boost::container::flat_set<AccountID>
getMentionedAccounts() const;

Expand Down
6 changes: 6 additions & 0 deletions src/libxrpl/protocol/STTx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,12 @@ STTx::getSeqProxy() const
return SeqProxy{SeqProxy::ticket, *ticketSeq};
}

std::uint32_t
STTx::getSequence() const
{
return getSeqProxy().value();
}

void
STTx::sign(PublicKey const& publicKey, SecretKey const& secretKey)
{
Expand Down
26 changes: 13 additions & 13 deletions src/xrpld/app/tx/detail/AMMCreate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,25 +214,25 @@ applyCreate(
auto const ammKeylet = keylet::amm(amount.issue(), amount2.issue());

// Mitigate same account exists possibility
auto const ammAccount = createPseudoAccount(sb, ammKeylet.key);
auto const maybe = createPseudoAccount(sb, ammKeylet.key);
// AMM account already exists (should not happen)
if (!ammAccount)
if (!maybe)
{
JLOG(j_.error()) << "AMM Instance: AMM already exists.";
return {ammAccount.error(), false};
return {maybe.error(), false};
}
auto& sleAMMRoot = *maybe;
auto const ammAccount = (*sleAMMRoot)[sfAccount];

// LP Token already exists. (should not happen)
auto const lptIss = ammLPTIssue(
amount.issue().currency, amount2.issue().currency, *ammAccount);
if (sb.read(keylet::line(*ammAccount, lptIss)))
amount.issue().currency, amount2.issue().currency, ammAccount);
if (sb.read(keylet::line(ammAccount, lptIss)))
{
JLOG(j_.error()) << "AMM Instance: LP Token already exists.";
return {tecDUPLICATE, false};
}

// Create AMM Root Account.
auto sleAMMRoot = sb.peek(keylet::account(*ammAccount));
// Note, that the trustlines created by AMM have 0 credit limit.
// This prevents shifting the balance between accounts via AMM,
// or sending unsolicited LPTokens. This is a desired behavior.
Expand All @@ -246,7 +246,7 @@ applyCreate(

// Create ltAMM
auto ammSle = std::make_shared<SLE>(ammKeylet);
ammSle->setAccountID(sfAccount, *ammAccount);
ammSle->setAccountID(sfAccount, ammAccount);
ammSle->setFieldAmount(sfLPTokenBalance, lpTokens);
auto const& [issue1, issue2] = std::minmax(amount.issue(), amount2.issue());
ammSle->setFieldIssue(sfAsset, STIssue{sfAsset, issue1});
Expand All @@ -256,15 +256,15 @@ applyCreate(
ctx_.view(), ammSle, account_, lptIss, ctx_.tx[sfTradingFee]);

// Add owner directory to link the root account and AMM object.
if (auto ter = dirLink(sb, *ammAccount, ammSle); ter)
if (auto ter = dirLink(sb, ammAccount, ammSle); ter)
{
JLOG(j_.debug()) << "AMM Instance: failed to insert owner dir";
return {tecDIR_FULL, false};
}
sb.insert(ammSle);

// Send LPT to LP.
auto res = accountSend(sb, *ammAccount, account_, lpTokens, ctx_.journal);
auto res = accountSend(sb, ammAccount, account_, lpTokens, ctx_.journal);
if (res != tesSUCCESS)
{
JLOG(j_.debug()) << "AMM Instance: failed to send LPT " << lpTokens;
Expand All @@ -275,7 +275,7 @@ applyCreate(
if (auto const res = accountSend(
sb,
account_,
*ammAccount,
ammAccount,
amount,
ctx_.journal,
WaiveTransferFee::Yes))
Expand All @@ -284,7 +284,7 @@ applyCreate(
if (!isXRP(amount))
{
if (SLE::pointer sleRippleState =
sb.peek(keylet::line(*ammAccount, amount.issue()));
sb.peek(keylet::line(ammAccount, amount.issue()));
!sleRippleState)
return tecINTERNAL;
else
Expand Down Expand Up @@ -313,7 +313,7 @@ applyCreate(
return {res, false};
}

JLOG(j_.debug()) << "AMM Instance: success " << *ammAccount << " "
JLOG(j_.debug()) << "AMM Instance: success " << ammAccount << " "
<< ammKeylet.key << " " << lpTokens << " " << amount << " "
<< amount2;
auto addOrderBook =
Expand Down
31 changes: 16 additions & 15 deletions src/xrpld/app/tx/detail/MPTokenIssuanceCreate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,18 @@ MPTokenIssuanceCreate::preflight(PreflightContext const& ctx)
return preflight2(ctx);
}

TER
Expected<MPTID, TER>
MPTokenIssuanceCreate::create(
ApplyView& view,
beast::Journal journal,
MPTCreateArgs const& args)
{
auto const acct = view.peek(keylet::account(args.account));
if (!acct)
return tecINTERNAL;

if (args.priorBalance <
view.fees().accountReserve((*acct)[sfOwnerCount] + 1))
return tecINSUFFICIENT_RESERVE;
return Unexpected(tecINTERNAL);

auto const mptIssuanceKeylet =
keylet::mptIssuance(args.account, args.sequence);
auto mptId = getMptID(args.account, args.sequence);
auto const mptIssuanceKeylet = keylet::mptIssuance(mptId);

// create the MPTokenIssuance
{
Expand All @@ -92,7 +88,7 @@ MPTokenIssuanceCreate::create(
describeOwnerDir(args.account));

if (!ownerNode)
return tecDIR_FULL;
return Unexpected(tecDIR_FULL);

auto mptIssuance = std::make_shared<SLE>(mptIssuanceKeylet);
(*mptIssuance)[sfFlags] = args.flags & ~tfUniversal;
Expand All @@ -119,24 +115,29 @@ MPTokenIssuanceCreate::create(
// Update owner count.
adjustOwnerCount(view, acct, 1, journal);

return tesSUCCESS;
return mptId;
}

TER
MPTokenIssuanceCreate::doApply()
{
auto const& tx = ctx_.tx;
return create(
ctx_.view(),
ctx_.journal,
{.priorBalance = mPriorBalance,
.account = account_,

auto const acct = view().peek(keylet::account(account_));
if (mPriorBalance < view().fees().accountReserve((*acct)[sfOwnerCount] + 1))
return tecINSUFFICIENT_RESERVE;

auto result = create(
view(),
j_,
{.account = account_,
.sequence = tx.getSeqProxy().value(),
.flags = tx.getFlags(),
.maxAmount = tx[~sfMaximumAmount],
.assetScale = tx[~sfAssetScale],
.transferFee = tx[~sfTransferFee],
.metadata = tx[~sfMPTokenMetadata]});
return result ? tesSUCCESS : result.error();
}

} // namespace ripple
15 changes: 8 additions & 7 deletions src/xrpld/app/tx/detail/MPTokenIssuanceCreate.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,20 @@
#define RIPPLE_TX_MPTOKENISSUANCECREATE_H_INCLUDED

#include <xrpld/app/tx/detail/Transactor.h>
#include <xrpl/basics/Expected.h>
#include <xrpl/protocol/UintTypes.h>

namespace ripple {

struct MPTCreateArgs
{
XRPAmount const& priorBalance;
AccountID const& account;
std::uint32_t sequence;
std::uint32_t flags;
std::optional<std::uint64_t> maxAmount;
std::optional<std::uint8_t> assetScale;
std::optional<std::uint16_t> transferFee;
std::optional<Slice> const& metadata;
std::uint32_t flags = 0;
std::optional<std::uint64_t> maxAmount{};
std::optional<std::uint8_t> assetScale{};
std::optional<std::uint16_t> transferFee{};
std::optional<Slice> const& metadata{};
};

class MPTokenIssuanceCreate : public Transactor
Expand All @@ -51,7 +52,7 @@ class MPTokenIssuanceCreate : public Transactor
TER
doApply() override;

static TER
static Expected<MPTID, TER>
create(ApplyView& view, beast::Journal journal, MPTCreateArgs const& args);
};

Expand Down
41 changes: 30 additions & 11 deletions src/xrpld/app/tx/detail/VaultSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <xrpl/protocol/STNumber.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/st.h>
#include "MPTokenIssuanceCreate.h"

namespace ripple {

Expand Down Expand Up @@ -52,18 +53,20 @@ VaultSet::doApply()
// we can consider downgrading them to `tef` or `tem`.

auto const& tx = ctx_.tx;
auto const& owner = account_;
auto sequence = tx.getSequence();

auto const& vaultId = tx[~sfVaultID];
auto keylet = vaultId ? Keylet{ltVAULT, *vaultId}
: keylet::vault(tx[sfAccount], tx[sfSequence]);
auto keylet =
vaultId ? Keylet{ltVAULT, *vaultId} : keylet::vault(owner, sequence);

auto vault = view().peek(keylet);

if (vault)
{
// Update existing object.
// Assert that submitter is the Owner.
if (tx[sfAccount] != (*vault)[sfOwner])
if (owner != (*vault)[sfOwner])
return tecNO_PERMISSION;
// Assert that Asset is the same if given.
if (tx.isFieldPresent(sfAsset) && tx[sfAsset] != (*vault)[sfAsset])
Expand All @@ -82,20 +85,36 @@ VaultSet::doApply()
return tecINCOMPLETE;

vault = std::make_shared<SLE>(keylet);
if (auto ter = dirLink(view(), tx[sfAccount], vault); ter)
if (auto ter = dirLink(view(), owner, vault); ter)
return ter;
auto pseudo = createPseudoAccount(view(), vault->key());
if (!pseudo)
return pseudo.error();
(*vault)[sfSequence] = tx[sfSequence];
(*vault)[sfOwner] = tx[sfAccount];
(*vault)[sfAccount] = pseudo.value();
auto maybe = createPseudoAccount(view(), vault->key());
if (!maybe)
return maybe.error();
auto& pseudo = *maybe;
auto pseudoId = (*pseudo)[sfAccount];
auto maybe2 = MPTokenIssuanceCreate::create(
view(),
j_,
{
.account = pseudoId,
.sequence = 1,
// !tfShareNonTransferable => lsfMPTCanEscrow, lsfMPTCanTrade,
// lsfMPTCanTransfer tfPrivate => lsfMPTRequireAuth
.flags = 0,
.metadata = tx[~sfMPTokenMetadata],
});
if (!maybe2)
return maybe2.error();
auto& mptId = *maybe2;
(*vault)[sfSequence] = sequence;
(*vault)[sfOwner] = owner;
(*vault)[sfAccount] = pseudoId;
(*vault)[~sfData] = tx[~sfData];
(*vault)[sfAsset] = tx[sfAsset];
(*vault)[sfAssetTotal] = 0;
(*vault)[sfAssetAvailable] = 0;
(*vault)[~sfAssetMaximum] = tx[~sfAssetMaximum];
// TODO: create MPT for share
(*vault)[sfMPTokenIssuanceID] = mptId;
// No `LossUnrealized`.
view().insert(vault);
}
Expand Down
2 changes: 1 addition & 1 deletion src/xrpld/ledger/View.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ describeOwnerDir(AccountID const& account);
[[nodiscard]] TER
dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr<SLE>& object);

[[nodiscard]] Expected<AccountID, TER>
[[nodiscard]] Expected<std::shared_ptr<SLE>, TER>
createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey);

// VFALCO NOTE Both STAmount parameters should just
Expand Down
4 changes: 2 additions & 2 deletions src/xrpld/ledger/detail/View.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr<SLE>& object)
return tesSUCCESS;
}

Expected<AccountID, TER>
Expected<std::shared_ptr<SLE>, TER>
createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey)
{
AccountID accountId;
Expand Down Expand Up @@ -876,7 +876,7 @@ createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey)
// account->setFieldH256(sfPseudoOwner, pseudoOwnerKey);
view.insert(account);

return accountId;
return std::move(account);
}

TER
Expand Down

0 comments on commit 884e20e

Please sign in to comment.