diff --git a/include/xrpl/hook/HookAPI.h b/include/xrpl/hook/HookAPI.h index fd8e46271..7e2bf0f82 100644 --- a/include/xrpl/hook/HookAPI.h +++ b/include/xrpl/hook/HookAPI.h @@ -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; }; diff --git a/include/xrpl/protocol/Feature.h b/include/xrpl/protocol/Feature.h index 823bc03a2..a04c9988d 100644 --- a/include/xrpl/protocol/Feature.h +++ b/include/xrpl/protocol/Feature.h @@ -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 diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index 1dfe26779..57c69f671 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -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) diff --git a/src/libxrpl/protocol/STTx.cpp b/src/libxrpl/protocol/STTx.cpp index 8d45f54cd..7758a6ae1 100644 --- a/src/libxrpl/protocol/STTx.cpp +++ b/src/libxrpl/protocol/STTx.cpp @@ -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; } } diff --git a/src/test/app/SetHook_test.cpp b/src/test/app/SetHook_test.cpp index 5caf6b33b..2cfe8ae14 100644 --- a/src/test/app/SetHook_test.cpp +++ b/src/test/app/SetHook_test.cpp @@ -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 + 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 diff --git a/src/test/app/SetHook_wasm.h b/src/test/app/SetHook_wasm.h index faf21ac31..882eac56e 100644 --- a/src/test/app/SetHook_wasm.h +++ b/src/test/app/SetHook_wasm.h @@ -16916,7 +16916,7 @@ std::map> wasm = { 0x64U, 0xE1U, 0xF1U, }}, - /* ==== WASM: 79 ==== */ + /* ==== WASM: 80 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17089,7 +17089,7 @@ std::map> wasm = { 0x54U, 0x5FU, 0x45U, 0x58U, 0x49U, 0x53U, 0x54U, 0x00U, }}, - /* ==== WASM: 80 ==== */ + /* ==== WASM: 81 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17237,7 +17237,161 @@ std::map> wasm = { 0x30U, 0x00U, 0x22U, 0x00U, 0x00U, 0x00U, 0x00U, }}, - /* ==== WASM: 81 ==== */ + /* ==== WASM: 82 ==== */ + {R"[test.hook]( + #include + 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]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x21U, + 0x05U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x04U, 0x7FU, + 0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, + 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, 0x01U, + 0x7FU, 0x01U, 0x7EU, 0x02U, 0x3BU, 0x04U, 0x03U, 0x65U, 0x6EU, 0x76U, + 0x02U, 0x5FU, 0x67U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0AU, + 0x6FU, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x70U, 0x61U, 0x72U, 0x61U, 0x6DU, + 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0CU, 0x73U, 0x74U, 0x6FU, + 0x5FU, 0x76U, 0x61U, 0x6CU, 0x69U, 0x64U, 0x61U, 0x74U, 0x65U, 0x00U, + 0x02U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, + 0x70U, 0x74U, 0x00U, 0x03U, 0x03U, 0x02U, 0x01U, 0x04U, 0x05U, 0x03U, + 0x01U, 0x00U, 0x02U, 0x06U, 0x27U, 0x06U, 0x7FU, 0x01U, 0x41U, 0xF0U, + 0x8FU, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xEAU, 0x0FU, 0x0BU, 0x7FU, + 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xF0U, 0x8FU, + 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, + 0x41U, 0x80U, 0x08U, 0x0BU, 0x07U, 0x08U, 0x01U, 0x04U, 0x68U, 0x6FU, + 0x6FU, 0x6BU, 0x00U, 0x04U, 0x0AU, 0xC4U, 0x80U, 0x00U, 0x01U, 0xC0U, + 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, 0x80U, 0x88U, 0x80U, + 0x80U, 0x00U, 0x41U, 0xE8U, 0x07U, 0x41U, 0xE8U, 0x8FU, 0x80U, 0x80U, + 0x00U, 0x41U, 0x01U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0xA7U, + 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x10U, 0x83U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x0BU, 0x0BU, 0xF8U, 0x07U, 0x02U, + 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0xE8U, 0x07U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x41U, 0xE8U, + 0x0FU, 0x0BU, 0x02U, 0x56U, 0x00U, + }}, + + /* ==== WASM: 83 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17334,7 +17488,7 @@ std::map> wasm = { 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 82 ==== */ + /* ==== WASM: 84 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17393,7 +17547,7 @@ std::map> wasm = { 0x4FU, 0x46U, 0x5FU, 0x42U, 0x4FU, 0x55U, 0x4EU, 0x44U, 0x53U, 0x00U, }}, - /* ==== WASM: 83 ==== */ + /* ==== WASM: 85 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17452,7 +17606,7 @@ std::map> wasm = { 0x4EU, 0x44U, 0x53U, 0x00U, }}, - /* ==== WASM: 84 ==== */ + /* ==== WASM: 86 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -19281,7 +19435,7 @@ std::map> wasm = { 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 85 ==== */ + /* ==== WASM: 87 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -20898,7 +21052,7 @@ std::map> wasm = { 0x2CU, 0x20U, 0x30U, 0x2CU, 0x20U, 0x30U, 0x29U, 0x29U, 0x00U, }}, - /* ==== WASM: 86 ==== */ + /* ==== WASM: 88 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -23831,7 +23985,7 @@ std::map> wasm = { 0x4FU, 0x4FU, 0x5FU, 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 87 ==== */ + /* ==== WASM: 89 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -25796,7 +25950,7 @@ std::map> wasm = { 0x54U, 0x4FU, 0x4FU, 0x5FU, 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 88 ==== */ + /* ==== WASM: 90 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -26081,7 +26235,7 @@ std::map> wasm = { 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 89 ==== */ + /* ==== WASM: 91 ==== */ {R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); @@ -26668,7 +26822,7 @@ std::map> wasm = { 0x4EU, 0x5FU, 0x46U, 0x41U, 0x49U, 0x4CU, 0x55U, 0x52U, 0x45U, 0x00U, }}, - /* ==== WASM: 90 ==== */ + /* ==== WASM: 92 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -26697,7 +26851,7 @@ std::map> wasm = { 0x0BU, }}, - /* ==== WASM: 91 ==== */ + /* ==== WASM: 93 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -26729,7 +26883,7 @@ std::map> wasm = { 0x20U, 0x52U, 0x65U, 0x6AU, 0x65U, 0x63U, 0x74U, 0x65U, 0x64U, 0x00U, }}, - /* ==== WASM: 92 ==== */ + /* ==== WASM: 94 ==== */ {R"[test.hook]( (module (type (;0;) (func (param i32 i32 i64) (result i64))) @@ -26756,7 +26910,7 @@ std::map> wasm = { 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x00U, 0x0BU, }}, - /* ==== WASM: 93 ==== */ + /* ==== WASM: 95 ==== */ {R"[test.hook]( (module (type (;0;) (func (param i32 i32) (result i32))) @@ -26809,7 +26963,7 @@ std::map> wasm = { 0x00U, 0x1AU, 0x0BU, }}, - /* ==== WASM: 94 ==== */ + /* ==== WASM: 96 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -33452,7 +33606,7 @@ std::map> wasm = { 0x39U, 0x30U, 0x31U, 0x32U, 0x33U, 0x00U, }}, - /* ==== WASM: 95 ==== */ + /* ==== WASM: 97 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -33498,7 +33652,7 @@ std::map> wasm = { 0x0BU, 0x06U, 0x76U, 0x61U, 0x6CU, 0x75U, 0x65U, 0x00U, }}, - /* ==== WASM: 96 ==== */ + /* ==== WASM: 98 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); diff --git a/src/xrpld/app/hook/detail/HookAPI.cpp b/src/xrpld/app/hook/detail/HookAPI.cpp index 71f4aadca..15be95e4c 100644 --- a/src/xrpld/app/hook/detail/HookAPI.cpp +++ b/src/xrpld/app/hook/detail/HookAPI.cpp @@ -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{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{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++;