Compare commits

..

1 Commits

Author SHA1 Message Date
Mayukha Vadari
62d9f40d33 Mark SmartEscrow as Supported::yes 2026-05-27 14:17:39 -04:00
5 changed files with 6 additions and 199 deletions

View File

@@ -168,19 +168,7 @@ def main():
if not os.environ.get("TIDY"):
return 0
# Derive the repo root from git so this keeps working regardless of where
# under the tree this script lives. Fall back to the script location
# (bin/pre-commit/ is two levels below the repo root) if git is unavailable.
result = subprocess.run(
["git", "rev-parse", "--show-toplevel"],
capture_output=True,
text=True,
cwd=Path(__file__).parent,
)
if result.returncode == 0:
repo_root = Path(result.stdout.strip())
else:
repo_root = Path(__file__).parent.parent.parent
repo_root = Path(__file__).parent.parent
files = staged_files(repo_root)
if not files:
return 0

View File

@@ -15,7 +15,7 @@
// Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order.
XRPL_FEATURE(SmartEscrow, Supported::No, VoteBehavior::DefaultNo)
XRPL_FEATURE(SmartEscrow, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (Cleanup3_2_0, Supported::No, VoteBehavior::DefaultNo)
XRPL_FEATURE(MPTokensV2, Supported::No, VoteBehavior::DefaultNo)
XRPL_FIX (Cleanup3_1_3, Supported::Yes, VoteBehavior::DefaultYes)

View File

@@ -21,7 +21,6 @@
#include <limits>
#include <memory>
#include <mutex>
#include <span>
#include <stdexcept>
#include <string>
#include <string_view>
@@ -278,7 +277,7 @@ InstanceWrapper::setGas(std::int64_t gas) const
ModulePtr
ModuleWrapper::init(StorePtr& s, Bytes const& wasmBin, beast::Journal j)
{
wasm_byte_vec_t const code{.size = wasmBin.size(), .data = (char*)(wasmBin.data())};
wasm_byte_vec_t const code{wasmBin.size(), (char*)(wasmBin.data())};
ModulePtr m = ModulePtr(wasm_module_new(s.get(), &code), &wasm_module_delete);
if (!m)
throw std::runtime_error("can't create module");
@@ -712,8 +711,8 @@ WasmiResult
WasmiEngine::call(FuncInfo const& f, std::vector<wasm_val_t>& in)
{
WasmiResult ret(NR);
wasm_val_vec_t const inv = in.empty() ? wasm_val_vec_t WASM_EMPTY_VEC
: wasm_val_vec_t{.size = in.size(), .data = in.data()};
wasm_val_vec_t const inv =
in.empty() ? wasm_val_vec_t WASM_EMPTY_VEC : wasm_val_vec_t{in.size(), in.data()};
#ifdef SHOW_CALL_TIME
auto const start = usecs();
@@ -800,134 +799,6 @@ WasmiEngine::run(
return Unexpected<TER>(tecFAILED_PROCESSING);
}
namespace {
struct CustomSection
{
std::string_view name;
std::span<char const> payload;
};
struct Version
{
std::string_view name;
std::string_view version;
Version(std::string_view theName, std::string_view theVersion)
: name{theName}, version{theVersion}
{
}
};
uint32_t
readLEB128(Bytes const& wasmCode, size_t& offset)
{
auto result = uint32_t{};
auto shift = uint32_t{};
while (offset < wasmCode.size())
{
auto byte = wasmCode[offset++];
result |= static_cast<uint32_t>(byte & (shift < 28 ? 0x7Fu : 0x0Fu)) << shift;
if ((byte & 0x80) == 0)
{
break;
}
shift += 7;
if (shift >= 32)
{
// Drain the rest of the bytes for this leb.
while (offset < wasmCode.size())
{
if ((wasmCode[offset++] & 0x80) == 0)
{
break;
}
}
break;
}
}
return result;
}
template <typename Filter>
void
filterCustomSections(Bytes const& wasmCode, Filter&& filter)
{
auto offset = size_t{8}; // Skip Magic number and Version
if (wasmCode.size() <= offset)
{
// There is nothing to parse.
return;
}
while (offset < wasmCode.size())
{
auto sectionId = wasmCode[offset++];
auto sectionSize = readLEB128(wasmCode, offset);
auto nextSection = offset + sectionSize;
if (nextSection > wasmCode.size())
{
break;
}
if (sectionId == 0)
{
// Wasm custom section marker.
auto customSection = CustomSection{};
auto size = readLEB128(wasmCode, offset);
if (offset + size > wasmCode.size() || offset + size > nextSection)
{
return;
}
customSection.name =
std::string_view{reinterpret_cast<char const*>(wasmCode.data()) + offset, size};
offset += size;
if (offset >= nextSection)
{
offset = nextSection;
continue;
}
size = nextSection - offset;
customSection.payload = std::span<char const>{
reinterpret_cast<char const*>(wasmCode.data()) + offset, size};
if (filter(customSection))
{
return;
}
}
offset = nextSection;
}
}
std::vector<Version>
extractVersionInfo(Bytes const& wasmCode)
{
static constexpr auto kCommonLib = "xrpl-common-stdlib-version";
static constexpr auto kEscrowLib = "xrpl-escrow-stdlib-version";
auto versions = std::vector<Version>{};
filterCustomSections(wasmCode, [&](auto const& section) {
if (section.name == kCommonLib || section.name == kEscrowLib)
{
versions.emplace_back(
section.name, std::string_view{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
Expected<WasmResult<int32_t>, TER>
WasmiEngine::runHlp(
Bytes const& wasmCode,
@@ -947,11 +818,6 @@ WasmiEngine::runHlp(
if (!hfs.checkSelf())
throw std::runtime_error("hfs isn't clean");
for (auto const& version : extractVersionInfo(wasmCode))
{
j_.debug() << "Module version: " << version.name << " " << version.version;
}
// Create and instantiate the module.
[[maybe_unused]] int const m = addModule(wasmCode, true, imports, gas);
@@ -1094,7 +960,7 @@ wasm_trap_t*
WasmiEngine::newTrap(std::string const& txt)
{
static char empty[1] = {0};
wasm_message_t msg = {.size = 1, .data = empty};
wasm_message_t msg = {1, empty};
if (!txt.empty())
wasm_name_new(&msg, txt.size() + 1, txt.c_str()); // include 0

View File

@@ -1,10 +1,8 @@
#include <test/app/wasm_fixtures/fixtures.h>
#include <test/jtx/Env.h>
#include <test/unit_test/SuiteJournal.h>
#include <xrpl/basics/Expected.h>
#include <xrpl/beast/unit_test/suite.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/tx/wasm/HostFunc.h>
@@ -229,36 +227,6 @@ struct Wasm_test : public beast::unit_test::Suite
checkResult(re, 6'912, 59);
}
void
testVersion()
{
testcase("wasm module test");
// wat2wasm --enable-annotations mymodule.wat -o mymodule.wasm
// xxd -p mymodule.wasm | tr -d '\n'
static auto const kWasmModule = hexToBytes(
"0061736d010000000105016000017f03020100040401700000070a010666696e69736800000a0601040041"
"010b00201a7872706c2d657363726f772d7374646c69622d76657273696f6e342e352e3600201a7872706c"
"2d636f6d6d6f6e2d7374646c69622d76657273696f6e312e322e33");
StreamSink sink{beast::Severity::Debug};
beast::Journal const journal{sink};
auto& vm = WasmEngine::instance();
auto hfs = HostFunctions{};
auto imports = ImportVec{};
WasmImpFunc<Add_proto>(imports, "func-add", reinterpret_cast<void*>(&add), &hfs);
[[maybe_unused]] auto result =
vm.run(kWasmModule, hfs, 10'000'000, "finish", wasmParams(), imports, journal);
auto const logged = sink.messages().str();
BEAST_EXPECT(
logged.find("Module version: xrpl-escrow-stdlib-version 4.5.6") != std::string::npos);
BEAST_EXPECT(
logged.find("Module version: xrpl-common-stdlib-version 1.2.3") != std::string::npos);
}
void
testBadWasm()
{
@@ -1581,8 +1549,6 @@ struct Wasm_test : public beast::unit_test::Suite
{
using namespace test::jtx;
testVersion();
testGetDataHelperFunctions();
testWasmLib();
testBadWasm();

View File

@@ -1,13 +0,0 @@
(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-version" "4.5.6")
(@custom "xrpl-common-stdlib-version" "1.2.3")
)