mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-18 18:15:50 +00:00
smart escrow devnet 1 host functions (#5353)
* devnet 1 host functions * clang-format * fix build issues
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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()),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
118
src/xrpld/app/misc/WasmHostFuncImpl.cpp
Normal file
118
src/xrpld/app/misc/WasmHostFuncImpl.cpp
Normal 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
|
||||
69
src/xrpld/app/misc/WasmHostFuncImpl.h
Normal file
69
src/xrpld/app/misc/WasmHostFuncImpl.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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_;
|
||||
// };
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user