mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
TicketSequence with non-zero Sequence is an error:
Before this change any non-zero Sequence field was handled as a non-ticketed transaction, even if a TicketSequence was present. We learned that this could lead to user confusion. So the rules are tightened up. Now if any transaction contains both a non-zero Sequence field and a TicketSequence field then that transaction returns a temSEQ_AND_TICKET error code. The (deprecated) "sign" and "submit" RPC commands are tuned up so they auto-insert a Sequence field of zero if they see a TicketSequence in the transaction. No amendment is needed because this change is going into the first release that supports the TicketBatch amendment.
This commit is contained in:
committed by
manojsdoshi
parent
c138338358
commit
a2e1a7a84d
@@ -57,7 +57,7 @@ preflight1(PreflightContext const& ctx)
|
||||
{
|
||||
// This is inappropriate in preflight0, because only Change transactions
|
||||
// skip this function, and those do not allow an sfTicketSequence field.
|
||||
if (ctx.tx.getSeqProxy().isTicket() &&
|
||||
if (ctx.tx.isFieldPresent(sfTicketSequence) &&
|
||||
!ctx.rules.enabled(featureTicketBatch))
|
||||
{
|
||||
return temMALFORMED;
|
||||
@@ -254,18 +254,29 @@ Transactor::checkSeqProxy(
|
||||
SeqProxy const t_seqProx = tx.getSeqProxy();
|
||||
SeqProxy const a_seq = SeqProxy::sequence((*sle)[sfSequence]);
|
||||
|
||||
if (t_seqProx.isSeq() && t_seqProx != a_seq)
|
||||
if (t_seqProx.isSeq())
|
||||
{
|
||||
if (a_seq < t_seqProx)
|
||||
if (tx.isFieldPresent(sfTicketSequence) &&
|
||||
view.rules().enabled(featureTicketBatch))
|
||||
{
|
||||
JLOG(j.trace()) << "applyTransaction: has future sequence number "
|
||||
<< "a_seq=" << a_seq << " t_seq=" << t_seqProx;
|
||||
return terPRE_SEQ;
|
||||
JLOG(j.trace()) << "applyTransaction: has both a TicketSequence "
|
||||
"and a non-zero Sequence number";
|
||||
return temSEQ_AND_TICKET;
|
||||
}
|
||||
if (t_seqProx != a_seq)
|
||||
{
|
||||
if (a_seq < t_seqProx)
|
||||
{
|
||||
JLOG(j.trace())
|
||||
<< "applyTransaction: has future sequence number "
|
||||
<< "a_seq=" << a_seq << " t_seq=" << t_seqProx;
|
||||
return terPRE_SEQ;
|
||||
}
|
||||
// It's an already-used sequence number.
|
||||
JLOG(j.trace()) << "applyTransaction: has past sequence number "
|
||||
<< "a_seq=" << a_seq << " t_seq=" << t_seqProx;
|
||||
return tefPAST_SEQ;
|
||||
}
|
||||
// It's an already-used sequence number.
|
||||
JLOG(j.trace()) << "applyTransaction: has past sequence number "
|
||||
<< "a_seq=" << a_seq << " t_seq=" << t_seqProx;
|
||||
return tefPAST_SEQ;
|
||||
}
|
||||
else if (t_seqProx.isTicket())
|
||||
{
|
||||
|
||||
@@ -115,9 +115,10 @@ enum TEMcodes : TERUnderlyingType {
|
||||
temCANNOT_PREAUTH_SELF,
|
||||
temINVALID_COUNT,
|
||||
|
||||
// An intermediate result used internally, should never be returned.
|
||||
temUNCERTAIN,
|
||||
temUNKNOWN,
|
||||
temUNCERTAIN, // An internal intermediate result; should never be returned.
|
||||
temUNKNOWN, // An internal intermediate result; should never be returned.
|
||||
|
||||
temSEQ_AND_TICKET,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -152,6 +152,7 @@ transResults()
|
||||
MAKE_ERROR(temINVALID_ACCOUNT_ID, "Malformed: A field contains an invalid account ID."),
|
||||
MAKE_ERROR(temCANNOT_PREAUTH_SELF, "Malformed: An account may not preauthorize itself."),
|
||||
MAKE_ERROR(temINVALID_COUNT, "Malformed: Count field outside valid range."),
|
||||
MAKE_ERROR(temSEQ_AND_TICKET, "Transaction contains a TicketSequence and a non-zero Sequence."),
|
||||
|
||||
MAKE_ERROR(terRETRY, "Retry transaction."),
|
||||
MAKE_ERROR(terFUNDS_SPENT, "DEPRECATED."),
|
||||
|
||||
@@ -441,7 +441,9 @@ transactionPreProcessImpl(
|
||||
{
|
||||
if (!tx_json.isMember(jss::Sequence))
|
||||
{
|
||||
if (!sle)
|
||||
bool const hasTicketSeq =
|
||||
tx_json.isMember(sfTicketSequence.jsonName);
|
||||
if (!hasTicketSeq && !sle)
|
||||
{
|
||||
JLOG(j.debug())
|
||||
<< "transactionSign: Failed to find source account "
|
||||
@@ -449,7 +451,8 @@ transactionPreProcessImpl(
|
||||
|
||||
return rpcError(rpcSRC_ACT_NOT_FOUND);
|
||||
}
|
||||
tx_json[jss::Sequence] = app.getTxQ().nextQueuableSeq(sle).value();
|
||||
tx_json[jss::Sequence] =
|
||||
hasTicketSeq ? 0 : app.getTxQ().nextQueuableSeq(sle).value();
|
||||
}
|
||||
|
||||
if (!tx_json.isMember(jss::Flags))
|
||||
|
||||
Reference in New Issue
Block a user