mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
Latests HF perf test (#5789)
This commit is contained in:
@@ -1356,8 +1356,7 @@ struct HostFuncImpl_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(result.has_value() && result.value() == 0);
|
||||
|
||||
// Should fail for too large data
|
||||
std::vector<uint8_t> bigData(
|
||||
1024 * 1024 + 1, 0x42); // > maxWasmDataLength
|
||||
std::vector<uint8_t> bigData(maxWasmDataLength + 1, 0x42);
|
||||
auto const tooBig =
|
||||
hfs.updateData(Slice(bigData.data(), bigData.size()));
|
||||
if (BEAST_EXPECT(!tooBig.has_value()))
|
||||
@@ -2102,6 +2101,7 @@ struct HostFuncImpl_test : public beast::unit_test::suite
|
||||
Bytes const float2 = {0xD4, 0x87, 0x1A, 0xFD, 0x49, 0x8D, 0x00, 0x00}; // 2
|
||||
Bytes const float10 = {0xD4, 0xC3, 0x8D, 0x7E, 0xA4, 0xC6, 0x80, 0x00}; // 10
|
||||
Bytes const floatInvalidZero = {0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // INVALID
|
||||
Bytes const floatPi = {0xD4, 0x8B, 0x29, 0x43, 0x0A, 0x25, 0x6D, 0x21}; // 3.141592653589793
|
||||
|
||||
std::string const invalid = "invalid_data";
|
||||
|
||||
@@ -2744,8 +2744,14 @@ struct HostFuncImpl_test : public beast::unit_test::suite
|
||||
}
|
||||
|
||||
{
|
||||
auto const result =
|
||||
hfs.floatPower(makeSlice(floatMaxIOU), 40000, 0);
|
||||
auto const result = hfs.floatPower(makeSlice(floatMaxIOU), 81, 0);
|
||||
BEAST_EXPECT(!result) &&
|
||||
BEAST_EXPECT(
|
||||
result.error() == HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
}
|
||||
|
||||
{
|
||||
auto const result = hfs.floatPower(makeSlice(floatMaxIOU), 2, 0);
|
||||
BEAST_EXPECT(!result) &&
|
||||
BEAST_EXPECT(
|
||||
result.error() ==
|
||||
@@ -2809,6 +2815,46 @@ struct HostFuncImpl_test : public beast::unit_test::suite
|
||||
result.error() == HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
}
|
||||
|
||||
// perf test logs
|
||||
// {
|
||||
// auto const result = hfs.floatLog(makeSlice(floatPi), 0);
|
||||
// if (BEAST_EXPECT(result))
|
||||
// {
|
||||
// std::cout << "lg(" << floatToString(makeSlice(floatPi))
|
||||
// << ") = " << floatToString(makeSlice(*result))
|
||||
// << std::endl;
|
||||
// }
|
||||
// }
|
||||
// {
|
||||
// auto const result = hfs.floatLog(makeSlice(floatIntMax), 0);
|
||||
// if (BEAST_EXPECT(result))
|
||||
// {
|
||||
// std::cout << "lg(" << floatToString(makeSlice(floatIntMax))
|
||||
// << ") = " << floatToString(makeSlice(*result))
|
||||
// << std::endl;
|
||||
// }
|
||||
// }
|
||||
|
||||
// {
|
||||
// auto const result = hfs.floatLog(makeSlice(floatMaxExp), 0);
|
||||
// if (BEAST_EXPECT(result))
|
||||
// {
|
||||
// std::cout << "lg(" << floatToString(makeSlice(floatMaxExp))
|
||||
// << ") = " << floatToString(makeSlice(*result))
|
||||
// << std::endl;
|
||||
// }
|
||||
// }
|
||||
|
||||
// {
|
||||
// auto const result = hfs.floatLog(makeSlice(floatMaxIOU), 0);
|
||||
// if (BEAST_EXPECT(result))
|
||||
// {
|
||||
// std::cout << "lg(" << floatToString(makeSlice(floatMaxIOU))
|
||||
// << ") = " << floatToString(makeSlice(*result))
|
||||
// << std::endl;
|
||||
// }
|
||||
// }
|
||||
|
||||
{
|
||||
auto const x =
|
||||
hfs.floatSet(9'500'000'000'000'001, -14, 0); // almost 80+15
|
||||
|
||||
@@ -605,13 +605,17 @@ public:
|
||||
struct PerfHostFunctions : public TestHostFunctions
|
||||
{
|
||||
Keylet leKey;
|
||||
std::shared_ptr<SLE const> currentLedgerObj = nullptr;
|
||||
bool isLedgerObjCached = false;
|
||||
|
||||
static int constexpr MAX_CACHE = 256;
|
||||
std::array<std::shared_ptr<SLE const>, MAX_CACHE> cache;
|
||||
// std::optional<Bytes> data_; // deferred data update, not used in
|
||||
// performance
|
||||
std::shared_ptr<STTx const> tx_;
|
||||
|
||||
void const* rt_ = nullptr;
|
||||
|
||||
public:
|
||||
PerfHostFunctions(
|
||||
test::jtx::Env& env,
|
||||
Keylet const& k,
|
||||
@@ -620,9 +624,113 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
Expected<std::int32_t, HostFunctionError>
|
||||
getLedgerSqn() override
|
||||
{
|
||||
auto seq = env_.current()->seq();
|
||||
if (seq > std::numeric_limits<int32_t>::max())
|
||||
return Unexpected(HostFunctionError::INTERNAL); // LCOV_EXCL_LINE
|
||||
return static_cast<int32_t>(seq);
|
||||
}
|
||||
|
||||
Expected<std::int32_t, HostFunctionError>
|
||||
getParentLedgerTime() override
|
||||
{
|
||||
auto time =
|
||||
env_.current()->parentCloseTime().time_since_epoch().count();
|
||||
if (time > std::numeric_limits<int32_t>::max())
|
||||
return Unexpected(HostFunctionError::INTERNAL);
|
||||
return static_cast<int32_t>(time);
|
||||
}
|
||||
|
||||
Expected<Hash, HostFunctionError>
|
||||
getParentLedgerHash() override
|
||||
{
|
||||
return env_.current()->info().parentHash;
|
||||
}
|
||||
|
||||
Expected<Hash, HostFunctionError>
|
||||
getLedgerAccountHash() override
|
||||
{
|
||||
return env_.current()->info().accountHash;
|
||||
}
|
||||
|
||||
Expected<Hash, HostFunctionError>
|
||||
getLedgerTransactionHash() override
|
||||
{
|
||||
return env_.current()->info().txHash;
|
||||
}
|
||||
|
||||
Expected<int32_t, HostFunctionError>
|
||||
getBaseFee() override
|
||||
{
|
||||
auto fee = env_.current()->fees().base.drops();
|
||||
if (fee > std::numeric_limits<int32_t>::max())
|
||||
return Unexpected(HostFunctionError::INTERNAL);
|
||||
return static_cast<int32_t>(fee);
|
||||
}
|
||||
|
||||
Expected<int32_t, HostFunctionError>
|
||||
isAmendmentEnabled(uint256 const& amendmentId) override
|
||||
{
|
||||
return env_.current()->rules().enabled(amendmentId);
|
||||
}
|
||||
|
||||
Expected<int32_t, HostFunctionError>
|
||||
isAmendmentEnabled(std::string_view const& amendmentName) override
|
||||
{
|
||||
auto const& table = env_.app().getAmendmentTable();
|
||||
auto const amendment = table.find(std::string(amendmentName));
|
||||
return env_.current()->rules().enabled(amendment);
|
||||
}
|
||||
|
||||
Expected<std::shared_ptr<SLE const>, HostFunctionError>
|
||||
getCurrentLedgerObj()
|
||||
{
|
||||
if (!isLedgerObjCached)
|
||||
{
|
||||
isLedgerObjCached = true;
|
||||
currentLedgerObj = env_.le(leKey);
|
||||
}
|
||||
if (currentLedgerObj)
|
||||
return currentLedgerObj;
|
||||
return Unexpected(HostFunctionError::LEDGER_OBJ_NOT_FOUND);
|
||||
}
|
||||
|
||||
Expected<std::shared_ptr<SLE const>, HostFunctionError>
|
||||
peekCurrentLedgerObj(int32_t cacheIdx)
|
||||
{
|
||||
--cacheIdx;
|
||||
if (cacheIdx < 0 || cacheIdx >= MAX_CACHE)
|
||||
return Unexpected(HostFunctionError::SLOT_OUT_RANGE);
|
||||
|
||||
if (!cache[cacheIdx])
|
||||
{ // return Unexpected(HostFunctionError::INVALID_SLOT);
|
||||
auto const r = getCurrentLedgerObj();
|
||||
if (!r)
|
||||
return Unexpected(r.error());
|
||||
cache[cacheIdx] = *r;
|
||||
}
|
||||
|
||||
return cache[cacheIdx];
|
||||
}
|
||||
|
||||
Expected<int32_t, HostFunctionError>
|
||||
normalizeCacheIndex(int32_t cacheIdx)
|
||||
{
|
||||
--cacheIdx;
|
||||
if (cacheIdx < 0 || cacheIdx >= MAX_CACHE)
|
||||
return Unexpected(HostFunctionError::SLOT_OUT_RANGE);
|
||||
if (!cache[cacheIdx])
|
||||
return Unexpected(HostFunctionError::EMPTY_SLOT);
|
||||
return cacheIdx;
|
||||
}
|
||||
|
||||
virtual Expected<int32_t, HostFunctionError>
|
||||
cacheLedgerObj(uint256 const&, int32_t cacheIdx) override
|
||||
{
|
||||
// auto const& keylet = keylet::unchecked(objId);
|
||||
|
||||
static int32_t intIdx = 0;
|
||||
|
||||
if (cacheIdx < 0 || cacheIdx > MAX_CACHE)
|
||||
@@ -648,158 +756,157 @@ public:
|
||||
return cacheIdx + 1;
|
||||
}
|
||||
|
||||
static Bytes
|
||||
getAnyFieldData(STBase const& obj)
|
||||
static Expected<Bytes, HostFunctionError>
|
||||
getAnyFieldData(STBase const* obj)
|
||||
{
|
||||
// auto const& fname = obj.getFName();
|
||||
auto const stype = obj.getSType();
|
||||
if (!obj)
|
||||
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
|
||||
|
||||
auto const stype = obj->getSType();
|
||||
switch (stype)
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
case STI_UNKNOWN:
|
||||
case STI_NOTPRESENT:
|
||||
return {};
|
||||
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
|
||||
break;
|
||||
// LCOV_EXCL_STOP
|
||||
case STI_OBJECT:
|
||||
case STI_ARRAY:
|
||||
return Unexpected(HostFunctionError::NOT_LEAF_FIELD);
|
||||
break;
|
||||
case STI_ACCOUNT: {
|
||||
auto const& super(static_cast<STAccount const&>(obj));
|
||||
auto const& data = super.value();
|
||||
return {data.begin(), data.end()};
|
||||
auto const* account(static_cast<STAccount const*>(obj));
|
||||
auto const& data = account->value();
|
||||
return Bytes{data.begin(), data.end()};
|
||||
}
|
||||
break;
|
||||
case STI_AMOUNT: {
|
||||
auto const& super(static_cast<STAmount const&>(obj));
|
||||
int64_t const data = super.xrp().drops();
|
||||
auto const* b = reinterpret_cast<uint8_t const*>(&data);
|
||||
auto const* e = reinterpret_cast<uint8_t const*>(&data + 1);
|
||||
return {b, e};
|
||||
case STI_AMOUNT:
|
||||
// will be processed by serializer
|
||||
break;
|
||||
case STI_ISSUE: {
|
||||
auto const* issue(static_cast<STIssue const*>(obj));
|
||||
Asset const& asset(issue->value());
|
||||
// XRP and IOU will be processed by serializer
|
||||
if (asset.holds<MPTIssue>())
|
||||
{
|
||||
// MPT
|
||||
auto const& mptIssue = asset.get<MPTIssue>();
|
||||
auto const& mptID = mptIssue.getMptID();
|
||||
return Bytes{mptID.cbegin(), mptID.cend()};
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STI_VL: {
|
||||
auto const& super(static_cast<STBlob const&>(obj));
|
||||
auto const& data = super.value();
|
||||
return {data.begin(), data.end()};
|
||||
auto const* vl(static_cast<STBlob const*>(obj));
|
||||
auto const& data = vl->value();
|
||||
return Bytes{data.begin(), data.end()};
|
||||
}
|
||||
break;
|
||||
case STI_UINT256: {
|
||||
auto const& super(static_cast<STBitString<256> const&>(obj));
|
||||
auto const& data = super.value();
|
||||
return {data.begin(), data.end()};
|
||||
}
|
||||
break;
|
||||
case STI_UINT32: {
|
||||
auto const& super(
|
||||
static_cast<STInteger<std::uint32_t> const&>(obj));
|
||||
std::uint32_t const data = super.value();
|
||||
case STI_UINT16: {
|
||||
auto const& num(
|
||||
static_cast<STInteger<std::uint16_t> const*>(obj));
|
||||
std::uint16_t const data = num->value();
|
||||
auto const* b = reinterpret_cast<uint8_t const*>(&data);
|
||||
auto const* e = reinterpret_cast<uint8_t const*>(&data + 1);
|
||||
return {b, e};
|
||||
return Bytes{b, e};
|
||||
}
|
||||
case STI_UINT32: {
|
||||
auto const* num(
|
||||
static_cast<STInteger<std::uint32_t> const*>(obj));
|
||||
std::uint32_t const data = num->value();
|
||||
auto const* b = reinterpret_cast<uint8_t const*>(&data);
|
||||
auto const* e = reinterpret_cast<uint8_t const*>(&data + 1);
|
||||
return Bytes{b, e};
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break; // default to serializer
|
||||
}
|
||||
|
||||
Serializer msg;
|
||||
obj.add(msg);
|
||||
obj->add(msg);
|
||||
auto const data = msg.getData();
|
||||
|
||||
return msg.getData();
|
||||
return data;
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
getTxField(SField const& fname) override
|
||||
{
|
||||
auto const* field = tx_->peekAtPField(fname);
|
||||
if (!field)
|
||||
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
|
||||
if ((STI_OBJECT == field->getSType()) ||
|
||||
(STI_ARRAY == field->getSType()))
|
||||
return Unexpected(HostFunctionError::NOT_LEAF_FIELD);
|
||||
|
||||
return getAnyFieldData(*field);
|
||||
return getAnyFieldData(tx_->peekAtPField(fname));
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
getCurrentLedgerObjField(SField const& fname) override
|
||||
{
|
||||
auto const sle = env_.le(leKey);
|
||||
auto const sle = getCurrentLedgerObj();
|
||||
if (!sle)
|
||||
return Unexpected(HostFunctionError::LEDGER_OBJ_NOT_FOUND);
|
||||
|
||||
auto const* field = sle->peekAtPField(fname);
|
||||
if (!field)
|
||||
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
|
||||
if ((STI_OBJECT == field->getSType()) ||
|
||||
(STI_ARRAY == field->getSType()))
|
||||
return Unexpected(HostFunctionError::NOT_LEAF_FIELD);
|
||||
|
||||
return getAnyFieldData(*field);
|
||||
return Unexpected(sle.error());
|
||||
return getAnyFieldData((*sle)->peekAtPField(fname));
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
getLedgerObjField(int32_t cacheIdx, SField const& fname) override
|
||||
{
|
||||
--cacheIdx;
|
||||
if (cacheIdx < 0 || cacheIdx >= MAX_CACHE)
|
||||
return Unexpected(HostFunctionError::SLOT_OUT_RANGE);
|
||||
auto const sle = peekCurrentLedgerObj(cacheIdx);
|
||||
if (!sle)
|
||||
return Unexpected(sle.error());
|
||||
return getAnyFieldData((*sle)->peekAtPField(fname));
|
||||
}
|
||||
|
||||
if (!cache[cacheIdx])
|
||||
{
|
||||
// return Unexpected(HostFunctionError::INVALID_SLOT);
|
||||
cache[cacheIdx] = env_.le(leKey);
|
||||
}
|
||||
|
||||
auto const* field = cache[cacheIdx]->peekAtPField(fname);
|
||||
if (!field)
|
||||
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
|
||||
if ((STI_OBJECT == field->getSType()) ||
|
||||
(STI_ARRAY == field->getSType()))
|
||||
return Unexpected(HostFunctionError::NOT_LEAF_FIELD);
|
||||
|
||||
return getAnyFieldData(*field);
|
||||
static inline bool
|
||||
noField(STBase const* field)
|
||||
{
|
||||
return !field || (STI_NOTPRESENT == field->getSType()) ||
|
||||
(STI_UNKNOWN == field->getSType());
|
||||
}
|
||||
|
||||
static Expected<STBase const*, HostFunctionError>
|
||||
locateField(STObject const& obj, Slice const& loc)
|
||||
locateField(STObject const& obj, Slice const& locator)
|
||||
{
|
||||
if (loc.empty() || (loc.size() & 3)) // must be multiple of 4
|
||||
if (locator.empty() || (locator.size() & 3)) // must be multiple of 4
|
||||
return Unexpected(HostFunctionError::LOCATOR_MALFORMED);
|
||||
|
||||
int32_t const* l = reinterpret_cast<int32_t const*>(loc.data());
|
||||
int32_t const sz = loc.size() / 4;
|
||||
int32_t const* locPtr =
|
||||
reinterpret_cast<int32_t const*>(locator.data());
|
||||
int32_t const locSize = locator.size() / 4;
|
||||
STBase const* field = nullptr;
|
||||
auto const& m = SField::getKnownCodeToField();
|
||||
auto const& knownSFields = SField::getKnownCodeToField();
|
||||
|
||||
{
|
||||
int32_t const c = l[0];
|
||||
auto const it = m.find(c);
|
||||
if (it == m.end())
|
||||
return Unexpected(HostFunctionError::LOCATOR_MALFORMED);
|
||||
auto const& fname(*it->second);
|
||||
int32_t const sfieldCode = locPtr[0];
|
||||
auto const it = knownSFields.find(sfieldCode);
|
||||
if (it == knownSFields.end())
|
||||
return Unexpected(HostFunctionError::INVALID_FIELD);
|
||||
|
||||
auto const& fname(*it->second);
|
||||
field = obj.peekAtPField(fname);
|
||||
if (!field || (STI_NOTPRESENT == field->getSType()))
|
||||
if (noField(field))
|
||||
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
|
||||
}
|
||||
|
||||
for (int i = 1; i < sz; ++i)
|
||||
for (int i = 1; i < locSize; ++i)
|
||||
{
|
||||
int32_t const c = l[i];
|
||||
int32_t const sfieldCode = locPtr[i];
|
||||
|
||||
if (STI_ARRAY == field->getSType())
|
||||
{
|
||||
auto const* arr = static_cast<STArray const*>(field);
|
||||
if (c >= arr->size())
|
||||
return Unexpected(HostFunctionError::LOCATOR_MALFORMED);
|
||||
field = &(arr->operator[](c));
|
||||
if (sfieldCode >= arr->size())
|
||||
return Unexpected(HostFunctionError::INDEX_OUT_OF_BOUNDS);
|
||||
field = &(arr->operator[](sfieldCode));
|
||||
}
|
||||
else if (STI_OBJECT == field->getSType())
|
||||
{
|
||||
auto const* o = static_cast<STObject const*>(field);
|
||||
|
||||
auto const it = m.find(c);
|
||||
if (it == m.end())
|
||||
return Unexpected(HostFunctionError::LOCATOR_MALFORMED);
|
||||
auto const& fname(*it->second);
|
||||
auto const it = knownSFields.find(sfieldCode);
|
||||
if (it == knownSFields.end())
|
||||
return Unexpected(HostFunctionError::INVALID_FIELD);
|
||||
|
||||
auto const& fname(*it->second);
|
||||
field = o->peekAtPField(fname);
|
||||
}
|
||||
else // simple field must be the last one
|
||||
@@ -807,7 +914,7 @@ public:
|
||||
return Unexpected(HostFunctionError::LOCATOR_MALFORMED);
|
||||
}
|
||||
|
||||
if (!field || (STI_NOTPRESENT == field->getSType()))
|
||||
if (noField(field))
|
||||
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
|
||||
}
|
||||
|
||||
@@ -822,57 +929,35 @@ public:
|
||||
auto const r = locateField(*tx_, locator);
|
||||
if (!r)
|
||||
return Unexpected(r.error());
|
||||
|
||||
auto const* field = r.value();
|
||||
if ((STI_OBJECT == field->getSType()) ||
|
||||
(STI_ARRAY == field->getSType()))
|
||||
return Unexpected(HostFunctionError::NOT_LEAF_FIELD);
|
||||
|
||||
return getAnyFieldData(*field);
|
||||
return getAnyFieldData(*r);
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
getCurrentLedgerObjNestedField(Slice const& locator) override
|
||||
{
|
||||
auto const sle = env_.le(leKey);
|
||||
auto const sle = getCurrentLedgerObj();
|
||||
if (!sle)
|
||||
return Unexpected(HostFunctionError::LEDGER_OBJ_NOT_FOUND);
|
||||
return Unexpected(sle.error());
|
||||
|
||||
auto const r = locateField(*sle, locator);
|
||||
auto const r = locateField(**sle, locator);
|
||||
if (!r)
|
||||
return Unexpected(r.error());
|
||||
|
||||
auto const* field = r.value();
|
||||
if ((STI_OBJECT == field->getSType()) ||
|
||||
(STI_ARRAY == field->getSType()))
|
||||
return Unexpected(HostFunctionError::NOT_LEAF_FIELD);
|
||||
|
||||
return getAnyFieldData(*field);
|
||||
return getAnyFieldData(*r);
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
getLedgerObjNestedField(int32_t cacheIdx, Slice const& locator) override
|
||||
{
|
||||
--cacheIdx;
|
||||
if (cacheIdx < 0 || cacheIdx >= MAX_CACHE)
|
||||
return Unexpected(HostFunctionError::SLOT_OUT_RANGE);
|
||||
auto const sle = peekCurrentLedgerObj(cacheIdx);
|
||||
if (!sle)
|
||||
return Unexpected(sle.error());
|
||||
|
||||
if (!cache[cacheIdx])
|
||||
{
|
||||
// return Unexpected(HostFunctionError::INVALID_SLOT);
|
||||
cache[cacheIdx] = env_.le(leKey);
|
||||
}
|
||||
|
||||
auto const r = locateField(*cache[cacheIdx], locator);
|
||||
auto const r = locateField(**sle, locator);
|
||||
if (!r)
|
||||
return Unexpected(r.error());
|
||||
|
||||
auto const* field = r.value();
|
||||
if ((STI_OBJECT == field->getSType()) ||
|
||||
(STI_ARRAY == field->getSType()))
|
||||
return Unexpected(HostFunctionError::NOT_LEAF_FIELD);
|
||||
|
||||
return getAnyFieldData(*field);
|
||||
return getAnyFieldData(*r);
|
||||
}
|
||||
|
||||
Expected<int32_t, HostFunctionError>
|
||||
@@ -882,7 +967,7 @@ public:
|
||||
return Unexpected(HostFunctionError::NO_ARRAY);
|
||||
|
||||
auto const* field = tx_->peekAtPField(fname);
|
||||
if (!field)
|
||||
if (noField(field))
|
||||
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
|
||||
|
||||
if (field->getSType() != STI_ARRAY)
|
||||
@@ -898,12 +983,12 @@ public:
|
||||
if (fname.fieldType != STI_ARRAY)
|
||||
return Unexpected(HostFunctionError::NO_ARRAY);
|
||||
|
||||
auto const sle = env_.le(leKey);
|
||||
auto const sle = getCurrentLedgerObj();
|
||||
if (!sle)
|
||||
return Unexpected(HostFunctionError::LEDGER_OBJ_NOT_FOUND);
|
||||
return Unexpected(sle.error());
|
||||
|
||||
auto const* field = sle->peekAtPField(fname);
|
||||
if (!field)
|
||||
auto const* field = (*sle)->peekAtPField(fname);
|
||||
if (noField(field))
|
||||
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
|
||||
|
||||
if (field->getSType() != STI_ARRAY)
|
||||
@@ -919,17 +1004,12 @@ public:
|
||||
if (fname.fieldType != STI_ARRAY)
|
||||
return Unexpected(HostFunctionError::NO_ARRAY);
|
||||
|
||||
if (cacheIdx < 0 || cacheIdx >= MAX_CACHE)
|
||||
return Unexpected(HostFunctionError::SLOT_OUT_RANGE);
|
||||
auto const sle = peekCurrentLedgerObj(cacheIdx);
|
||||
if (!sle)
|
||||
return Unexpected(sle.error());
|
||||
|
||||
if (!cache[cacheIdx])
|
||||
{
|
||||
// return Unexpected(HostFunctionError::INVALID_SLOT);
|
||||
cache[cacheIdx] = env_.le(leKey);
|
||||
}
|
||||
|
||||
auto const* field = cache[cacheIdx]->peekAtPField(fname);
|
||||
if (!field)
|
||||
auto const* field = (*sle)->peekAtPField(fname);
|
||||
if (noField(field))
|
||||
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
|
||||
|
||||
if (field->getSType() != STI_ARRAY)
|
||||
@@ -957,10 +1037,11 @@ public:
|
||||
Expected<int32_t, HostFunctionError>
|
||||
getCurrentLedgerObjNestedArrayLen(Slice const& locator) override
|
||||
{
|
||||
auto const sle = env_.le(leKey);
|
||||
auto const sle = getCurrentLedgerObj();
|
||||
if (!sle)
|
||||
return Unexpected(HostFunctionError::LEDGER_OBJ_NOT_FOUND);
|
||||
auto const r = locateField(*sle, locator);
|
||||
return Unexpected(sle.error());
|
||||
|
||||
auto const r = locateField(**sle, locator);
|
||||
if (!r)
|
||||
return Unexpected(r.error());
|
||||
auto const* field = r.value();
|
||||
@@ -975,17 +1056,11 @@ public:
|
||||
Expected<int32_t, HostFunctionError>
|
||||
getLedgerObjNestedArrayLen(int32_t cacheIdx, Slice const& locator) override
|
||||
{
|
||||
--cacheIdx;
|
||||
if (cacheIdx < 0 || cacheIdx >= MAX_CACHE)
|
||||
return Unexpected(HostFunctionError::SLOT_OUT_RANGE);
|
||||
auto const sle = peekCurrentLedgerObj(cacheIdx);
|
||||
if (!sle)
|
||||
return Unexpected(sle.error());
|
||||
|
||||
if (!cache[cacheIdx])
|
||||
{
|
||||
// return Unexpected(HostFunctionError::INVALID_SLOT);
|
||||
cache[cacheIdx] = env_.le(leKey);
|
||||
}
|
||||
|
||||
auto const r = locateField(*cache[cacheIdx], locator);
|
||||
auto const r = locateField(**sle, locator);
|
||||
if (!r)
|
||||
return Unexpected(r.error());
|
||||
|
||||
@@ -1001,6 +1076,9 @@ public:
|
||||
Expected<int32_t, HostFunctionError>
|
||||
updateData(Slice const& data) override
|
||||
{
|
||||
if (data.size() > maxWasmDataLength)
|
||||
return Unexpected(HostFunctionError::DATA_FIELD_TOO_LARGE);
|
||||
|
||||
ripple::detail::ApplyViewBase v(
|
||||
env_.app().openLedger().current().get(), tapNONE);
|
||||
|
||||
@@ -1014,6 +1092,19 @@ public:
|
||||
return data.size();
|
||||
}
|
||||
|
||||
Expected<int32_t, HostFunctionError>
|
||||
checkSignature(
|
||||
Slice const& message,
|
||||
Slice const& signature,
|
||||
Slice const& pubkey) override
|
||||
{
|
||||
if (!publicKeyType(pubkey))
|
||||
return Unexpected(HostFunctionError::INVALID_PARAMS);
|
||||
|
||||
PublicKey const pk(pubkey);
|
||||
return verify(pk, message, signature, /*canonical*/ true);
|
||||
}
|
||||
|
||||
Expected<Hash, HostFunctionError>
|
||||
computeSha512HalfHash(Slice const& data) override
|
||||
{
|
||||
@@ -1021,6 +1112,215 @@ public:
|
||||
return hash;
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
accountKeylet(AccountID const& account) override
|
||||
{
|
||||
if (!account)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
auto const keylet = keylet::account(account);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
ammKeylet(Asset const& issue1, Asset const& issue2) override
|
||||
{
|
||||
if (issue1 == issue2)
|
||||
return Unexpected(HostFunctionError::INVALID_PARAMS);
|
||||
|
||||
// note: this should be removed with the MPT DEX amendment
|
||||
if (issue1.holds<MPTIssue>() || issue2.holds<MPTIssue>())
|
||||
return Unexpected(HostFunctionError::INVALID_PARAMS);
|
||||
|
||||
auto const keylet = keylet::amm(issue1, issue2);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
checkKeylet(AccountID const& account, std::uint32_t seq) override
|
||||
{
|
||||
if (!account)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
auto const keylet = keylet::check(account, seq);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
credentialKeylet(
|
||||
AccountID const& subject,
|
||||
AccountID const& issuer,
|
||||
Slice const& credentialType) override
|
||||
{
|
||||
if (!subject || !issuer)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
|
||||
if (credentialType.empty() ||
|
||||
credentialType.size() > maxCredentialTypeLength)
|
||||
return Unexpected(HostFunctionError::INVALID_PARAMS);
|
||||
|
||||
auto const keylet = keylet::credential(subject, issuer, credentialType);
|
||||
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
didKeylet(AccountID const& account) override
|
||||
{
|
||||
if (!account)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
auto const keylet = keylet::did(account);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
delegateKeylet(AccountID const& account, AccountID const& authorize)
|
||||
override
|
||||
{
|
||||
if (!account || !authorize)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
if (account == authorize)
|
||||
return Unexpected(HostFunctionError::INVALID_PARAMS);
|
||||
auto const keylet = keylet::delegate(account, authorize);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
depositPreauthKeylet(AccountID const& account, AccountID const& authorize)
|
||||
override
|
||||
{
|
||||
if (!account || !authorize)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
if (account == authorize)
|
||||
return Unexpected(HostFunctionError::INVALID_PARAMS);
|
||||
auto const keylet = keylet::depositPreauth(account, authorize);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
escrowKeylet(AccountID const& account, std::uint32_t seq) override
|
||||
{
|
||||
if (!account)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
auto const keylet = keylet::escrow(account, seq);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
lineKeylet(
|
||||
AccountID const& account1,
|
||||
AccountID const& account2,
|
||||
Currency const& currency) override
|
||||
{
|
||||
if (!account1 || !account2)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
if (account1 == account2)
|
||||
return Unexpected(HostFunctionError::INVALID_PARAMS);
|
||||
if (currency.isZero())
|
||||
return Unexpected(HostFunctionError::INVALID_PARAMS);
|
||||
|
||||
auto const keylet = keylet::line(account1, account2, currency);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
mptIssuanceKeylet(AccountID const& issuer, std::uint32_t seq) override
|
||||
{
|
||||
if (!issuer)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
|
||||
auto const keylet = keylet::mptIssuance(seq, issuer);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
mptokenKeylet(MPTID const& mptid, AccountID const& holder) override
|
||||
{
|
||||
if (!mptid)
|
||||
return Unexpected(HostFunctionError::INVALID_PARAMS);
|
||||
if (!holder)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
|
||||
auto const keylet = keylet::mptoken(mptid, holder);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
nftOfferKeylet(AccountID const& account, std::uint32_t seq) override
|
||||
{
|
||||
if (!account)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
auto const keylet = keylet::nftoffer(account, seq);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
offerKeylet(AccountID const& account, std::uint32_t seq) override
|
||||
{
|
||||
if (!account)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
auto const keylet = keylet::offer(account, seq);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
oracleKeylet(AccountID const& account, std::uint32_t documentId) override
|
||||
{
|
||||
if (!account)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
auto const keylet = keylet::oracle(account, documentId);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
paychanKeylet(
|
||||
AccountID const& account,
|
||||
AccountID const& destination,
|
||||
std::uint32_t seq) override
|
||||
{
|
||||
if (!account || !destination)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
if (account == destination)
|
||||
return Unexpected(HostFunctionError::INVALID_PARAMS);
|
||||
auto const keylet = keylet::payChan(account, destination, seq);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
permissionedDomainKeylet(AccountID const& account, std::uint32_t seq)
|
||||
override
|
||||
{
|
||||
if (!account)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
auto const keylet = keylet::permissionedDomain(account, seq);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
signersKeylet(AccountID const& account) override
|
||||
{
|
||||
if (!account)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
auto const keylet = keylet::signers(account);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
ticketKeylet(AccountID const& account, std::uint32_t seq) override
|
||||
{
|
||||
if (!account)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
auto const keylet = keylet::ticket(account, seq);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
vaultKeylet(AccountID const& account, std::uint32_t seq) override
|
||||
{
|
||||
if (!account)
|
||||
return Unexpected(HostFunctionError::INVALID_ACCOUNT);
|
||||
auto const keylet = keylet::vault(account, seq);
|
||||
return Bytes{keylet.key.begin(), keylet.key.end()};
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
getNFT(AccountID const& account, uint256 const& nftId) override
|
||||
{
|
||||
@@ -1044,6 +1344,40 @@ public:
|
||||
Slice const s = ouri->value();
|
||||
return Bytes(s.begin(), s.end());
|
||||
}
|
||||
|
||||
Expected<Bytes, HostFunctionError>
|
||||
getNFTIssuer(uint256 const& nftId) override
|
||||
{
|
||||
auto const issuer = nft::getIssuer(nftId);
|
||||
if (!issuer)
|
||||
return Unexpected(HostFunctionError::INVALID_PARAMS);
|
||||
|
||||
return Bytes{issuer.begin(), issuer.end()};
|
||||
}
|
||||
|
||||
Expected<std::uint32_t, HostFunctionError>
|
||||
getNFTTaxon(uint256 const& nftId) override
|
||||
{
|
||||
return nft::toUInt32(nft::getTaxon(nftId));
|
||||
}
|
||||
|
||||
Expected<int32_t, HostFunctionError>
|
||||
getNFTFlags(uint256 const& nftId) override
|
||||
{
|
||||
return nft::getFlags(nftId);
|
||||
}
|
||||
|
||||
Expected<int32_t, HostFunctionError>
|
||||
getNFTTransferFee(uint256 const& nftId) override
|
||||
{
|
||||
return nft::getTransferFee(nftId);
|
||||
}
|
||||
|
||||
Expected<std::uint32_t, HostFunctionError>
|
||||
getNFTSerial(uint256 const& nftId) override
|
||||
{
|
||||
return nft::getSerial(nftId);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
||||
@@ -519,7 +519,7 @@ struct Wasm_test : public beast::unit_test::suite
|
||||
if (BEAST_EXPECT(re.has_value()))
|
||||
{
|
||||
BEAST_EXPECTS(re->result == 1, std::to_string(re->result));
|
||||
BEAST_EXPECTS(re->cost == 91'412, std::to_string(re->cost));
|
||||
BEAST_EXPECTS(re->cost == 96'942, std::to_string(re->cost));
|
||||
}
|
||||
env.close();
|
||||
}
|
||||
@@ -534,7 +534,7 @@ struct Wasm_test : public beast::unit_test::suite
|
||||
if (BEAST_EXPECT(re.has_value()))
|
||||
{
|
||||
BEAST_EXPECTS(re->result == 1, std::to_string(re->result));
|
||||
BEAST_EXPECTS(re->cost == 6'533, std::to_string(re->cost));
|
||||
BEAST_EXPECTS(re->cost == 2'053, std::to_string(re->cost));
|
||||
}
|
||||
env.close();
|
||||
}
|
||||
@@ -550,13 +550,12 @@ struct Wasm_test : public beast::unit_test::suite
|
||||
|
||||
// std::string const funcName("test");
|
||||
auto const& wasmHex = hfPerfTest;
|
||||
// auto const& wasmHex = opcCallPerfTest;
|
||||
std::string const wasmStr = boost::algorithm::unhex(wasmHex);
|
||||
std::vector<uint8_t> const wasm(wasmStr.begin(), wasmStr.end());
|
||||
|
||||
std::string const credType = "abcde";
|
||||
std::string const credType2 = "fghijk";
|
||||
std::string const credType3 = "0123456";
|
||||
// std::string const credType = "abcde";
|
||||
// std::string const credType2 = "fghijk";
|
||||
// std::string const credType3 = "0123456";
|
||||
// char const uri[] = "uri";
|
||||
|
||||
Account const alan{"alan"};
|
||||
@@ -597,7 +596,7 @@ struct Wasm_test : public beast::unit_test::suite
|
||||
// {issuer, credType2},
|
||||
// {issuer, credType3}}));
|
||||
|
||||
// cREATE nft
|
||||
// create nft
|
||||
[[maybe_unused]] uint256 const nft0{
|
||||
token::getNextID(env, alan, 0u)};
|
||||
env(token::mint(alan, 0u));
|
||||
@@ -649,7 +648,7 @@ struct Wasm_test : public beast::unit_test::suite
|
||||
Bytes const wasm(wasmStr.begin(), wasmStr.end());
|
||||
TestHostFunctions hfs(env, 0);
|
||||
|
||||
auto const allowance = 148'406;
|
||||
auto const allowance = 153'296;
|
||||
auto re = runEscrowWasm(
|
||||
wasm, ESCROW_FUNCTION_NAME, {}, &hfs, allowance, env.journal);
|
||||
|
||||
|
||||
@@ -9571,41 +9571,38 @@ extern std::string const deepRecursionHex =
|
||||
"2d657874";
|
||||
|
||||
extern std::string const hfPerfTest =
|
||||
"0061736d0100000001180460037f7f7e017f60057f7f7f7f7f017f600000"
|
||||
"6000017f021d0203656e760974726163655f6e756d000003656e76057472"
|
||||
"616365000103030202030503010002068601167f0041a0090b7f0041a011"
|
||||
"0b7f0041e0080b7f0041a0080b7f0041c0080b7f004180080b7f00418408"
|
||||
"0b7f004188080b7f00418c080b7f004190080b7f004194080b7f00419808"
|
||||
"0b7f004180090b7f004180080b7f0041e0110b7f0041e0110b7f0041e091"
|
||||
"040b7f004180080b7f0041e091040b7f00418080080b7f0041000b7f0041"
|
||||
"010b07c50219066d656d6f72790200115f5f7761736d5f63616c6c5f6374"
|
||||
"6f727300020666696e6973680003036275660300076c6f635f6275660301"
|
||||
"036d73670302086572725f686561640303096572725f646174613103040a"
|
||||
"53465f4163636f756e7403050e53465f44657374696e6174696f6e030608"
|
||||
"53465f4d656d6f7303070753465f4d656d6f03080b53465f4d656d6f4461"
|
||||
"746103090753465f44617461030a1753465f417574686f72697a65437265"
|
||||
"64656e7469616c73030b066163635f6964030c0c5f5f64736f5f68616e64"
|
||||
"6c65030d0a5f5f646174615f656e64030e0b5f5f737461636b5f6c6f7703"
|
||||
"0f0c5f5f737461636b5f6869676803100d5f5f676c6f62616c5f62617365"
|
||||
"03110b5f5f686561705f6261736503120a5f5f686561705f656e6403130d"
|
||||
"5f5f6d656d6f72795f6261736503140c5f5f7461626c655f626173650315"
|
||||
"0aa2010202000b9c0102017f017e41807821000340200041a0116a420037"
|
||||
"0300200041086a22000d000b41d811420037030041d011420037030041c8"
|
||||
"11420037030041c011420037030041b811420037030041b0114200370300"
|
||||
"41a811428d801c37030041a011429a803c3703000240034041e008411020"
|
||||
"0110004118460440200142017c220142c0843d520d010c020b0b41a00841"
|
||||
"1441c0084113410010011a0b41010b0b840104004180080b340100080003"
|
||||
"00080009000f000a000e000d0007001b0007001a000f0000000000676574"
|
||||
"5f6c65646765725f73716e206572726f720041c0080b13696e76616c6964"
|
||||
"2072657475726e2073697a650041e0080b104e6577206163636f756e7420"
|
||||
"69643a20004180090b14fc4f9afac9f1a8db807fda7dc9247bb557569d58"
|
||||
"007f0970726f647563657273010c70726f6365737365642d62790105636c"
|
||||
"616e675f31392e312e352d776173692d73646b202868747470733a2f2f67"
|
||||
"69746875622e636f6d2f6c6c766d2f6c6c766d2d70726f6a656374206162"
|
||||
"346235613264623538323935386166316565333038613739306366646234"
|
||||
"32626432343732302900490f7461726765745f6665617475726573042b0f"
|
||||
"6d757461626c652d676c6f62616c732b087369676e2d6578742b0f726566"
|
||||
"6572656e63652d74797065732b0a6d756c746976616c7565";
|
||||
"0061736d0100000001190460057f7f7f7f7f017f60047f7f7f7f017f6000006000017f0236"
|
||||
"0303656e7609666c6f61745f6c6f67000003656e76057472616365000003656e7612747261"
|
||||
"63655f6f70617175655f666c6f617400010303020203050301000206aa011c7f0041b0090b"
|
||||
"7f004193090b7f0041b0080b7f0041c0080b7f0041e0080b7f004180090b7f004180080b7f"
|
||||
"004184080b7f004188080b7f00418c080b7f004190080b7f004194080b7f004198080b7f00"
|
||||
"419c080b7f0041a0080b7f0041a4080b7f0041a8080b7f0041ac080b7f00419b090b7f0041"
|
||||
"80080b7f0041b0110b7f0041b0110b7f0041b091040b7f004180080b7f0041b091040b7f00"
|
||||
"418080080b7f0041000b7f0041010b0785031f066d656d6f72790200115f5f7761736d5f63"
|
||||
"616c6c5f63746f727300030666696e697368000403627566030001610301086572725f6865"
|
||||
"61640302096572725f6461746131030305696e707574030406726573756c74030508495445"
|
||||
"525f4d4158030609484153485f53495a450307084143435f53495a4503080d43555252454e"
|
||||
"43595f53495a4503090b4b45594c45545f53495a45030a0a53465f4163636f756e74030b0e"
|
||||
"53465f44657374696e6174696f6e030c0853465f4d656d6f73030d0753465f4d656d6f030e"
|
||||
"0b53465f4d656d6f44617461030f0753465f4461746103101753465f417574686f72697a65"
|
||||
"43726564656e7469616c730311016203120c5f5f64736f5f68616e646c6503130a5f5f6461"
|
||||
"74615f656e6403140b5f5f737461636b5f6c6f7703150c5f5f737461636b5f686967680316"
|
||||
"0d5f5f676c6f62616c5f6261736503170b5f5f686561705f6261736503180a5f5f68656170"
|
||||
"5f656e6403190d5f5f6d656d6f72795f62617365031a0c5f5f7461626c655f62617365031b"
|
||||
"0a7c0202000b7701017f41807821000340200041b0116a4200370300200041086a22000d00"
|
||||
"0b41c0843d210002400340419309410841b009418008410010004108460440200041016b22"
|
||||
"000d010c020b0b41b008410f41c0084113410010011a0b41e0084111419309410810021a41"
|
||||
"8009411241b009410810021a41010b0b9f0104004180080b53809698002000000014000000"
|
||||
"1400000020000000010008000300080009000f000a000e000d0007001b0007001a000f0066"
|
||||
"6c6f61745f6c6f67206572726f7200696e76616c69642072657475726e2073697a650041e0"
|
||||
"080b11666c6f61745f6c6f6720696e7075743a20004180090b12666c6f61745f6c6f672072"
|
||||
"6573756c743a20004193090b10d48b29430a256d21d920c49ba5e353f8007f0970726f6475"
|
||||
"63657273010c70726f6365737365642d62790105636c616e675f31392e312e352d77617369"
|
||||
"2d73646b202868747470733a2f2f6769746875622e636f6d2f6c6c766d2f6c6c766d2d7072"
|
||||
"6f6a6563742061623462356132646235383239353861663165653330386137393063666462"
|
||||
"3432626432343732302900490f7461726765745f6665617475726573042b0f6d757461626c"
|
||||
"652d676c6f62616c732b087369676e2d6578742b0f7265666572656e63652d74797065732b"
|
||||
"0a6d756c746976616c7565";
|
||||
|
||||
extern std::string const allKeyletsWasmHex =
|
||||
"0061736d0100000001530a60057f7f7f7f7f017f60047f7f7f7f017f60067f7f7f7f7f7f01"
|
||||
|
||||
@@ -50,7 +50,15 @@ class WasmHostFunctionsImpl : public HostFunctions
|
||||
}
|
||||
|
||||
Expected<int32_t, HostFunctionError>
|
||||
normalizeCacheIndex(int32_t cacheIdx);
|
||||
normalizeCacheIndex(int32_t cacheIdx)
|
||||
{
|
||||
--cacheIdx;
|
||||
if (cacheIdx < 0 || cacheIdx >= MAX_CACHE)
|
||||
return Unexpected(HostFunctionError::SLOT_OUT_RANGE);
|
||||
if (!cache[cacheIdx])
|
||||
return Unexpected(HostFunctionError::EMPTY_SLOT);
|
||||
return cacheIdx;
|
||||
}
|
||||
|
||||
public:
|
||||
WasmHostFunctionsImpl(ApplyContext& ctx, Keylet const& leKey)
|
||||
|
||||
@@ -90,17 +90,6 @@ WasmHostFunctionsImpl::isAmendmentEnabled(std::string_view const& amendmentName)
|
||||
return ctx.view().rules().enabled(amendment);
|
||||
}
|
||||
|
||||
Expected<int32_t, HostFunctionError>
|
||||
WasmHostFunctionsImpl::normalizeCacheIndex(int32_t cacheIdx)
|
||||
{
|
||||
--cacheIdx;
|
||||
if (cacheIdx < 0 || cacheIdx >= MAX_CACHE)
|
||||
return Unexpected(HostFunctionError::SLOT_OUT_RANGE);
|
||||
if (!cache[cacheIdx])
|
||||
return Unexpected(HostFunctionError::EMPTY_SLOT);
|
||||
return cacheIdx;
|
||||
}
|
||||
|
||||
Expected<int32_t, HostFunctionError>
|
||||
WasmHostFunctionsImpl::cacheLedgerObj(uint256 const& objId, int32_t cacheIdx)
|
||||
{
|
||||
@@ -1296,7 +1285,7 @@ floatPowerImpl(Slice const& x, int32_t n, int32_t mode)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (n < 0)
|
||||
if ((n < 0) || (n > IOUAmount::maxExponent))
|
||||
return Unexpected(HostFunctionError::FLOAT_INPUT_MALFORMED);
|
||||
|
||||
SetRound rm(mode);
|
||||
|
||||
@@ -107,7 +107,11 @@ getDataSField(IW const* _runtime, wasm_val_vec_t const* params, int32_t& i)
|
||||
|
||||
template <class IW>
|
||||
Expected<Slice, HostFunctionError>
|
||||
getDataSlice(IW const* runtime, wasm_val_vec_t const* params, int32_t& i)
|
||||
getDataSlice(
|
||||
IW const* runtime,
|
||||
wasm_val_vec_t const* params,
|
||||
int32_t& i,
|
||||
bool isUpdate = false)
|
||||
{
|
||||
auto const ptr = params->data[i].of.i32;
|
||||
auto const size = params->data[i + 1].of.i32;
|
||||
@@ -117,7 +121,7 @@ getDataSlice(IW const* runtime, wasm_val_vec_t const* params, int32_t& i)
|
||||
if (!size)
|
||||
return Slice();
|
||||
|
||||
if (size > maxWasmDataLength)
|
||||
if (size > (isUpdate ? maxWasmDataLength : maxWasmParamLength))
|
||||
return Unexpected(HostFunctionError::DATA_FIELD_TOO_LARGE);
|
||||
|
||||
auto memory = runtime ? runtime->getMem() : wmem();
|
||||
@@ -751,7 +755,7 @@ updateData_wrap(
|
||||
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
|
||||
int index = 0;
|
||||
|
||||
auto const bytes = getDataSlice(runtime, params, index);
|
||||
auto const bytes = getDataSlice(runtime, params, index, true);
|
||||
if (!bytes)
|
||||
{
|
||||
return hfResult(results, bytes.error());
|
||||
@@ -1491,7 +1495,7 @@ trace_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
|
||||
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
|
||||
int index = 0;
|
||||
|
||||
if (params->data[1].of.i32 + params->data[3].of.i32 > maxWasmDataLength)
|
||||
if (params->data[1].of.i32 + params->data[3].of.i32 > maxWasmParamLength)
|
||||
{
|
||||
return hfResult(results, HostFunctionError::DATA_FIELD_TOO_LARGE);
|
||||
}
|
||||
@@ -1524,7 +1528,7 @@ traceNum_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
|
||||
auto* hf = reinterpret_cast<HostFunctions*>(env);
|
||||
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
|
||||
int index = 0;
|
||||
if (params->data[1].of.i32 > maxWasmDataLength)
|
||||
if (params->data[1].of.i32 > maxWasmParamLength)
|
||||
{
|
||||
return hfResult(results, HostFunctionError::DATA_FIELD_TOO_LARGE);
|
||||
}
|
||||
@@ -1554,7 +1558,7 @@ traceAccount_wrap(
|
||||
auto* hf = reinterpret_cast<HostFunctions*>(env);
|
||||
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
|
||||
|
||||
if (params->data[1].of.i32 > maxWasmDataLength)
|
||||
if (params->data[1].of.i32 > maxWasmParamLength)
|
||||
return hfResult(results, HostFunctionError::DATA_FIELD_TOO_LARGE);
|
||||
|
||||
int i = 0;
|
||||
@@ -1579,7 +1583,7 @@ traceFloat_wrap(
|
||||
auto* hf = reinterpret_cast<HostFunctions*>(env);
|
||||
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
|
||||
|
||||
if (params->data[1].of.i32 > maxWasmDataLength)
|
||||
if (params->data[1].of.i32 > maxWasmParamLength)
|
||||
return hfResult(results, HostFunctionError::DATA_FIELD_TOO_LARGE);
|
||||
|
||||
int i = 0;
|
||||
@@ -1604,7 +1608,7 @@ traceAmount_wrap(
|
||||
auto* hf = reinterpret_cast<HostFunctions*>(env);
|
||||
auto const* runtime = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
|
||||
|
||||
if (params->data[1].of.i32 > maxWasmDataLength)
|
||||
if (params->data[1].of.i32 > maxWasmParamLength)
|
||||
return hfResult(results, HostFunctionError::DATA_FIELD_TOO_LARGE);
|
||||
|
||||
int i = 0;
|
||||
|
||||
@@ -44,9 +44,9 @@ setCommonHostFunctions(HostFunctions* hfs, std::vector<WasmImportFunc>& i)
|
||||
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, isAmendmentEnabled, "amendment_enabled", hfs, 100);
|
||||
|
||||
WASM_IMPORT_FUNC2(i, cacheLedgerObj, "cache_ledger_obj", hfs, 5000);
|
||||
WASM_IMPORT_FUNC2(i, cacheLedgerObj, "cache_ledger_obj", hfs, 5'000);
|
||||
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);
|
||||
@@ -60,20 +60,20 @@ setCommonHostFunctions(HostFunctions* hfs, std::vector<WasmImportFunc>& i)
|
||||
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, checkSignature, "check_sig", hfs, 2000);
|
||||
WASM_IMPORT_FUNC2(i, checkSignature, "check_sig", hfs, 300);
|
||||
WASM_IMPORT_FUNC2(i, computeSha512HalfHash, "compute_sha512_half", hfs, 2000);
|
||||
|
||||
WASM_IMPORT_FUNC2(i, accountKeylet, "account_keylet", hfs, 350);
|
||||
WASM_IMPORT_FUNC2(i, ammKeylet, "amm_keylet", hfs, 350);
|
||||
WASM_IMPORT_FUNC2(i, ammKeylet, "amm_keylet", hfs, 450);
|
||||
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, lineKeylet, "line_keylet", hfs, 400);
|
||||
WASM_IMPORT_FUNC2(i, mptIssuanceKeylet, "mpt_issuance_keylet", hfs, 350);
|
||||
WASM_IMPORT_FUNC2(i, mptokenKeylet, "mptoken_keylet", hfs, 350);
|
||||
WASM_IMPORT_FUNC2(i, mptokenKeylet, "mptoken_keylet", hfs, 500);
|
||||
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);
|
||||
@@ -84,7 +84,7 @@ setCommonHostFunctions(HostFunctions* hfs, std::vector<WasmImportFunc>& i)
|
||||
WASM_IMPORT_FUNC2(i, vaultKeylet, "vault_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, getNFTIssuer, "get_nft_issuer", hfs, 70);
|
||||
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);
|
||||
@@ -96,17 +96,17 @@ setCommonHostFunctions(HostFunctions* hfs, std::vector<WasmImportFunc>& i)
|
||||
WASM_IMPORT_FUNC2(i, traceFloat, "trace_opaque_float", hfs, 500);
|
||||
WASM_IMPORT_FUNC2(i, traceAmount, "trace_amount", 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);
|
||||
WASM_IMPORT_FUNC2(i, floatFromInt, "float_from_int", hfs, 100);
|
||||
WASM_IMPORT_FUNC2(i, floatFromUint, "float_from_uint", hfs, 130);
|
||||
WASM_IMPORT_FUNC2(i, floatSet, "float_set", hfs, 100);
|
||||
WASM_IMPORT_FUNC2(i, floatCompare, "float_compare", hfs, 80);
|
||||
WASM_IMPORT_FUNC2(i, floatAdd, "float_add", hfs, 160);
|
||||
WASM_IMPORT_FUNC2(i, floatSubtract, "float_subtract", hfs, 160);
|
||||
WASM_IMPORT_FUNC2(i, floatMultiply, "float_multiply", hfs, 300);
|
||||
WASM_IMPORT_FUNC2(i, floatDivide, "float_divide", hfs, 300);
|
||||
WASM_IMPORT_FUNC2(i, floatRoot, "float_root", hfs, 5'500);
|
||||
WASM_IMPORT_FUNC2(i, floatPower, "float_pow", hfs, 5'500);
|
||||
WASM_IMPORT_FUNC2(i, floatLog, "float_log", hfs, 12'000);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user