clean up WASM functions a bit (#5628)

This commit is contained in:
Mayukha Vadari
2025-08-05 18:06:34 -04:00
committed by GitHub
parent 58741d2791
commit 38c7a27010
4 changed files with 114 additions and 88 deletions

View File

@@ -141,14 +141,19 @@ struct Wasm_test : public beast::unit_test::suite
Env env{*this};
TestLedgerDataProvider hf(&env);
std::string const funcName("finish");
std::vector<WasmImportFunc> imports;
WASM_IMPORT_FUNC2(imports, getLedgerSqn, "get_ledger_sqn", &hf, 33);
auto& engine = WasmEngine::instance();
auto re = engine.run(
wasm, funcName, {}, imports, &hf, 1'000'000, env.journal);
wasm,
ESCROW_FUNCTION_NAME,
{},
imports,
&hf,
1'000'000,
env.journal);
// code takes 11 gas + 1 getLedgerSqn call
if (BEAST_EXPECT(re.has_value()))
@@ -160,7 +165,8 @@ struct Wasm_test : public beast::unit_test::suite
env.close();
// empty module - run the same instance
re = engine.run({}, funcName, {}, imports, &hf, 1'000'000, env.journal);
re = engine.run(
{}, ESCROW_FUNCTION_NAME, {}, imports, &hf, 1'000'000, env.journal);
// code takes 22 gas + 2 getLedgerSqn calls
if (BEAST_EXPECT(re.has_value()))
@@ -327,10 +333,9 @@ struct Wasm_test : public beast::unit_test::suite
"6d756c746976616c7565";
auto wasmStr = boost::algorithm::unhex(std::string(badWasmHex));
std::vector<uint8_t> wasm(wasmStr.begin(), wasmStr.end());
std::string funcName("finish");
auto const re =
preflightEscrowWasm(wasm, funcName, {}, &hfs, env.journal);
auto const re = preflightEscrowWasm(
wasm, ESCROW_FUNCTION_NAME, {}, &hfs, env.journal);
BEAST_EXPECT(!isTesSuccess(re));
}
}
@@ -348,8 +353,8 @@ struct Wasm_test : public beast::unit_test::suite
Env env{*this};
{
TestHostFunctions nfs(env, 0);
std::string funcName("finish");
auto re = runEscrowWasm(wasm, funcName, {}, &nfs, 100'000);
auto re =
runEscrowWasm(wasm, ESCROW_FUNCTION_NAME, {}, &nfs, 100'000);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECT(re->result && (re->cost == 41'132));
@@ -369,8 +374,8 @@ struct Wasm_test : public beast::unit_test::suite
}
};
BadTestHostFunctions nfs(env);
std::string funcName("finish");
auto re = runEscrowWasm(wasm, funcName, {}, &nfs, 100000);
auto re =
runEscrowWasm(wasm, ESCROW_FUNCTION_NAME, {}, &nfs, 100000);
BEAST_EXPECT(re.has_value() && !re->result && (re->cost == 5831));
// std::cout << "bad case (access nonexistent field) result "
// << re.error() << std::endl;
@@ -389,8 +394,8 @@ struct Wasm_test : public beast::unit_test::suite
}
};
BadTestHostFunctions nfs(env);
std::string funcName("finish");
auto re = runEscrowWasm(wasm, funcName, {}, &nfs, 100'000);
auto re =
runEscrowWasm(wasm, ESCROW_FUNCTION_NAME, {}, &nfs, 100'000);
BEAST_EXPECT(re.has_value() && !re->result && (re->cost == 5831));
// std::cout << "bad case (more than MAX_PAGES) result "
// << re.error() << std::endl;
@@ -431,7 +436,6 @@ struct Wasm_test : public beast::unit_test::suite
{
auto wasmStr = boost::algorithm::unhex(ledgerSqnHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
std::string const funcName("finish");
TestLedgerDataProvider ledgerDataProvider(&env);
std::vector<WasmImportFunc> imports;
@@ -441,7 +445,13 @@ struct Wasm_test : public beast::unit_test::suite
auto& engine = WasmEngine::instance();
auto re = engine.run(
wasm, funcName, {}, imports, nullptr, 1'000'000, env.journal);
wasm,
ESCROW_FUNCTION_NAME,
{},
imports,
nullptr,
1'000'000,
env.journal);
// expected import not provided
BEAST_EXPECT(!re);
@@ -453,8 +463,6 @@ struct Wasm_test : public beast::unit_test::suite
{
testcase("wasm test host functions cost");
std::string const funcName("finish");
using namespace test::jtx;
Env env(*this);
@@ -471,7 +479,13 @@ struct Wasm_test : public beast::unit_test::suite
i.gas = 0;
auto re = engine.run(
wasm, funcName, {}, imp, &hfs, 1'000'000, env.journal);
wasm,
ESCROW_FUNCTION_NAME,
{},
imp,
&hfs,
1'000'000,
env.journal);
if (BEAST_EXPECT(re.has_value()))
{
@@ -498,7 +512,13 @@ struct Wasm_test : public beast::unit_test::suite
std::vector<WasmImportFunc> const imp = createWasmImport(&hfs);
auto re = engine.run(
wasm, funcName, {}, imp, &hfs, 1'000'000, env.journal);
wasm,
ESCROW_FUNCTION_NAME,
{},
imp,
&hfs,
1'000'000,
env.journal);
if (BEAST_EXPECT(re.has_value()))
{
@@ -542,7 +562,6 @@ struct Wasm_test : public beast::unit_test::suite
using namespace jtx;
using namespace std::chrono;
std::string const funcName("finish");
// std::string const funcName("test");
auto const& wasmHex = hfPerfTest;
// auto const& wasmHex = opcCallPerfTest;
@@ -614,7 +633,7 @@ struct Wasm_test : public beast::unit_test::suite
PerfHostFunctions nfs(env, k, env.tx());
auto re = runEscrowWasm(wasm, funcName, {}, &nfs);
auto re = runEscrowWasm(wasm, ESCROW_FUNCTION_NAME, {}, &nfs);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECT(re->result);

View File

@@ -34,6 +34,71 @@
namespace ripple {
static void
setCommonHostFunctions(HostFunctions* hfs, std::vector<WasmImportFunc>& i)
{
// clang-format off
WASM_IMPORT_FUNC2(i, getLedgerSqn, "get_ledger_sqn", hfs, 60);
WASM_IMPORT_FUNC2(i, getParentLedgerTime, "get_parent_ledger_time", hfs, 60);
WASM_IMPORT_FUNC2(i, getParentLedgerHash, "get_parent_ledger_hash", hfs, 60);
WASM_IMPORT_FUNC2(i, getLedgerAccountHash, "get_ledger_account_hash", hfs, 60);
WASM_IMPORT_FUNC2(i, getLedgerTransactionHash, "get_ledger_tx_hash", hfs, 60);
WASM_IMPORT_FUNC2(i, getBaseFee, "get_base_fee", hfs, 60);
WASM_IMPORT_FUNC2(i, isAmendmentEnabled, "amendment_enabled", hfs, 60);
WASM_IMPORT_FUNC2(i, cacheLedgerObj, "cache_ledger_obj", hfs, 5000);
WASM_IMPORT_FUNC2(i, getTxField, "get_tx_field", hfs, 70);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjField, "get_current_ledger_obj_field", hfs, 70);
WASM_IMPORT_FUNC2(i, getLedgerObjField, "get_ledger_obj_field", hfs, 70);
WASM_IMPORT_FUNC2(i, getTxNestedField, "get_tx_nested_field", hfs, 110);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjNestedField, "get_current_ledger_obj_nested_field", hfs, 110);
WASM_IMPORT_FUNC2(i, getLedgerObjNestedField, "get_ledger_obj_nested_field", hfs, 110);
WASM_IMPORT_FUNC2(i, getTxArrayLen, "get_tx_array_len", hfs, 40);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjArrayLen, "get_current_ledger_obj_array_len", hfs, 40);
WASM_IMPORT_FUNC2(i, getLedgerObjArrayLen, "get_ledger_obj_array_len", hfs, 40);
WASM_IMPORT_FUNC2(i, getTxNestedArrayLen, "get_tx_nested_array_len", hfs, 70);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjNestedArrayLen, "get_current_ledger_obj_nested_array_len", hfs, 70);
WASM_IMPORT_FUNC2(i, getLedgerObjNestedArrayLen, "get_ledger_obj_nested_array_len", hfs, 70);
WASM_IMPORT_FUNC2(i, updateData, "update_data", hfs, 1000);
WASM_IMPORT_FUNC2(i, checkSignature, "check_sig", hfs, 2000);
WASM_IMPORT_FUNC2(i, computeSha512HalfHash, "compute_sha512_half", hfs, 2000);
WASM_IMPORT_FUNC2(i, accountKeylet, "account_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, checkKeylet, "check_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, credentialKeylet, "credential_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, delegateKeylet, "delegate_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, depositPreauthKeylet, "deposit_preauth_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, didKeylet, "did_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, escrowKeylet, "escrow_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, lineKeylet, "line_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, nftOfferKeylet, "nft_offer_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, offerKeylet, "offer_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, oracleKeylet, "oracle_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, paychanKeylet, "paychan_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, signersKeylet, "signers_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, ticketKeylet, "ticket_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, getNFT, "get_nft", hfs, 1000);
WASM_IMPORT_FUNC2(i, getNFTIssuer, "get_nft_issuer", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTTaxon, "get_nft_taxon", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTFlags, "get_nft_flags", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTTransferFee, "get_nft_transfer_fee", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTSerial, "get_nft_serial", hfs, 60);
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
}
std::vector<WasmImportFunc>
createWasmImport(HostFunctions* hfs)
{
@@ -41,68 +106,8 @@ createWasmImport(HostFunctions* hfs)
if (hfs)
{
// clang-format off
WASM_IMPORT_FUNC2(i, getLedgerSqn, "get_ledger_sqn", hfs, 60);
WASM_IMPORT_FUNC2(i, getParentLedgerTime, "get_parent_ledger_time", hfs, 60);
WASM_IMPORT_FUNC2(i, getParentLedgerHash, "get_parent_ledger_hash", hfs, 60);
WASM_IMPORT_FUNC2(i, getLedgerAccountHash, "get_ledger_account_hash", hfs, 60);
WASM_IMPORT_FUNC2(i, getLedgerTransactionHash, "get_ledger_tx_hash", hfs, 60);
WASM_IMPORT_FUNC2(i, getBaseFee, "get_base_fee", hfs, 60);
WASM_IMPORT_FUNC2(i, isAmendmentEnabled, "amendment_enabled", hfs, 60);
WASM_IMPORT_FUNC2(i, cacheLedgerObj, "cache_ledger_obj", hfs, 5000);
WASM_IMPORT_FUNC2(i, getTxField, "get_tx_field", hfs, 70);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjField, "get_current_ledger_obj_field", hfs, 70);
WASM_IMPORT_FUNC2(i, getLedgerObjField, "get_ledger_obj_field", hfs, 70);
WASM_IMPORT_FUNC2(i, getTxNestedField, "get_tx_nested_field", hfs, 110);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjNestedField, "get_current_ledger_obj_nested_field", hfs, 110);
WASM_IMPORT_FUNC2(i, getLedgerObjNestedField, "get_ledger_obj_nested_field", hfs, 110);
WASM_IMPORT_FUNC2(i, getTxArrayLen, "get_tx_array_len", hfs, 40);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjArrayLen, "get_current_ledger_obj_array_len", hfs, 40);
WASM_IMPORT_FUNC2(i, getLedgerObjArrayLen, "get_ledger_obj_array_len", hfs, 40);
WASM_IMPORT_FUNC2(i, getTxNestedArrayLen, "get_tx_nested_array_len", hfs, 70);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjNestedArrayLen, "get_current_ledger_obj_nested_array_len", hfs, 70);
WASM_IMPORT_FUNC2(i, getLedgerObjNestedArrayLen, "get_ledger_obj_nested_array_len", hfs, 70);
WASM_IMPORT_FUNC2(i, updateData, "update_data", hfs, 1000);
WASM_IMPORT_FUNC2(i, checkSignature, "check_sig", hfs, 2000);
WASM_IMPORT_FUNC2(i, computeSha512HalfHash, "compute_sha512_half", hfs, 2000);
WASM_IMPORT_FUNC2(i, accountKeylet, "account_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, checkKeylet, "check_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, credentialKeylet, "credential_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, delegateKeylet, "delegate_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, depositPreauthKeylet, "deposit_preauth_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, didKeylet, "did_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, escrowKeylet, "escrow_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, lineKeylet, "line_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, nftOfferKeylet, "nft_offer_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, offerKeylet, "offer_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, oracleKeylet, "oracle_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, paychanKeylet, "paychan_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, signersKeylet, "signers_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, ticketKeylet, "ticket_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, getNFT, "get_nft", hfs, 1000);
WASM_IMPORT_FUNC2(i, getNFTIssuer, "get_nft_issuer", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTTaxon, "get_nft_taxon", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTFlags, "get_nft_flags", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTTransferFee, "get_nft_transfer_fee", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTSerial, "get_nft_serial", hfs, 60);
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
setCommonHostFunctions(hfs, i);
WASM_IMPORT_FUNC2(i, updateData, "update_data", hfs, 1000);
}
return i;

