mirror of
https://github.com/Xahau/xahaud.git
synced 2026-06-04 01:06:37 +00:00
dump
This commit is contained in:
@@ -59,6 +59,7 @@ buildLedgerImpl(
|
||||
OpenView accum(&*built);
|
||||
assert(!accum.open());
|
||||
applyTxs(accum, built);
|
||||
std::cout << "BuildLedger::buildLedgerImpl: " << "\n";
|
||||
accum.apply(*built);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ OpenLedger::accept(
|
||||
// Apply local tx
|
||||
for (auto const& item : locals)
|
||||
{
|
||||
// std::cout << "OpenLedger::accept: TXQu" << "\n";
|
||||
JLOG(j_.trace()) << "OpenLedger::accept: getTxQ" << "\n";
|
||||
app.getTxQ().apply(app, *next, item.second, flags, j_);
|
||||
}
|
||||
|
||||
@@ -134,6 +134,10 @@ OpenLedger::accept(
|
||||
// skip emitted txns
|
||||
if (tx->isFieldPresent(sfEmitDetails))
|
||||
continue;
|
||||
|
||||
// skip emitted txns
|
||||
if (tx->isFieldPresent(sfBatchIndex))
|
||||
continue;
|
||||
|
||||
if (auto const toSkip = app.getHashRouter().shouldRelay(txId))
|
||||
{
|
||||
|
||||
@@ -1397,7 +1397,7 @@ NetworkOPsImp::apply(std::unique_lock<std::mutex>& batchLock)
|
||||
if (e.failType == FailHard::yes)
|
||||
flags |= tapFAIL_HARD;
|
||||
|
||||
// std::cout << "NetworkOPsImp::apply: TXQu" << "\n";
|
||||
std::cout << "NetworkOPsImp::apply: getTxQ" << "\n";
|
||||
auto const result = app_.getTxQ().apply(
|
||||
app_, view, e.transaction->getSTransaction(), flags, j);
|
||||
e.result = result.first;
|
||||
|
||||
@@ -56,10 +56,20 @@ ApplyContext::discard()
|
||||
void
|
||||
ApplyContext::apply(TER ter)
|
||||
{
|
||||
// std::cout << "ApplyContext::apply" << "\n";
|
||||
std::cout << "ApplyContext::apply: " << ter << "\n";
|
||||
std::cout << "ApplyContext::apply: " << (flags_ & tapPREFLIGHT_BATCH) << "\n";
|
||||
// std::cout << "tx: " << tx.getTransactionID() << "\n";
|
||||
// if (flags_ == tapPREFLIGHT_BATCH)
|
||||
// return;
|
||||
// if (ter == tecBATCH_FAILURE || flags_ == tapPREFLIGHT_BATCH)
|
||||
// {
|
||||
// std::cout << "ApplyContext::apply: " << "FAILURE" << "\n";
|
||||
// return;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// view_->apply(base_, tx, ter, journal);
|
||||
// }
|
||||
view_->apply(base_, tx, ter, journal);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/protocol/TER.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/tx/applySteps.h>
|
||||
#include <ripple/app/tx/impl/ApplyContext.h>
|
||||
#include <ripple/app/tx/impl/Batch.h>
|
||||
@@ -52,6 +52,7 @@
|
||||
#include <ripple/ledger/View.h>
|
||||
#include <ripple/protocol/Feature.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/TER.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -229,10 +230,10 @@ invoke_preclaim(PreclaimContext const& ctx)
|
||||
if (result != tesSUCCESS)
|
||||
return result;
|
||||
|
||||
result = T::checkFee(ctx, calculateBaseFee(ctx.view, ctx.tx));
|
||||
// result = T::checkFee(ctx, calculateBaseFee(ctx.view, ctx.tx));
|
||||
|
||||
if (result != tesSUCCESS)
|
||||
return result;
|
||||
// if (result != tesSUCCESS)
|
||||
// return result;
|
||||
|
||||
result = T::checkSign(ctx);
|
||||
|
||||
@@ -366,38 +367,41 @@ Batch::preclaim(PreclaimContext const& ctx)
|
||||
preclaimResponses.push_back(response);
|
||||
}
|
||||
|
||||
// Handle Atomicity
|
||||
// for (const auto& response : preclaimResponses)
|
||||
// {
|
||||
// if (response != tesSUCCESS)
|
||||
// {
|
||||
// return response;
|
||||
// }
|
||||
// }
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
std::vector<TER> doApplyResponses;
|
||||
// void
|
||||
// Batch::updateAccount(Sandbox& sb)
|
||||
// {
|
||||
// auto const sle = ctx_.base_.read(keylet::account(account_));
|
||||
// if (!sle)
|
||||
// return tefINTERNAL;
|
||||
|
||||
// auto const sleSrcAcc = sb.peek(keylet::account(account_));
|
||||
// if (!sleSrcAcc)
|
||||
// return tefINTERNAL;
|
||||
|
||||
// auto const feePaid = ctx_.tx[sfFee].xrp();
|
||||
// sleSrcAcc->setFieldAmount(sfBalance, sle->getFieldAmount(sfBalance).xrp() - feePaid);
|
||||
// sb.update(sleSrcAcc);
|
||||
// sb.apply(ctx_.rawView());
|
||||
// }
|
||||
|
||||
TER
|
||||
Batch::doApply()
|
||||
{
|
||||
// std::cout << "Batch::doApply()" << "\n";
|
||||
std::cout << "Batch::doApply()" << "\n";
|
||||
Sandbox sb(&ctx_.view());
|
||||
// Sandbox sb(ctx_.base_.base_, view().flags());
|
||||
|
||||
uint32_t flags = ctx_.tx.getFlags();
|
||||
if (flags & tfBatchMask)
|
||||
return temINVALID_FLAG;
|
||||
|
||||
// SANITIZE
|
||||
std::vector<STTx> stxTxns;
|
||||
auto const& txns = ctx_.tx.getFieldArray(sfRawTransactions);
|
||||
for (std::size_t i = 0; i < txns.size(); ++i)
|
||||
{
|
||||
// std::cout << "START" << "\n";
|
||||
ApplyViewImpl& avi = dynamic_cast<ApplyViewImpl&>(ctx_.view());
|
||||
STObject meta{sfBatchExecution};
|
||||
|
||||
auto const& txn = txns[i];
|
||||
if (!txn.isFieldPresent(sfTransactionType))
|
||||
{
|
||||
@@ -409,9 +413,61 @@ Batch::doApply()
|
||||
auto const tt = txn.getFieldU16(sfTransactionType);
|
||||
auto const txtype = safe_cast<TxType>(tt);
|
||||
auto const stx = STTx(txtype, [&txn](STObject& obj) { obj = std::move(txn); });
|
||||
stxTxns.push_back(stx);
|
||||
}
|
||||
|
||||
// OpenView(&ctx_.view())
|
||||
JLOG(ctx_.journal.error()) << "Batch: SUBMITTING: " << preclaimResponses[i];
|
||||
// DRY RUN
|
||||
// std::cout << "DRYRUN::size(): " << stxTxns.size() << "\n";
|
||||
// std::vector<std::pair<std::uint16_t, TER>> dryVector;
|
||||
// for (std::size_t i = 0; i < stxTxns.size(); ++i)
|
||||
// {
|
||||
// auto const& stx = stxTxns[i];
|
||||
// ApplyContext actx(
|
||||
// ctx_.app,
|
||||
// ctx_.base_,
|
||||
// stx,
|
||||
// preclaimResponses[i],
|
||||
// ctx_.view().fees().base,
|
||||
// tapPREFLIGHT_BATCH,
|
||||
// ctx_.journal);
|
||||
// auto const result = invoke_apply(actx);
|
||||
// dryVector.emplace_back(stx.getTxnType(), result.first);
|
||||
// std::cout << "ApplyContext::size(): " << actx.size() << "\n";
|
||||
// actx.discard();
|
||||
// }
|
||||
|
||||
ApplyViewImpl& avi = dynamic_cast<ApplyViewImpl&>(ctx_.view());
|
||||
// for (auto const& dryRun : dryVector)
|
||||
// {
|
||||
// STObject meta{sfBatchExecution};
|
||||
// meta.setFieldU8(sfTransactionResult, TERtoInt(dryRun.second));
|
||||
// meta.setFieldU16(sfTransactionType, dryRun.first);
|
||||
// avi.addBatchExecutionMetaData(std::move(meta));
|
||||
|
||||
// // tfBatchAtomic
|
||||
// if (dryRun.second != tesSUCCESS && flags & tfBatchAtomic)
|
||||
// {
|
||||
// std::cout << "tfBatchAtomic::Failed" << "\n";
|
||||
// sb.apply(ctx_.rawView());
|
||||
// return tecBATCH_FAILURE;
|
||||
// }
|
||||
// }
|
||||
|
||||
// ctx_.discard();
|
||||
|
||||
// // reset avi
|
||||
// std::vector<STObject> executions;
|
||||
// std::vector<STObject> emissions;
|
||||
// std::vector<STObject> batch;
|
||||
// avi.setHookMetaData(std::move(executions), std::move(emissions), std::move(batch));
|
||||
|
||||
// WET RUN
|
||||
TER result = tesSUCCESS;
|
||||
for (std::size_t i = 0; i < stxTxns.size(); ++i)
|
||||
{
|
||||
STObject meta{sfBatchExecution};
|
||||
|
||||
auto const& stx = stxTxns[i];
|
||||
ApplyContext actx(
|
||||
ctx_.app,
|
||||
ctx_.base_,
|
||||
@@ -420,54 +476,60 @@ Batch::doApply()
|
||||
ctx_.view().fees().base,
|
||||
view().flags(),
|
||||
ctx_.journal);
|
||||
auto const result = invoke_apply(actx);
|
||||
meta.setFieldU8(sfTransactionResult, TERtoInt(result.first));
|
||||
meta.setFieldU16(sfTransactionType, tt);
|
||||
if (result.first == tesSUCCESS)
|
||||
meta.setFieldH256(sfTransactionHash, stx.getTransactionID());
|
||||
|
||||
avi.addBatchExecutionMetaData(std::move(meta));
|
||||
|
||||
if (result.first != tesSUCCESS)
|
||||
{
|
||||
actx.discard();
|
||||
auto const _result = invoke_apply(actx);
|
||||
|
||||
meta.setFieldU8(sfTransactionResult, TERtoInt(_result.first));
|
||||
meta.setFieldU16(sfTransactionType, stx.getTxnType());
|
||||
if(_result.first != tesSUCCESS)
|
||||
meta.setFieldH256(sfTransactionHash, stx.getTransactionID());
|
||||
|
||||
avi.addBatchExecutionMetaData(std::move(meta));
|
||||
|
||||
std::cout << "tfBatchFirst: " << (flags & tfBatchFirst) << "\n";
|
||||
std::cout << "tfBatchOne: " << (flags & tfBatchOne) << "\n";
|
||||
std::cout << "tfBatchAtomic: " << _result.first << "\n";
|
||||
|
||||
if (_result.first != tesSUCCESS)
|
||||
{
|
||||
if (flags & tfBatchFirst)
|
||||
{
|
||||
return tecFAILED_PROCESSING;
|
||||
actx.discard();
|
||||
result = tecBATCH_FAILURE;
|
||||
break;
|
||||
}
|
||||
if (flags & tfBatchOne)
|
||||
{
|
||||
actx.discard();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
doApplyResponses.push_back(result.first);
|
||||
|
||||
if (_result.first == tesSUCCESS && flags & tfBatchOne)
|
||||
{
|
||||
result = tecBATCH_FAILURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto const sle = ctx_.base_.read(keylet::account(account_));
|
||||
if (!sle)
|
||||
auto const sleBase = ctx_.base_.read(keylet::account(account_));
|
||||
if (!sleBase)
|
||||
return tefINTERNAL;
|
||||
|
||||
auto const sleSrcAcc = sb.peek(keylet::account(account_));
|
||||
if (!sleSrcAcc)
|
||||
return tefINTERNAL;
|
||||
|
||||
// std::cout << "ACCOUNT BASE SEQ: " << sleBase->getFieldU32(sfSequence) << "\n";
|
||||
// std::cout << "ACCOUNT BASE BALANCE: " << sleBase->getFieldAmount(sfBalance) << "\n";
|
||||
// std::cout << "ACCOUNT SEQ: " << sleSrcAcc->getFieldU32(sfSequence) << "\n";
|
||||
// std::cout << "ACCOUNT BALANCE: " << mSourceBalance << "\n";
|
||||
// std::cout << "ACCOUNT BALANCE=: " << sle->getFieldAmount(sfBalance) << "\n";
|
||||
sleSrcAcc->setFieldAmount(sfBalance, sle->getFieldAmount(sfBalance));
|
||||
// std::cout << "ACCOUNT BALANCE: " << sleSrcAcc->getFieldAmount(sfBalance) << "\n";
|
||||
|
||||
auto const feePaid = ctx_.tx[sfFee].xrp();
|
||||
sleSrcAcc->setFieldU32(sfSequence, sleBase->getFieldU32(sfSequence));
|
||||
sleSrcAcc->setFieldAmount(sfBalance, sleBase->getFieldAmount(sfBalance).xrp() - feePaid);
|
||||
sb.update(sleSrcAcc);
|
||||
|
||||
for (auto applyResp : doApplyResponses)
|
||||
{
|
||||
if (applyResp != tesSUCCESS)
|
||||
{
|
||||
if (flags & tfBatchAtomic)
|
||||
{
|
||||
ctx_.discard();
|
||||
return tecFAILED_PROCESSING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sb.apply(ctx_.rawView());
|
||||
return tesSUCCESS;
|
||||
return result;
|
||||
}
|
||||
|
||||
XRPAmount
|
||||
|
||||
@@ -531,6 +531,7 @@ TER
|
||||
Transactor::payFee()
|
||||
{
|
||||
auto const feePaid = ctx_.tx[sfFee].xrp();
|
||||
std::cout << "feePaid: " << feePaid << "\n";
|
||||
|
||||
auto const sle = view().peek(keylet::account(account_));
|
||||
// RH NOTE: we don't need to check for ttIMPORT here because this function
|
||||
@@ -541,7 +542,9 @@ Transactor::payFee()
|
||||
// Deduct the fee, so it's not available during the transaction.
|
||||
// Will only write the account back if the transaction succeeds.
|
||||
|
||||
std::cout << "mSourceBalance1.1: " << mSourceBalance << "\n";
|
||||
mSourceBalance -= feePaid;
|
||||
std::cout << "mSourceBalance1.2: " << mSourceBalance << "\n";
|
||||
sle->setFieldAmount(sfBalance, mSourceBalance);
|
||||
|
||||
// VFALCO Should we call view().rawDestroyXRP() here as well?
|
||||
@@ -557,9 +560,12 @@ Transactor::checkSeqProxy(
|
||||
{
|
||||
auto const id = tx.getAccountID(sfAccount);
|
||||
|
||||
auto const tt = tx.getTxnType();
|
||||
|
||||
auto const sle = view.read(keylet::account(id));
|
||||
|
||||
SeqProxy const t_seqProx = tx.getSeqProxy();
|
||||
std::cout << "Transactor::checkSeqProxy: " << t_seqProx.value() << "\n";
|
||||
if (!sle)
|
||||
{
|
||||
if (view.rules().enabled(featureImport) &&
|
||||
@@ -613,6 +619,7 @@ Transactor::checkSeqProxy(
|
||||
return terPRE_SEQ;
|
||||
}
|
||||
// It's an already-used sequence number.
|
||||
JLOG(j.trace()) << "applyTransaction: " << tt;
|
||||
JLOG(j.trace()) << "applyTransaction: has past sequence number "
|
||||
<< "a_seq=" << a_seq << " t_seq=" << t_seqProx;
|
||||
return tefPAST_SEQ;
|
||||
@@ -808,10 +815,8 @@ Transactor::apply()
|
||||
preCompute();
|
||||
|
||||
auto const tt = ctx_.tx.getTxnType();
|
||||
// std::cout << "tt: " << tt << "\n";
|
||||
// std::cout << "id: " << ctx_.tx.getTransactionID() << "\n";
|
||||
// if (tt == ttBATCH)
|
||||
// return doApply();
|
||||
std::cout << "tt: " << tt << "\n";
|
||||
std::cout << "id: " << ctx_.tx.getTransactionID() << "\n";
|
||||
|
||||
// If the transactor requires a valid account and the transaction doesn't
|
||||
// list one, preflight will have already a flagged a failure.
|
||||
@@ -827,11 +832,7 @@ Transactor::apply()
|
||||
|
||||
if (sle)
|
||||
{
|
||||
// std::cout << "mSourceBalance: " << mSourceBalance << "\n";
|
||||
// std::cout << "mPriorBalance: " << mPriorBalance << "\n";
|
||||
// std::cout << "mSourceBalance=: " << (mSourceBalance - mPriorBalance) << "\n";
|
||||
mPriorBalance = STAmount{(*sle)[sfBalance]}.xrp();
|
||||
// std::cout << "mPriorBalance: " << mPriorBalance << "\n";
|
||||
mSourceBalance = mPriorBalance;
|
||||
|
||||
TER result = consumeSeqProxy(sle);
|
||||
@@ -847,9 +848,6 @@ Transactor::apply()
|
||||
|
||||
view().update(sle);
|
||||
}
|
||||
|
||||
// std::cout << "Transactor::apply" << "\n";
|
||||
|
||||
return doApply();
|
||||
}
|
||||
|
||||
@@ -1168,10 +1166,11 @@ Transactor::reset(XRPAmount fee)
|
||||
ApplyViewImpl& avi = dynamic_cast<ApplyViewImpl&>(ctx_.view());
|
||||
std::vector<STObject> executions;
|
||||
std::vector<STObject> emissions;
|
||||
avi.copyHookMetaData(executions, emissions);
|
||||
std::vector<STObject> batch;
|
||||
avi.copyHookMetaData(executions, emissions, batch);
|
||||
ctx_.discard();
|
||||
ApplyViewImpl& avi2 = dynamic_cast<ApplyViewImpl&>(ctx_.view());
|
||||
avi2.setHookMetaData(std::move(executions), std::move(emissions));
|
||||
avi2.setHookMetaData(std::move(executions), std::move(emissions), std::move(batch));
|
||||
|
||||
auto const txnAcct =
|
||||
view().peek(keylet::account(ctx_.tx.getAccountID(sfAccount)));
|
||||
@@ -1849,7 +1848,8 @@ Transactor::operator()()
|
||||
if (ctx_.size() > oversizeMetaDataCap)
|
||||
result = tecOVERSIZE;
|
||||
|
||||
if (isTecClaim(result) && (view().flags() & tapFAIL_HARD))
|
||||
if ((isTecClaim(result) && (view().flags() & tapFAIL_HARD)) ||
|
||||
view().flags() & tapPREFLIGHT_BATCH)
|
||||
{
|
||||
// If the tapFAIL_HARD flag is set, a tec result
|
||||
// must not do anything
|
||||
@@ -2083,6 +2083,8 @@ Transactor::operator()()
|
||||
ctx_.destroyXRP(fee);
|
||||
|
||||
// Once we call apply, we will no longer be able to look at view()
|
||||
std::cout << "Transaction::apply" << "\n";
|
||||
std::cout << "Transaction::apply: " << (view().flags() & tapPREFLIGHT_BATCH) << "\n";
|
||||
ctx_.apply(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -105,16 +105,19 @@ public:
|
||||
void
|
||||
setHookMetaData(
|
||||
std::vector<STObject>&& executions,
|
||||
std::vector<STObject>&& emissions)
|
||||
std::vector<STObject>&& emissions,
|
||||
std::vector<STObject>&& batch)
|
||||
{
|
||||
hookExecution_ = std::move(executions);
|
||||
hookEmission_ = std::move(emissions);
|
||||
batchExecution_ = std::move(batch);
|
||||
}
|
||||
|
||||
void
|
||||
copyHookMetaData(
|
||||
std::vector<STObject>& execution /* in */,
|
||||
std::vector<STObject>& emission /* in */)
|
||||
std::vector<STObject>& emission /* in */,
|
||||
std::vector<STObject>& batch /* in */)
|
||||
{
|
||||
std::copy(
|
||||
hookExecution_.begin(),
|
||||
@@ -124,6 +127,10 @@ public:
|
||||
hookEmission_.begin(),
|
||||
hookEmission_.end(),
|
||||
std::back_inserter(emission));
|
||||
std::copy(
|
||||
batchExecution_.begin(),
|
||||
batchExecution_.end(),
|
||||
std::back_inserter(batch));
|
||||
}
|
||||
|
||||
uint16_t
|
||||
|
||||
@@ -54,6 +54,7 @@ public:
|
||||
void
|
||||
apply(RawView& to)
|
||||
{
|
||||
std::cout << "Sandbox::apply: " << "\n";
|
||||
items_.apply(to);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@ ApplyViewImpl::ApplyViewImpl(ReadView const* base, ApplyFlags flags)
|
||||
void
|
||||
ApplyViewImpl::apply(OpenView& to, STTx const& tx, TER ter, beast::Journal j)
|
||||
{
|
||||
// std::cout << "ApplyViewImpl::apply" << "\n";
|
||||
std::cout << "ApplyViewImpl::apply" << "\n";
|
||||
items_.apply(to, tx, ter, deliver_, batchExecution_, hookExecution_, hookEmission_, j);
|
||||
}
|
||||
|
||||
|
||||
@@ -130,6 +130,8 @@ void
|
||||
OpenView::apply(TxsRawView& to) const
|
||||
{
|
||||
// std::cout << "OpenView::apply" << "\n";
|
||||
// std::cout << "OpenView::apply: " << items_.size() << "\n";
|
||||
std::cout << "OpenView::apply: " << txs_.size() << "\n";
|
||||
items_.apply(to);
|
||||
for (auto const& item : txs_)
|
||||
{
|
||||
|
||||
@@ -410,6 +410,7 @@ extern SF_UINT32 const sfRewardLgrLast;
|
||||
extern SF_UINT32 const sfFirstNFTokenSequence;
|
||||
extern SF_UINT32 const sfImportSequence;
|
||||
extern SF_UINT32 const sfXahauActivationLgrSeq;
|
||||
extern SF_UINT32 const sfBatchIndex;
|
||||
|
||||
// 64-bit integers (common)
|
||||
extern SF_UINT64 const sfIndexNext;
|
||||
|
||||
@@ -340,6 +340,7 @@ enum TECcodes : TERUnderlyingType {
|
||||
tecXCHAIN_SELF_COMMIT = 185, // RESERVED - XCHAIN
|
||||
tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR = 186, // RESERVED - XCHAIN
|
||||
tecINSUF_RESERVE_SELLER = 187,
|
||||
tecBATCH_FAILURE = 188,
|
||||
tecLAST_POSSIBLE_ENTRY = 255,
|
||||
};
|
||||
|
||||
|
||||
@@ -171,6 +171,7 @@ constexpr std::uint32_t const tfOptOut = 0x00000001;
|
||||
enum BatchFlags : std::uint32_t {
|
||||
tfBatchAtomic = 0x00000001,
|
||||
tfBatchFirst = 0x00000002,
|
||||
tfBatchOne = 0x00000004,
|
||||
};
|
||||
|
||||
constexpr std::uint32_t const tfBatchMask =
|
||||
|
||||
@@ -157,6 +157,7 @@ CONSTRUCT_TYPED_SFIELD(sfLockCount, "LockCount", UINT32,
|
||||
|
||||
CONSTRUCT_TYPED_SFIELD(sfFirstNFTokenSequence, "FirstNFTokenSequence", UINT32, 50);
|
||||
|
||||
CONSTRUCT_TYPED_SFIELD(sfBatchIndex, "BatchIndex", UINT32, 95);
|
||||
CONSTRUCT_TYPED_SFIELD(sfXahauActivationLgrSeq, "XahauActivationLgrSeq",UINT32, 96);
|
||||
CONSTRUCT_TYPED_SFIELD(sfImportSequence, "ImportSequence", UINT32, 97);
|
||||
CONSTRUCT_TYPED_SFIELD(sfRewardTime, "RewardTime", UINT32, 98);
|
||||
|
||||
@@ -188,6 +188,10 @@ STTx::getSeqProxy() const
|
||||
if (seq != 0)
|
||||
return SeqProxy::sequence(seq);
|
||||
|
||||
// std::uint32_t const batchIndex{getFieldU32(sfBatchIndex)};
|
||||
// if (batchIndex != 0)
|
||||
// return SeqProxy::sequence(batchIndex);
|
||||
|
||||
std::optional<std::uint32_t> const ticketSeq{operator[](~sfTicketSequence)};
|
||||
if (!ticketSeq)
|
||||
// No TicketSequence specified. Return the Sequence, whatever it is.
|
||||
|
||||
@@ -92,6 +92,7 @@ transResults()
|
||||
MAKE_ERROR(tecREQUIRES_FLAG, "The transaction or part-thereof requires a flag that wasn't set."),
|
||||
MAKE_ERROR(tecPRECISION_LOSS, "The amounts used by the transaction cannot interact."),
|
||||
MAKE_ERROR(tecINSUF_RESERVE_SELLER, "The seller of an object has insufficient reserves, and thus cannot complete the sale."),
|
||||
MAKE_ERROR(tecBATCH_FAILURE, "Tx Batch Failure."),
|
||||
MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
|
||||
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),
|
||||
MAKE_ERROR(tefBAD_AUTH, "Transaction's public key is not authorized."),
|
||||
|
||||
@@ -45,6 +45,7 @@ TxFormats::TxFormats()
|
||||
{sfHookParameters, soeOPTIONAL},
|
||||
{sfOperationLimit, soeOPTIONAL},
|
||||
{sfCloseResolution, soeOPTIONAL},
|
||||
{sfBatchIndex, soeOPTIONAL},
|
||||
};
|
||||
|
||||
add(jss::AccountSet,
|
||||
|
||||
@@ -22,6 +22,33 @@
|
||||
#include <ripple/protocol/jss.h>
|
||||
#include <test/jtx.h>
|
||||
|
||||
// tfBatchOne
|
||||
// Tx1: Payment = tecUNFUNDED => Leave
|
||||
// Tx2: Payment = tesSUCCESS => Leave
|
||||
// TER(tesSUCCESS)
|
||||
|
||||
// tfBatchFirst
|
||||
// Tx1: Payment = tesSUCCESS => Leave
|
||||
// Tx2: Payment = tecUNFUNDED => Leave
|
||||
// TER(tesSUCCESS)
|
||||
|
||||
// tfBatchAtomic
|
||||
// Tx1: Payment = tesSUCCESS => Revert
|
||||
// Tx2: Payment = tecUNFUNDED => Leave
|
||||
// TER(tecBATCH_FAILURE)
|
||||
|
||||
// Broadcast - Manually broadcast the inner transactions
|
||||
// Stacking Views
|
||||
// TicketCreate as first of batch
|
||||
// Sequence optional except when needed specifically
|
||||
// Bypass the queue for inner transactions
|
||||
// Fee only on outer - if 2 payments and fee escellation make sure that the outer tx includes the fee escallation for all inner
|
||||
// Look at TicketCreate for creating virtual tickets (Transactor.cpp) (TransactionConsequences.cpp)
|
||||
// If we have the batch index, the virtual ticket number is seq of batch + batch index.
|
||||
// Think about multiple different angles of this. AccountA & AccountB.
|
||||
|
||||
// OptionB: Use OfferID
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
|
||||
@@ -61,9 +88,9 @@ class Batch_test : public beast::unit_test::suite
|
||||
jv[sfRawTransactions.jsonName][index] = Json::Value{};
|
||||
jv[sfRawTransactions.jsonName][index][jss::RawTransaction] = tx;
|
||||
jv[sfRawTransactions.jsonName][index][jss::RawTransaction][jss::SigningPubKey] = strHex(account.pk());
|
||||
jv[sfRawTransactions.jsonName][index][jss::RawTransaction][sfFee.jsonName] = to_string(feeDrops);
|
||||
jv[sfRawTransactions.jsonName][index][jss::RawTransaction][sfFee.jsonName] = 0;
|
||||
jv[sfRawTransactions.jsonName][index][jss::RawTransaction][jss::Sequence] = next;
|
||||
// jv[sfRawTransactions.jsonName][index][jss::RawTransaction][sfCloseResolution.jsonName] = next;
|
||||
jv[sfRawTransactions.jsonName][index][jss::RawTransaction][sfBatchIndex.jsonName] = next;
|
||||
return jv;
|
||||
}
|
||||
|
||||
@@ -91,7 +118,6 @@ class Batch_test : public beast::unit_test::suite
|
||||
// // beast::severities::kWarning
|
||||
// beast::severities::kTrace};
|
||||
|
||||
|
||||
auto const feeDrops = env.current()->fees().base;
|
||||
|
||||
auto const alice = Account("alice");
|
||||
@@ -221,18 +247,18 @@ class Batch_test : public beast::unit_test::suite
|
||||
Json::Value jv;
|
||||
jv[jss::TransactionType] = jss::Batch;
|
||||
jv[jss::Account] = alice.human();
|
||||
jv[jss::Sequence] = seq + 2;
|
||||
jv[jss::Sequence] = seq;
|
||||
|
||||
// Batch Transactions
|
||||
jv[sfRawTransactions.jsonName] = Json::Value{Json::arrayValue};
|
||||
|
||||
// Tx 1
|
||||
Json::Value const tx1 = pay(alice, bob, XRP(1));
|
||||
jv = addBatchTx(jv, tx1, alice, feeDrops, 0, seq);
|
||||
jv = addBatchTx(jv, tx1, alice, feeDrops, 0, seq + 1);
|
||||
|
||||
// Tx 2
|
||||
Json::Value const tx2 = pay(alice, bob, XRP(1));
|
||||
jv = addBatchTx(jv, tx2, alice, feeDrops, 1, seq + 1);
|
||||
jv = addBatchTx(jv, tx2, alice, feeDrops, 1, seq + 2);
|
||||
|
||||
env(jv, fee(feeDrops * 2), ter(tesSUCCESS));
|
||||
env.close();
|
||||
@@ -243,11 +269,22 @@ class Batch_test : public beast::unit_test::suite
|
||||
}};
|
||||
|
||||
Json::Value params;
|
||||
params[jss::transaction] = env.tx()->getJson(JsonOptions::none)[jss::hash];
|
||||
auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
params[jss::ledger_index] = env.current()->seq() - 1;
|
||||
params[jss::transactions] = true;
|
||||
params[jss::expand] = true;
|
||||
auto const jrr = env.rpc("json", "ledger", to_string(params));
|
||||
std::cout << "jrr: " << jrr << "\n";
|
||||
auto const meta = jrr[jss::result][jss::meta];
|
||||
validateBatchTxns(meta, testCases);
|
||||
|
||||
// Json::Value params;
|
||||
// params[jss::transaction] = env.tx()->getJson(JsonOptions::none)[jss::hash];
|
||||
// auto const jrr = env.rpc("json", "tx", to_string(params));
|
||||
// std::cout << "jrr: " << jrr << "\n";
|
||||
// auto const meta = jrr[jss::result][jss::meta];
|
||||
// validateBatchTxns(meta, testCases);
|
||||
|
||||
std::cout << "seq: " << env.seq(alice) << "\n";
|
||||
std::cout << "alice: " << env.balance(alice) << "\n";
|
||||
std::cout << "bob: " << env.balance(bob) << "\n";
|
||||
|
||||
BEAST_EXPECT(env.seq(alice) == 2);
|
||||
BEAST_EXPECT(env.balance(alice) == XRP(1000) - XRP(2) - (feeDrops * 2));
|
||||
@@ -275,21 +312,33 @@ class Batch_test : public beast::unit_test::suite
|
||||
Json::Value jv;
|
||||
jv[jss::TransactionType] = jss::Batch;
|
||||
jv[jss::Account] = alice.human();
|
||||
jv[jss::Sequence] = seq;
|
||||
|
||||
// Batch Transactions
|
||||
jv[sfRawTransactions.jsonName] = Json::Value{Json::arrayValue};
|
||||
|
||||
// Tx 1
|
||||
Json::Value const tx1 = pay(alice, bob, XRP(1));
|
||||
jv = addBatchTx(jv, tx1, alice, feeDrops, 0, 0);
|
||||
jv = addBatchTx(jv, tx1, alice, feeDrops, 0, seq + 1);
|
||||
|
||||
// Tx 2
|
||||
Json::Value const tx2 = pay(alice, bob, XRP(999));
|
||||
jv = addBatchTx(jv, tx2, alice, feeDrops, 1, 0);
|
||||
jv = addBatchTx(jv, tx2, alice, feeDrops, 1, seq + 2);
|
||||
|
||||
env(jv, fee(feeDrops * 2), txflags(tfBatchAtomic), ter(tecFAILED_PROCESSING));
|
||||
env(jv, fee(feeDrops * 2), txflags(tfBatchAtomic), ter(tecBATCH_FAILURE));
|
||||
env.close();
|
||||
|
||||
Json::Value params;
|
||||
params[jss::ledger_index] = env.current()->seq() - 1;
|
||||
params[jss::transactions] = true;
|
||||
params[jss::expand] = true;
|
||||
auto const jrr = env.rpc("json", "ledger", to_string(params));
|
||||
std::cout << "jrr: " << jrr << "\n";
|
||||
|
||||
std::cout << "seq: " << env.seq(alice) << "\n";
|
||||
std::cout << "alice: " << env.balance(alice) << "\n";
|
||||
std::cout << "bob: " << env.balance(bob) << "\n";
|
||||
|
||||
BEAST_EXPECT(env.seq(alice) == 2);
|
||||
BEAST_EXPECT(env.balance(alice) == XRP(1000) - (feeDrops * 2));
|
||||
BEAST_EXPECT(env.balance(bob) == XRP(1000));
|
||||
@@ -303,7 +352,14 @@ class Batch_test : public beast::unit_test::suite
|
||||
using namespace test::jtx;
|
||||
using namespace std::literals;
|
||||
|
||||
test::jtx::Env env{*this, envconfig()};
|
||||
// test::jtx::Env env{*this, envconfig()};
|
||||
Env env{
|
||||
*this,
|
||||
envconfig(),
|
||||
features,
|
||||
nullptr,
|
||||
// beast::severities::kWarning
|
||||
beast::severities::kTrace};
|
||||
auto const feeDrops = env.current()->fees().base;
|
||||
|
||||
auto const alice = Account("alice");
|
||||
@@ -312,9 +368,11 @@ class Batch_test : public beast::unit_test::suite
|
||||
env.fund(XRP(1000), alice, bob, carol);
|
||||
env.close();
|
||||
|
||||
auto const seq = env.seq("alice");
|
||||
Json::Value jv;
|
||||
jv[jss::TransactionType] = jss::Batch;
|
||||
jv[jss::Account] = alice.human();
|
||||
jv[jss::Sequence] = seq;
|
||||
|
||||
// Batch Transactions
|
||||
jv[sfRawTransactions.jsonName] = Json::Value{Json::arrayValue};
|
||||
@@ -325,18 +383,29 @@ class Batch_test : public beast::unit_test::suite
|
||||
|
||||
// Tx 2
|
||||
Json::Value const tx2 = pay(alice, bob, XRP(999));
|
||||
jv = addBatchTx(jv, tx2, alice, feeDrops, 1, 0);
|
||||
jv = addBatchTx(jv, tx2, alice, feeDrops, 1, 1);
|
||||
|
||||
// Tx 3
|
||||
Json::Value const tx3 = pay(alice, bob, XRP(1));
|
||||
jv = addBatchTx(jv, tx3, alice, feeDrops, 2, 0);
|
||||
jv = addBatchTx(jv, tx3, alice, feeDrops, 2, 2);
|
||||
|
||||
env(jv, fee(feeDrops * 3), txflags(tfBatchFirst), ter(tecFAILED_PROCESSING));
|
||||
env(jv, fee(feeDrops * 3), txflags(tfBatchFirst), ter(tecBATCH_FAILURE));
|
||||
env.close();
|
||||
|
||||
BEAST_EXPECT(env.seq(alice) == 2);
|
||||
BEAST_EXPECT(env.balance(alice) == XRP(1000) - (feeDrops * 3));
|
||||
BEAST_EXPECT(env.balance(bob) == XRP(1000));
|
||||
Json::Value params;
|
||||
params[jss::ledger_index] = env.current()->seq() - 1;
|
||||
params[jss::transactions] = true;
|
||||
params[jss::expand] = true;
|
||||
auto const jrr = env.rpc("json", "ledger", to_string(params));
|
||||
std::cout << "jrr: " << jrr << "\n";
|
||||
|
||||
std::cout << "seq: " << env.seq(alice) << "\n";
|
||||
std::cout << "alice: " << env.balance(alice) << "\n";
|
||||
std::cout << "bob: " << env.balance(bob) << "\n";
|
||||
|
||||
BEAST_EXPECT(env.seq(alice) == 4);
|
||||
BEAST_EXPECT(env.balance(alice) == XRP(1000) - XRP(1));
|
||||
BEAST_EXPECT(env.balance(bob) == XRP(1000) + XRP(1));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user