fixInnerObjTemplate: set inner object template (#4906)

Add `STObject` constructor to explicitly set the inner object template.
This allows certain AMM transactions to apply in the same ledger:

There is no issue if the trading fee is greater than or equal to 0.01%.
If the trading fee is less than 0.01%, then:
- After AMM create, AMM transactions must wait for one ledger to close
  (3-5 seconds).
- After one ledger is validated, all AMM transactions succeed, as
  appropriate, except for AMMVote.
- The first AMMVote which votes for a 0 trading fee in a ledger will
  succeed. Subsequent AMMVote transactions which vote for a 0 trading
  fee will wait for the next ledger (3-5 seconds). This behavior repeats
  for each ledger.

This has no effect on the ultimate correctness of AMM. This amendment
will allow the transactions described above to succeed as expected, even
if the trading fee is 0 and the transactions are applied within one
ledger (block).
This commit is contained in:
Gregory Tsipenyuk
2024-02-07 16:58:12 -05:00
committed by tequ
parent c29a632d0c
commit 71ffc69819
13 changed files with 363 additions and 31 deletions

View File

@@ -18,7 +18,9 @@
//==============================================================================
#include <ripple/basics/Log.h>
#include <ripple/protocol/Feature.h>
#include <ripple/protocol/InnerObjectFormats.h>
#include <ripple/protocol/Rules.h>
#include <ripple/protocol/STAccount.h>
#include <ripple/protocol/STArray.h>
#include <ripple/protocol/STBlob.h>
@@ -57,6 +59,19 @@ STObject::STObject(SerialIter& sit, SField const& name, int depth) noexcept(
set(sit, depth);
}
STObject
STObject::makeInnerObject(SField const& name, Rules const& rules)
{
STObject obj{name};
if (rules.enabled(fixInnerObjTemplate))
{
if (SOTemplate const* elements =
InnerObjectFormats::getInstance().findSOTemplateBySField(name))
obj.set(*elements);
}
return obj;
}
STBase*
STObject::copy(std::size_t n, void* buf) const
{
@@ -646,16 +661,22 @@ STObject::getFieldArray(SField const& field) const
void
STObject::set(std::unique_ptr<STBase> v)
{
auto const i = getFieldIndex(v->getFName());
set(std::move(*v.get()));
}
void
STObject::set(STBase&& v)
{
auto const i = getFieldIndex(v.getFName());
if (i != -1)
{
v_[i] = std::move(*v);
v_[i] = std::move(v);
}
else
{
if (!isFree())
Throw<std::runtime_error>("missing field in templated STObject");
v_.emplace_back(std::move(*v));
v_.emplace_back(std::move(v));
}
}