mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-28 15:05:53 +00:00
Implement native support for Price Oracles. A Price Oracle is used to bring real-world data, such as market prices, onto the blockchain, enabling dApps to access and utilize information that resides outside the blockchain. Add Price Oracle functionality: - OracleSet: create or update the Oracle object - OracleDelete: delete the Oracle object To support this functionality add: - New RPC method, `get_aggregate_price`, to calculate aggregate price for a token pair of the specified oracles - `ltOracle` object The `ltOracle` object maintains: - Oracle Owner's account - Oracle's metadata - Up to ten token pairs with the scaled price - The last update time the token pairs were updated Add Oracle unit-tests
111 lines
3.2 KiB
C++
111 lines
3.2 KiB
C++
//------------------------------------------------------------------------------
|
|
/*
|
|
This file is part of rippled: https://github.com/ripple/rippled
|
|
Copyright (c) 2023 Ripple Labs Inc.
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
//==============================================================================
|
|
|
|
#include <ripple/app/tx/impl/DeleteOracle.h>
|
|
#include <ripple/ledger/Sandbox.h>
|
|
#include <ripple/ledger/View.h>
|
|
#include <ripple/protocol/Feature.h>
|
|
#include <ripple/protocol/Rules.h>
|
|
#include <ripple/protocol/TxFlags.h>
|
|
|
|
namespace ripple {
|
|
|
|
NotTEC
|
|
DeleteOracle::preflight(PreflightContext const& ctx)
|
|
{
|
|
if (!ctx.rules.enabled(featurePriceOracle))
|
|
return temDISABLED;
|
|
|
|
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
|
|
return ret;
|
|
|
|
if (ctx.tx.getFlags() & tfUniversalMask)
|
|
{
|
|
JLOG(ctx.j.debug()) << "Oracle Delete: invalid flags.";
|
|
return temINVALID_FLAG;
|
|
}
|
|
|
|
return preflight2(ctx);
|
|
}
|
|
|
|
TER
|
|
DeleteOracle::preclaim(PreclaimContext const& ctx)
|
|
{
|
|
if (!ctx.view.exists(keylet::account(ctx.tx.getAccountID(sfAccount))))
|
|
return terNO_ACCOUNT;
|
|
|
|
if (auto const sle = ctx.view.read(keylet::oracle(
|
|
ctx.tx.getAccountID(sfAccount), ctx.tx[sfOracleDocumentID]));
|
|
!sle)
|
|
{
|
|
JLOG(ctx.j.debug()) << "Oracle Delete: Oracle does not exist.";
|
|
return tecNO_ENTRY;
|
|
}
|
|
else if (ctx.tx.getAccountID(sfAccount) != sle->getAccountID(sfOwner))
|
|
{
|
|
// this can't happen because of the above check
|
|
JLOG(ctx.j.debug()) << "Oracle Delete: invalid account.";
|
|
return tecINTERNAL;
|
|
}
|
|
return tesSUCCESS;
|
|
}
|
|
|
|
TER
|
|
DeleteOracle::deleteOracle(
|
|
ApplyView& view,
|
|
std::shared_ptr<SLE> const& sle,
|
|
AccountID const& account,
|
|
beast::Journal j)
|
|
{
|
|
if (!sle)
|
|
return tesSUCCESS;
|
|
|
|
if (!view.dirRemove(
|
|
keylet::ownerDir(account), (*sle)[sfOwnerNode], sle->key(), true))
|
|
{
|
|
JLOG(j.fatal()) << "Unable to delete Oracle from owner.";
|
|
return tefBAD_LEDGER;
|
|
}
|
|
|
|
auto const sleOwner = view.peek(keylet::account(account));
|
|
if (!sleOwner)
|
|
return tecINTERNAL;
|
|
|
|
auto const count =
|
|
sle->getFieldArray(sfPriceDataSeries).size() > 5 ? -2 : -1;
|
|
|
|
adjustOwnerCount(view, sleOwner, count, j);
|
|
|
|
view.erase(sle);
|
|
|
|
return tesSUCCESS;
|
|
}
|
|
|
|
TER
|
|
DeleteOracle::doApply()
|
|
{
|
|
if (auto sle = ctx_.view().peek(
|
|
keylet::oracle(account_, ctx_.tx[sfOracleDocumentID])))
|
|
return deleteOracle(ctx_.view(), sle, account_, j_);
|
|
|
|
return tecINTERNAL;
|
|
}
|
|
|
|
} // namespace ripple
|