diff --git a/include/xrpl/basics/Number.h b/include/xrpl/basics/Number.h index 9ee05bfb45..eb28721ec3 100644 --- a/include/xrpl/basics/Number.h +++ b/include/xrpl/basics/Number.h @@ -342,6 +342,10 @@ abs(Number x) noexcept Number power(Number const& f, unsigned n); +// logarithm with base 10 +Number +lg(Number const& value); + // Returns f^(1/d) // Uses Newton–Raphson iterations until the result stops changing // to find the root of the polynomial g(x) = x^d - f diff --git a/src/libxrpl/basics/Number.cpp b/src/libxrpl/basics/Number.cpp index f43288b57b..50583cc290 100644 --- a/src/libxrpl/basics/Number.cpp +++ b/src/libxrpl/basics/Number.cpp @@ -623,6 +623,48 @@ power(Number const& f, unsigned n) return r; } +// Continued fraction approximation of ln(x) +static Number +ln(Number const& x, unsigned iterations = 50) +{ + if (x <= 0) + throw std::runtime_error("Not positive value"); + + Number const z = (x - 1) / (x + 1); + Number const zz = z * z; + Number denom = Number(1, -10); + + // Construct the fraction from the bottom up + for (int i = iterations; i > 0; --i) + { + Number k(2 * i - 1); + denom = k - (i * i * zz / denom); + } + + auto const r = 2 * z / denom; + return r; +} + +Number +lg(Number const& x) +{ + static Number const ln10 = ln(Number(10)); + + if (x <= Number(10)) + { + auto const r = ln(x) / ln10; + return r; + } + + // ln(x) = ln(normX * 10^norm) = ln(normX) + norm * ln(10) + int diffExp = 15 + x.exponent(); + Number const normalX = x / Number(1, diffExp); // (1 <= normalX < 10) + auto const lnX = ln(normalX) + diffExp * ln10; + + auto const r = lnX / ln10; + return r; +} + // Returns f^(1/d) // Uses Newton–Raphson iterations until the result stops changing // to find the non-negative root of the polynomial g(x) = x^d - f diff --git a/src/test/app/TestHostFunctions.h b/src/test/app/TestHostFunctions.h index 45de5d7b93..0752d6f6f4 100644 --- a/src/test/app/TestHostFunctions.h +++ b/src/test/app/TestHostFunctions.h @@ -26,6 +26,7 @@ #include namespace ripple { + namespace test { struct TestLedgerDataProvider : public HostFunctions @@ -378,6 +379,89 @@ public: #endif return msg.size() + sizeof(data); } + + Expected + traceFloat(std::string_view const& msg, Slice const& data) override + { +#ifdef DEBUG_OUTPUT + auto& j = std::cerr; +#else + auto j = getJournal().trace(); +#endif + auto const s = floatToString(data); + j << "WAMR TRACE FLOAT: " << msg << " " << s; + +#ifdef DEBUG_OUTPUT + j << std::endl; +#endif + return msg.size() + s.size(); + } + + Expected + floatFromInt(int64_t x, int32_t mode) override + { + return floatFromIntImpl(x, mode); + } + + Expected + floatFromUint(uint64_t x, int32_t mode) override + { + return floatFromUintImpl(x, mode); + } + + Expected + floatSet(int64_t mantissa, int32_t exponent, int32_t mode) override + { + return floatSetImpl(mantissa, exponent, mode); + } + + Expected + floatCompare(Slice const& x, Slice const& y) override + { + return floatCompareImpl(x, y); + } + + Expected + floatAdd(Slice const& x, Slice const& y, int32_t mode) override + { + return floatAddImpl(x, y, mode); + } + + Expected + floatSubtract(Slice const& x, Slice const& y, int32_t mode) override + { + return floatSubtractImpl(x, y, mode); + } + + Expected + floatMultiply(Slice const& x, Slice const& y, int32_t mode) override + { + return floatMultiplyImpl(x, y, mode); + } + + Expected + floatDivide(Slice const& x, Slice const& y, int32_t mode) override + { + return floatDivideImpl(x, y, mode); + } + + Expected + floatRoot(Slice const& x, int32_t n, int32_t mode) override + { + return floatRootImpl(x, n, mode); + } + + Expected + floatPower(Slice const& x, int32_t n, int32_t mode) override + { + return floatPowerImpl(x, n, mode); + } + + Expected + floatLog(Slice const& x, int32_t mode) override + { + return floatLogImpl(x, mode); + } }; struct TestHostFunctionsSink : public TestHostFunctions diff --git a/src/test/app/Wasm_test.cpp b/src/test/app/Wasm_test.cpp index 5eee6014e5..98e06a8636 100644 --- a/src/test/app/Wasm_test.cpp +++ b/src/test/app/Wasm_test.cpp @@ -509,6 +509,31 @@ struct Wasm_test : public beast::unit_test::suite } } + void + testFloat() + { + testcase("float point"); + + std::string const funcName("finish"); + + using namespace test::jtx; + + Env env(*this); + { + std::string const wasmHex = floatHex; + std::string const wasmStr = boost::algorithm::unhex(wasmHex); + std::vector const wasm(wasmStr.begin(), wasmStr.end()); + + TestHostFunctions hf(env, 0); + auto re = runEscrowWasm(wasm, funcName, {}, &hf, 100'000); + if (BEAST_EXPECT(re.has_value())) + { + BEAST_EXPECT(re->result && (re->cost == 91'412)); + } + env.close(); + } + } + void perfTest() { @@ -656,6 +681,7 @@ struct Wasm_test : public beast::unit_test::suite testHFCost(); testEscrowWasmDN(); + testFloat(); testCodecovWasm(); diff --git a/src/test/app/wasm_fixtures/fixtures.cpp b/src/test/app/wasm_fixtures/fixtures.cpp index bddb076df9..d01835988a 100644 --- a/src/test/app/wasm_fixtures/fixtures.cpp +++ b/src/test/app/wasm_fixtures/fixtures.cpp @@ -12222,3 +12222,151 @@ extern std::string const codecovWasm = "31352900490f7461726765745f6665617475726573042b0f6d757461626c652d676c6f6261" "6c732b087369676e2d6578742b0f7265666572656e63652d74797065732b0a6d756c746976" "616c7565"; + +extern std::string const floatHex = + "0061736d0100000001430860057f7f7f7f7f017f60047e7f7f7f017f60047f7f7f7f017f60" + "057f7e7f7f7f017f60077f7f7f7f7f7f7f017f60067f7f7f7f7f7f017f60037f7f7e017f60" + "00017f02c9020e08686f73745f6c6962057472616365000008686f73745f6c69620e666c6f" + "61745f66726f6d5f696e74000108686f73745f6c69620f666c6f61745f66726f6d5f75696e" + "74000008686f73745f6c69621274726163655f6f70617175655f666c6f6174000208686f73" + "745f6c696209666c6f61745f736574000308686f73745f6c69620d666c6f61745f636f6d70" + "617265000208686f73745f6c696209666c6f61745f616464000408686f73745f6c69620e66" + "6c6f61745f7375627472616374000408686f73745f6c69620e666c6f61745f6d756c746970" + "6c79000408686f73745f6c69620c666c6f61745f646976696465000408686f73745f6c6962" + "09666c6f61745f706f77000508686f73745f6c69620974726163655f6e756d000608686f73" + "745f6c69620a666c6f61745f726f6f74000508686f73745f6c696209666c6f61745f6c6f67" + "00000302010705030100110619037f01418080c0000b7f0041b48ac0000b7f0041c08ac000" + "0b072e04066d656d6f727902000666696e697368000e0a5f5f646174615f656e6403010b5f" + "5f686561705f6261736503020acf1301cc1301027f23808080800041206b22002480808080" + "00418080c08000411d4100410041001080808080001a2000420037031002400240428ce000" + "200041106a410841001081808080004108470d00419d80c080004117200041106a41084101" + "1080808080001a0c010b41b480c08000411e4100410041001080808080001a0b2000428ce0" + "0037031802400240200041186a4108200041106a410841001082808080004108470d0041d2" + "80c080004117200041106a41081083808080001a0c010b41e980c08000411e410041004100" + "1080808080001a0b02400240410242fb00200041106a410841001084808080004108470d00" + "418781c080004121200041106a41081083808080001a0c010b41a881c08000412641004100" + "41001080808080001a0b41ce81c08000411541e381c0800041081083808080001a41f381c0" + "8000411641eb81c0800041081083808080001a418982c08000411b41004100410010808080" + "80001a20004200370318024002404201200041186a410841001081808080004108470d0041" + "a482c08000410f200041186a41081083808080001a0c010b41b382c0800041164100410041" + "001080808080001a0b02400240200041186a410841e381c0800041081085808080000d0041" + "c982c08000411b4100410041001080808080001a0c010b41e482c08000411b410041004100" + "1080808080001a0b02400240200041186a410841eb81c0800041081085808080004101470d" + "0041ff82c0800041234100410041001080808080001a0c010b41a283c08000412441004100" + "41001080808080001a0b0240024041eb81c080004108200041186a41081085808080004102" + "470d0041c683c0800041234100410041001080808080001a0c010b41e983c0800041244100" + "410041001080808080001a0b418d84c0800041204100410041001080808080001a200042d4" + "87b6f4c7d4b1c000370310410921010340200041106a410841e381c080004108200041106a" + "410841001086808080001a2001417f6a22010d000b20004200370318420a200041186a4108" + "41001081808080001a02400240200041186a4108200041106a41081085808080000d0041ad" + "84c0800041144100410041001080808080001a0c010b41c184c08000411341004100410010" + "80808080001a0b410b21010340200041106a410841e381c080004108200041106a41084100" + "1087808080001a2001417f6a22010d000b02400240200041106a410841eb81c08000410810" + "85808080000d0041d484c0800041194100410041001080808080001a0c010b41ed84c08000" + "41184100410041001080808080001a0b418585c0800041234100410041001080808080001a" + "20004200370300420a2000410841001081808080001a200042d487b6f4c7d4b1c000370308" + "410621010340200041086a410820004108200041086a410841001088808080001a2001417f" + "6a22010d000b2000420037031042c0843d200041106a410841001081808080001a02400240" + "200041106a4108200041086a41081085808080000d0041a885c08000411941004100410010" + "80808080001a0c010b41c185c0800041184100410041001080808080001a0b410721010340" + "200041086a410820004108200041086a410841001089808080001a2001417f6a22010d000b" + "20004200370318417f4201200041186a410841001084808080001a02400240200041086a41" + "08200041186a41081085808080000d0041d985c0800041174100410041001080808080001a" + "0c010b41f085c0800041164100410041001080808080001a0b418686c08000411741004100" + "41001080808080001a2000420037030841e381c0800041084103200041086a41084100108a" + "808080001a419d86c080004112200041086a41081083808080001a41eb81c0800041084106" + "200041086a41084100108a808080001a41af86c080004118200041086a4108108380808000" + "1a200042003703104209200041106a410841001081808080001a200041106a410841022000" + "41086a41084100108a808080001a41c786c080004114200041086a41081083808080001a20" + "0041106a41084100200041086a41084100108a808080001a41db86c080004117200041086a" + "41081083808080001a200042003703184200200041186a410841001081808080001a200041" + "186a41084102200041086a41084100108a808080001a41f286c080004114200041086a4108" + "1083808080001a418687c080004138200041186a41084100200041086a41084100108a8080" + "8000ac108b808080001a41be87c0800041184100410041001080808080001a200042003703" + "084209200041086a410841001081808080001a20004200370310200041086a410841022000" + "41106a41084100108c808080001a41d687c080004112200041106a41081083808080001a20" + "0041086a41084103200041106a41084100108c808080001a41e887c080004112200041106a" + "41081083808080001a2000420037031842c0843d200041186a410841001081808080001a20" + "0041186a41084103200041106a41084100108c808080001a41fa87c080004118200041106a" + "41081083808080001a200041186a41084106200041106a41084100108c808080001a419288" + "c08000411c200041106a41081083808080001a41ae88c08000411741004100410010808080" + "80001a2000420037031042c0843d200041106a410841001081808080001a20004200370318" + "200041106a4108200041186a41084100108d808080001a41c588c080004114200041186a41" + "081083808080001a41d988c08000411a4100410041001080808080001a2000420037031841" + "e381c08000410841eb81c080004108200041186a410841001088808080001a0240024041eb" + "81c080004108200041186a41081085808080000d0041f388c0800041164100410041001080" + "808080001a0c010b418989c0800041154100410041001080808080001a0b41eb81c0800041" + "0841eb81c080004108200041186a410841001088808080001a0240024041e381c080004108" + "200041186a41081085808080000d00419e89c0800041174100410041001080808080001a0c" + "010b41b589c0800041164100410041001080808080001a0b41cb89c08000411a4100410041" + "001080808080001a2000420037031020004200370318420a200041186a4108410010818080" + "80001a41e381c080004108200041186a4108200041106a410841001089808080001a41e589" + "c080004119200041106a41081083808080001a41e381c080004108200041106a4108200041" + "106a410841001089808080001a41fe89c08000410f200041106a41081083808080001a0240" + "0240200041186a4108200041106a41081085808080000d00418d8ac0800041144100410041" + "001080808080001a0c010b41a18ac0800041134100410041001080808080001a0b20004120" + "6a24808080800041010b0bbe0a0100418080c0000bb40a0a24242420746573745f666c6f61" + "745f66726f6d5f7761736d202424242020666c6f61742066726f6d20693634203132333030" + "3a2020666c6f61742066726f6d206936342031323330303a206661696c65642020666c6f61" + "742066726f6d207536342031323330303a2020666c6f61742066726f6d2075363420313233" + "30303a206661696c65642020666c6f61742066726f6d2065787020322c206d616e74697373" + "61203132333a2020666c6f61742066726f6d2065787020322c206d616e746973736120333a" + "206661696c65642020666c6f61742066726f6d20636f6e737420313ad4838d7ea4c6800094" + "838d7ea4c680002020666c6f61742066726f6d20636f6e7374202d313a0a24242420746573" + "745f666c6f61745f636f6d70617265202424242020666c6f61742066726f6d20313a202066" + "6c6f61742066726f6d20313a206661696c65642020666c6f61742066726f6d2031203d3d20" + "464c4f41545f4f4e452020666c6f61742066726f6d203120213d20464c4f41545f4f4e4520" + "20666c6f61742066726f6d2031203e20464c4f41545f4e454741544956455f4f4e45202066" + "6c6f61742066726f6d203120213e20464c4f41545f4e454741544956455f4f4e452020464c" + "4f41545f4e454741544956455f4f4e45203c20666c6f61742066726f6d20312020464c4f41" + "545f4e454741544956455f4f4e4520213c20666c6f61742066726f6d20310a242424207465" + "73745f666c6f61745f6164645f737562747261637420242424202072657065617465642061" + "64643a20676f6f6420207265706561746564206164643a2062616420207265706561746564" + "2073756274726163743a20676f6f64202072657065617465642073756274726163743a2062" + "61640a24242420746573745f666c6f61745f6d756c7469706c795f64697669646520242424" + "20207265706561746564206d756c7469706c793a20676f6f6420207265706561746564206d" + "756c7469706c793a2062616420207265706561746564206469766964653a20676f6f642020" + "7265706561746564206469766964653a206261640a24242420746573745f666c6f61745f70" + "6f77202424242020666c6f61742063756265206f6620313a2020666c6f6174203674682070" + "6f776572206f66202d313a2020666c6f617420737175617265206f6620393a2020666c6f61" + "742030746820706f776572206f6620393a2020666c6f617420737175617265206f6620303a" + "2020666c6f61742030746820706f776572206f6620302028657870656374696e6720494e56" + "414c49445f504152414d53206572726f72293a0a24242420746573745f666c6f61745f726f" + "6f74202424242020666c6f61742073717274206f6620393a2020666c6f6174206362727420" + "6f6620393a2020666c6f61742063627274206f6620313030303030303a2020666c6f617420" + "36746820726f6f74206f6620313030303030303a0a24242420746573745f666c6f61745f6c" + "6f672024242420206c6f675f3130206f6620313030303030303a0a24242420746573745f66" + "6c6f61745f6e65676174652024242420206e656761746520636f6e737420313a20676f6f64" + "20206e656761746520636f6e737420313a2062616420206e656761746520636f6e7374202d" + "313a20676f6f6420206e656761746520636f6e7374202d313a206261640a24242420746573" + "745f666c6f61745f696e76657274202424242020696e76657274206120666c6f6174206672" + "6f6d2031303a2020696e7665727420616761696e3a2020696e766572742074776963653a20" + "676f6f642020696e766572742074776963653a20626164009c06046e616d65001110666c6f" + "61745f74657374732e7761736d01e1050f002b5f5a4e387872706c5f73746434686f737435" + "7472616365313768303332393563316538663365373233614501355f5a4e387872706c5f73" + "746434686f73743134666c6f61745f66726f6d5f696e743137683032306436373439326164" + "39346333304502365f5a4e387872706c5f73746434686f73743135666c6f61745f66726f6d" + "5f75696e74313768346166373638366538353062383432364503395f5a4e387872706c5f73" + "746434686f7374313874726163655f6f70617175655f666c6f617431376831396639386666" + "35663362313932336245042f5f5a4e387872706c5f73746434686f737439666c6f61745f73" + "6574313768323964346230383964626561326664624505345f5a4e387872706c5f73746434" + "686f73743133666c6f61745f636f6d70617265313768346362313239626634623330373233" + "6445062f5f5a4e387872706c5f73746434686f737439666c6f61745f616464313768383661" + "336165636435336234643937374507355f5a4e387872706c5f73746434686f73743134666c" + "6f61745f7375627472616374313768653033313036323931393464333931364508355f5a4e" + "387872706c5f73746434686f73743134666c6f61745f6d756c7469706c7931376830323839" + "3337633039656534323630644509335f5a4e387872706c5f73746434686f73743132666c6f" + "61745f64697669646531376834363036323038303562623237353632450a2f5f5a4e387872" + "706c5f73746434686f737439666c6f61745f706f7731376833326463303662646430303338" + "626331450b2f5f5a4e387872706c5f73746434686f73743974726163655f6e756d31376830" + "336535336633646539393463633033450c315f5a4e387872706c5f73746434686f73743130" + "666c6f61745f726f6f7431376863656632313139376565656136653630450d2f5f5a4e3878" + "72706c5f73746434686f737439666c6f61745f6c6f67313768323530663038303633353663" + "35653639450e0666696e697368071201000f5f5f737461636b5f706f696e746572090a0100" + "072e726f64617461004d0970726f64756365727302086c616e677561676501045275737400" + "0c70726f6365737365642d6279010572757374631d312e38382e3020283662303062633338" + "3820323032352d30362d3233290094010f7461726765745f6665617475726573082b0b6275" + "6c6b2d6d656d6f72792b0f62756c6b2d6d656d6f72792d6f70742b1663616c6c2d696e6469" + "726563742d6f7665726c6f6e672b0a6d756c746976616c75652b0f6d757461626c652d676c" + "6f62616c732b136e6f6e7472617070696e672d6670746f696e742b0f7265666572656e6365" + "2d74797065732b087369676e2d657874"; diff --git a/src/test/app/wasm_fixtures/fixtures.h b/src/test/app/wasm_fixtures/fixtures.h index b82b9aadcf..3ffb41caf9 100644 --- a/src/test/app/wasm_fixtures/fixtures.h +++ b/src/test/app/wasm_fixtures/fixtures.h @@ -60,3 +60,5 @@ extern std::string const opcCallPerfTest; extern std::string const keyletHostFunctions; extern std::string const codecovWasm; + +extern std::string const floatHex; diff --git a/src/xrpld/app/misc/WasmHostFunc.h b/src/xrpld/app/misc/WasmHostFunc.h index 00f89a4ac7..84e3882cc0 100644 --- a/src/xrpld/app/misc/WasmHostFunc.h +++ b/src/xrpld/app/misc/WasmHostFunc.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -49,8 +50,46 @@ enum class HostFunctionError : int32_t { INVALID_ACCOUNT = -16, INVALID_FIELD = -17, INDEX_OUT_OF_BOUNDS = -18, + FLOAT_INPUT_MALFORMED = -19, + FLOAT_COMPUTATION_ERROR = -20, }; +std::string +floatToString(Slice const& data); + +Expected +floatFromIntImpl(int64_t x, int32_t mode); + +Expected +floatFromUintImpl(uint64_t x, int32_t mode); + +Expected +floatSetImpl(int64_t mantissa, int32_t exponent, int32_t mode); + +Expected +floatCompareImpl(Slice const& x, Slice const& y); + +Expected +floatAddImpl(Slice const& x, Slice const& y, int32_t mode); + +Expected +floatSubtractImpl(Slice const& x, Slice const& y, int32_t mode); + +Expected +floatMultiplyImpl(Slice const& x, Slice const& y, int32_t mode); + +Expected +floatDivideImpl(Slice const& x, Slice const& y, int32_t mode); + +Expected +floatRootImpl(Slice const& x, int32_t n, int32_t mode); + +Expected +floatPowerImpl(Slice const& x, int32_t n, int32_t mode); + +Expected +floatLogImpl(Slice const& x, int32_t mode); + struct HostFunctions { virtual void @@ -289,6 +328,78 @@ struct HostFunctions return Unexpected(HostFunctionError::INTERNAL); } + virtual Expected + traceFloat(std::string_view const& msg, Slice const& data) + { + return Unexpected(HostFunctionError::INTERNAL); + } + + virtual Expected + floatFromInt(int64_t x, int32_t mode) + { + return Unexpected(HostFunctionError::INTERNAL); + } + + virtual Expected + floatFromUint(uint64_t x, int32_t mode) + { + return Unexpected(HostFunctionError::INTERNAL); + } + + virtual Expected + floatSet(int64_t mantissa, int32_t exponent, int32_t mode) + { + return Unexpected(HostFunctionError::INTERNAL); + } + + virtual Expected + floatCompare(Slice const& x, Slice const& y) + { + return Unexpected(HostFunctionError::INTERNAL); + } + + virtual Expected + floatAdd(Slice const& x, Slice const& y, int32_t mode) + { + return Unexpected(HostFunctionError::INTERNAL); + } + + virtual Expected + floatSubtract(Slice const& x, Slice const& y, int32_t mode) + { + return Unexpected(HostFunctionError::INTERNAL); + } + + virtual Expected + floatMultiply(Slice const& x, Slice const& y, int32_t mode) + { + return Unexpected(HostFunctionError::INTERNAL); + } + + virtual Expected + floatDivide(Slice const& x, Slice const& y, int32_t mode) + { + return Unexpected(HostFunctionError::INTERNAL); + } + + virtual Expected + floatRoot(Slice const& x, int32_t n, int32_t mode) + { + return Unexpected(HostFunctionError::INTERNAL); + } + + virtual Expected + floatPower(Slice const& x, int32_t n, int32_t mode) + { + return Unexpected(HostFunctionError::INTERNAL); + } + + virtual Expected + floatLog(Slice const& x, int32_t mode) + { + return Unexpected(HostFunctionError::INTERNAL); + } + virtual ~HostFunctions() = default; }; diff --git a/src/xrpld/app/misc/WasmHostFuncImpl.cpp b/src/xrpld/app/misc/WasmHostFuncImpl.cpp index 7dce3b865a..d8f452159a 100644 --- a/src/xrpld/app/misc/WasmHostFuncImpl.cpp +++ b/src/xrpld/app/misc/WasmHostFuncImpl.cpp @@ -654,4 +654,544 @@ WasmHostFunctionsImpl::traceNum(std::string_view const& msg, int64_t data) return msg.size() + sizeof(data); } +Expected +WasmHostFunctionsImpl::traceFloat( + std::string_view const& msg, + Slice const& data) +{ +#ifdef DEBUG_OUTPUT + auto j = getJournal().error(); +#else + auto j = getJournal().trace(); +#endif + auto const s = floatToString(data); + j << "WAMR TRACE FLOAT(" << leKey.key << "): " << msg << " " << s; + return msg.size() + s.size(); +} + +Expected +WasmHostFunctionsImpl::floatFromInt(int64_t x, int32_t mode) +{ + return floatFromIntImpl(x, mode); +} + +Expected +WasmHostFunctionsImpl::floatFromUint(uint64_t x, int32_t mode) +{ + return floatFromUintImpl(x, mode); +} + +Expected +WasmHostFunctionsImpl::floatSet( + int64_t mantissa, + int32_t exponent, + int32_t mode) +{ + return floatSetImpl(mantissa, exponent, mode); +} + +Expected +WasmHostFunctionsImpl::floatCompare(Slice const& x, Slice const& y) +{ + return floatCompareImpl(x, y); +} + +Expected +WasmHostFunctionsImpl::floatAdd(Slice const& x, Slice const& y, int32_t mode) +{ + return floatAddImpl(x, y, mode); +} + +Expected +WasmHostFunctionsImpl::floatSubtract( + Slice const& x, + Slice const& y, + int32_t mode) +{ + return floatSubtractImpl(x, y, mode); +} + +Expected +WasmHostFunctionsImpl::floatMultiply( + Slice const& x, + Slice const& y, + int32_t mode) +{ + return floatMultiplyImpl(x, y, mode); +} + +Expected +WasmHostFunctionsImpl::floatDivide(Slice const& x, Slice const& y, int32_t mode) +{ + return floatDivideImpl(x, y, mode); +} + +Expected +WasmHostFunctionsImpl::floatRoot(Slice const& x, int32_t n, int32_t mode) +{ + return floatRootImpl(x, n, mode); +} + +Expected +WasmHostFunctionsImpl::floatPower(Slice const& x, int32_t n, int32_t mode) +{ + return floatPowerImpl(x, n, mode); +} + +Expected +WasmHostFunctionsImpl::floatLog(Slice const& x, int32_t mode) +{ + return floatLogImpl(x, mode); +} + +class Number2 : public Number +{ + bool good_; + + enum Issue { XRP, MPT, IOU }; + Issue issue_; + +public: + Number2(Slice const& data) : Number(0), good_(false), issue_(IOU) + { + if (data.size() != 8) + return; + + uint64_t const v = SerialIter(data).get64(); + int const neg = (v & STAmount::cPositive) ? 1 : -1; + + Number x; + + if (v & STAmount::cIssuedCurrency) + { + // IOU + int32_t const e = + static_cast((v >> (64 - 10)) & ((1ull << 8) - 1)); + int64_t const m = neg * (v & ((1ull << 54) - 1)); + x = !m ? Number() : Number(m, e - 97); + if (m && (x.exponent() > 80 || x.exponent() < -96)) + return; // invalid number + issue_ = IOU; + } + else if (v & STAmount::cMPToken) + { + // MPT + int64_t const m = neg * (v & ((1ull << 61) - 1)); + x = !m ? Number() : Number(m); + issue_ = MPT; + } + else + { + // XRP + int64_t const m = neg * (v & ((1ull << 61) - 1)); + x = !m ? Number() : Number(m); + issue_ = XRP; + } + + *static_cast(this) = x; + good_ = true; + } + + Number2(int64_t x) : Number(x), good_(true), issue_(IOU) + { + } + + Number2(uint64_t x) : Number(0), good_(false), issue_(IOU) + { + if (x <= + std::numeric_limits< + std::invoke_result_t>:: + max()) + *static_cast(this) = Number(x); + else + { + *static_cast(this) = Number(x / 10, 1) + Number(x % 10); + } + + good_ = true; + } + + Number2(int64_t mantissa, int32_t exponent) + : Number(mantissa, exponent), good_(true), issue_(IOU) + { + } + + Number2(Number const& n) : Number(n), good_(true), issue_(IOU) + { + } + + operator bool() const + { + return good_; + } + + Expected + toBytes() const + { + uint64_t v = mantissa() >= 0 ? STAmount::cPositive : 0; + + if (issue_ == IOU) + { + v |= STAmount::cIssuedCurrency; + + if (!mantissa()) + { + if (exponent() != std::numeric_limits::lowest()) + return Unexpected( + HostFunctionError::FLOAT_COMPUTATION_ERROR); + } + else if (exponent() > 80 || exponent() < -96) + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); + + uint64_t absM = mantissa() >= 0 ? mantissa() : -mantissa(); + if (absM > ((1ull << 54) - 1)) + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); + + v |= absM; + + int const e = (!mantissa() ? 0 : exponent()) + 97; + v |= ((uint64_t)e) << 54; + } + else if (issue_ == MPT) + { + v |= STAmount::cMPToken; + uint64_t x = toUInt(61); + if (x == std::numeric_limits::max()) + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); + v |= x; + } + else + { + uint64_t x = toUInt(61); + if (x == std::numeric_limits::max()) + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); + v |= x; + } + + Serializer msg; + msg.add64(v); + auto const data = msg.getData(); + return data; + } + +protected: + uint64_t + toUInt(unsigned bits) const + { + if (bits >= sizeof(uint64_t) * 8) + return std::numeric_limits::max(); + + uint64_t maxV = (1ull << bits) - 1; + uint64_t absM = mantissa() >= 0 ? mantissa() : -mantissa(); + + if (!absM) + return 0; + else if (exponent() < 0) + { + for (int i = 0; i > exponent(); --i) + { + if (absM < 10) + return std::numeric_limits::max(); // underflow + absM /= 10; + } + } + else + { + for (int i = 0; i < exponent(); ++i) + { + if (absM > maxV / 10) + return std::numeric_limits::max(); // overflow + absM *= 10; + } + } + + return absM > maxV ? std::numeric_limits::max() : absM; + } +}; + +struct SetRound +{ + Number::rounding_mode oldMode_; + bool good_; + + SetRound(int32_t mode) : oldMode_(Number::getround()), good_(false) + { + if (mode < Number::rounding_mode::to_nearest || + mode > Number::rounding_mode::upward) + return; + + Number::setround(static_cast(mode)); + good_ = true; + } + + ~SetRound() + { + Number::setround(oldMode_); + } + + operator bool() const + { + return good_; + } +}; + +std::string +floatToString(Slice const& data) +{ + Number2 const num(data); + if (!num) + { + std::string hex; + hex.reserve(data.size() * 2); + boost::algorithm::hex( + data.begin(), data.end(), std::back_inserter(hex)); + return "Invalid data: " + hex; + } + + auto const s = to_string(num); + return s; +} + +Expected +floatFromIntImpl(int64_t x, int32_t mode) +{ + try + { + SetRound rm(mode); + if (!rm) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + + Number2 num(x); + if (!num) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + + return num.toBytes(); + } + catch (...) + { + } + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); +} + +Expected +floatFromUintImpl(uint64_t x, int32_t mode) +{ + try + { + SetRound rm(mode); + if (!rm) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + + Number2 num(x); + if (!num) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + + return num.toBytes(); + } + catch (...) + { + } + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); +} + +Expected +floatSetImpl(int64_t mantissa, int32_t exponent, int32_t mode) +{ + try + { + SetRound rm(mode); + if (!rm) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 num(mantissa, exponent); + if (!num) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + return num.toBytes(); + } + catch (...) + { + } + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); +} + +Expected +floatCompareImpl(Slice const& x, Slice const& y) +{ + try + { + Number2 xx(x); + if (!xx) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 yy(y); + if (!yy) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + return xx < yy ? 2 : (xx == yy ? 0 : 1); + } + catch (...) + { + } + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); +} + +Expected +floatAddImpl(Slice const& x, Slice const& y, int32_t mode) +{ + try + { + SetRound rm(mode); + if (!rm) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + + Number2 xx(x); + if (!xx) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 yy(y); + if (!yy) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 res = xx + yy; + return res.toBytes(); + } + catch (...) + { + } + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); +} + +Expected +floatSubtractImpl(Slice const& x, Slice const& y, int32_t mode) +{ + try + { + SetRound rm(mode); + if (!rm) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 xx(x); + if (!xx) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 yy(y); + if (!yy) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 res = xx - yy; + return res.toBytes(); + } + catch (...) + { + } + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); +} + +Expected +floatMultiplyImpl(Slice const& x, Slice const& y, int32_t mode) +{ + try + { + SetRound rm(mode); + if (!rm) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 xx(x); + if (!xx) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 yy(y); + if (!yy) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 res = xx * yy; + return res.toBytes(); + } + catch (...) + { + } + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); +} + +Expected +floatDivideImpl(Slice const& x, Slice const& y, int32_t mode) +{ + try + { + SetRound rm(mode); + if (!rm) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 xx(x); + if (!xx) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 yy(y); + if (!yy) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 res = xx / yy; + return res.toBytes(); + } + catch (...) + { + } + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); +} + +Expected +floatRootImpl(Slice const& x, int32_t n, int32_t mode) +{ + try + { + SetRound rm(mode); + if (!rm) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + + Number2 xx(x); + if (!xx) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 const res(root(xx, n)); + + return res.toBytes(); + } + catch (...) + { + } + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); +} + +Expected +floatPowerImpl(Slice const& x, int32_t n, int32_t mode) +{ + try + { + SetRound rm(mode); + if (!rm) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + + Number2 xx(x); + if (!xx) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + if (xx == Number() && !n) + return Unexpected(HostFunctionError::INVALID_PARAMS); + + Number2 const res(power(xx, n, 1)); + + return res.toBytes(); + } + catch (...) + { + } + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); +} + +Expected +floatLogImpl(Slice const& x, int32_t mode) +{ + try + { + SetRound rm(mode); + if (!rm) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + + Number2 xx(x); + if (!xx) + return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED); + Number2 const res(lg(xx)); + + return res.toBytes(); + } + catch (...) + { + } + return Unexpected(HostFunctionError::FLOAT_COMPUTATION_ERROR); +} + } // namespace ripple diff --git a/src/xrpld/app/misc/WasmHostFuncImpl.h b/src/xrpld/app/misc/WasmHostFuncImpl.h index 1fdfbbb20d..e23df2c6ec 100644 --- a/src/xrpld/app/misc/WasmHostFuncImpl.h +++ b/src/xrpld/app/misc/WasmHostFuncImpl.h @@ -190,6 +190,42 @@ public: Expected traceNum(std::string_view const& msg, int64_t data) override; + + Expected + traceFloat(std::string_view const& msg, Slice const& data) override; + + Expected + floatFromInt(int64_t x, int32_t mode) override; + + Expected + floatFromUint(uint64_t x, int32_t mode) override; + + Expected + floatSet(int64_t mantissa, int32_t exponent, int32_t mode) override; + + Expected + floatCompare(Slice const& x, Slice const& y) override; + + Expected + floatAdd(Slice const& x, Slice const& y, int32_t mode) override; + + Expected + floatSubtract(Slice const& x, Slice const& y, int32_t mode) override; + + Expected + floatMultiply(Slice const& x, Slice const& y, int32_t mode) override; + + Expected + floatDivide(Slice const& x, Slice const& y, int32_t mode) override; + + Expected + floatRoot(Slice const& x, int32_t n, int32_t mode) override; + + Expected + floatPower(Slice const& x, int32_t n, int32_t mode) override; + + Expected + floatLog(Slice const& x, int32_t mode) override; }; } // namespace ripple diff --git a/src/xrpld/app/misc/WasmHostFuncWrapper.cpp b/src/xrpld/app/misc/WasmHostFuncWrapper.cpp index a3a6f858c9..d9488c3b4e 100644 --- a/src/xrpld/app/misc/WasmHostFuncWrapper.cpp +++ b/src/xrpld/app/misc/WasmHostFuncWrapper.cpp @@ -22,6 +22,7 @@ #include #include +#include #include namespace ripple { @@ -64,7 +65,7 @@ setData( template Expected -getDataInt32(IW const* _rt, wasm_val_vec_t const* params, int32_t& i) +getDataInt32(IW const* _runtime, wasm_val_vec_t const* params, int32_t& i) { auto const result = params->data[i].of.i32; i++; @@ -73,16 +74,29 @@ getDataInt32(IW const* _rt, wasm_val_vec_t const* params, int32_t& i) template Expected -getDataInt64(IW const* _rt, wasm_val_vec_t const* params, int32_t& i) +getDataInt64(IW const* _runtime, wasm_val_vec_t const* params, int32_t& i) { auto const result = params->data[i].of.i64; i++; return result; } +template +Expected +getDataUint64(IW const* runtime, wasm_val_vec_t const* params, int32_t& i) +{ + auto const r = getDataSlice(runtime, params, i); + if (!r) + return Unexpected(r.error()); + if (r->size() != sizeof(uint64_t)) + return Unexpected(HostFunctionError::INVALID_PARAMS); + + return *reinterpret_cast(r->data()); +} + template Expected -getDataSField(IW const* _rt, wasm_val_vec_t const* params, int32_t& i) +getDataSField(IW const* _runtime, wasm_val_vec_t const* params, int32_t& i) { auto const& m = SField::getKnownCodeToField(); auto const it = m.find(params->data[i].of.i32); @@ -217,7 +231,9 @@ returnResult( { return hfResult(results, res.error()); } - if constexpr (std::is_same_v, Bytes>) + + using t = std::decay_t; + if constexpr (std::is_same_v) { return hfResult( results, @@ -228,7 +244,7 @@ returnResult( res->data(), res->size())); } - else if constexpr (std::is_same_v, Hash>) + else if constexpr (std::is_same_v) { return hfResult( results, @@ -239,13 +255,11 @@ returnResult( res->data(), res->size())); } - else if constexpr (std::is_same_v, int32_t>) + else if constexpr (std::is_same_v) { return hfResult(results, res.value()); } - else if constexpr (std::is_same_v< - std::decay_t, - std::uint32_t>) + else if constexpr (std::is_same_v) { auto const resultValue = res.value(); return hfResult( @@ -1044,7 +1058,6 @@ ticketKeylet_wrap( results, hf->ticketKeylet(acc.value(), seq.value()), index); - ; } wasm_trap_t* @@ -1131,6 +1144,310 @@ traceNum_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results) runtime, params, results, hf->traceNum(*msg, *number), index); } +wasm_trap_t* +traceFloat_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results) +{ + auto* hf = reinterpret_cast(env); + auto const* runtime = reinterpret_cast(hf->getRT()); + + if (params->data[1].of.i32 > maxWasmDataLength) + return hfResult(results, HostFunctionError::DATA_FIELD_TOO_LARGE); + + int i = 0; + auto const msg = getDataString(runtime, params, i); + if (!msg) + return hfResult(results, msg.error()); + + auto const number = getDataSlice(runtime, params, i); + if (!number) + return hfResult(results, number.error()); + + return returnResult( + runtime, params, results, hf->traceFloat(*msg, *number), i); +} + +wasm_trap_t* +floatFromInt_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results) +{ + auto* hf = reinterpret_cast(env); + auto const* runtime = reinterpret_cast(hf->getRT()); + + int i = 0; + auto const x = getDataInt64(runtime, params, i); + if (!x) + return hfResult(results, x.error()); + + i = 3; + auto const rounding = getDataInt32(runtime, params, i); + if (!rounding) + return hfResult(results, rounding.error()); + + i = 1; + return returnResult( + runtime, params, results, hf->floatFromInt(*x, *rounding), i); +} + +wasm_trap_t* +floatFromUint_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results) +{ + auto* hf = reinterpret_cast(env); + auto const* runtime = reinterpret_cast(hf->getRT()); + + int i = 0; + auto const x = getDataUint64(runtime, params, i); + if (!x) + return hfResult(results, x.error()); + + i = 4; + auto const rounding = getDataInt32(runtime, params, i); + if (!rounding) + return hfResult(results, rounding.error()); + + i = 2; + return returnResult( + runtime, params, results, hf->floatFromUint(*x, *rounding), i); +} + +wasm_trap_t* +floatSet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results) +{ + auto* hf = reinterpret_cast(env); + auto const* runtime = reinterpret_cast(hf->getRT()); + + int i = 0; + auto const exp = getDataInt32(runtime, params, i); + if (!exp) + return hfResult(results, exp.error()); + + auto const mant = getDataInt64(runtime, params, i); + if (!mant) + return hfResult(results, mant.error()); + + i = 4; + auto const rounding = getDataInt32(runtime, params, i); + if (!rounding) + return hfResult(results, rounding.error()); + + i = 2; + return returnResult( + runtime, params, results, hf->floatSet(*mant, *exp, *rounding), i); +} + +wasm_trap_t* +floatCompare_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results) +{ + auto* hf = reinterpret_cast(env); + auto const* runtime = reinterpret_cast(hf->getRT()); + + int i = 0; + auto const x = getDataSlice(runtime, params, i); + if (!x) + return hfResult(results, x.error()); + + auto const y = getDataSlice(runtime, params, i); + if (!y) + return hfResult(results, y.error()); + + return returnResult(runtime, params, results, hf->floatCompare(*x, *y), i); +} + +wasm_trap_t* +floatAdd_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results) +{ + auto* hf = reinterpret_cast(env); + auto const* runtime = reinterpret_cast(hf->getRT()); + + int i = 0; + auto const x = getDataSlice(runtime, params, i); + if (!x) + return hfResult(results, x.error()); + + auto const y = getDataSlice(runtime, params, i); + if (!y) + return hfResult(results, y.error()); + + i = 6; + auto const rounding = getDataInt32(runtime, params, i); + if (!rounding) + return hfResult(results, rounding.error()); + + i = 4; + return returnResult( + runtime, params, results, hf->floatAdd(*x, *y, *rounding), i); +} + +wasm_trap_t* +floatSubtract_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results) +{ + auto* hf = reinterpret_cast(env); + auto const* runtime = reinterpret_cast(hf->getRT()); + + int i = 0; + auto const x = getDataSlice(runtime, params, i); + if (!x) + return hfResult(results, x.error()); + + auto const y = getDataSlice(runtime, params, i); + if (!y) + return hfResult(results, y.error()); + + i = 6; + auto const rounding = getDataInt32(runtime, params, i); + if (!rounding) + return hfResult(results, rounding.error()); + + i = 4; + return returnResult( + runtime, params, results, hf->floatSubtract(*x, *y, *rounding), i); +} + +wasm_trap_t* +floatMultiply_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results) +{ + auto* hf = reinterpret_cast(env); + auto const* runtime = reinterpret_cast(hf->getRT()); + + int i = 0; + auto const x = getDataSlice(runtime, params, i); + if (!x) + return hfResult(results, x.error()); + + auto const y = getDataSlice(runtime, params, i); + if (!y) + return hfResult(results, y.error()); + + i = 6; + auto const rounding = getDataInt32(runtime, params, i); + if (!rounding) + return hfResult(results, rounding.error()); + + i = 4; + return returnResult( + runtime, params, results, hf->floatMultiply(*x, *y, *rounding), i); +} + +wasm_trap_t* +floatDivide_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results) +{ + auto* hf = reinterpret_cast(env); + auto const* runtime = reinterpret_cast(hf->getRT()); + + int i = 0; + auto const x = getDataSlice(runtime, params, i); + if (!x) + return hfResult(results, x.error()); + + auto const y = getDataSlice(runtime, params, i); + if (!y) + return hfResult(results, y.error()); + + i = 6; + auto const rounding = getDataInt32(runtime, params, i); + if (!rounding) + return hfResult(results, rounding.error()); + + i = 4; + return returnResult( + runtime, params, results, hf->floatDivide(*x, *y, *rounding), i); +} + +wasm_trap_t* +floatRoot_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results) +{ + auto* hf = reinterpret_cast(env); + auto const* runtime = reinterpret_cast(hf->getRT()); + + int i = 0; + auto const x = getDataSlice(runtime, params, i); + if (!x) + return hfResult(results, x.error()); + + auto const n = getDataInt32(runtime, params, i); + if (!n) + return hfResult(results, n.error()); + + i = 5; + auto const rounding = getDataInt32(runtime, params, i); + if (!rounding) + return hfResult(results, rounding.error()); + + i = 3; + return returnResult( + runtime, params, results, hf->floatRoot(*x, *n, *rounding), i); +} + +wasm_trap_t* +floatPower_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results) +{ + auto* hf = reinterpret_cast(env); + auto const* runtime = reinterpret_cast(hf->getRT()); + + int i = 0; + auto const x = getDataSlice(runtime, params, i); + if (!x) + return hfResult(results, x.error()); + + auto const n = getDataInt32(runtime, params, i); + if (!n) + return hfResult(results, n.error()); + + i = 5; + auto const rounding = getDataInt32(runtime, params, i); + if (!rounding) + return hfResult(results, rounding.error()); + + i = 3; + return returnResult( + runtime, params, results, hf->floatPower(*x, *n, *rounding), i); +} + +wasm_trap_t* +floatLog_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results) +{ + auto* hf = reinterpret_cast(env); + auto const* runtime = reinterpret_cast(hf->getRT()); + + int i = 0; + auto const x = getDataSlice(runtime, params, i); + if (!x) + return hfResult(results, x.error()); + + i = 4; + auto const rounding = getDataInt32(runtime, params, i); + if (!rounding) + return hfResult(results, rounding.error()); + + i = 2; + return returnResult( + runtime, params, results, hf->floatLog(*x, *rounding), i); +} + +namespace test { + class MockInstanceWrapper { wmem mem_; @@ -1148,8 +1465,6 @@ public: } }; -namespace test { - // LCOV_EXCL_START bool testGetDataIncrement() diff --git a/src/xrpld/app/misc/WasmHostFuncWrapper.h b/src/xrpld/app/misc/WasmHostFuncWrapper.h index 2259771632..6bad18b368 100644 --- a/src/xrpld/app/misc/WasmHostFuncWrapper.h +++ b/src/xrpld/app/misc/WasmHostFuncWrapper.h @@ -313,4 +313,113 @@ using traceNum_proto = int32_t(uint8_t const*, int32_t, int64_t); wasm_trap_t* traceNum_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results); +using traceFloat_proto = + int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t); +wasm_trap_t* +traceFloat_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results); + +using floatFromInt_proto = int32_t(int64_t, uint8_t*, int32_t, int32_t); +wasm_trap_t* +floatFromInt_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results); + +using floatFromUint_proto = + int32_t(uint8_t const*, int32_t, uint8_t*, int32_t, int32_t); +wasm_trap_t* +floatFromUint_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results); + +using floatSet_proto = int32_t(int32_t, int64_t, uint8_t*, int32_t, int32_t); +wasm_trap_t* +floatSet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results); + +using floatCompare_proto = + int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t); +wasm_trap_t* +floatCompare_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results); + +using floatAdd_proto = int32_t( + uint8_t const*, + int32_t, + uint8_t const*, + int32_t, + uint8_t*, + int32_t, + int32_t); +wasm_trap_t* +floatAdd_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results); + +using floatSubtract_proto = int32_t( + uint8_t const*, + int32_t, + uint8_t const*, + int32_t, + uint8_t*, + int32_t, + int32_t); +wasm_trap_t* +floatSubtract_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results); + +using floatMultiply_proto = int32_t( + uint8_t const*, + int32_t, + uint8_t const*, + int32_t, + uint8_t*, + int32_t, + int32_t); +wasm_trap_t* +floatMultiply_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results); + +using floatDivide_proto = int32_t( + uint8_t const*, + int32_t, + uint8_t const*, + int32_t, + uint8_t*, + int32_t, + int32_t); +wasm_trap_t* +floatDivide_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results); + +using floatRoot_proto = + int32_t(uint8_t const*, int32_t, int32_t, uint8_t*, int32_t, int32_t); +wasm_trap_t* +floatRoot_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results); + +using floatPower_proto = + int32_t(uint8_t const*, int32_t, int32_t, uint8_t*, int32_t, int32_t); +wasm_trap_t* +floatPower_wrap( + void* env, + wasm_val_vec_t const* params, + wasm_val_vec_t* results); + +using floatLog_proto = + int32_t(uint8_t const*, int32_t, uint8_t*, int32_t, int32_t); +wasm_trap_t* +floatLog_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results); + } // namespace ripple diff --git a/src/xrpld/app/misc/WasmVM.cpp b/src/xrpld/app/misc/WasmVM.cpp index 0b94150db2..9194943737 100644 --- a/src/xrpld/app/misc/WasmVM.cpp +++ b/src/xrpld/app/misc/WasmVM.cpp @@ -77,6 +77,19 @@ createWasmImport(HostFunctions* hfs) WASM_IMPORT_FUNC2(i, getNFT, "get_nft", hfs, 1000); WASM_IMPORT_FUNC (i, trace, hfs, 500); WASM_IMPORT_FUNC2(i, traceNum, "trace_num", hfs, 500); + WASM_IMPORT_FUNC2(i, traceFloat, "trace_opaque_float", hfs, 500); + + WASM_IMPORT_FUNC2(i, floatFromInt, "float_from_int", hfs, 1000); + WASM_IMPORT_FUNC2(i, floatFromUint, "float_from_uint", hfs, 1000); + WASM_IMPORT_FUNC2(i, floatSet, "float_set", hfs, 1000); + WASM_IMPORT_FUNC2(i, floatCompare, "float_compare", hfs, 1000); + WASM_IMPORT_FUNC2(i, floatAdd, "float_add", hfs, 1000); + WASM_IMPORT_FUNC2(i, floatSubtract, "float_subtract", hfs, 1000); + WASM_IMPORT_FUNC2(i, floatMultiply, "float_multiply", hfs, 1000); + WASM_IMPORT_FUNC2(i, floatDivide, "float_divide", hfs, 1000); + WASM_IMPORT_FUNC2(i, floatRoot, "float_root", hfs, 1000); + WASM_IMPORT_FUNC2(i, floatPower, "float_pow", hfs, 1000); + WASM_IMPORT_FUNC2(i, floatLog, "float_log", hfs, 1000); // clang-format on }