smart escrow devnet 1 host functions (#5353)

* devnet 1 host functions

* clang-format

* fix build issues
This commit is contained in:
pwang200
2025-03-24 17:07:17 -04:00
committed by GitHub
parent 911c0466c0
commit 1573a443b7
11 changed files with 2625 additions and 5119 deletions

View File

@@ -2,7 +2,9 @@
#include <cstdio>
int main(int argc, char const** argv) {
int
main(int argc, char const** argv)
{
std::printf("%s\n", ripple::BuildInfo::getVersionString().c_str());
return 0;
}

View File

@@ -451,8 +451,8 @@ mulDivU(Source1 value, Dest mul, Source2 div)
}
using namespace boost::multiprecision;
uint128_t product;
using uint128 = boost::multiprecision::uint128_t;
uint128 product;
product = multiply(
product,
static_cast<std::uint64_t>(value.value()),

View File

@@ -152,11 +152,12 @@ mulRatio(
bool roundUp)
{
using namespace boost::multiprecision;
using int128 = boost::multiprecision::int128_t;
if (!den)
Throw<std::runtime_error>("division by zero");
int128_t const amt128(amt.value());
int128 const amt128(amt.value());
auto const neg = amt.value() < 0;
auto const m = amt128 * num;
auto r = m / den;

View File

@@ -286,11 +286,12 @@ mulRatio(
bool roundUp)
{
using namespace boost::multiprecision;
using int128 = boost::multiprecision::int128_t;
if (!den)
Throw<std::runtime_error>("division by zero");
int128_t const amt128(amt.drops());
int128 const amt128(amt.drops());
auto const neg = amt.drops() < 0;
auto const m = amt128 * num;
auto r = m / den;

View File

@@ -1672,22 +1672,22 @@ struct Escrow_test : public beast::unit_test::suite
// Tests whether the ledger index is >= 5
// #[no_mangle]
// pub fn ready() -> bool {
// unsafe { host_lib::get_ledger_sqn() >= 5}
// unsafe { host_lib::getLedgerSqn() >= 5}
// }
static auto wasmHex =
"0061736d010000000105016000017f021b0108686f73745f6c69620e6765745f6c"
"65646765725f73716e0000030201000405017001010105030100100619037f0141"
"8080c0000b7f00418080c0000b7f00418080c0000b072d04066d656d6f72790200"
"05726561647900010a5f5f646174615f656e6403010b5f5f686561705f62617365"
"03020a0d010b0010808080800041044a0b006e046e616d65000e0d7761736d5f6c"
"69622e7761736d01430200395f5a4e387761736d5f6c696238686f73745f6c6962"
"31346765745f6c65646765725f73716e3137686663383539386237646539633036"
"64624501057265616479071201000f5f5f737461636b5f706f696e746572005509"
"70726f64756365727302086c616e6775616765010452757374000c70726f636573"
"7365642d62790105727573746325312e38332e302d6e696768746c792028633266"
"37346333663920323032342d30392d30392900490f7461726765745f6665617475"
"726573042b0a6d756c746976616c75652b0f6d757461626c652d676c6f62616c73"
"2b0f7265666572656e63652d74797065732b087369676e2d657874";
"0061736d010000000105016000017f02190108686f73745f6c69620c6765744c65"
"6467657253716e0000030201000405017001010105030100100619037f01418080"
"c0000b7f00418080c0000b7f00418080c0000b072d04066d656d6f727902000572"
"6561647900010a5f5f646174615f656e6403010b5f5f686561705f626173650302"
"0a0d010b0010808080800041044a0b006c046e616d65000e0d7761736d5f6c6962"
"2e7761736d01410200375f5a4e387761736d5f6c696238686f73745f6c69623132"
"6765744c656467657253716e313768303033306666356636376562356638314501"
"057265616479071201000f5f5f737461636b5f706f696e74657200550970726f64"
"756365727302086c616e6775616765010452757374000c70726f6365737365642d"
"62790105727573746325312e38332e302d6e696768746c79202863326637346333"
"663920323032342d30392d30392900490f7461726765745f666561747572657304"
"2b0a6d756c746976616c75652b0f6d757461626c652d676c6f62616c732b0f7265"
"666572656e63652d74797065732b087369676e2d657874";
{
// featureSmartEscrow disabled
@@ -1827,22 +1827,22 @@ struct Escrow_test : public beast::unit_test::suite
// Tests whether the ledger index is >= 5
// #[no_mangle]
// pub fn ready() -> bool {
// unsafe { host_lib::get_ledger_sqn() >= 5}
// unsafe { host_lib::getLedgerSqn() >= 5}
// }
static auto wasmHex =
"0061736d010000000105016000017f021b0108686f73745f6c69620e6765745f6c"
"65646765725f73716e0000030201000405017001010105030100100619037f0141"
"8080c0000b7f00418080c0000b7f00418080c0000b072d04066d656d6f72790200"
"05726561647900010a5f5f646174615f656e6403010b5f5f686561705f62617365"
"03020a0d010b0010808080800041044a0b006e046e616d65000e0d7761736d5f6c"
"69622e7761736d01430200395f5a4e387761736d5f6c696238686f73745f6c6962"
"31346765745f6c65646765725f73716e3137686663383539386237646539633036"
"64624501057265616479071201000f5f5f737461636b5f706f696e746572005509"
"70726f64756365727302086c616e6775616765010452757374000c70726f636573"
"7365642d62790105727573746325312e38332e302d6e696768746c792028633266"
"37346333663920323032342d30392d30392900490f7461726765745f6665617475"
"726573042b0a6d756c746976616c75652b0f6d757461626c652d676c6f62616c73"
"2b0f7265666572656e63652d74797065732b087369676e2d657874";
"0061736d010000000105016000017f02190108686f73745f6c69620c6765744c65"
"6467657253716e0000030201000405017001010105030100100619037f01418080"
"c0000b7f00418080c0000b7f00418080c0000b072d04066d656d6f727902000572"
"6561647900010a5f5f646174615f656e6403010b5f5f686561705f626173650302"
"0a0d010b0010808080800041044a0b006c046e616d65000e0d7761736d5f6c6962"
"2e7761736d01410200375f5a4e387761736d5f6c696238686f73745f6c69623132"
"6765744c656467657253716e313768303033306666356636376562356638314501"
"057265616479071201000f5f5f737461636b5f706f696e74657200550970726f64"
"756365727302086c616e6775616765010452757374000c70726f6365737365642d"
"62790105727573746325312e38332e302d6e696768746c79202863326637346333"
"663920323032342d30392d30392900490f7461726765745f666561747572657304"
"2b0a6d756c746976616c75652b0f6d757461626c652d676c6f62616c732b0f7265"
"666572656e63652d74797065732b087369676e2d657874";
{
// basic FinishFunction situation

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,118 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include "xrpld/app/misc/WasmHostFuncImpl.h"
#include "xrpl/protocol/digest.h"
namespace ripple {
int32_t
WasmHostFunctionsImpl::getLedgerSqn()
{
return ctx.view().seq();
}
int32_t
WasmHostFunctionsImpl::getParentLedgerTime()
{
return ctx.view().parentCloseTime().time_since_epoch().count(); // TODO try
}
// TODO remove json code after deciding encoding scheme
std::optional<Bytes>
WasmHostFunctionsImpl::getTxField(const std::string& fname)
{
auto js = ctx.tx.getJson(JsonOptions::none);
if (js.isMember(fname))
{
auto s = js.get(fname, Json::Value::null).asString();
return Bytes{s.begin(), s.end()};
}
else
return std::nullopt;
}
std::optional<Bytes>
WasmHostFunctionsImpl::getLedgerEntryField(
int32_t type,
Bytes const& kdata,
const std::string& fname)
{
auto kl = [&]() -> std::optional<ripple::Keylet> {
if (type == ltACCOUNT_ROOT)
{
std::string s(kdata.begin(), kdata.end());
auto const account = parseBase58<AccountID>(s);
if (account)
{
return keylet::account(account.value());
}
}
return std::nullopt;
}();
if (!kl || !ctx.view().exists(kl.value()))
return std::nullopt;
auto js = ctx.view().read(kl.value())->getJson(JsonOptions::none);
if (js.isMember(fname))
{
auto s = js.get(fname, Json::Value::null).asString();
return Bytes{s.begin(), s.end()};
}
else
return std::nullopt;
}
std::optional<Bytes>
WasmHostFunctionsImpl::getCurrentLedgerEntryField(const std::string& fname)
{
if (!ctx.view().exists(leKey))
return std::nullopt;
auto js = ctx.view().read(leKey)->getJson(JsonOptions::none);
if (js.isMember(fname))
{
auto s = js.get(fname, Json::Value::null).asString();
return Bytes{s.begin(), s.end()};
}
else
return std::nullopt;
}
bool
WasmHostFunctionsImpl::updateData(const Bytes& data)
{
if (!ctx.view().exists(leKey))
return false;
auto sle = ctx.view().peek(leKey);
sle->setFieldVL(sfData, data);
ctx.view().update(sle);
return true;
}
Hash
WasmHostFunctionsImpl::computeSha512HalfHash(const Bytes& data)
{
auto const hash = sha512Half(data);
return uint256::fromVoid(hash.data());
}
} // namespace ripple

View File

@@ -0,0 +1,69 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_APP_MISC_WASMHOSTFUNCIMPL_H_INLCUDED
#define RIPPLE_APP_MISC_WASMHOSTFUNCIMPL_H_INLCUDED
#include <xrpl/basics/Expected.h>
#include <xrpl/protocol/TER.h>
#include "xrpl/basics/base_uint.h"
#include "xrpld/app/misc/WasmVM.h"
#include "xrpld/app/tx/detail/ApplyContext.h"
#include <wasmedge/wasmedge.h>
namespace ripple {
class WasmHostFunctionsImpl : public HostFunctions
{
public:
WasmHostFunctionsImpl(ApplyContext& ctx, Keylet leKey)
: ctx(ctx), leKey(leKey)
{
}
int32_t
getLedgerSqn() override;
int32_t
getParentLedgerTime() override;
std::optional<Bytes>
getTxField(std::string const& fname) override;
std::optional<Bytes>
getLedgerEntryField(
int32_t type,
Bytes const& kdata,
std::string const& fname) override;
std::optional<Bytes>
getCurrentLedgerEntryField(std::string const& fname) override;
bool
updateData(Bytes const& data) override;
Hash
computeSha512HalfHash(Bytes const& data) override;
private:
ApplyContext& ctx;
Keylet leKey;
};
} // namespace ripple
#endif // RIPPLE_APP_MISC_WASMHOSTFUNCIMPL_H_INLCUDED

View File

@@ -19,496 +19,275 @@
#include <xrpld/app/misc/WasmVM.h>
// WasmVM::WasmVM(beast::Journal j)
// : j_(j)
//{
// }
#include "xrpl/protocol/AccountID.h"
#include "xrpl/protocol/LedgerFormats.h"
namespace ripple {
Expected<bool, TER>
runEscrowWasm(
std::vector<uint8_t> const& wasmCode,
std::string const& funcName,
int32_t input)
WasmEdge_Result
getLedgerSqn(
void* data,
const WasmEdge_CallingFrameContext*,
const WasmEdge_Value*,
WasmEdge_Value* out)
{
WasmEdge_VMContext* VMCxt = WasmEdge_VMCreate(NULL, NULL);
WasmEdge_Value Params[1] = {WasmEdge_ValueGenI32(input)};
WasmEdge_Value Returns[1];
WasmEdge_String FuncName = WasmEdge_StringCreateByCString(funcName.c_str());
WasmEdge_Result Res = WasmEdge_VMRunWasmFromBuffer(
VMCxt,
wasmCode.data(),
wasmCode.size(),
FuncName,
Params,
1,
Returns,
1);
bool ok = WasmEdge_ResultOK(Res);
bool re = false;
if (ok)
{
auto result = WasmEdge_ValueGetI32(Returns[0]);
// printf("Get the result: %d\n", result);
if (result != 0)
re = true;
}
else
{
printf("Error message: %s\n", WasmEdge_ResultGetMessage(Res));
}
WasmEdge_VMDelete(VMCxt);
WasmEdge_StringDelete(FuncName);
if (ok)
return re;
else
return Unexpected<TER>(tecFAILED_PROCESSING);
out[0] = WasmEdge_ValueGenI32(((HostFunctions*)data)->getLedgerSqn());
return WasmEdge_Result_Success;
}
Expected<bool, TER>
runEscrowWasm(
std::vector<uint8_t> const& wasmCode,
std::string const& funcName,
std::vector<uint8_t> const& accountID)
WasmEdge_Result
getParentLedgerTime(
void* data,
const WasmEdge_CallingFrameContext*,
const WasmEdge_Value*,
WasmEdge_Value* out)
{
auto dataLen = (int32_t)accountID.size();
// printf("accountID size: %d\n", dataLen);
WasmEdge_VMContext* VMCxt = WasmEdge_VMCreate(NULL, NULL);
out[0] =
WasmEdge_ValueGenI32(((HostFunctions*)data)->getParentLedgerTime());
return WasmEdge_Result_Success;
}
WasmEdge_Value allocParams[1] = {WasmEdge_ValueGenI32(dataLen)};
WasmEdge_Value allocReturns[1];
WasmEdge_String allocFunc = WasmEdge_StringCreateByCString("allocate");
WasmEdge_Result allocRes = WasmEdge_VMRunWasmFromBuffer(
VMCxt,
wasmCode.data(),
wasmCode.size(),
allocFunc,
allocParams,
1,
allocReturns,
1);
bool ok = WasmEdge_ResultOK(allocRes);
bool re = false;
if (ok)
Expected<Bytes, WasmEdge_Result>
getParameterData(
const WasmEdge_CallingFrameContext* fm,
const WasmEdge_Value* in,
size_t index)
{
auto fnameOffset = (uint32_t)WasmEdge_ValueGetI32(in[index]);
auto fnameLen = (uint32_t)WasmEdge_ValueGetI32(in[index + 1]);
Bytes fname(fnameLen, char{0});
WasmEdge_MemoryInstanceContext* mem =
WasmEdge_CallingFrameGetMemoryInstance(fm, 0);
WasmEdge_Result Res = WasmEdge_MemoryInstanceGetData(
mem, (uint8_t*)(fname.data()), fnameOffset, fnameLen);
if (WasmEdge_ResultOK(Res))
{
auto pointer = WasmEdge_ValueGetI32(allocReturns[0]);
// printf("Alloc pointer: %d\n", pointer);
return fname;
}
else
{
return Unexpected<WasmEdge_Result>(Res);
}
}
const WasmEdge_ModuleInstanceContext* m =
WasmEdge_VMGetActiveModule(VMCxt);
WasmEdge_String mName = WasmEdge_StringCreateByCString("memory");
WasmEdge_MemoryInstanceContext* mi =
WasmEdge_ModuleInstanceFindMemory(m, mName);
WasmEdge_Result setRes = WasmEdge_MemoryInstanceSetData(
mi, accountID.data(), pointer, dataLen);
Expected<std::string, WasmEdge_Result>
getFieldName(
const WasmEdge_CallingFrameContext* fm,
const WasmEdge_Value* in,
size_t index)
{
auto dataRes = getParameterData(fm, in, index);
if (dataRes)
{
return std::string(dataRes.value().begin(), dataRes->end());
}
else
{
return Unexpected<WasmEdge_Result>(dataRes.error());
}
}
ok = WasmEdge_ResultOK(setRes);
if (ok)
Expected<WasmEdge_Value, WasmEdge_Result>
setData(const WasmEdge_CallingFrameContext* fm, Bytes const& data)
{
auto alloc = [fm](int32_t dataLen) -> int32_t {
WasmEdge_String allocFunc = WasmEdge_StringCreateByCString("allocate");
auto mod = WasmEdge_CallingFrameGetModuleInstance(fm);
WasmEdge_FunctionInstanceContext* func =
WasmEdge_ModuleInstanceFindFunction(mod, allocFunc);
WasmEdge_Value allocParams[1] = {
WasmEdge_ValueGenI32(dataLen)}; // 4 for prepend the data size
WasmEdge_Value allocReturns[1];
auto executor = WasmEdge_CallingFrameGetExecutor(fm);
auto res = WasmEdge_ExecutorInvoke(
executor, func, allocParams, 1, allocReturns, 1);
if (WasmEdge_ResultOK(res))
{
// printf("Set data ok\n");
WasmEdge_Value params[2] = {
WasmEdge_ValueGenI32(pointer), WasmEdge_ValueGenI32(dataLen)};
WasmEdge_Value returns[1];
WasmEdge_String func =
WasmEdge_StringCreateByCString(funcName.c_str());
WasmEdge_Result funcRes =
WasmEdge_VMExecute(VMCxt, func, params, 2, returns, 1);
ok = WasmEdge_ResultOK(funcRes);
if (ok)
{
// printf("func ok\n");
re = (WasmEdge_ValueGetI32(returns[0]) == 1);
}
else
{
printf(
"Func message: %s\n", WasmEdge_ResultGetMessage(funcRes));
}
return WasmEdge_ValueGetI32(allocReturns[0]);
}
else
{
printf(
"Set error message: %s\n", WasmEdge_ResultGetMessage(setRes));
return 0;
}
}
else
{
printf(
"Alloc error message: %s\n", WasmEdge_ResultGetMessage(allocRes));
}
WasmEdge_VMDelete(VMCxt);
// TODO free everything
// WasmEdge_StringDelete(FuncName);
if (ok)
{
// printf("runEscrowWasm ok, result %d\n", re);
return re;
}
else
return Unexpected<TER>(tecFAILED_PROCESSING);
}
Expected<bool, TER>
runEscrowWasm(
std::vector<uint8_t> const& wasmCode,
std::string const& funcName,
std::vector<uint8_t> const& escrow_tx_json_data,
std::vector<uint8_t> const& escrow_lo_json_data)
{
WasmEdge_VMContext* VMCxt = WasmEdge_VMCreate(NULL, NULL);
WasmEdge_Result loadRes =
WasmEdge_VMLoadWasmFromBuffer(VMCxt, wasmCode.data(), wasmCode.size());
if (!WasmEdge_ResultOK(loadRes))
{
printf("load error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
WasmEdge_Result validateRes = WasmEdge_VMValidate(VMCxt);
if (!WasmEdge_ResultOK(validateRes))
{
printf("validate error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
WasmEdge_Result instantiateRes = WasmEdge_VMInstantiate(VMCxt);
if (!WasmEdge_ResultOK(instantiateRes))
{
printf("instantiate error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
auto wasmAlloc = [VMCxt](std::vector<uint8_t> const& data) -> int32_t {
auto dataLen = (int32_t)data.size();
WasmEdge_Value allocParams[1] = {WasmEdge_ValueGenI32(dataLen)};
WasmEdge_Value allocReturns[1];
WasmEdge_String allocFunc = WasmEdge_StringCreateByCString("allocate");
WasmEdge_Result allocRes = WasmEdge_VMExecute(
VMCxt, allocFunc, allocParams, 1, allocReturns, 1);
if (WasmEdge_ResultOK(allocRes))
{
auto pointer = WasmEdge_ValueGetI32(allocReturns[0]);
// printf("alloc ptr %d, len %d\n", pointer, dataLen);
const WasmEdge_ModuleInstanceContext* m =
WasmEdge_VMGetActiveModule(VMCxt);
WasmEdge_String mName = WasmEdge_StringCreateByCString("memory");
WasmEdge_MemoryInstanceContext* mi =
WasmEdge_ModuleInstanceFindMemory(m, mName);
WasmEdge_Result setRes = WasmEdge_MemoryInstanceSetData(
mi, data.data(), pointer, dataLen);
if (WasmEdge_ResultOK(setRes))
{
return pointer;
}
}
return 0;
};
auto tx_ptr = wasmAlloc(escrow_tx_json_data);
auto lo_ptr = wasmAlloc(escrow_lo_json_data);
if (tx_ptr == 0 || lo_ptr == 0)
auto dataLen = (int32_t)data.size();
auto dataPtr = alloc(dataLen);
auto retPtr = alloc(8);
if (dataPtr && retPtr)
{
printf("data error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
auto txLen = (int32_t)escrow_tx_json_data.size();
auto loLen = (int32_t)escrow_lo_json_data.size();
WasmEdge_Value params[4] = {
WasmEdge_ValueGenI32(tx_ptr),
WasmEdge_ValueGenI32(txLen),
WasmEdge_ValueGenI32(lo_ptr),
WasmEdge_ValueGenI32(loLen)};
WasmEdge_Value returns[1];
WasmEdge_String func = WasmEdge_StringCreateByCString(funcName.c_str());
WasmEdge_Result funcRes =
WasmEdge_VMExecute(VMCxt, func, params, 4, returns, 1);
if (WasmEdge_ResultOK(funcRes))
{
// printf("func ok\n");
return WasmEdge_ValueGetI32(returns[0]) == 1;
}
else
{
printf("Func message: %s\n", WasmEdge_ResultGetMessage(funcRes));
return Unexpected<TER>(tecFAILED_PROCESSING);
}
}
Expected<std::pair<bool, std::string>, TER>
runEscrowWasmP4(
std::vector<uint8_t> const& wasmCode,
std::string const& funcName,
std::vector<uint8_t> const& escrow_tx_json_data,
std::vector<uint8_t> const& escrow_lo_json_data)
{
WasmEdge_VMContext* VMCxt = WasmEdge_VMCreate(NULL, NULL);
WasmEdge_Result loadRes =
WasmEdge_VMLoadWasmFromBuffer(VMCxt, wasmCode.data(), wasmCode.size());
if (!WasmEdge_ResultOK(loadRes))
{
printf("load error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
WasmEdge_Result validateRes = WasmEdge_VMValidate(VMCxt);
if (!WasmEdge_ResultOK(validateRes))
{
printf("validate error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
WasmEdge_Result instantiateRes = WasmEdge_VMInstantiate(VMCxt);
if (!WasmEdge_ResultOK(instantiateRes))
{
printf("instantiate error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
auto wasmAlloc = [VMCxt](std::vector<uint8_t> const& data) -> int32_t {
auto dataLen = (int32_t)data.size();
WasmEdge_Value allocParams[1] = {WasmEdge_ValueGenI32(dataLen)};
WasmEdge_Value allocReturns[1];
WasmEdge_String allocFunc = WasmEdge_StringCreateByCString("allocate");
WasmEdge_Result allocRes = WasmEdge_VMExecute(
VMCxt, allocFunc, allocParams, 1, allocReturns, 1);
if (WasmEdge_ResultOK(allocRes))
auto mem = WasmEdge_CallingFrameGetMemoryInstance(fm, 0);
auto res =
WasmEdge_MemoryInstanceSetData(mem, data.data(), dataPtr, dataLen);
if (WasmEdge_ResultOK(res))
{
auto pointer = WasmEdge_ValueGetI32(allocReturns[0]);
// printf("alloc ptr %d, len %d\n", pointer, dataLen);
const WasmEdge_ModuleInstanceContext* m =
WasmEdge_VMGetActiveModule(VMCxt);
WasmEdge_String mName = WasmEdge_StringCreateByCString("memory");
WasmEdge_MemoryInstanceContext* mi =
WasmEdge_ModuleInstanceFindMemory(m, mName);
WasmEdge_Result setRes = WasmEdge_MemoryInstanceSetData(
mi, data.data(), pointer, dataLen);
if (WasmEdge_ResultOK(setRes))
unsigned char intBuf[8]; // little-endian
for (size_t i = 0; i < 4; ++i)
{
return pointer;
intBuf[i] = (dataPtr >> (i * 8)) & 0xFF;
}
for (size_t i = 0; i < 4; ++i)
{
intBuf[i + 4] = (dataLen >> (i * 8)) & 0xFF;
}
res = WasmEdge_MemoryInstanceSetData(mem, intBuf, retPtr, 8);
if (WasmEdge_ResultOK(res))
{
return WasmEdge_ValueGenI32(retPtr);
}
}
return 0;
};
auto tx_ptr = wasmAlloc(escrow_tx_json_data);
auto lo_ptr = wasmAlloc(escrow_lo_json_data);
if (tx_ptr == 0 || lo_ptr == 0)
{
printf("data error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
auto txLen = (int32_t)escrow_tx_json_data.size();
auto loLen = (int32_t)escrow_lo_json_data.size();
WasmEdge_Value params[4] = {
WasmEdge_ValueGenI32(tx_ptr),
WasmEdge_ValueGenI32(txLen),
WasmEdge_ValueGenI32(lo_ptr),
WasmEdge_ValueGenI32(loLen)};
WasmEdge_Value returns[1];
WasmEdge_String func = WasmEdge_StringCreateByCString(funcName.c_str());
WasmEdge_Result funcRes =
WasmEdge_VMExecute(VMCxt, func, params, 4, returns, 1);
if (WasmEdge_ResultOK(funcRes))
{
auto pointer = WasmEdge_ValueGetI32(returns[0]);
const WasmEdge_ModuleInstanceContext* m =
WasmEdge_VMGetActiveModule(VMCxt);
WasmEdge_String mName = WasmEdge_StringCreateByCString("memory");
WasmEdge_MemoryInstanceContext* mi =
WasmEdge_ModuleInstanceFindMemory(m, mName);
uint8_t buff[9];
WasmEdge_Result getRes =
WasmEdge_MemoryInstanceGetData(mi, buff, pointer, 9);
if (!WasmEdge_ResultOK(getRes))
{
printf(
"re mem get message: %s\n", WasmEdge_ResultGetMessage(getRes));
return Unexpected<TER>(tecFAILED_PROCESSING);
}
auto flag = buff[0];
auto leToInt32 = [](const uint8_t* d) -> uint32_t {
uint32_t r = 0;
for (int i = 0; i < 4; ++i)
{
r |= static_cast<uint32_t>(d[i]) << (i * 8);
// printf("leToInt32 %d\n", r);
}
return r;
};
auto ret_pointer =
leToInt32(reinterpret_cast<const uint8_t*>(&buff[1]));
auto ret_len = leToInt32(reinterpret_cast<const uint8_t*>(&buff[5]));
// printf("re flag %d, ptr %d, len %d\n", flag, ret_pointer,
// ret_len);
std::vector<uint8_t> buff2(ret_len);
getRes = WasmEdge_MemoryInstanceGetData(
mi, buff2.data(), ret_pointer, ret_len);
if (!WasmEdge_ResultOK(getRes))
{
printf(
"re 2 mem get message: %s\n",
WasmEdge_ResultGetMessage(getRes));
return Unexpected<TER>(tecFAILED_PROCESSING);
}
std::string newData(buff2.begin(), buff2.end());
// free
WasmEdge_String freeFunc = WasmEdge_StringCreateByCString("deallocate");
WasmEdge_Value freeParams[2] = {
WasmEdge_ValueGenI32(ret_pointer), WasmEdge_ValueGenI32(ret_len)};
WasmEdge_Value freeReturns[0];
WasmEdge_VMExecute(VMCxt, freeFunc, freeParams, 2, freeReturns, 0);
// free pointer too, with len = 9 too
freeParams[0] = WasmEdge_ValueGenI32(pointer);
freeParams[1] = WasmEdge_ValueGenI32(9);
WasmEdge_VMExecute(VMCxt, freeFunc, freeParams, 2, freeReturns, 0);
return std::pair<bool, std::string>(flag == 1, newData);
}
else
{
printf("Func message: %s\n", WasmEdge_ResultGetMessage(funcRes));
return Unexpected<TER>(tecFAILED_PROCESSING);
}
return Unexpected<WasmEdge_Result>(WasmEdge_Result_Fail);
}
WasmEdge_Result
get_ledger_sqn(
getTxField(
void* data,
const WasmEdge_CallingFrameContext*,
const WasmEdge_Value* In,
WasmEdge_Value* Out)
const WasmEdge_CallingFrameContext* fm,
const WasmEdge_Value* in,
WasmEdge_Value* out)
{
Out[0] =
WasmEdge_ValueGenI32(((LedgerDataProvider*)data)->get_ledger_sqn());
auto fname = getFieldName(fm, in, 0);
if (!fname)
return fname.error();
auto fieldData = ((HostFunctions*)data)->getTxField(fname.value());
if (!fieldData)
return WasmEdge_Result_Fail;
auto pointer = setData(fm, fieldData.value());
if (!pointer)
return pointer.error();
out[0] = pointer.value();
// out[1] = WasmEdge_ValueGenI32((int)fieldData.value().size());
return WasmEdge_Result_Success;
}
Expected<bool, TER>
runEscrowWasm(
std::vector<uint8_t> const& wasmCode,
std::string const& funcName,
LedgerDataProvider* ledgerDataProvider)
{
WasmEdge_VMContext* VMCxt = WasmEdge_VMCreate(NULL, NULL);
{ // register host function
WasmEdge_ValType ReturnList[1] = {WasmEdge_ValTypeGenI32()};
WasmEdge_FunctionTypeContext* HostFType =
WasmEdge_FunctionTypeCreate(NULL, 0, ReturnList, 1);
WasmEdge_FunctionInstanceContext* HostFunc =
WasmEdge_FunctionInstanceCreate(
HostFType, get_ledger_sqn, ledgerDataProvider, 0);
WasmEdge_FunctionTypeDelete(HostFType);
WasmEdge_String HostName = WasmEdge_StringCreateByCString("host_lib");
WasmEdge_ModuleInstanceContext* HostMod =
WasmEdge_ModuleInstanceCreate(HostName);
WasmEdge_StringDelete(HostName);
WasmEdge_String HostFuncName =
WasmEdge_StringCreateByCString("get_ledger_sqn");
WasmEdge_ModuleInstanceAddFunction(HostMod, HostFuncName, HostFunc);
WasmEdge_StringDelete(HostFuncName);
WasmEdge_Result regRe =
WasmEdge_VMRegisterModuleFromImport(VMCxt, HostMod);
if (!WasmEdge_ResultOK(regRe))
{
printf("host func reg error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
}
WasmEdge_Result loadRes =
WasmEdge_VMLoadWasmFromBuffer(VMCxt, wasmCode.data(), wasmCode.size());
if (!WasmEdge_ResultOK(loadRes))
{
printf("load error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
WasmEdge_Result validateRes = WasmEdge_VMValidate(VMCxt);
if (!WasmEdge_ResultOK(validateRes))
{
printf("validate error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
WasmEdge_Result instantiateRes = WasmEdge_VMInstantiate(VMCxt);
if (!WasmEdge_ResultOK(instantiateRes))
{
printf("instantiate error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
WasmEdge_Value funcReturns[1];
WasmEdge_String func = WasmEdge_StringCreateByCString(funcName.c_str());
WasmEdge_Result funcRes =
WasmEdge_VMExecute(VMCxt, func, NULL, 0, funcReturns, 1);
bool ok = WasmEdge_ResultOK(funcRes);
bool re = false;
if (ok)
{
auto result = WasmEdge_ValueGetI32(funcReturns[0]);
if (result != 0)
re = true;
}
else
{
printf("Error message: %s\n", WasmEdge_ResultGetMessage(funcRes));
}
WasmEdge_VMDelete(VMCxt);
WasmEdge_StringDelete(func);
if (ok)
return re;
else
return Unexpected<TER>(tecFAILED_PROCESSING);
}
WasmEdge_Result
constInt(
getLedgerEntryField(
void* data,
const WasmEdge_CallingFrameContext*,
const WasmEdge_Value* In,
WasmEdge_Value* Out)
const WasmEdge_CallingFrameContext* fm,
const WasmEdge_Value* in,
WasmEdge_Value* out)
{
Out[0] = WasmEdge_ValueGenI32(5);
auto type = WasmEdge_ValueGetI32(in[0]);
auto lkData = getParameterData(fm, in, 1);
if (!lkData)
return lkData.error();
auto fname = getFieldName(fm, in, 3);
if (!fname)
return fname.error();
auto fieldData =
((HostFunctions*)data)
->getLedgerEntryField(type, lkData.value(), fname.value());
if (!fieldData)
return WasmEdge_Result_Fail;
auto pointer = setData(fm, fieldData.value());
if (!pointer)
return pointer.error();
out[0] = pointer.value();
// out[1] = WasmEdge_ValueGenI32((int)fieldData.value().size());
return WasmEdge_Result_Success;
}
Expected<EscrowResultP6, TER>
WasmEdge_Result
getCurrentLedgerEntryField(
void* data,
const WasmEdge_CallingFrameContext* fm,
const WasmEdge_Value* in,
WasmEdge_Value* out)
{
auto fname = getFieldName(fm, in, 0);
if (!fname)
return fname.error();
auto fieldData =
((HostFunctions*)data)->getCurrentLedgerEntryField(fname.value());
if (!fieldData)
return WasmEdge_Result_Fail;
auto pointer = setData(fm, fieldData.value());
if (!pointer)
return pointer.error();
out[0] = pointer.value();
// out[1] = WasmEdge_ValueGenI32((int)fieldData.value().size());
return WasmEdge_Result_Success;
}
WasmEdge_Result
updateData(
void* data,
const WasmEdge_CallingFrameContext* fm,
const WasmEdge_Value* in,
WasmEdge_Value* out)
{
auto fname = getParameterData(fm, in, 0);
if (!fname)
return fname.error();
if (((HostFunctions*)data)->updateData(fname.value()))
return WasmEdge_Result_Success;
else
return WasmEdge_Result_Fail;
}
WasmEdge_Result
computeSha512HalfHash(
void* data,
const WasmEdge_CallingFrameContext* fm,
const WasmEdge_Value* in,
WasmEdge_Value* out)
{
auto fname = getParameterData(fm, in, 0);
if (!fname)
return fname.error();
auto hres = ((HostFunctions*)data)->computeSha512HalfHash(fname.value());
Bytes digest{hres.begin(), hres.end()};
auto pointer = setData(fm, digest);
if (!pointer)
return pointer.error();
out[0] = pointer.value();
// out[1] = WasmEdge_ValueGenI32(32);
return WasmEdge_Result_Success;
}
WasmEdge_Result
print(
void* data,
const WasmEdge_CallingFrameContext* fm,
const WasmEdge_Value* in,
WasmEdge_Value* out)
{
auto f = getParameterData(fm, in, 0);
if (!f)
return f.error();
std::string s(f.value().begin(), f.value().end());
std::cout << s << std::endl;
return WasmEdge_Result_Success;
}
Expected<EscrowResult, TER>
runEscrowWasm(
std::vector<uint8_t> const& wasmCode,
std::string const& funcName,
int32_t gasLimit,
int32_t input)
HostFunctions* hfs,
uint64_t gasLimit)
{
// WasmEdge_LogOff();
// TODO deletes
// create VM and set cost limit
WasmEdge_ConfigureContext* conf = WasmEdge_ConfigureCreate();
WasmEdge_ConfigureStatisticsSetInstructionCounting(conf, true);
WasmEdge_ConfigureStatisticsSetCostMeasuring(conf, true);
WasmEdge_ConfigureSetMaxMemoryPage(conf, MAX_PAGES);
WasmEdge_VMContext* VMCxt = WasmEdge_VMCreate(conf, NULL);
WasmEdge_StatisticsContext* StatCxt =
@@ -516,36 +295,168 @@ runEscrowWasm(
WasmEdge_StatisticsSetCostLimit(StatCxt, gasLimit);
{ // register host function
WasmEdge_ValType ReturnList[1] = {WasmEdge_ValTypeGenI32()};
WasmEdge_FunctionTypeContext* HostFType =
WasmEdge_FunctionTypeCreate(NULL, 0, ReturnList, 1);
WasmEdge_FunctionInstanceContext* HostFunc =
WasmEdge_FunctionInstanceCreate(HostFType, constInt, nullptr, 100);
WasmEdge_FunctionTypeDelete(HostFType);
// module
WasmEdge_String libName = WasmEdge_StringCreateByCString("host_lib");
WasmEdge_ModuleInstanceContext* hostMod =
WasmEdge_ModuleInstanceCreate(libName);
WasmEdge_StringDelete(libName);
WasmEdge_String HostName = WasmEdge_StringCreateByCString("host_lib");
WasmEdge_ModuleInstanceContext* HostMod =
WasmEdge_ModuleInstanceCreate(HostName);
WasmEdge_StringDelete(HostName);
// getLedgerSqn
{
WasmEdge_ValType returnList[1] = {WasmEdge_ValTypeGenI32()};
WasmEdge_FunctionTypeContext* hostFuncType =
WasmEdge_FunctionTypeCreate(NULL, 0, returnList, 1);
WasmEdge_FunctionInstanceContext* hostFunc =
WasmEdge_FunctionInstanceCreate(
hostFuncType, getLedgerSqn, hfs, 100);
// WasmEdge_FunctionTypeDelete(hostFuncType);
WasmEdge_String HostFuncName =
WasmEdge_StringCreateByCString("constInt");
WasmEdge_ModuleInstanceAddFunction(HostMod, HostFuncName, HostFunc);
WasmEdge_StringDelete(HostFuncName);
WasmEdge_String fName =
WasmEdge_StringCreateByCString("getLedgerSqn");
WasmEdge_ModuleInstanceAddFunction(hostMod, fName, hostFunc);
// WasmEdge_StringDelete(fName);
// WasmEdge_FunctionInstanceDelete(hostFunc);
}
// getParentLedgerTime
{
WasmEdge_ValType returnList[1] = {WasmEdge_ValTypeGenI32()};
WasmEdge_FunctionTypeContext* hostFuncType =
WasmEdge_FunctionTypeCreate(NULL, 0, returnList, 1);
WasmEdge_FunctionInstanceContext* hostFunc =
WasmEdge_FunctionInstanceCreate(
hostFuncType, getParentLedgerTime, hfs, 100);
// WasmEdge_FunctionTypeDelete(hostFuncType);
WasmEdge_String fName =
WasmEdge_StringCreateByCString("getParentLedgerTime");
WasmEdge_ModuleInstanceAddFunction(hostMod, fName, hostFunc);
// WasmEdge_StringDelete(fName);
// WasmEdge_FunctionInstanceDelete(hostFunc);
}
// getTxField
{
WasmEdge_ValType inputList[2] = {
WasmEdge_ValTypeGenI32(), WasmEdge_ValTypeGenI32()};
WasmEdge_ValType returnList[1] = {WasmEdge_ValTypeGenI32()};
WasmEdge_FunctionTypeContext* hostFuncType =
WasmEdge_FunctionTypeCreate(inputList, 2, returnList, 1);
WasmEdge_FunctionInstanceContext* hostFunc =
WasmEdge_FunctionInstanceCreate(
hostFuncType, getTxField, hfs, 100);
// WasmEdge_FunctionTypeDelete(hostFuncType);
// WasmEdge_FunctionInstanceDelete(hostFunc);
WasmEdge_String fName =
WasmEdge_StringCreateByCString("getTxField");
WasmEdge_ModuleInstanceAddFunction(hostMod, fName, hostFunc);
// WasmEdge_StringDelete(fName);
}
// getLedgerEntryField
{
WasmEdge_ValType inputList[5] = {
WasmEdge_ValTypeGenI32(),
WasmEdge_ValTypeGenI32(),
WasmEdge_ValTypeGenI32(),
WasmEdge_ValTypeGenI32(),
WasmEdge_ValTypeGenI32()};
WasmEdge_ValType returnList[1] = {WasmEdge_ValTypeGenI32()};
WasmEdge_FunctionTypeContext* hostFuncType =
WasmEdge_FunctionTypeCreate(inputList, 5, returnList, 1);
WasmEdge_FunctionInstanceContext* hostFunc =
WasmEdge_FunctionInstanceCreate(
hostFuncType, getLedgerEntryField, hfs, 100);
// WasmEdge_FunctionTypeDelete(hostFuncType);
// WasmEdge_FunctionInstanceDelete(hostFunc);
WasmEdge_String fName =
WasmEdge_StringCreateByCString("getLedgerEntryField");
WasmEdge_ModuleInstanceAddFunction(hostMod, fName, hostFunc);
// WasmEdge_StringDelete(fName);
}
// getCurrentLedgerEntryField
{
WasmEdge_ValType inputList[2] = {
WasmEdge_ValTypeGenI32(), WasmEdge_ValTypeGenI32()};
WasmEdge_ValType returnList[1] = {WasmEdge_ValTypeGenI32()};
WasmEdge_FunctionTypeContext* hostFuncType =
WasmEdge_FunctionTypeCreate(inputList, 2, returnList, 1);
WasmEdge_FunctionInstanceContext* hostFunc =
WasmEdge_FunctionInstanceCreate(
hostFuncType, getCurrentLedgerEntryField, hfs, 100);
// WasmEdge_FunctionTypeDelete(hostFuncType);
// WasmEdge_FunctionInstanceDelete(hostFunc);
WasmEdge_String fName =
WasmEdge_StringCreateByCString("getCurrentLedgerEntryField");
WasmEdge_ModuleInstanceAddFunction(hostMod, fName, hostFunc);
// WasmEdge_StringDelete(fName);
}
// updateData
{
WasmEdge_ValType inputList[2] = {
WasmEdge_ValTypeGenI32(), WasmEdge_ValTypeGenI32()};
WasmEdge_FunctionTypeContext* hostFuncType =
WasmEdge_FunctionTypeCreate(inputList, 2, NULL, 0);
WasmEdge_FunctionInstanceContext* hostFunc =
WasmEdge_FunctionInstanceCreate(
hostFuncType, updateData, hfs, 100);
// WasmEdge_FunctionTypeDelete(hostFuncType);
// WasmEdge_FunctionInstanceDelete(hostFunc);
WasmEdge_String fName =
WasmEdge_StringCreateByCString("updateData");
WasmEdge_ModuleInstanceAddFunction(hostMod, fName, hostFunc);
// WasmEdge_StringDelete(fName);
}
// computeSha512HalfHash
{
WasmEdge_ValType inputList[2] = {
WasmEdge_ValTypeGenI32(), WasmEdge_ValTypeGenI32()};
WasmEdge_ValType returnList[1] = {WasmEdge_ValTypeGenI32()};
WasmEdge_FunctionTypeContext* hostFuncType =
WasmEdge_FunctionTypeCreate(inputList, 2, returnList, 1);
WasmEdge_FunctionInstanceContext* hostFunc =
WasmEdge_FunctionInstanceCreate(
hostFuncType, computeSha512HalfHash, hfs, 100);
// WasmEdge_FunctionTypeDelete(hostFuncType);
// WasmEdge_FunctionInstanceDelete(hostFunc);
WasmEdge_String fName =
WasmEdge_StringCreateByCString("computeSha512HalfHash");
WasmEdge_ModuleInstanceAddFunction(hostMod, fName, hostFunc);
// WasmEdge_StringDelete(fName);
}
// print
{
WasmEdge_ValType inputList[2] = {
WasmEdge_ValTypeGenI32(), WasmEdge_ValTypeGenI32()};
WasmEdge_FunctionTypeContext* hostFuncType =
WasmEdge_FunctionTypeCreate(inputList, 2, NULL, 0);
WasmEdge_FunctionInstanceContext* hostFunc =
WasmEdge_FunctionInstanceCreate(hostFuncType, print, hfs, 100);
// WasmEdge_FunctionTypeDelete(hostFuncType);
// WasmEdge_FunctionInstanceDelete(hostFunc);
WasmEdge_String fName = WasmEdge_StringCreateByCString("print");
WasmEdge_ModuleInstanceAddFunction(hostMod, fName, hostFunc);
// WasmEdge_StringDelete(fName);
}
WasmEdge_Result regRe =
WasmEdge_VMRegisterModuleFromImport(VMCxt, HostMod);
WasmEdge_VMRegisterModuleFromImport(VMCxt, hostMod);
if (!WasmEdge_ResultOK(regRe))
{
printf("host func reg error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
}
WasmEdge_Result loadRes =
WasmEdge_VMLoadWasmFromBuffer(VMCxt, wasmCode.data(), wasmCode.size());
if (!WasmEdge_ResultOK(loadRes))
{
printf("load error\n");
printf("load error, %p, %d\n", wasmCode.data(), wasmCode.size());
return Unexpected<TER>(tecFAILED_PROCESSING);
}
WasmEdge_Result validateRes = WasmEdge_VMValidate(VMCxt);
@@ -560,20 +471,23 @@ runEscrowWasm(
printf("instantiate error\n");
return Unexpected<TER>(tecFAILED_PROCESSING);
}
WasmEdge_Value funcReturns[1];
WasmEdge_String func = WasmEdge_StringCreateByCString(funcName.c_str());
WasmEdge_Value Params[1] = {WasmEdge_ValueGenI32(input)};
WasmEdge_Result funcRes =
WasmEdge_VMExecute(VMCxt, func, Params, 1, NULL, 0);
WasmEdge_VMExecute(VMCxt, func, NULL, 0, funcReturns, 1);
bool ok = WasmEdge_ResultOK(funcRes);
EscrowResultP6 re;
EscrowResult re;
if (ok)
{
auto sc = WasmEdge_VMGetStatisticsContext(VMCxt);
re.cost = WasmEdge_StatisticsGetTotalCost(sc);
// WasmEdge_StatisticsGetTotalCost, WasmEdge_StatisticsGetInstrCount
re.result = true;
auto result = WasmEdge_ValueGetI32(funcReturns[0]);
if (result != 0)
re.result = true;
else
re.result = false;
}
else
{
@@ -588,5 +502,4 @@ runEscrowWasm(
else
return Unexpected<TER>(tecFAILED_PROCESSING);
}
} // namespace ripple

View File

@@ -20,78 +20,81 @@
#define RIPPLE_APP_MISC_WASMVM_H_INLCUDED
#include <xrpl/basics/Expected.h>
// #include <xrpl/beast/utility/Journal.h>
#include <xrpl/protocol/TER.h>
#include "xrpl/basics/base_uint.h"
#include <wasmedge/wasmedge.h>
namespace ripple {
const uint32_t MAX_PAGES = 128; // 8MB = 64KB*128
Expected<bool, TER>
runEscrowWasm(
std::vector<uint8_t> const& wasmCode,
std::string const& funcName,
int32_t input);
typedef std::vector<uint8_t> Bytes;
typedef ripple::uint256 Hash;
Expected<bool, TER>
runEscrowWasm(
std::vector<uint8_t> const& wasmCode,
std::string const& funcName,
std::vector<uint8_t> const& accountID);
template <typename T>
struct WasmResult
{
T result;
uint64_t cost;
};
typedef WasmResult<bool> EscrowResult;
Expected<bool, TER>
runEscrowWasm(
std::vector<uint8_t> const& wasmCode,
std::string const& funcName,
std::vector<uint8_t> const& escrow_tx_json_data,
std::vector<uint8_t> const& escrow_lo_json_data);
Expected<std::pair<bool, std::string>, TER>
runEscrowWasmP4(
std::vector<uint8_t> const& wasmCode,
std::string const& funcName,
std::vector<uint8_t> const& escrow_tx_json_data,
std::vector<uint8_t> const& escrow_lo_json_data);
struct LedgerDataProvider
struct HostFunctions
{
virtual int32_t
get_ledger_sqn()
getLedgerSqn()
{
return 1;
}
virtual ~LedgerDataProvider() = default;
virtual int32_t
getParentLedgerTime()
{
return 1;
}
virtual std::optional<Bytes>
getTxField(std::string const& fname)
{
return Bytes{};
}
virtual std::optional<Bytes>
getLedgerEntryField(
int32_t type,
Bytes const& kdata,
std::string const& fname)
{
return Bytes{};
}
virtual std::optional<Bytes>
getCurrentLedgerEntryField(std::string const& fname)
{
return Bytes{};
}
virtual bool
updateData(Bytes const& data)
{
return true;
}
virtual Hash
computeSha512HalfHash(Bytes const& data)
{
return Hash{};
}
virtual ~HostFunctions() = default;
};
Expected<bool, TER>
Expected<EscrowResult, TER>
runEscrowWasm(
std::vector<uint8_t> const& wasmCode,
std::string const& funcName,
LedgerDataProvider* ledgerDataProvider);
struct EscrowResultP6
{
bool result;
int32_t cost;
};
Expected<EscrowResultP6, TER>
runEscrowWasm(
std::vector<uint8_t> const& wasmCode,
std::string const& funcName,
int32_t gasLimit,
int32_t input);
HostFunctions* hfs,
uint64_t gasLimit);
} // namespace ripple
#endif // RIPPLE_APP_MISC_WASMVM_H_INLCUDED
// class WasmVM final
//{
// public:
// explicit WasmVM(beast::Journal j);
// ~WasmVM() = default;
//
// private:
// beast::Journal j_;
// };

View File

@@ -19,6 +19,7 @@
#include <xrpld/app/misc/CredentialHelpers.h>
#include <xrpld/app/misc/HashRouter.h>
#include <xrpld/app/misc/WasmHostFuncImpl.h>
#include <xrpld/app/misc/WasmVM.h>
#include <xrpld/app/tx/detail/Escrow.h>
#include <xrpld/conditions/Condition.h>
@@ -434,22 +435,6 @@ EscrowFinish::preclaim(PreclaimContext const& ctx)
return tesSUCCESS;
}
struct EscrowLedgerDataProvider : public LedgerDataProvider
{
ApplyView& view_;
public:
EscrowLedgerDataProvider(ApplyView& view) : view_(view)
{
}
int32_t
get_ledger_sqn() override
{
return (int32_t)view_.seq();
}
};
TER
EscrowFinish::doApply()
{
@@ -601,14 +586,15 @@ EscrowFinish::doApply()
std::vector<uint8_t> escrowTxData(escrowTx.begin(), escrowTx.end());
std::vector<uint8_t> escrowObjData(escrowObj.begin(), escrowObj.end());
EscrowLedgerDataProvider ledgerDataProvider(ctx_.view());
WasmHostFunctionsImpl ledgerDataProvider(ctx_, k);
auto re = runEscrowWasm(wasm, funcName, &ledgerDataProvider);
auto re = runEscrowWasm(wasm, funcName, &ledgerDataProvider, 100000);
JLOG(j_.trace()) << "Escrow WASM ran";
if (re.has_value())
{
auto reValue = re.value();
JLOG(j_.debug()) << "WASM Success: " + std::to_string(reValue);
auto reValue = re.value().result;
JLOG(j_.debug()) << "WASM Success: " + std::to_string(reValue)
<< ", cost: " << re.value().cost;
if (!reValue)
{
// ctx_.view().update(slep);