View File

@@ -34,6 +34,8 @@ static std::string_view const W_ALLOC = "allocate";
static std::string_view const W_DEALLOC = "deallocate";
static std::string_view const W_PROC_EXIT = "proc_exit";
static std::string_view const ESCROW_FUNCTION_NAME = "finish";
uint32_t const MAX_PAGES = 128; // 8MB = 64KB*128
class WamrEngine;
@@ -92,7 +94,7 @@ createWasmImport(HostFunctions* hfs);
Expected<EscrowResult, TER>
runEscrowWasm(
Bytes const& wasmCode,
std::string_view funcName,
std::string_view funcName = ESCROW_FUNCTION_NAME,
std::vector<WasmParam> const& params = {},
HostFunctions* hfs = nullptr,
int64_t gasLimit = -1,
@@ -101,7 +103,7 @@ runEscrowWasm(
NotTEC
preflightEscrowWasm(
Bytes const& wasmCode,
std::string_view funcName,
std::string_view funcName = ESCROW_FUNCTION_NAME,
std::vector<WasmParam> const& params = {},
HostFunctions* hfs = nullptr,
beast::Journal j = beast::Journal(beast::Journal::getNullSink()));

View File

@@ -232,7 +232,8 @@ EscrowCreate::preflight(PreflightContext const& ctx)
}
HostFunctions mock;
auto const re = preflightEscrowWasm(code, "finish", {}, &mock, ctx.j);
auto const re =
preflightEscrowWasm(code, ESCROW_FUNCTION_NAME, {}, &mock, ctx.j);
if (!isTesSuccess(re))
{
JLOG(ctx.j.debug()) << "EscrowCreate.FinishFunction bad WASM";
@@ -1266,7 +1267,6 @@ EscrowFinish::doApply()
// WASM execution
auto const wasmStr = slep->getFieldVL(sfFinishFunction);
std::vector<uint8_t> wasm(wasmStr.begin(), wasmStr.end());
std::string funcName("finish");
WasmHostFunctionsImpl ledgerDataProvider(ctx_, k);
@@ -1276,8 +1276,8 @@ EscrowFinish::doApply()
return tecINTERNAL;
}
std::uint32_t allowance = ctx_.tx[sfComputationAllowance];
auto re =
runEscrowWasm(wasm, funcName, {}, &ledgerDataProvider, allowance);
auto re = runEscrowWasm(
wasm, ESCROW_FUNCTION_NAME, {}, &ledgerDataProvider, allowance);
JLOG(j_.trace()) << "Escrow WASM ran";
if (re.has_value())
{