From 72b9918168666ab3533227471ba2891ae8df23ae Mon Sep 17 00:00:00 2001 From: TimothyBanks Date: Tue, 14 Jul 2026 15:51:31 -0400 Subject: [PATCH] feat: smart-escrow/versioning --- src/libxrpl/tx/wasm/WasmiVM.cpp | 24 ++++++++++++------- src/test/app/Wasm_test.cpp | 22 +++++++++++++++++ .../app/wasm_fixtures/wat/custom_version.wat | 13 ++++++++++ 3 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 src/test/app/wasm_fixtures/wat/custom_version.wat diff --git a/src/libxrpl/tx/wasm/WasmiVM.cpp b/src/libxrpl/tx/wasm/WasmiVM.cpp index 8608ec0c24..3a325a74e6 100644 --- a/src/libxrpl/tx/wasm/WasmiVM.cpp +++ b/src/libxrpl/tx/wasm/WasmiVM.cpp @@ -848,13 +848,13 @@ filterCustomSections(Bytes const& wasmCode, Filter&& filter) auto customSection = CustomSection{}; auto size = readLEB128(wasmCode, offset); - customSection.name = std::string_view{ - std::begin(wasmCode) + offset, std::begin(wasmCode) + offset + size}; - offset += nameSize; + customSection.name = + std::string_view{reinterpret_cast(wasmCode.data()) + offset, size}; + offset += size; size = nextSection - offset; customSection.payload = std::span{ - std::begin(wasmCode) + offset, std::begin(wasmCode) + offset + size}; + reinterpret_cast(wasmCode.data()) + offset, size}; if (filter(customSection)) { @@ -875,15 +875,18 @@ extractVersionInfo(Bytes const& wasmCode) filterCustomSections(wasmCode, [&](auto const& section) { if (section.name == kCommonLib || section.name == kEscrowLib) { - versions.emplace_back(Version { - .name = section.name, - .version = std::string_view{section.payload.data(), section.payload.size()}; - }); + versions.emplace_back( + Version{ + .name = section.name, + .version = std::string_view{ + reinterpret_cast(section.payload.data()), + section.payload.size()}}); } // Just read until we have found all the information we are looking for. return versions.size() == 2; }); + return versions; } } // namespace @@ -909,6 +912,11 @@ WasmiEngine::runHlp( auto versionInfo = extractVersionInfo(wasmCode); + for (auto const& version : versionInfo) + { + std::cout << version.name << " " << version.version << "\n"; + } + // Create and instantiate the module. [[maybe_unused]] int const m = addModule(wasmCode, true, imports, gas); diff --git a/src/test/app/Wasm_test.cpp b/src/test/app/Wasm_test.cpp index 537b8b2330..998d121697 100644 --- a/src/test/app/Wasm_test.cpp +++ b/src/test/app/Wasm_test.cpp @@ -227,6 +227,26 @@ struct Wasm_test : public beast::unit_test::Suite checkResult(re, 6'912, 59); } + void + testVersion() + { + testcase("wasm lib test"); + static auto const kWasmModule = hexToBytes( + "0061736d010000000105016000017f03020100040401700000070a010666696e69736800000a0601040041" + "010b0018127872706c2d657363726f772d7374646c6962342e352e360018127872706c2d636f6d6d6f6e2d" + "7374646c6962312e322e33"); + + auto& vm = WasmEngine::instance(); + + HostFunctions hfs; + ImportVec imports; + WasmImpFunc(imports, "func-add", reinterpret_cast(&add), &hfs); + + auto re = vm.run(kWasmModule, hfs, 10'000'000, "finish", wasmParams(1234), imports); + + checkResult(re, 1, 59); + } + void testBadWasm() { @@ -1549,6 +1569,8 @@ struct Wasm_test : public beast::unit_test::Suite { using namespace test::jtx; + testVersion(); + testGetDataHelperFunctions(); testWasmLib(); testBadWasm(); diff --git a/src/test/app/wasm_fixtures/wat/custom_version.wat b/src/test/app/wasm_fixtures/wat/custom_version.wat new file mode 100644 index 0000000000..899a0b7958 --- /dev/null +++ b/src/test/app/wasm_fixtures/wat/custom_version.wat @@ -0,0 +1,13 @@ +(module + ;; Define a table with exactly 0 entries + (table 0 funcref) + + ;; Standard finish function + (func $finish (result i32) + i32.const 1 + ) + (export "finish" (func $finish)) + + (@custom "xrpl-escrow-stdlib" "4.5.6") + (@custom "xrpl-common-stdlib" "1.2.3") +)