Merge remote-tracking branch 'upstream/dev' into sync-2.4.0

This commit is contained in:
tequ
2025-12-01 12:53:49 +09:00
5 changed files with 179 additions and 15 deletions

View File

@@ -80,7 +80,7 @@ namespace detail {
// Feature.cpp. Because it's only used to reserve storage, and determine how // 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 // 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. // the actual number of amendments. A LogicError on startup will verify this.
static constexpr std::size_t numFeatures = 111; static constexpr std::size_t numFeatures = 112;
/** Amendments that this server supports and the default voting behavior. /** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated Whether they are enabled depends on the Rules defined in the validated

View File

@@ -50,6 +50,7 @@ XRPL_FEATURE(DID, Supported::no, VoteBehavior::DefaultNo
XRPL_FIX (DisallowIncomingV1, Supported::yes, VoteBehavior::DefaultYes) XRPL_FIX (DisallowIncomingV1, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(XChainBridge, Supported::no, VoteBehavior::DefaultNo) XRPL_FEATURE(XChainBridge, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(AMM, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(AMM, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (StoSubarray, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (StoEmplaceFieldIdCheck, Supported::yes, VoteBehavior::DefaultYes) XRPL_FIX (StoEmplaceFieldIdCheck, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (EtxnFeeBase, Supported::yes, VoteBehavior::DefaultYes) XRPL_FIX (EtxnFeeBase, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (CronStacking, Supported::yes, VoteBehavior::DefaultYes) XRPL_FIX (CronStacking, Supported::yes, VoteBehavior::DefaultYes)

View File

@@ -10574,14 +10574,15 @@ public:
testcase("Test sto_subarray"); testcase("Test sto_subarray");
using namespace jtx; using namespace jtx;
Env env{*this, features};
auto const bob = Account{"bob"}; auto const bob = Account{"bob"};
auto const alice = Account{"alice"}; auto const alice = Account{"alice"};
env.fund(XRP(10000), alice); {
env.fund(XRP(10000), bob); Env env{*this, features};
TestHook hook = wasm[R"[test.hook]( env.fund(XRP(10000), alice);
env.fund(XRP(10000), bob);
TestHook hook = wasm[R"[test.hook](
#include <stdint.h> #include <stdint.h>
extern int32_t _g (uint32_t id, uint32_t maxiter); extern int32_t _g (uint32_t id, uint32_t maxiter);
#define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1)
@@ -10632,14 +10633,102 @@ public:
} }
)[test.hook]"]; )[test.hook]"];
// install the hook on alice // install the hook on alice
env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0),
M("set sto_subarray"), M("set sto_subarray"),
HSFEE); HSFEE);
env.close(); env.close();
// invoke the hook // invoke the hook
env(pay(bob, alice, XRP(1)), M("test sto_subarray"), fee(XRP(1))); env(pay(bob, alice, XRP(1)), M("test sto_subarray"), fee(XRP(1)));
}
{
TestHook hook = wasm[R"[test.hook](
#include <stdint.h>
extern int32_t _g (uint32_t id, uint32_t maxiter);
#define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1)
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t sto_subarray(
uint32_t read_ptr, uint32_t read_len, uint32_t field_id);
#define DOESNT_EXIST -5
// { Amounts: [{AmountEntry: {Amount: "100"}}] }
uint8_t sto[] =
{
0xF0U,0x5CU,0xE0U,0x5BU,0x61U,0x40U,0x00U,0x00U,0x00U,0x00U,
0x00U,0x00U,0x64U,0xE1U,0xF1U
};
int64_t hook(uint32_t reserved )
{
_g(1,1);
uint8_t hash[32];
// should be DOESNT_EXIST after Amendment enabled
int64_t result1 = sto_subarray(sto, sizeof(sto), 1);
// should be position 2 length 12
// before Amendment enabled, returns pos 1, len 33
int64_t result2 = sto_subarray(sto, sizeof(sto), 0);
accept(0,0,result1+result2);
}
)[test.hook]"];
for (auto isFixStoSubarray : {true, false})
{
Env env{
*this,
isFixStoSubarray ? features | fixStoSubarray
: features - fixStoSubarray};
env.fund(XRP(10000), alice, bob);
env.close();
// install the hook on alice
env(ripple::test::jtx::hook(
alice, {{hso(hook, overrideFlag)}}, 0),
M("set sto_subarray"),
HSFEE);
env.close();
// invoke the hook
env(pay(bob, alice, XRP(1)),
M("test sto_subarray"),
fee(XRP(1)));
env.close();
auto const meta = env.meta();
BEAST_REQUIRE(meta);
BEAST_REQUIRE(meta->isFieldPresent(sfHookExecutions));
auto const hookExecutions =
meta->getFieldArray(sfHookExecutions);
BEAST_REQUIRE(hookExecutions.size() == 1);
auto const hookExecution = hookExecutions[0];
BEAST_REQUIRE(hookExecution.isFieldPresent(sfHookReturnCode));
auto const returnCode =
hookExecution.getFieldU64(sfHookReturnCode);
if (isFixStoSubarray)
{
auto const doesntExistError = -5;
auto const position = 2;
auto const length = 12;
BEAST_REQUIRE(
returnCode ==
(doesntExistError + ((int64_t)position << 32) +
length));
}
else
{
auto const parseError = -18;
auto const position = 1;
auto const length = 33;
BEAST_REQUIRE(
returnCode ==
(parseError + ((int64_t)position << 32) + length));
}
}
}
} }
void void

View File

@@ -16746,6 +16746,65 @@ std::map<std::string, std::vector<uint8_t>> wasm = {
0x00U, 0x00U,
}}, }},
/* ==== WASM: 79 ==== */
{R"[test.hook](
#include <stdint.h>
extern int32_t _g (uint32_t id, uint32_t maxiter);
#define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1)
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t sto_subarray(
uint32_t read_ptr, uint32_t read_len, uint32_t field_id);
#define DOESNT_EXIST -5
// { Amounts: [{AmountEntry: {Amount: "100"}}] }
uint8_t sto[] =
{
0xF0U,0x5CU,0xE0U,0x5BU,0x61U,0x40U,0x00U,0x00U,0x00U,0x00U,
0x00U,0x00U,0x64U,0xE1U,0xF1U
};
int64_t hook(uint32_t reserved )
{
_g(1,1);
uint8_t hash[32];
// should be DOESNT_EXIST after Amendment enabled
int64_t result1 = sto_subarray(sto, sizeof(sto), 1);
// should be position 2 length 12
// before Amendment enabled, returns pos 1, len 33
int64_t result2 = sto_subarray(sto, sizeof(sto), 0);
accept(0,0,result1+result2);
}
)[test.hook]",
{
0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x1AU,
0x04U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU,
0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U,
0x7EU, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x02U, 0x2AU, 0x03U, 0x03U,
0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x00U, 0x03U, 0x65U,
0x6EU, 0x76U, 0x0CU, 0x73U, 0x74U, 0x6FU, 0x5FU, 0x73U, 0x75U, 0x62U,
0x61U, 0x72U, 0x72U, 0x61U, 0x79U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU,
0x76U, 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x02U,
0x03U, 0x02U, 0x01U, 0x03U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x06U,
0x27U, 0x06U, 0x7FU, 0x01U, 0x41U, 0x90U, 0x88U, 0x04U, 0x0BU, 0x7FU,
0x00U, 0x41U, 0x8FU, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U,
0x0BU, 0x7FU, 0x00U, 0x41U, 0x90U, 0x88U, 0x04U, 0x0BU, 0x7FU, 0x00U,
0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU,
0x07U, 0x08U, 0x01U, 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x03U,
0x0AU, 0xC1U, 0x80U, 0x00U, 0x01U, 0xBDU, 0x80U, 0x00U, 0x01U, 0x01U,
0x7EU, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U,
0x00U, 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x41U, 0x80U, 0x88U, 0x80U,
0x80U, 0x00U, 0x41U, 0x0FU, 0x41U, 0x01U, 0x10U, 0x81U, 0x80U, 0x80U,
0x80U, 0x00U, 0x41U, 0x80U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x0FU,
0x41U, 0x00U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x7CU, 0x10U,
0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x0BU, 0x0BU,
0x16U, 0x01U, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x0FU, 0xF0U, 0x5CU,
0xE0U, 0x5BU, 0x61U, 0x40U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
0x64U, 0xE1U, 0xF1U,
}},
/* ==== WASM: 79 ==== */ /* ==== WASM: 79 ==== */
{R"[test.hook]( {R"[test.hook](
#include <stdint.h> #include <stdint.h>

View File

@@ -4311,10 +4311,25 @@ DEFINE_HOOK_FUNCTION(
// unwrap the array if it is wrapped, // unwrap the array if it is wrapped,
// by removing a byte from the start and end // by removing a byte from the start and end
// why here 0xF0?
// STI_ARRAY = 0xF0
// eg) Signers field value = 0x03 => 0xF3
// eg) Amounts field value = 0x5C => 0xF0, 0x5C
if ((*upto & 0xF0U) == 0xF0U) if ((*upto & 0xF0U) == 0xF0U)
{ {
upto++; if (view.rules().enabled(fixStoSubarray) && *upto == 0xF0U)
end--; {
// field value > 15
upto++;
upto++;
end--;
}
else
{
// field value <= 15
upto++;
end--;
}
} }
if (upto >= end) if (upto >= end)