mirror of
https://github.com/Xahau/xahaud.git
synced 2026-07-27 09:00:09 +00:00
Compare commits
8 Commits
sync-2.4.0
...
HookAPISer
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f244d888d | ||
|
|
3c49f80013 | ||
|
|
090e4ad25e | ||
|
|
01e7ee4f03 | ||
|
|
222772d99b | ||
|
|
9e6135ba42 | ||
|
|
f0329b4054 | ||
|
|
5a9baed9d0 |
@@ -300,7 +300,17 @@ enum keylet_code : uint32_t {
|
||||
NFT_OFFER = 23,
|
||||
HOOK_DEFINITION = 24,
|
||||
HOOK_STATE_DIR = 25,
|
||||
CRON = 26
|
||||
CRON = 26,
|
||||
AMM = 27,
|
||||
BRIDGE = 28,
|
||||
XCHAIN_OWNED_CLAIM_ID = 29,
|
||||
XCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID = 30,
|
||||
DID = 31,
|
||||
ORACLE = 32,
|
||||
MPTOKEN_ISSUANCE = 33,
|
||||
MPTOKEN = 34,
|
||||
CREDENTIAL = 35,
|
||||
PERMISSIONED_DOMAIN = 36,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -329,14 +329,15 @@ private:
|
||||
int32_t,
|
||||
parse_error>
|
||||
get_stobject_length(
|
||||
unsigned char* start, // in - begin iterator
|
||||
unsigned char* maxptr, // in - end iterator
|
||||
int& type, // out - populated by serialized type code
|
||||
int& field, // out - populated by serialized field code
|
||||
int& payload_start, // out - the start of actual payload data for
|
||||
// this type
|
||||
int& payload_length, // out - the length of actual payload data for
|
||||
// this type
|
||||
unsigned char* start, // in - begin iterator
|
||||
unsigned char* maxptr, // in - end iterator
|
||||
int& type, // out - populated by serialized type code
|
||||
int& field, // out - populated by serialized field code
|
||||
int& payload_start, // out - the start of actual payload data for
|
||||
// this type
|
||||
int& payload_length, // out - the length of actual payload data for
|
||||
// this type
|
||||
Rules const& rules,
|
||||
int recursion_depth = 0) // used internally
|
||||
const;
|
||||
};
|
||||
|
||||
@@ -80,7 +80,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 = 110;
|
||||
static constexpr std::size_t numFeatures = 111;
|
||||
|
||||
/** Amendments that this server supports and the default voting behavior.
|
||||
Whether they are enabled depends on the Rules defined in the validated
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
// If you add an amendment here, then do not forget to increment `numFeatures`
|
||||
// in include/xrpl/protocol/Feature.h.
|
||||
|
||||
XRPL_FEATURE(HookAPISerializedType240, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(PermissionedDomains, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(DynamicNFT, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(Credentials, Supported::no, VoteBehavior::DefaultNo)
|
||||
|
||||
@@ -487,7 +487,7 @@ isMemoOkay(STObject const& st, std::string& reason)
|
||||
if (!paramObj->isFieldPresent(sfHookParameterValue) ||
|
||||
paramObj->getFieldVL(sfHookParameterValue).size() > maxVal)
|
||||
{
|
||||
reason = "HookParameterValue cannot exceed 128 bytes.";
|
||||
reason = "HookParameterValue cannot exceed 256 bytes.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10951,6 +10951,186 @@ public:
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test sto_validate"), fee(XRP(1)));
|
||||
|
||||
{
|
||||
// test STIs
|
||||
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 rollback (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t sto_validate(uint32_t, uint32_t);
|
||||
extern int64_t otxn_param(uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
#define ASSERT(x)\
|
||||
if (!(x))\
|
||||
rollback((uint32_t)#x, sizeof(#x), __LINE__);
|
||||
#define SBUF(x) (uint32_t)(x), sizeof(x)
|
||||
|
||||
uint8_t buf[1000];
|
||||
int64_t hook(uint32_t reserved)
|
||||
{
|
||||
_g(1,1);
|
||||
|
||||
int64_t size = otxn_param(SBUF(buf), "V", 1);
|
||||
int64_t result = sto_validate(buf, size);
|
||||
|
||||
accept(0,0,result);
|
||||
}
|
||||
)[test.hook]"];
|
||||
|
||||
for (auto feature : {
|
||||
features - featureHookAPISerializedType240,
|
||||
features | featureHookAPISerializedType240,
|
||||
})
|
||||
{
|
||||
Env env{*this, feature};
|
||||
|
||||
env.fund(XRP(10000), alice, bob);
|
||||
env.close();
|
||||
|
||||
auto hasEnabled = env.current()->rules().enabled(
|
||||
featureHookAPISerializedType240);
|
||||
|
||||
// install the hook on alice
|
||||
env(ripple::test::jtx::hook(
|
||||
alice, {{hso(hook, overrideFlag)}}, 0),
|
||||
M("set sto_validate"),
|
||||
HSFEE);
|
||||
env.close();
|
||||
|
||||
// invoke the hook
|
||||
auto buildTx = [&](std::string value) {
|
||||
auto payJv = pay(bob, alice, XRP(1));
|
||||
|
||||
Json::Value params{Json::arrayValue};
|
||||
auto& param = params[0U][jss::HookParameter];
|
||||
param[jss::HookParameterName] = strHex(std::string("V"));
|
||||
param[jss::HookParameterValue] = value;
|
||||
payJv[jss::HookParameters] = params;
|
||||
return payJv;
|
||||
};
|
||||
|
||||
auto testSTI = [&](std::string value, bool expectedResult) {
|
||||
auto tx = buildTx(value);
|
||||
env(tx, M("test STI"), fee(XRP(1)));
|
||||
env.close();
|
||||
|
||||
auto const result = env.meta()
|
||||
->getFieldArray(sfHookExecutions)[0]
|
||||
.getFieldU64(sfHookReturnCode);
|
||||
if (expectedResult)
|
||||
BEAST_EXPECTS(result == 1, value);
|
||||
else
|
||||
BEAST_EXPECTS(result == 0, value);
|
||||
};
|
||||
|
||||
// STI_UINT32
|
||||
testSTI("2200000001", true);
|
||||
// STI_UINT64
|
||||
testSTI("301100000000000003E8", true);
|
||||
// STI_UINT128
|
||||
testSTI("4100000000000000000000000000000000", true);
|
||||
// STI_UINT256
|
||||
testSTI(
|
||||
"5060000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000",
|
||||
true);
|
||||
// STI_AMOUNT
|
||||
testSTI("614000000000000064", true);
|
||||
testSTI(
|
||||
"61D5038D7EA4C680000000000000000000000000005553440000000000"
|
||||
"AE123A8556F3CF91154711376AFB0F894F832B3D",
|
||||
true);
|
||||
// STI_VL
|
||||
testSTI("7504DEADBEEF", true);
|
||||
// STI_ACCOUNT
|
||||
testSTI("8114AE123A8556F3CF91154711376AFB0F894F832B3D", true);
|
||||
// STI_NUMBER
|
||||
// testSTI("000400000000000000000000000000000001", true);
|
||||
// STI_OBJECT
|
||||
testSTI("E05C22000000017504DEADBEEFE1", true);
|
||||
// STI_ARRAY
|
||||
testSTI(
|
||||
"F05CE05B614000000000000064E1E05B61D5038D7EA4C6800000000000"
|
||||
"00000000000000005553440000000000AE123A8556F3CF91154711376A"
|
||||
"FB0F894F832B3DE1F1",
|
||||
true);
|
||||
// STI_UINT8
|
||||
testSTI("00101003", true);
|
||||
// STI_UINT160
|
||||
testSTI("01110000000000000000000000000000000000000000", true);
|
||||
// STI_PATHSET
|
||||
testSTI(
|
||||
"0112300000000000000000000000005553440000000000AE123A8556F3"
|
||||
"CF91154711376AFB0F894F832B3D00",
|
||||
hasEnabled);
|
||||
testSTI(
|
||||
"0112310A20B3C85F482532A9578DBB3950B85CA06594D1000000000000"
|
||||
"00000000000042544300000000000A20B3C85F482532A9578DBB3950B8"
|
||||
"5CA06594D13000000000000000000000000055534400000000000A20B3"
|
||||
"C85F482532A9578DBB3950B85CA06594D1FF3157180C769B66D942EE69"
|
||||
"E6DCC940CA48D82337AD00000000000000000000000042544300000000"
|
||||
"0057180C769B66D942EE69E6DCC940CA48D82337AD1000000000000000"
|
||||
"0000000000000000000000000030000000000000000000000000555344"
|
||||
"00000000000A20B3C85F482532A9578DBB3950B85CA06594D100",
|
||||
hasEnabled);
|
||||
// STI_VECTOR256
|
||||
testSTI(
|
||||
"0013634000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000",
|
||||
true);
|
||||
// STI_UINT96
|
||||
// testSTI("000400000000000000000000000000000001", true);
|
||||
// STI_UINT192
|
||||
// testSTI("000400000000000000000000000000000001", true);
|
||||
// STI_UINT384
|
||||
// testSTI("000400000000000000000000000000000001", true);
|
||||
// STI_UINT512
|
||||
// testSTI("000400000000000000000000000000000001", true);
|
||||
// STI_ISSUE
|
||||
testSTI(
|
||||
"03180000000000000000000000005553440000000000AE123A8556F3CF"
|
||||
"91154711376AFB0F894F832B3D",
|
||||
hasEnabled);
|
||||
testSTI(
|
||||
"03180000000000000000000000000000000000000000", hasEnabled);
|
||||
// STI_XCHAIN_BRIDGE
|
||||
/// Native-Native
|
||||
testSTI(
|
||||
"011914AE123A8556F3CF91154711376AFB0F894F832B3D000000000000"
|
||||
"000000000000000000000000000014AE123A8556F3CF91154711376AFB"
|
||||
"0F894F832B3D0000000000000000000000000000000000000000",
|
||||
hasEnabled);
|
||||
/// IOU-Native
|
||||
testSTI(
|
||||
"011914AE123A8556F3CF91154711376AFB0F894F832B3D000000000000"
|
||||
"0000000000005553440000000000AE123A8556F3CF91154711376AFB0F"
|
||||
"894F832B3D14AE123A8556F3CF91154711376AFB0F894F832B3D000000"
|
||||
"0000"
|
||||
"000000000000000000000000000000",
|
||||
hasEnabled);
|
||||
/// Native-IOU
|
||||
testSTI(
|
||||
"011914AE123A8556F3CF91154711376AFB0F894F832B3D000000000000"
|
||||
"0000000000005553440000000000AE123A8556F3CF91154711376AFB0F"
|
||||
"894F832B3D14AE123A8556F3CF91154711376AFB0F894F832B3D000000"
|
||||
"0000000000000000000000000000000000",
|
||||
hasEnabled);
|
||||
/// IOU-IOU
|
||||
testSTI(
|
||||
"011914AE123A8556F3CF91154711376AFB0F894F832B3D000000000000"
|
||||
"0000000000005553440000000000AE123A8556F3CF91154711376AFB0F"
|
||||
"894F832B3D14AE123A8556F3CF91154711376AFB0F894F832B3D000000"
|
||||
"0000000000000000005553440000000000AE123A8556F3CF9115471137"
|
||||
"6AFB0F894F832B3D",
|
||||
hasEnabled);
|
||||
// STI_CURRENCY
|
||||
testSTI(
|
||||
"011A0000000000000000000000005553440000000000", hasEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -11414,7 +11594,19 @@ public:
|
||||
#define KEYLET_PAYCHAN 21
|
||||
#define KEYLET_EMITTED_TXN 22
|
||||
#define KEYLET_NFT_OFFER 23
|
||||
#define KEYLET_HOOK_DEFINITION 24
|
||||
#define KEYLET_HOOK_STATE_DIR 25
|
||||
#define KEYLET_CRON 26
|
||||
#define KEYLET_AMM 27
|
||||
#define KEYLET_BRIDGE 28
|
||||
#define KEYLET_XCHAIN_OWNED_CLAIM_ID 29
|
||||
#define KEYLET_XCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID 30
|
||||
#define KEYLET_DID 31
|
||||
#define KEYLET_ORACLE 32
|
||||
#define KEYLET_MPTOKEN_ISSUANCE 33
|
||||
#define KEYLET_MPTOKEN 34
|
||||
#define KEYLET_CREDENTIAL 35
|
||||
#define KEYLET_PERMISSIONED_DOMAIN 36
|
||||
#define ASSERT(x)\
|
||||
if (!(x))\
|
||||
rollback((uint32_t)#x, sizeof(#x), __LINE__);
|
||||
@@ -11462,6 +11654,22 @@ public:
|
||||
0x3AU,0x51U,0x8AU,0x22U,0x53U,0x81U,0x60U,0x84U,0x1CU,0x14U,0x32U,0xFEU,
|
||||
0x6FU,0x3EU,0x6DU,0x6EU,0x76U,0x29U,0xFBU,0xBAU
|
||||
};
|
||||
|
||||
uint8_t asset1[] = // USD.rB6v18pQ765Z9DH5RQsTFevoQPFmRtBqhT
|
||||
{
|
||||
0x00U,0x00U,0x00U,0x00U,0x00U,0x00U,0x00U,0x00U,0x00U,0x00U,
|
||||
0x00U,0x00U,0x55U,0x53U,0x44U,0x00U,0x00U,0x00U,0x00U,0x00U,
|
||||
0x75U,0x6EU,0xDEU,0x88U,0xA9U,0x07U,0xD4U,0xCCU,0xF3U,0x8DU,0x6AU,0xDBU,
|
||||
0x9FU,0xC7U,0x94U,0x64U,0x19U,0xF0U,0xC4U,0x1DU
|
||||
};
|
||||
|
||||
uint8_t asset2[] = // EUR.raKM1bZkGmASBqN5v2swrf2uAPJ32Cd8GV
|
||||
{
|
||||
0x00U,0x00U,0x00U,0x00U,0x00U,0x00U,0x00U,0x00U,0x00U,0x00U,
|
||||
0x00U,0x00U,0x45U,0x48U,0x52U,0x00U,0x00U,0x00U,0x00U,0x00U,
|
||||
0x3AU,0x51U,0x8AU,0x22U,0x53U,0x81U,0x60U,0x84U,0x1CU,0x14U,0x32U,0xFEU,
|
||||
0x6FU,0x3EU,0x6DU,0x6EU,0x76U,0x29U,0xFBU,0xBAU
|
||||
};
|
||||
|
||||
int64_t hook(uint32_t reserved )
|
||||
{
|
||||
@@ -11916,11 +12124,76 @@ public:
|
||||
0,0
|
||||
)));
|
||||
|
||||
|
||||
ASSERT(34 == (e=util_keylet(buf, 34, KEYLET_NFT_OFFER,
|
||||
SBUF(a), SBUF(ns),
|
||||
0,0
|
||||
)));
|
||||
|
||||
ASSERT(34 == (e=util_keylet(buf, 34, KEYLET_HOOK_DEFINITION,
|
||||
SBUF(ns),
|
||||
0,0,
|
||||
0,0
|
||||
)));
|
||||
|
||||
ASSERT(34 == (e=util_keylet(buf, 34, KEYLET_HOOK_STATE_DIR,
|
||||
SBUF(a), SBUF(ns),
|
||||
0,0
|
||||
)));
|
||||
|
||||
ASSERT(34 == (e=util_keylet(buf, 34, KEYLET_AMM,
|
||||
SBUF(asset1), SBUF(asset2),
|
||||
0,0
|
||||
)));
|
||||
|
||||
ASSERT(INVALID_ARGUMENT == (e=util_keylet(buf, 34, KEYLET_BRIDGE,
|
||||
SBUF(a), SBUF(b),
|
||||
0,0
|
||||
)));
|
||||
|
||||
ASSERT(INVALID_ARGUMENT == (e=util_keylet(buf, 34, KEYLET_XCHAIN_OWNED_CLAIM_ID,
|
||||
SBUF(a), SBUF(b),
|
||||
0,0
|
||||
)));
|
||||
|
||||
ASSERT(INVALID_ARGUMENT == (e=util_keylet(buf, 34, KEYLET_XCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID,
|
||||
SBUF(a), SBUF(b),
|
||||
0,0
|
||||
)));
|
||||
|
||||
ASSERT(INVALID_ARGUMENT == (e=util_keylet(buf, 34, KEYLET_DID,
|
||||
SBUF(a),
|
||||
0,0,
|
||||
0,0
|
||||
)));
|
||||
|
||||
ASSERT(34 == (e=util_keylet(buf, 34, KEYLET_ORACLE,
|
||||
SBUF(a), 3,
|
||||
0,
|
||||
0,0
|
||||
)));
|
||||
|
||||
ASSERT(INVALID_ARGUMENT == (e=util_keylet(buf, 34, KEYLET_MPTOKEN_ISSUANCE,
|
||||
SBUF(a),
|
||||
0,0,
|
||||
0,0
|
||||
)));
|
||||
|
||||
ASSERT(INVALID_ARGUMENT == (e=util_keylet(buf, 34, KEYLET_MPTOKEN,
|
||||
SBUF(a),
|
||||
0,0,
|
||||
0,0
|
||||
)));
|
||||
|
||||
ASSERT(INVALID_ARGUMENT == (e=util_keylet(buf, 34, KEYLET_CREDENTIAL,
|
||||
SBUF(a), SBUF(b),
|
||||
0,0
|
||||
)));
|
||||
|
||||
ASSERT(INVALID_ARGUMENT == (e=util_keylet(buf, 34, KEYLET_PERMISSIONED_DOMAIN,
|
||||
SBUF(a),
|
||||
0,0,
|
||||
0,0
|
||||
)));
|
||||
|
||||
ASSERT(34 == (e=util_keylet(buf, 34, KEYLET_CRON, SBUF(a), 1, 0, 0, 0)));
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -355,7 +355,14 @@ HookAPI::sto_validate(Bytes const& data) const
|
||||
{
|
||||
int type = -1, field = -1, payload_start = -1, payload_length = -1;
|
||||
auto const length = get_stobject_length(
|
||||
upto, end, type, field, payload_start, payload_length, 0);
|
||||
upto,
|
||||
end,
|
||||
type,
|
||||
field,
|
||||
payload_start,
|
||||
payload_length,
|
||||
hookCtx.applyCtx.view().rules(),
|
||||
0);
|
||||
if (!length)
|
||||
return 0;
|
||||
upto += length.value();
|
||||
@@ -389,7 +396,14 @@ HookAPI::sto_subfield(Bytes const& data, uint32_t field_id) const
|
||||
{
|
||||
int type = -1, field = -1, payload_start = -1, payload_length = -1;
|
||||
auto const length = get_stobject_length(
|
||||
upto, end, type, field, payload_start, payload_length, 0);
|
||||
upto,
|
||||
end,
|
||||
type,
|
||||
field,
|
||||
payload_start,
|
||||
payload_length,
|
||||
hookCtx.applyCtx.view().rules(),
|
||||
0);
|
||||
if (!length)
|
||||
return Unexpected(PARSE_ERROR);
|
||||
if ((type << 16) + field == field_id)
|
||||
@@ -464,7 +478,14 @@ HookAPI::sto_subarray(Bytes const& data, uint32_t index_id) const
|
||||
{
|
||||
int type = -1, field = -1, payload_start = -1, payload_length = -1;
|
||||
auto const length = get_stobject_length(
|
||||
upto, end, type, field, payload_start, payload_length, 0);
|
||||
upto,
|
||||
end,
|
||||
type,
|
||||
field,
|
||||
payload_start,
|
||||
payload_length,
|
||||
hookCtx.applyCtx.view().rules(),
|
||||
0);
|
||||
if (!length)
|
||||
return Unexpected(PARSE_ERROR);
|
||||
|
||||
@@ -530,6 +551,7 @@ HookAPI::sto_emplace(
|
||||
field,
|
||||
payload_start,
|
||||
payload_length,
|
||||
hookCtx.applyCtx.view().rules(),
|
||||
0);
|
||||
if (!length)
|
||||
return Unexpected(PARSE_ERROR);
|
||||
@@ -565,7 +587,14 @@ HookAPI::sto_emplace(
|
||||
{
|
||||
int type = -1, field = -1, payload_start = -1, payload_length = -1;
|
||||
auto const length = get_stobject_length(
|
||||
upto, end, type, field, payload_start, payload_length, 0);
|
||||
upto,
|
||||
end,
|
||||
type,
|
||||
field,
|
||||
payload_start,
|
||||
payload_length,
|
||||
hookCtx.applyCtx.view().rules(),
|
||||
0);
|
||||
if (!length)
|
||||
return Unexpected(PARSE_ERROR);
|
||||
if ((type << 16) + field == field_id)
|
||||
@@ -2998,12 +3027,20 @@ HookAPI::get_stobject_length(
|
||||
int& payload_start, // out - the start of actual payload data for this type
|
||||
int& payload_length, // out - the length of actual payload data for this
|
||||
// type
|
||||
Rules const& rules,
|
||||
int recursion_depth) // used internally
|
||||
const
|
||||
{
|
||||
if (recursion_depth > 10)
|
||||
return Unexpected(pe_excessive_nesting);
|
||||
|
||||
uint16_t max_sti_type = rules.enabled(featureHookAPISerializedType240)
|
||||
? STI_CURRENCY
|
||||
: STI_VECTOR256;
|
||||
|
||||
if (type > max_sti_type)
|
||||
return pe_unknown_type_early;
|
||||
|
||||
unsigned char* end = maxptr;
|
||||
unsigned char* upto = start;
|
||||
int high = *upto >> 4;
|
||||
@@ -3055,14 +3092,20 @@ HookAPI::get_stobject_length(
|
||||
auto const& fieldObj = ripple::SField::getField;
|
||||
*/
|
||||
|
||||
if (type < 1 || type > 19 || (type >= 9 && type <= 13))
|
||||
// type 10~13 are reserved
|
||||
if (type < 1 || max_sti_type < type || (10 <= type && type <= 13))
|
||||
return Unexpected(pe_unknown_type_early);
|
||||
|
||||
// not supported types
|
||||
if (type == STI_NUMBER || type == STI_UINT96 || type == STI_UINT192 ||
|
||||
type == STI_UINT384 || type == STI_UINT512)
|
||||
return pe_unknown_type_early;
|
||||
|
||||
bool is_vl =
|
||||
(type == SerializedTypeID::STI_ACCOUNT ||
|
||||
type == SerializedTypeID::STI_VL ||
|
||||
type == SerializedTypeID::STI_PATHSET ||
|
||||
type == SerializedTypeID::STI_VECTOR256);
|
||||
(type == STI_ACCOUNT || type == STI_VL ||
|
||||
(type == STI_PATHSET &&
|
||||
!rules.enabled(featureHookAPISerializedType240)) ||
|
||||
type == STI_VECTOR256);
|
||||
|
||||
int length = -1;
|
||||
if (is_vl)
|
||||
@@ -3095,42 +3138,116 @@ HookAPI::get_stobject_length(
|
||||
return Unexpected(pe_unexpected_end);
|
||||
}
|
||||
}
|
||||
else if ((type >= 1 && type <= 5) || type == 16 || type == 17)
|
||||
else if (
|
||||
(type >= STI_UINT16 && type <= STI_UINT256) || type == STI_UINT8 ||
|
||||
type == STI_UINT160 || type == STI_CURRENCY)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case SerializedTypeID::STI_UINT16:
|
||||
case STI_UINT16:
|
||||
length = 2;
|
||||
break;
|
||||
case SerializedTypeID::STI_UINT32:
|
||||
case STI_UINT32:
|
||||
length = 4;
|
||||
break;
|
||||
case SerializedTypeID::STI_UINT64:
|
||||
case STI_UINT64:
|
||||
length = 8;
|
||||
break;
|
||||
case SerializedTypeID::STI_UINT128:
|
||||
case STI_UINT128:
|
||||
length = 16;
|
||||
break;
|
||||
case SerializedTypeID::STI_UINT256:
|
||||
case STI_UINT256:
|
||||
length = 32;
|
||||
break;
|
||||
case SerializedTypeID::STI_UINT8:
|
||||
case STI_UINT8:
|
||||
length = 1;
|
||||
break;
|
||||
case SerializedTypeID::STI_UINT160:
|
||||
case STI_UINT160:
|
||||
length = 20;
|
||||
break;
|
||||
case STI_CURRENCY:
|
||||
length = 20;
|
||||
break;
|
||||
default:
|
||||
length = -1;
|
||||
break;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (type == SerializedTypeID::STI_AMOUNT)
|
||||
else if (type == STI_AMOUNT) /* AMOUNT */
|
||||
{
|
||||
length = (*upto >> 6 == 1) ? 8 : 48;
|
||||
if (upto >= end)
|
||||
return Unexpected(pe_unexpected_end);
|
||||
}
|
||||
else if (
|
||||
type == STI_PATHSET && rules.enabled(featureHookAPISerializedType240))
|
||||
{
|
||||
length = 0;
|
||||
while (upto + length < end)
|
||||
{
|
||||
// iterate Path step
|
||||
while (*(upto + length) & 0x01 || *(upto + length) & 0x10 ||
|
||||
*(upto + length) & 0x20)
|
||||
{
|
||||
int flag = *(upto + length++);
|
||||
// flag shoud be 0x01 or 0x10 or 0x20 or those union
|
||||
if (flag == 0 || flag & ~(0x01 | 0x10 | 0x20))
|
||||
return pe_unexpected_end;
|
||||
if (flag & 0x01) // account
|
||||
length += 20;
|
||||
if (flag & 0x10) // currency
|
||||
length += 20;
|
||||
if (flag & 0x20) // issuer
|
||||
length += 20;
|
||||
|
||||
int next_flag = *(upto + length);
|
||||
if (next_flag == 0x00 || next_flag == 0xff)
|
||||
// end of Path step
|
||||
break;
|
||||
}
|
||||
|
||||
// continue or end of Paths
|
||||
int lastflag = *(upto + length++);
|
||||
if (lastflag == 0xff)
|
||||
continue; // continue byte
|
||||
else if (lastflag == 0x00)
|
||||
break; // end byte
|
||||
else
|
||||
return pe_unexpected_end;
|
||||
}
|
||||
if (upto >= end)
|
||||
return pe_unexpected_end;
|
||||
}
|
||||
else if (type == STI_ISSUE)
|
||||
{
|
||||
auto zero20 = std::array<char, 20>{0};
|
||||
// if first 20 byte is all zeros return 20
|
||||
// else return 40
|
||||
if (memcmp(upto, zero20.data(), 20) == 0)
|
||||
length = 20;
|
||||
else
|
||||
length = 40;
|
||||
}
|
||||
else if (type == STI_XCHAIN_BRIDGE)
|
||||
{
|
||||
auto zero20 = std::array<char, 20>{0};
|
||||
// Lock Chain
|
||||
length = 1; // Door Account1 prefix length
|
||||
length += 20; // Door Account1 length
|
||||
// Door Issue1
|
||||
if (memcmp(upto + length, zero20.data(), 20) == 0)
|
||||
length += 20; // only Currency
|
||||
else
|
||||
length += 40; // Currency and Issue
|
||||
|
||||
// Issuing Chain
|
||||
length += 1; // Door Account2 prefix length
|
||||
length += 20; // Door Account2 length
|
||||
// Door Issue2
|
||||
if (memcmp(upto + length, zero20.data(), 20) == 0)
|
||||
length += 20; // only Currency
|
||||
else
|
||||
length += 40; // Currency and Issue
|
||||
}
|
||||
|
||||
if (length > -1)
|
||||
{
|
||||
@@ -3149,8 +3266,7 @@ HookAPI::get_stobject_length(
|
||||
return length + (upto - start);
|
||||
}
|
||||
|
||||
if (type == SerializedTypeID::STI_OBJECT ||
|
||||
type == SerializedTypeID::STI_ARRAY)
|
||||
if (type == STI_OBJECT || type == STI_ARRAY)
|
||||
{
|
||||
payload_start = upto - start;
|
||||
|
||||
@@ -3165,6 +3281,7 @@ HookAPI::get_stobject_length(
|
||||
subfield,
|
||||
payload_start_,
|
||||
payload_length_,
|
||||
hookCtx.applyCtx.view().rules(),
|
||||
recursion_depth + 1);
|
||||
DBG_PRINTF(
|
||||
"%d get_stobject_length i %d %d-%d, upto %d sublength %d\n",
|
||||
@@ -3180,8 +3297,8 @@ HookAPI::get_stobject_length(
|
||||
if (upto >= end)
|
||||
return Unexpected(pe_unexpected_end);
|
||||
|
||||
if ((*upto == 0xE1U && type == 0xEU) ||
|
||||
(*upto == 0xF1U && type == 0xFU))
|
||||
if ((*upto == 0xE1U && type == 0xEU) || // STI_OBJECT Maker
|
||||
(*upto == 0xF1U && type == 0xFU)) // STI_ARRAY Maker
|
||||
{
|
||||
payload_length = upto - start - payload_start;
|
||||
upto++;
|
||||
|
||||
@@ -2327,7 +2327,13 @@ DEFINE_HOOK_FUNCTION(
|
||||
case keylet_code::OWNER_DIR:
|
||||
case keylet_code::SIGNERS:
|
||||
case keylet_code::ACCOUNT:
|
||||
case keylet_code::HOOK: {
|
||||
case keylet_code::HOOK:
|
||||
case keylet_code::DID: {
|
||||
if (keylet_type == keylet_code::DID)
|
||||
{
|
||||
if (!applyCtx.view().rules().enabled(featureDID))
|
||||
return INVALID_ARGUMENT;
|
||||
}
|
||||
if (a == 0 || b == 0)
|
||||
return INVALID_ARGUMENT;
|
||||
|
||||
@@ -2350,13 +2356,43 @@ DEFINE_HOOK_FUNCTION(
|
||||
? ripple::keylet::signers(id)
|
||||
: keylet_type == keylet_code::OWNER_DIR
|
||||
? ripple::keylet::ownerDir(id)
|
||||
: keylet_type == keylet_code::DID
|
||||
? ripple::keylet::did(id)
|
||||
: ripple::keylet::account(id);
|
||||
|
||||
return serialize_keylet(kl, memory, write_ptr, write_len);
|
||||
}
|
||||
|
||||
// keylets that take 20 byte account id, and (4 byte uint for 32
|
||||
// byte hash)
|
||||
// keylets that take 20 byte account id, and (4 byte uint for 32
|
||||
// byte hash)
|
||||
case keylet_code::ORACLE: {
|
||||
if (!applyCtx.view().rules().enabled(featurePriceOracle))
|
||||
return INVALID_ARGUMENT;
|
||||
|
||||
if (a == 0 || b == 0)
|
||||
return INVALID_ARGUMENT;
|
||||
if (d != 0 || e != 0 || f != 0)
|
||||
return INVALID_ARGUMENT;
|
||||
|
||||
uint32_t read_ptr = a, read_len = b;
|
||||
|
||||
if (NOT_IN_BOUNDS(read_ptr, read_len, memory_length))
|
||||
return OUT_OF_BOUNDS;
|
||||
|
||||
if (read_len != 20)
|
||||
return INVALID_ARGUMENT;
|
||||
|
||||
ripple::AccountID id = AccountID::fromVoid(memory + read_ptr);
|
||||
|
||||
uint32_t seqId = c;
|
||||
|
||||
ripple::Keylet kl = ripple::keylet::oracle(id, seqId);
|
||||
|
||||
return serialize_keylet(kl, memory, write_ptr, write_len);
|
||||
}
|
||||
|
||||
// keylets that take 20 byte account id, and UInt32or256 (4 byte
|
||||
// uint or 32 byte hash)
|
||||
case keylet_code::OFFER:
|
||||
case keylet_code::CHECK:
|
||||
case keylet_code::ESCROW:
|
||||
@@ -2639,6 +2675,62 @@ DEFINE_HOOK_FUNCTION(
|
||||
|
||||
return serialize_keylet(kl, memory, write_ptr, write_len);
|
||||
}
|
||||
|
||||
// keylets that take two 40 byte assets
|
||||
case keylet_code::AMM: {
|
||||
if (!applyCtx.view().rules().enabled(featureAMM))
|
||||
return INVALID_ARGUMENT;
|
||||
|
||||
if (a == 0 || b == 0 || c == 0 || d == 0)
|
||||
return INVALID_ARGUMENT;
|
||||
|
||||
if (e != 0 || f != 0)
|
||||
return INVALID_ARGUMENT;
|
||||
|
||||
uint32_t aread_ptr = a, aread_len = b;
|
||||
uint32_t bread_ptr = c, bread_len = d;
|
||||
|
||||
if (NOT_IN_BOUNDS(aread_ptr, aread_len, memory_length) ||
|
||||
NOT_IN_BOUNDS(bread_ptr, bread_len, memory_length))
|
||||
return OUT_OF_BOUNDS;
|
||||
|
||||
if (aread_len != 40 || bread_len != 40)
|
||||
return INVALID_ARGUMENT;
|
||||
|
||||
Currency aCur = Currency::fromVoid(memory + aread_ptr);
|
||||
Currency bCur = Currency::fromVoid(memory + bread_ptr);
|
||||
|
||||
AccountID aAcc = AccountID::fromVoid(memory + aread_ptr + 20);
|
||||
AccountID bAcc = AccountID::fromVoid(memory + bread_ptr + 20);
|
||||
|
||||
Issue aIss = Issue{aCur, aAcc};
|
||||
Issue bIss = Issue{bCur, bAcc};
|
||||
|
||||
ripple::Keylet kl =
|
||||
ripple::keylet::amm(Asset{aIss}, Asset{bIss});
|
||||
|
||||
return serialize_keylet(kl, memory, write_ptr, write_len);
|
||||
}
|
||||
case keylet_code::BRIDGE:
|
||||
case keylet_code::XCHAIN_OWNED_CLAIM_ID:
|
||||
case keylet_code::XCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID: {
|
||||
if (!applyCtx.view().rules().enabled(featureXChainBridge))
|
||||
return INVALID_ARGUMENT;
|
||||
}
|
||||
case keylet_code::MPTOKEN_ISSUANCE:
|
||||
case keylet_code::MPTOKEN: {
|
||||
if (!applyCtx.view().rules().enabled(featureMPTokensV1))
|
||||
return INVALID_ARGUMENT;
|
||||
}
|
||||
case keylet_code::CREDENTIAL: {
|
||||
if (!applyCtx.view().rules().enabled(featureCredentials))
|
||||
return INVALID_ARGUMENT;
|
||||
}
|
||||
case keylet_code::PERMISSIONED_DOMAIN: {
|
||||
if (!applyCtx.view().rules().enabled(
|
||||
featurePermissionedDomains))
|
||||
return INVALID_ARGUMENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
|
||||
Reference in New Issue
Block a user