mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-19 01:55:48 +00:00
ttImport (#65)
Add support for Burn2Mint and key import from original XRPL network in new txn type: ttIMPORT. Needs further testing.
This commit is contained in:
@@ -443,6 +443,7 @@ target_sources (rippled PRIVATE
|
||||
src/ripple/app/tx/impl/SetRegularKey.cpp
|
||||
src/ripple/app/tx/impl/SetHook.cpp
|
||||
src/ripple/app/tx/impl/ClaimReward.cpp
|
||||
src/ripple/app/tx/impl/Import.cpp
|
||||
src/ripple/app/tx/impl/Invoke.cpp
|
||||
src/ripple/app/tx/impl/SetSignerList.cpp
|
||||
src/ripple/app/tx/impl/SetTrust.cpp
|
||||
|
||||
@@ -1324,6 +1324,13 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (config_->IMPORT_VL_KEYS.empty())
|
||||
{
|
||||
JLOG(m_journal.fatal()) << "IMPORT_VL_KEYS section must be specified in validators file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// Server
|
||||
|
||||
@@ -755,8 +755,14 @@ TxQ::apply(
|
||||
auto const account = (*tx)[sfAccount];
|
||||
Keylet const accountKey{keylet::account(account)};
|
||||
auto const sleAccount = view.read(accountKey);
|
||||
|
||||
if (!sleAccount)
|
||||
{
|
||||
if (tx->getTxnType() == ttIMPORT)
|
||||
return {telCAN_NOT_QUEUE_IMPORT, false};
|
||||
|
||||
return {terNO_ACCOUNT, false};
|
||||
}
|
||||
|
||||
// If the transaction needs a Ticket is that Ticket in the ledger?
|
||||
SeqProxy const acctSeqProx = SeqProxy::sequence((*sleAccount)[sfSequence]);
|
||||
@@ -1809,19 +1815,27 @@ TxQ::tryDirectApply(
|
||||
auto const account = (*tx)[sfAccount];
|
||||
auto const sleAccount = view.read(keylet::account(account));
|
||||
|
||||
const bool isFirstImport = !sleAccount && view.rules().enabled(featureImport) && tx->getTxnType() == ttIMPORT;
|
||||
|
||||
// Don't attempt to direct apply if the account is not in the ledger.
|
||||
if (!sleAccount)
|
||||
if (!sleAccount && !isFirstImport)
|
||||
return {};
|
||||
|
||||
SeqProxy const acctSeqProx = SeqProxy::sequence((*sleAccount)[sfSequence]);
|
||||
SeqProxy const txSeqProx = tx->getSeqProxy();
|
||||
std::optional<SeqProxy> txSeqProx;
|
||||
|
||||
// Can only directly apply if the transaction sequence matches the account
|
||||
// sequence or if the transaction uses a ticket.
|
||||
if (txSeqProx.isSeq() && txSeqProx != acctSeqProx)
|
||||
return {};
|
||||
if (!isFirstImport)
|
||||
{
|
||||
SeqProxy const acctSeqProx = SeqProxy::sequence((*sleAccount)[sfSequence]);
|
||||
txSeqProx = tx->getSeqProxy();
|
||||
|
||||
FeeLevel64 const requiredFeeLevel = [this, &view, flags]() {
|
||||
// Can only directly apply if the transaction sequence matches the account
|
||||
// sequence or if the transaction uses a ticket.
|
||||
if (txSeqProx->isSeq() && *txSeqProx != acctSeqProx)
|
||||
return {};
|
||||
}
|
||||
|
||||
FeeLevel64 const requiredFeeLevel = isFirstImport ? FeeLevel64 { 0 } :
|
||||
[this, &view, flags]() {
|
||||
std::lock_guard lock(mutex_);
|
||||
return getRequiredFeeLevel(
|
||||
view, flags, feeMetrics_.getSnapshot(), lock);
|
||||
@@ -1856,11 +1870,12 @@ TxQ::tryDirectApply(
|
||||
if (accountIter != byAccount_.end())
|
||||
{
|
||||
TxQAccount& txQAcct = accountIter->second;
|
||||
if (auto const existingIter =
|
||||
txQAcct.transactions.find(txSeqProx);
|
||||
existingIter != txQAcct.transactions.end())
|
||||
if (txSeqProx)
|
||||
{
|
||||
removeFromByFee(existingIter, tx);
|
||||
auto const existingIter =
|
||||
txQAcct.transactions.find(*txSeqProx);
|
||||
if (existingIter != txQAcct.transactions.end())
|
||||
removeFromByFee(existingIter, tx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1325
src/ripple/app/tx/impl/Import.cpp
Normal file
1325
src/ripple/app/tx/impl/Import.cpp
Normal file
File diff suppressed because it is too large
Load Diff
66
src/ripple/app/tx/impl/Import.h
Normal file
66
src/ripple/app/tx/impl/Import.h
Normal file
@@ -0,0 +1,66 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_IMPORT_H_INCLUDED
|
||||
#define RIPPLE_TX_IMPORT_H_INCLUDED
|
||||
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <memory>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class Import : public Transactor
|
||||
{
|
||||
public:
|
||||
// newly imported accounts get 2 XRP
|
||||
static constexpr XRPAmount INITIAL_IMPORT_XRP{2 * DROPS_PER_XRP};
|
||||
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Custom};
|
||||
|
||||
static std::pair<
|
||||
std::unique_ptr<STTx const>,
|
||||
std::unique_ptr<STObject const>>
|
||||
getInnerTxn(STTx const& outer, beast::Journal const& j,Json::Value const* xpop = 0);
|
||||
|
||||
explicit Import(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <ripple/protocol/STArray.h>
|
||||
#include <ripple/protocol/SystemParameters.h>
|
||||
#include <ripple/protocol/nftPageMask.h>
|
||||
#include <ripple/app/tx/impl/Import.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -134,16 +135,47 @@ XRPNotCreated::visitEntry(
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!before && after->getType() == ltACCOUNT_ROOT)
|
||||
accountsCreated_++;
|
||||
}
|
||||
|
||||
bool
|
||||
XRPNotCreated::finalize(
|
||||
STTx const&,
|
||||
STTx const& tx,
|
||||
TER const,
|
||||
XRPAmount const fee,
|
||||
ReadView const&,
|
||||
ReadView const& view,
|
||||
beast::Journal const& j)
|
||||
{
|
||||
|
||||
if (view.rules().enabled(featureImport) && tx.getTxnType() == ttIMPORT)
|
||||
{
|
||||
// different rules for ttIMPORT
|
||||
auto const [inner, meta] = Import::getInnerTxn(tx, j);
|
||||
if (!inner || !meta)
|
||||
return false;
|
||||
|
||||
auto const result = meta->getFieldU8(sfTransactionResult);
|
||||
|
||||
XRPAmount dropsAdded =
|
||||
result == tesSUCCESS || (result >= tecCLAIM && result <= tecLAST_POSSIBLE_ENTRY)
|
||||
? inner->getFieldAmount(sfFee).xrp() // burned in PoB
|
||||
: beast::zero; // if the txn didnt burn a fee we add nothing
|
||||
|
||||
if (accountsCreated_ == 1)
|
||||
dropsAdded += Import::INITIAL_IMPORT_XRP; // welcome amount for new imports
|
||||
|
||||
JLOG(j.trace())
|
||||
<< "Invariant XRPNotCreated Import: "
|
||||
<< "dropsAdded: " << dropsAdded
|
||||
<< " fee.drops(): " << fee.drops()
|
||||
<< " drops_: " << drops_
|
||||
<< " dropsAdded - fee.drops(): " << dropsAdded - fee.drops();
|
||||
|
||||
return (drops_ == dropsAdded.drops() - fee.drops());
|
||||
}
|
||||
|
||||
// The net change should never be positive, as this would mean that the
|
||||
// transaction created XRP out of thin air. That's not possible.
|
||||
if (drops_ > 0)
|
||||
@@ -493,7 +525,8 @@ ValidNewAccountRoot::finalize(
|
||||
}
|
||||
|
||||
// From this point on we know exactly one account was created.
|
||||
if (tx.getTxnType() == ttPAYMENT && result == tesSUCCESS)
|
||||
auto tt = tx.getTxnType();
|
||||
if ((tt == ttPAYMENT || tt == ttIMPORT) && result == tesSUCCESS)
|
||||
{
|
||||
std::uint32_t const startingSeq{
|
||||
view.rules().enabled(featureDeletableAccounts) ? view.seq() : 1};
|
||||
|
||||
@@ -118,6 +118,7 @@ public:
|
||||
class XRPNotCreated
|
||||
{
|
||||
std::int64_t drops_ = 0;
|
||||
std::uint32_t accountsCreated_ = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
|
||||
@@ -401,7 +401,12 @@ Transactor::checkFee(PreclaimContext const& ctx, XRPAmount baseFee)
|
||||
auto const id = ctx.tx.getAccountID(sfAccount);
|
||||
auto const sle = ctx.view.read(keylet::account(id));
|
||||
if (!sle)
|
||||
{
|
||||
if (ctx.tx.getTxnType() == ttIMPORT)
|
||||
return tesSUCCESS;
|
||||
|
||||
return terNO_ACCOUNT;
|
||||
}
|
||||
|
||||
auto const balance = (*sle)[sfBalance].xrp();
|
||||
|
||||
@@ -429,6 +434,7 @@ Transactor::payFee()
|
||||
auto const feePaid = ctx_.tx[sfFee].xrp();
|
||||
|
||||
auto const sle = view().peek(keylet::account(account_));
|
||||
// RH NOTE: we don't need to check for ttIMPORT here because this function is skipped if the sle doesn't exist
|
||||
if (!sle)
|
||||
return tefINTERNAL;
|
||||
|
||||
@@ -453,15 +459,27 @@ Transactor::checkSeqProxy(
|
||||
|
||||
auto const sle = view.read(keylet::account(id));
|
||||
|
||||
SeqProxy const t_seqProx = tx.getSeqProxy();
|
||||
if (!sle)
|
||||
{
|
||||
|
||||
if (view.rules().enabled(featureImport) &&
|
||||
tx.getTxnType() == ttIMPORT &&
|
||||
t_seqProx.isSeq() &&
|
||||
tx[sfSequence] == 0)
|
||||
{
|
||||
JLOG(j.trace())
|
||||
<< "applyTransaction: allowing first Import txn with seq=0 "
|
||||
<< toBase58(id);
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
JLOG(j.trace())
|
||||
<< "applyTransaction: delay: source account does not exist "
|
||||
<< toBase58(id);
|
||||
return terNO_ACCOUNT;
|
||||
}
|
||||
|
||||
SeqProxy const t_seqProx = tx.getSeqProxy();
|
||||
SeqProxy const a_seq = SeqProxy::sequence((*sle)[sfSequence]);
|
||||
|
||||
// pass all emitted tx provided their seq is 0
|
||||
@@ -537,7 +555,8 @@ Transactor::checkPriorTxAndLastLedger(PreclaimContext const& ctx)
|
||||
|
||||
auto const sle = ctx.view.read(keylet::account(id));
|
||||
|
||||
if (!sle)
|
||||
bool const isFirstImport = !sle && ctx.view.rules().enabled(featureImport) && ctx.tx.getTxnType() == ttIMPORT;
|
||||
if (!sle && !isFirstImport)
|
||||
{
|
||||
JLOG(ctx.j.trace())
|
||||
<< "applyTransaction: delay: source account does not exist "
|
||||
@@ -545,10 +564,11 @@ Transactor::checkPriorTxAndLastLedger(PreclaimContext const& ctx)
|
||||
return terNO_ACCOUNT;
|
||||
}
|
||||
|
||||
if (ctx.tx.isFieldPresent(sfAccountTxnID) &&
|
||||
(sle->getFieldH256(sfAccountTxnID) !=
|
||||
ctx.tx.getFieldH256(sfAccountTxnID)))
|
||||
return tefWRONG_PRIOR;
|
||||
if (ctx.tx.isFieldPresent(sfAccountTxnID))
|
||||
{
|
||||
if (isFirstImport || sle->getFieldH256(sfAccountTxnID) != ctx.tx.getFieldH256(sfAccountTxnID))
|
||||
return tefWRONG_PRIOR;
|
||||
}
|
||||
|
||||
if (ctx.tx.isFieldPresent(sfLastLedgerSequence) &&
|
||||
(ctx.view.seq() > ctx.tx.getFieldU32(sfLastLedgerSequence)))
|
||||
@@ -653,8 +673,9 @@ Transactor::apply()
|
||||
auto const sle = view().peek(keylet::account(account_));
|
||||
|
||||
// sle must exist except for transactions
|
||||
// that allow zero account.
|
||||
assert(sle != nullptr || account_ == beast::zero);
|
||||
// that allow zero account. (and ttIMPORT)
|
||||
assert(sle != nullptr || account_ == beast::zero ||
|
||||
view().rules().enabled(featureImport) && ctx_.tx.getTxnType() == ttIMPORT);
|
||||
|
||||
if (sle)
|
||||
{
|
||||
@@ -694,6 +715,11 @@ Transactor::checkSign(PreclaimContext const& ctx)
|
||||
return telNON_LOCAL_EMITTED_TXN;
|
||||
}
|
||||
|
||||
// pass ttIMPORTs, their signatures are checked at the preflight against the internal xpop txn
|
||||
if (ctx.view.rules().enabled(featureImport) &&
|
||||
ctx.tx.getTxnType() == ttIMPORT)
|
||||
return tesSUCCESS;
|
||||
|
||||
// If the pk is empty, then we must be multi-signing.
|
||||
if (ctx.tx.getSigningPubKey().empty())
|
||||
return checkMultiSign(ctx);
|
||||
@@ -717,6 +743,7 @@ Transactor::checkSingleSign(PreclaimContext const& ctx)
|
||||
auto const idSigner = calcAccountID(PublicKey(makeSlice(pkSigner)));
|
||||
auto const idAccount = ctx.tx.getAccountID(sfAccount);
|
||||
auto const sleAccount = ctx.view.read(keylet::account(idAccount));
|
||||
|
||||
if (!sleAccount)
|
||||
return terNO_ACCOUNT;
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <ripple/app/tx/impl/SetSignerList.h>
|
||||
#include <ripple/app/tx/impl/SetTrust.h>
|
||||
#include <ripple/app/tx/impl/SetHook.h>
|
||||
#include <ripple/app/tx/impl/Import.h>
|
||||
#include <ripple/app/tx/impl/Invoke.h>
|
||||
#include <ripple/app/tx/impl/URIToken.h>
|
||||
|
||||
@@ -155,6 +156,8 @@ invoke_preflight(PreflightContext const& ctx)
|
||||
return invoke_preflight_helper<NFTokenAcceptOffer>(ctx);
|
||||
case ttCLAIM_REWARD:
|
||||
return invoke_preflight_helper<ClaimReward>(ctx);
|
||||
case ttIMPORT:
|
||||
return invoke_preflight_helper<Import>(ctx);
|
||||
case ttINVOKE:
|
||||
return invoke_preflight_helper<Invoke>(ctx);
|
||||
case ttURITOKEN_MINT:
|
||||
@@ -194,7 +197,9 @@ invoke_preclaim(PreclaimContext const& ctx)
|
||||
if (result != tesSUCCESS)
|
||||
return result;
|
||||
|
||||
result = T::checkFee(ctx, calculateBaseFee(ctx.view, ctx.tx));
|
||||
result =
|
||||
ctx.tx.getTxnType() == ttIMPORT ? tesSUCCESS :
|
||||
T::checkFee(ctx, calculateBaseFee(ctx.view, ctx.tx));
|
||||
|
||||
if (result != tesSUCCESS)
|
||||
return result;
|
||||
@@ -270,6 +275,8 @@ invoke_preclaim(PreclaimContext const& ctx)
|
||||
return invoke_preclaim<NFTokenAcceptOffer>(ctx);
|
||||
case ttCLAIM_REWARD:
|
||||
return invoke_preclaim<ClaimReward>(ctx);
|
||||
case ttIMPORT:
|
||||
return invoke_preclaim<Import>(ctx);
|
||||
case ttINVOKE:
|
||||
return invoke_preclaim<Invoke>(ctx);
|
||||
case ttURITOKEN_MINT:
|
||||
@@ -346,6 +353,8 @@ invoke_calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
return NFTokenAcceptOffer::calculateBaseFee(view, tx);
|
||||
case ttCLAIM_REWARD:
|
||||
return ClaimReward::calculateBaseFee(view, tx);
|
||||
case ttIMPORT:
|
||||
return Import::calculateBaseFee(view, tx);
|
||||
case ttINVOKE:
|
||||
return Invoke::calculateBaseFee(view, tx);
|
||||
case ttURITOKEN_MINT:
|
||||
@@ -516,6 +525,10 @@ invoke_apply(ApplyContext& ctx)
|
||||
ClaimReward p(ctx);
|
||||
return p();
|
||||
}
|
||||
case ttIMPORT: {
|
||||
Import p(ctx);
|
||||
return p();
|
||||
}
|
||||
case ttINVOKE: {
|
||||
Invoke p(ctx);
|
||||
return p();
|
||||
|
||||
@@ -150,6 +150,8 @@ public:
|
||||
std::vector<std::string> IPS_FIXED; // Fixed Peer IPs from rippled.cfg.
|
||||
std::vector<std::string> SNTP_SERVERS; // SNTP servers from rippled.cfg.
|
||||
|
||||
std::vector<std::string> IMPORT_VL_KEYS;
|
||||
|
||||
enum StartUpType { FRESH, NORMAL, LOAD, LOAD_FILE, REPLAY, NETWORK };
|
||||
StartUpType START_UP = NORMAL;
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ struct ConfigSection
|
||||
#define SECTION_SWEEP_INTERVAL "sweep_interval"
|
||||
#define SECTION_XPOP_HISTORY "xpop_history"
|
||||
#define SECTION_NETWORK_ID "network_id"
|
||||
#define SECTION_IMPORT_VL_KEYS "import_vl_keys"
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
|
||||
@@ -837,7 +837,7 @@ Config::loadFromString(std::string const& fileContents)
|
||||
BETA_RPC_API = beast::lexicalCastThrow<bool>(strTemp);
|
||||
|
||||
// Do not load trusted validator configuration for standalone mode
|
||||
if (!RUN_STANDALONE)
|
||||
do
|
||||
{
|
||||
// If a file was explicitly specified, then throw if the
|
||||
// path is malformed or if the file does not exist or is
|
||||
@@ -906,6 +906,21 @@ Config::loadFromString(std::string const& fileContents)
|
||||
|
||||
auto iniFile = parseIniFile(data, true);
|
||||
|
||||
if (auto importKeys =
|
||||
getIniFileSection(iniFile, SECTION_IMPORT_VL_KEYS))
|
||||
IMPORT_VL_KEYS = *importKeys;
|
||||
else
|
||||
Throw<std::runtime_error>(
|
||||
"The file specified in [" SECTION_VALIDATORS_FILE
|
||||
"] "
|
||||
"does not contain a [" SECTION_IMPORT_VL_KEYS
|
||||
"] section: " +
|
||||
validatorsFile.string());
|
||||
|
||||
if (RUN_STANDALONE)
|
||||
break;
|
||||
|
||||
|
||||
auto entries = getIniFileSection(iniFile, SECTION_VALIDATORS);
|
||||
|
||||
if (entries)
|
||||
@@ -929,6 +944,8 @@ Config::loadFromString(std::string const& fileContents)
|
||||
if (valListKeys)
|
||||
section(SECTION_VALIDATOR_LIST_KEYS).append(*valListKeys);
|
||||
|
||||
|
||||
|
||||
if (!entries && !valKeyEntries && !valListKeys)
|
||||
Throw<std::runtime_error>(
|
||||
"The file specified in [" SECTION_VALIDATORS_FILE
|
||||
@@ -943,6 +960,7 @@ Config::loadFromString(std::string const& fileContents)
|
||||
validatorsFile.string());
|
||||
}
|
||||
|
||||
|
||||
// Consolidate [validator_keys] and [validators]
|
||||
section(SECTION_VALIDATORS)
|
||||
.append(section(SECTION_VALIDATOR_KEYS).lines());
|
||||
@@ -954,7 +972,7 @@ Config::loadFromString(std::string const& fileContents)
|
||||
"[" + std::string(SECTION_VALIDATOR_LIST_KEYS) +
|
||||
"] config section is missing");
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
{
|
||||
auto const part = section("features");
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace detail {
|
||||
// Feature.cpp. Because it's only used to reserve storage, and determine how
|
||||
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
|
||||
// the actual number of amendments. A LogicError on startup will verify this.
|
||||
static constexpr std::size_t numFeatures = 62;
|
||||
static constexpr std::size_t numFeatures = 63;
|
||||
|
||||
/** Amendments that this server supports and the default voting behavior.
|
||||
Whether they are enabled depends on the Rules defined in the validated
|
||||
@@ -350,6 +350,7 @@ extern uint256 const featureXRPFees;
|
||||
extern uint256 const fixUniversalNumber;
|
||||
extern uint256 const fixNonFungibleTokensV1_2;
|
||||
extern uint256 const fixNFTokenRemint;
|
||||
extern uint256 const featureImport;
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
|
||||
@@ -408,6 +408,7 @@ extern SF_UINT32 const sfRewardTime;
|
||||
extern SF_UINT32 const sfRewardLgrFirst;
|
||||
extern SF_UINT32 const sfRewardLgrLast;
|
||||
extern SF_UINT32 const sfFirstNFTokenSequence;
|
||||
extern SF_UINT32 const sfImportSequence;
|
||||
|
||||
// 64-bit integers (common)
|
||||
extern SF_UINT64 const sfIndexNext;
|
||||
|
||||
@@ -64,7 +64,9 @@ enum TELcodes : TERUnderlyingType {
|
||||
telWRONG_NETWORK,
|
||||
telREQUIRES_NETWORK_ID,
|
||||
telNETWORK_ID_MAKES_TX_NON_CANONICAL,
|
||||
telNON_LOCAL_EMITTED_TXN
|
||||
telNON_LOCAL_EMITTED_TXN,
|
||||
telIMPORT_VL_KEY_NOT_RECOGNISED,
|
||||
telCAN_NOT_QUEUE_IMPORT,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -180,6 +182,7 @@ enum TEFcodes : TERUnderlyingType {
|
||||
tefTOO_BIG,
|
||||
tefNO_TICKET,
|
||||
tefNFTOKEN_IS_NOT_TRANSFERABLE,
|
||||
tefPAST_IMPORT_SEQ,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -332,7 +335,8 @@ enum TECcodes : TERUnderlyingType {
|
||||
tecXCHAIN_ACCOUNT_CREATE_TOO_MANY = 183, // RESERVED - XCHAIN
|
||||
tecXCHAIN_PAYMENT_FAILED = 184, // RESERVED - XCHAIN
|
||||
tecXCHAIN_SELF_COMMIT = 185, // RESERVED - XCHAIN
|
||||
tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR = 186 // RESERVED - XCHAIN
|
||||
tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR = 186, // RESERVED - XCHAIN
|
||||
tecLAST_POSSIBLE_ENTRY = 255,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -146,6 +146,10 @@ enum TxType : std::uint16_t
|
||||
ttURITOKEN_CREATE_SELL_OFFER = 48,
|
||||
ttURITOKEN_CANCEL_SELL_OFFER = 49,
|
||||
|
||||
/** This transaciton accepts a proof of burn from an external network as a basis
|
||||
* for minting according to featureImport */
|
||||
ttIMPORT = 97,
|
||||
|
||||
/** This transaction resets accumulator/counters and claims a reward for holding an average balance
|
||||
* from a specified hook */
|
||||
ttCLAIM_REWARD = 98,
|
||||
|
||||
@@ -456,6 +456,7 @@ REGISTER_FEATURE(Hooks, Supported::yes, VoteBehavior::De
|
||||
REGISTER_FEATURE(BalanceRewards, Supported::yes, VoteBehavior::DefaultYes);
|
||||
REGISTER_FEATURE(PaychanAndEscrowForTokens, Supported::yes, VoteBehavior::DefaultNo);
|
||||
REGISTER_FEATURE(URIToken, Supported::yes, VoteBehavior::DefaultNo);
|
||||
REGISTER_FEATURE(Import, Supported::yes, VoteBehavior::DefaultNo);
|
||||
|
||||
// The following amendments are obsolete, but must remain supported
|
||||
// because they could potentially get enabled.
|
||||
|
||||
@@ -62,6 +62,7 @@ LedgerFormats::LedgerFormats()
|
||||
{sfRewardTime, soeOPTIONAL},
|
||||
{sfRewardAccumulator, soeOPTIONAL},
|
||||
{sfFirstNFTokenSequence, soeOPTIONAL},
|
||||
{sfImportSequence, soeOPTIONAL},
|
||||
},
|
||||
commonFields);
|
||||
|
||||
|
||||
@@ -156,6 +156,8 @@ CONSTRUCT_TYPED_SFIELD(sfEmitGeneration, "EmitGeneration", UINT32,
|
||||
CONSTRUCT_TYPED_SFIELD(sfLockCount, "LockCount", UINT32, 49);
|
||||
|
||||
CONSTRUCT_TYPED_SFIELD(sfFirstNFTokenSequence, "FirstNFTokenSequence", UINT32, 50);
|
||||
|
||||
CONSTRUCT_TYPED_SFIELD(sfImportSequence, "ImportSequence", UINT32, 97);
|
||||
CONSTRUCT_TYPED_SFIELD(sfRewardTime, "RewardTime", UINT32, 98);
|
||||
CONSTRUCT_TYPED_SFIELD(sfRewardLgrFirst, "RewardLgrFirst", UINT32, 99);
|
||||
CONSTRUCT_TYPED_SFIELD(sfRewardLgrLast, "RewardLgrLast", UINT32, 100);
|
||||
@@ -249,8 +251,6 @@ CONSTRUCT_TYPED_SFIELD(sfNFTokenBrokerFee, "NFTokenBrokerFee", AMOUNT,
|
||||
CONSTRUCT_TYPED_SFIELD(sfHookCallbackFee, "HookCallbackFee", AMOUNT, 20);
|
||||
CONSTRUCT_TYPED_SFIELD(sfLockedBalance, "LockedBalance", AMOUNT, 21);
|
||||
|
||||
// Reserve 20 & 21 for Hooks
|
||||
|
||||
// currency amount (fees)
|
||||
CONSTRUCT_TYPED_SFIELD(sfBaseFeeDrops, "BaseFeeDrops", AMOUNT, 22);
|
||||
CONSTRUCT_TYPED_SFIELD(sfReserveBaseDrops, "ReserveBaseDrops", AMOUNT, 23);
|
||||
|
||||
@@ -106,6 +106,7 @@ transResults()
|
||||
MAKE_ERROR(tefNO_AUTH_REQUIRED, "Auth is not required."),
|
||||
MAKE_ERROR(tefNOT_MULTI_SIGNING, "Account has no appropriate list of multi-signers."),
|
||||
MAKE_ERROR(tefPAST_SEQ, "This sequence number has already passed."),
|
||||
MAKE_ERROR(tefPAST_IMPORT_SEQ, "This import sequence number has already been used."),
|
||||
MAKE_ERROR(tefWRONG_PRIOR, "This previous transaction does not match."),
|
||||
MAKE_ERROR(tefBAD_AUTH_MASTER, "Auth for unclaimed account needs correct master key."),
|
||||
MAKE_ERROR(tefINVARIANT_FAILED, "Fee claim violated invariants for the transaction."),
|
||||
@@ -130,6 +131,7 @@ transResults()
|
||||
MAKE_ERROR(telREQUIRES_NETWORK_ID, "Transactions submitted to this node/network must include a correct NetworkID field."),
|
||||
MAKE_ERROR(telNETWORK_ID_MAKES_TX_NON_CANONICAL, "Transactions submitted to this node/network must NOT include a NetworkID field."),
|
||||
MAKE_ERROR(telNON_LOCAL_EMITTED_TXN, "Emitted transaction cannot be applied because it was not generated locally."),
|
||||
MAKE_ERROR(telCAN_NOT_QUEUE_IMPORT, "Import transaction was not able to be directly applied and cannot be queued."),
|
||||
|
||||
MAKE_ERROR(temMALFORMED, "Malformed transaction."),
|
||||
MAKE_ERROR(temBAD_AMOUNT, "Can only send positive amounts."),
|
||||
|
||||
@@ -35,7 +35,6 @@ TxFormats::TxFormats()
|
||||
{sfLastLedgerSequence, soeOPTIONAL},
|
||||
{sfAccountTxnID, soeOPTIONAL},
|
||||
{sfFee, soeREQUIRED},
|
||||
{sfOperationLimit, soeOPTIONAL},
|
||||
{sfMemos, soeOPTIONAL},
|
||||
{sfSigningPubKey, soeREQUIRED},
|
||||
{sfTxnSignature, soeOPTIONAL},
|
||||
@@ -44,6 +43,7 @@ TxFormats::TxFormats()
|
||||
{sfFirstLedgerSequence, soeOPTIONAL},
|
||||
{sfNetworkID, soeOPTIONAL},
|
||||
{sfHookParameters, soeOPTIONAL},
|
||||
{sfOperationLimit, soeOPTIONAL},
|
||||
};
|
||||
|
||||
add(jss::AccountSet,
|
||||
@@ -358,6 +358,13 @@ TxFormats::TxFormats()
|
||||
},
|
||||
commonFields);
|
||||
|
||||
add(jss::Import,
|
||||
ttIMPORT,
|
||||
{
|
||||
{sfBlob, soeREQUIRED},
|
||||
},
|
||||
commonFields);
|
||||
|
||||
add(jss::Invoke,
|
||||
ttINVOKE,
|
||||
{
|
||||
|
||||
@@ -86,6 +86,7 @@ JSS(HookGrant); // field
|
||||
JSS(isSerialized); // out: RPC server_definitions
|
||||
JSS(isSigningField); // out: RPC server_definitions
|
||||
JSS(isVLEncoded); // out: RPC server_definitions
|
||||
JSS(Import);
|
||||
JSS(Invalid); //
|
||||
JSS(Invoke); // transaction type
|
||||
JSS(InvoiceID); // field
|
||||
@@ -163,6 +164,7 @@ JSS(account_history_tx_first); // out: Account txn history subscribe
|
||||
JSS(accounts); // in: LedgerEntry, Subscribe,
|
||||
// handlers/Ledger, Unsubscribe
|
||||
JSS(accounts_proposed); // in: Subscribe, Unsubscribe
|
||||
JSS(acroot);
|
||||
JSS(action);
|
||||
JSS(acquiring); // out: LedgerRequest
|
||||
JSS(address); // out: PeerImp
|
||||
@@ -231,7 +233,10 @@ JSS(converge_time_s); // out: NetworkOPs
|
||||
JSS(cookie); // out: NetworkOPs
|
||||
JSS(count); // in: AccountTx*, ValidatorList
|
||||
JSS(counters); // in/out: retrieve counters
|
||||
JSS(coins);
|
||||
JSS(children);
|
||||
JSS(ctid); // in/out: Tx RPC
|
||||
JSS(cres);
|
||||
JSS(currency_a); // out: BookChanges
|
||||
JSS(currency_b); // out: BookChanges
|
||||
JSS(currentShard); // out: NodeToShardStatus
|
||||
@@ -504,6 +509,7 @@ JSS(paths); // in: RipplePathFind
|
||||
JSS(paths_canonical); // out: RipplePathFind
|
||||
JSS(paths_computed); // out: PathRequest, RipplePathFind
|
||||
JSS(payment_channel); // in: LedgerEntry
|
||||
JSS(pclose);
|
||||
JSS(peer); // in: AccountLines
|
||||
JSS(peer_authorized); // out: AccountLines
|
||||
JSS(peer_id); // out: RCLCxPeerPos
|
||||
@@ -511,6 +517,7 @@ JSS(peers); // out: InboundLedger, handlers/Peers, Overlay
|
||||
JSS(peer_disconnects); // Severed peer connection counter.
|
||||
JSS(peer_disconnects_resources); // Severed peer connections because of
|
||||
// excess resource consumption.
|
||||
JSS(phash);
|
||||
JSS(port); // in: Connect
|
||||
JSS(previous); // out: Reservations
|
||||
JSS(previous_ledger); // out: LedgerPropose
|
||||
@@ -643,6 +650,7 @@ JSS(treenode_track_size); // out: GetCounts
|
||||
JSS(trusted); // out: UnlList
|
||||
JSS(trusted_validator_keys); // out: ValidatorList
|
||||
JSS(tx); // out: STTx, AccountTx*
|
||||
JSS(txroot);
|
||||
JSS(tx_blob); // in/out: Submit,
|
||||
// in: TransactionSign, AccountTx*
|
||||
JSS(tx_hash); // in: TransactionEntry
|
||||
@@ -697,6 +705,7 @@ JSS(validation_private_key); // out: ValidationCreate
|
||||
JSS(validation_public_key); // out: ValidationCreate, ValidationSeed
|
||||
JSS(validation_quorum); // out: NetworkOPs
|
||||
JSS(validation_seed); // out: ValidationCreate, ValidationSeed
|
||||
JSS(validation);
|
||||
JSS(validations); // out: AmendmentTableImpl
|
||||
JSS(validator_sites); // out: ValidatorSites
|
||||
JSS(value); // out: STAmount
|
||||
|
||||
Reference in New Issue
Block a user