Merge branch 'ripple/smart-escrow' into ripple/se/supported

This commit is contained in:
Mayukha Vadari
2025-10-06 17:01:38 -04:00
committed by GitHub
20 changed files with 1580 additions and 1249 deletions

View File

@@ -0,0 +1,935 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2025 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 <test/app/wasm_fixtures/fixtures.h>
#include <test/jtx.h>
#include <xrpld/app/tx/applySteps.h>
#include <xrpld/app/wasm/WasmVM.h>
#include <xrpl/ledger/Dir.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/jss.h>
#include <algorithm>
#include <iterator>
namespace ripple {
namespace test {
struct EscrowSmart_test : public beast::unit_test::suite
{
void
testCreateFinishFunctionPreflight(FeatureBitset features)
{
testcase("Test preflight checks involving FinishFunction");
using namespace jtx;
using namespace std::chrono;
Account const alice{"alice"};
Account const carol{"carol"};
// Tests whether the ledger index is >= 5
// getLedgerSqn() >= 5}
static auto wasmHex = ledgerSqnWasmHex;
{
// featureSmartEscrow disabled
Env env(*this, features - featureSmartEscrow);
env.fund(XRP(5000), alice, carol);
XRPAmount const txnFees = env.current()->fees().base + 1000;
auto escrowCreate = escrow::create(alice, carol, XRP(1000));
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 100s),
fee(txnFees),
ter(temDISABLED));
env.close();
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 100s),
escrow::data("00112233"),
fee(txnFees),
ter(temDISABLED));
env.close();
}
{
// FinishFunction > max length
Env env(
*this,
envconfig([](std::unique_ptr<Config> cfg) {
cfg->FEES.extension_size_limit = 10; // 10 bytes
return cfg;
}),
features);
XRPAmount const txnFees = env.current()->fees().base + 1000;
// create escrow
env.fund(XRP(5000), alice, carol);
auto escrowCreate = escrow::create(alice, carol, XRP(500));
// 11-byte string
std::string longWasmHex = "00112233445566778899AA";
env(escrowCreate,
escrow::finish_function(longWasmHex),
escrow::cancel_time(env.now() + 100s),
fee(txnFees),
ter(temMALFORMED));
env.close();
}
{
// Data without FinishFunction
Env env(*this, features);
XRPAmount const txnFees = env.current()->fees().base + 100000;
// create escrow
env.fund(XRP(5000), alice, carol);
auto escrowCreate = escrow::create(alice, carol, XRP(500));
std::string longData(4, 'A');
env(escrowCreate,
escrow::data(longData),
escrow::finish_time(env.now() + 100s),
fee(txnFees),
ter(temMALFORMED));
env.close();
}
{
// Data > max length
Env env(*this, features);
XRPAmount const txnFees = env.current()->fees().base + 100000;
// create escrow
env.fund(XRP(5000), alice, carol);
auto escrowCreate = escrow::create(alice, carol, XRP(500));
// string of length maxWasmDataLength * 2 + 2
std::string longData(maxWasmDataLength * 2 + 2, 'B');
env(escrowCreate,
escrow::data(longData),
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 100s),
fee(txnFees),
ter(temMALFORMED));
env.close();
}
Env env(
*this,
envconfig([](std::unique_ptr<Config> cfg) {
cfg->START_UP = Config::FRESH;
return cfg;
}),
features);
XRPAmount const txnFees =
env.current()->fees().base * 10 + wasmHex.size() / 2 * 5;
// create escrow
env.fund(XRP(5000), alice, carol);
auto escrowCreate = escrow::create(alice, carol, XRP(500));
// Success situations
{
// FinishFunction + CancelAfter
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 20s),
fee(txnFees));
env.close();
}
{
// FinishFunction + Condition + CancelAfter
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 30s),
escrow::condition(escrow::cb1),
fee(txnFees));
env.close();
}
{
// FinishFunction + FinishAfter + CancelAfter
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 40s),
escrow::finish_time(env.now() + 2s),
fee(txnFees));
env.close();
}
{
// FinishFunction + FinishAfter + Condition + CancelAfter
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 50s),
escrow::condition(escrow::cb1),
escrow::finish_time(env.now() + 2s),
fee(txnFees));
env.close();
}
// Failure situations (i.e. all other combinations)
{
// only FinishFunction
env(escrowCreate,
escrow::finish_function(wasmHex),
fee(txnFees),
ter(temBAD_EXPIRATION));
env.close();
}
{
// FinishFunction + FinishAfter
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::finish_time(env.now() + 2s),
fee(txnFees),
ter(temBAD_EXPIRATION));
env.close();
}
{
// FinishFunction + Condition
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::condition(escrow::cb1),
fee(txnFees),
ter(temBAD_EXPIRATION));
env.close();
}
{
// FinishFunction + FinishAfter + Condition
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::condition(escrow::cb1),
escrow::finish_time(env.now() + 2s),
fee(txnFees),
ter(temBAD_EXPIRATION));
env.close();
}
{
// FinishFunction 0 length
env(escrowCreate,
escrow::finish_function(""),
escrow::cancel_time(env.now() + 60s),
fee(txnFees),
ter(temMALFORMED));
env.close();
}
{
// Not enough fees
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 70s),
fee(txnFees - 1),
ter(telINSUF_FEE_P));
env.close();
}
{
// FinishFunction nonexistent host function
// pub fn finish() -> bool {
// unsafe { host_lib::bad() >= 5 }
// }
auto const badWasmHex =
"0061736d010000000105016000017f02100108686f73745f6c696203626164"
"00000302010005030100100611027f00418080c0000b7f00418080c0000b07"
"2e04066d656d6f727902000666696e69736800010a5f5f646174615f656e64"
"03000b5f5f686561705f6261736503010a09010700100041044a0b004d0970"
"726f64756365727302086c616e6775616765010452757374000c70726f6365"
"737365642d6279010572757374631d312e38352e3120283465623136313235"
"3020323032352d30332d31352900490f7461726765745f6665617475726573"
"042b0f6d757461626c652d676c6f62616c732b087369676e2d6578742b0f72"
"65666572656e63652d74797065732b0a6d756c746976616c7565";
env(escrowCreate,
escrow::finish_function(badWasmHex),
escrow::cancel_time(env.now() + 100s),
fee(txnFees),
ter(temBAD_WASM));
env.close();
}
}
void
testFinishWasmFailures(FeatureBitset features)
{
testcase("EscrowFinish Smart Escrow failures");
using namespace jtx;
using namespace std::chrono;
Account const alice{"alice"};
Account const carol{"carol"};
// Tests whether the ledger index is >= 5
// getLedgerSqn() >= 5}
static auto wasmHex = ledgerSqnWasmHex;
{
// featureSmartEscrow disabled
Env env(*this, features - featureSmartEscrow);
env.fund(XRP(5000), alice, carol);
XRPAmount const txnFees =
env.current()->fees().base * 10 + wasmHex.size() / 2 * 5;
env(escrow::finish(carol, alice, 1),
fee(txnFees),
escrow::comp_allowance(4),
ter(temDISABLED));
env.close();
}
{
// ComputationAllowance > max compute limit
Env env(
*this,
envconfig([](std::unique_ptr<Config> cfg) {
cfg->FEES.extension_compute_limit = 1'000; // in gas
return cfg;
}),
features);
env.fund(XRP(5000), alice, carol);
// Run past the flag ledger so that a Fee change vote occurs and
// updates FeeSettings. (It also activates all supported
// amendments.)
for (auto i = env.current()->seq(); i <= 257; ++i)
env.close();
auto const allowance = 1'001;
env(escrow::finish(carol, alice, 1),
fee(env.current()->fees().base + allowance),
escrow::comp_allowance(allowance),
ter(temBAD_LIMIT));
}
Env env(*this, features);
// Run past the flag ledger so that a Fee change vote occurs and
// updates FeeSettings. (It also activates all supported
// amendments.)
for (auto i = env.current()->seq(); i <= 257; ++i)
env.close();
XRPAmount const txnFees =
env.current()->fees().base * 10 + wasmHex.size() / 2 * 5;
env.fund(XRP(5000), alice, carol);
// create escrow
auto const seq = env.seq(alice);
env(escrow::create(alice, carol, XRP(500)),
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 100s),
fee(txnFees));
env.close();
{
// no ComputationAllowance field
env(escrow::finish(carol, alice, seq),
ter(tefWASM_FIELD_NOT_INCLUDED));
}
{
// ComputationAllowance value of 0
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(0),
ter(temBAD_LIMIT));
}
{
// not enough fees
// This function takes 4 gas
// In testing, 1 gas costs 1 drop
auto const finishFee = env.current()->fees().base + 3;
env(escrow::finish(carol, alice, seq),
fee(finishFee),
escrow::comp_allowance(4),
ter(telINSUF_FEE_P));
}
{
// not enough gas
// This function takes 4 gas
// In testing, 1 gas costs 1 drop
auto const finishFee = env.current()->fees().base + 4;
env(escrow::finish(carol, alice, seq),
fee(finishFee),
escrow::comp_allowance(2),
ter(tecFAILED_PROCESSING));
}
{
// ComputationAllowance field included w/no FinishFunction on
// escrow
auto const seq2 = env.seq(alice);
env(escrow::create(alice, carol, XRP(500)),
escrow::finish_time(env.now() + 10s),
escrow::cancel_time(env.now() + 100s));
env.close();
auto const allowance = 100;
env(escrow::finish(carol, alice, seq2),
fee(env.current()->fees().base +
(allowance * env.current()->fees().gasPrice) /
MICRO_DROPS_PER_DROP +
1),
escrow::comp_allowance(allowance),
ter(tefNO_WASM));
}
}
void
testFinishFunction(FeatureBitset features)
{
testcase("Example escrow function");
using namespace jtx;
using namespace std::chrono;
Account const alice{"alice"};
Account const carol{"carol"};
// Tests whether the ledger index is >= 5
// getLedgerSqn() >= 5}
auto const& wasmHex = ledgerSqnWasmHex;
std::uint32_t const allowance = 66;
auto escrowCreate = escrow::create(alice, carol, XRP(1000));
auto [createFee, finishFee] = [&]() {
Env env(*this, features);
auto createFee =
env.current()->fees().base * 10 + wasmHex.size() / 2 * 5;
auto finishFee = env.current()->fees().base +
(allowance * env.current()->fees().gasPrice) /
MICRO_DROPS_PER_DROP +
1;
return std::make_pair(createFee, finishFee);
}();
{
// basic FinishFunction situation
Env env(*this, features);
// create escrow
env.fund(XRP(5000), alice, carol);
auto const seq = env.seq(alice);
BEAST_EXPECT(env.ownerCount(alice) == 0);
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 100s),
fee(createFee));
env.close();
if (BEAST_EXPECT(env.ownerCount(alice) == 2))
{
env.require(balance(alice, XRP(4000) - createFee));
env.require(balance(carol, XRP(5000)));
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecWASM_REJECTED));
env(escrow::finish(alice, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecWASM_REJECTED));
env(escrow::finish(alice, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecWASM_REJECTED));
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecWASM_REJECTED));
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecWASM_REJECTED));
env.close();
{
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed)))
BEAST_EXPECTS(
env.meta()->getFieldU32(sfGasUsed) == allowance,
std::to_string(env.meta()->getFieldU32(sfGasUsed)));
}
env(escrow::finish(alice, alice, seq),
fee(finishFee),
escrow::comp_allowance(allowance),
ter(tesSUCCESS));
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed)))
BEAST_EXPECTS(
txMeta->getFieldU32(sfGasUsed) == allowance,
std::to_string(txMeta->getFieldU32(sfGasUsed)));
if (BEAST_EXPECT(txMeta->isFieldPresent(sfWasmReturnCode)))
BEAST_EXPECTS(
txMeta->getFieldI32(sfWasmReturnCode) == 5,
std::to_string(txMeta->getFieldI32(sfWasmReturnCode)));
BEAST_EXPECT(env.ownerCount(alice) == 0);
}
}
{
// FinishFunction + Condition
Env env(*this, features);
env.fund(XRP(5000), alice, carol);
BEAST_EXPECT(env.ownerCount(alice) == 0);
auto const seq = env.seq(alice);
// create escrow
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::condition(escrow::cb1),
escrow::cancel_time(env.now() + 100s),
fee(createFee));
env.close();
auto const conditionFinishFee = finishFee +
env.current()->fees().base * (32 + (escrow::fb1.size() / 16));
if (BEAST_EXPECT(env.ownerCount(alice) == 2))
{
env.require(balance(alice, XRP(4000) - createFee));
env.require(balance(carol, XRP(5000)));
// no fulfillment provided, function fails
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecCRYPTOCONDITION_ERROR));
// fulfillment provided, function fails
env(escrow::finish(carol, alice, seq),
escrow::condition(escrow::cb1),
escrow::fulfillment(escrow::fb1),
escrow::comp_allowance(allowance),
fee(conditionFinishFee),
ter(tecWASM_REJECTED));
if (BEAST_EXPECT(env.meta()->isFieldPresent(sfGasUsed)))
BEAST_EXPECTS(
env.meta()->getFieldU32(sfGasUsed) == allowance,
std::to_string(env.meta()->getFieldU32(sfGasUsed)));
env.close();
// no fulfillment provided, function succeeds
env(escrow::finish(alice, alice, seq),
escrow::comp_allowance(allowance),
fee(conditionFinishFee),
ter(tecCRYPTOCONDITION_ERROR));
// wrong fulfillment provided, function succeeds
env(escrow::finish(alice, alice, seq),
escrow::condition(escrow::cb1),
escrow::fulfillment(escrow::fb2),
escrow::comp_allowance(allowance),
fee(conditionFinishFee),
ter(tecCRYPTOCONDITION_ERROR));
// fulfillment provided, function succeeds, tx succeeds
env(escrow::finish(alice, alice, seq),
escrow::condition(escrow::cb1),
escrow::fulfillment(escrow::fb1),
escrow::comp_allowance(allowance),
fee(conditionFinishFee),
ter(tesSUCCESS));
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed)))
BEAST_EXPECT(txMeta->getFieldU32(sfGasUsed) == allowance);
if (BEAST_EXPECT(txMeta->isFieldPresent(sfWasmReturnCode)))
BEAST_EXPECTS(
txMeta->getFieldI32(sfWasmReturnCode) == 6,
std::to_string(txMeta->getFieldI32(sfWasmReturnCode)));
env.close();
BEAST_EXPECT(env.ownerCount(alice) == 0);
}
}
{
// FinishFunction + FinishAfter
Env env(*this, features);
// create escrow
env.fund(XRP(5000), alice, carol);
auto const seq = env.seq(alice);
BEAST_EXPECT(env.ownerCount(alice) == 0);
auto const ts = env.now() + 97s;
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::finish_time(ts),
escrow::cancel_time(env.now() + 1000s),
fee(createFee));
env.close();
if (BEAST_EXPECT(env.ownerCount(alice) == 2))
{
env.require(balance(alice, XRP(4000) - createFee));
env.require(balance(carol, XRP(5000)));
// finish time hasn't passed, function fails
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee + 1),
ter(tecNO_PERMISSION));
env.close();
// finish time hasn't passed, function succeeds
for (; env.now() < ts; env.close())
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee + 2),
ter(tecNO_PERMISSION));
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee + 1),
ter(tesSUCCESS));
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed)))
BEAST_EXPECT(txMeta->getFieldU32(sfGasUsed) == allowance);
if (BEAST_EXPECT(txMeta->isFieldPresent(sfWasmReturnCode)))
BEAST_EXPECTS(
txMeta->getFieldI32(sfWasmReturnCode) == 13,
std::to_string(txMeta->getFieldI32(sfWasmReturnCode)));
BEAST_EXPECT(env.ownerCount(alice) == 0);
}
}
{
// FinishFunction + FinishAfter #2
Env env(*this, features);
// create escrow
env.fund(XRP(5000), alice, carol);
auto const seq = env.seq(alice);
BEAST_EXPECT(env.ownerCount(alice) == 0);
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::finish_time(env.now() + 2s),
escrow::cancel_time(env.now() + 100s),
fee(createFee));
// Don't close the ledger here
if (BEAST_EXPECT(env.ownerCount(alice) == 2))
{
env.require(balance(alice, XRP(4000) - createFee));
env.require(balance(carol, XRP(5000)));
// finish time hasn't passed, function fails
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecNO_PERMISSION));
env.close();
// finish time has passed, function fails
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecWASM_REJECTED));
if (BEAST_EXPECT(env.meta()->isFieldPresent(sfGasUsed)))
BEAST_EXPECTS(
env.meta()->getFieldU32(sfGasUsed) == allowance,
std::to_string(env.meta()->getFieldU32(sfGasUsed)));
env.close();
// finish time has passed, function succeeds, tx succeeds
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tesSUCCESS));
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed)))
BEAST_EXPECT(txMeta->getFieldU32(sfGasUsed) == allowance);
if (BEAST_EXPECT(txMeta->isFieldPresent(sfWasmReturnCode)))
BEAST_EXPECTS(
txMeta->getFieldI32(sfWasmReturnCode) == 6,
std::to_string(txMeta->getFieldI32(sfWasmReturnCode)));
env.close();
BEAST_EXPECT(env.ownerCount(alice) == 0);
}
}
}
void
testUpdateDataOnFailure(FeatureBitset features)
{
testcase("Update escrow data on failure");
using namespace jtx;
using namespace std::chrono;
// wasm that always fails
static auto const wasmHex = updateDataWasmHex;
Account const alice{"alice"};
Account const carol{"carol"};
Env env(*this, features);
// create escrow
env.fund(XRP(5000), alice);
auto const seq = env.seq(alice);
BEAST_EXPECT(env.ownerCount(alice) == 0);
auto escrowCreate = escrow::create(alice, alice, XRP(1000));
XRPAmount txnFees =
env.current()->fees().base * 10 + wasmHex.size() / 2 * 5;
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::finish_time(env.now() + 2s),
escrow::cancel_time(env.now() + 100s),
fee(txnFees));
env.close();
env.close();
env.close();
if (BEAST_EXPECT(
env.ownerCount(alice) == (1 + wasmHex.size() / 2 / 500)))
{
env.require(balance(alice, XRP(4000) - txnFees));
auto const allowance = 1'015;
XRPAmount const finishFee = env.current()->fees().base +
(allowance * env.current()->fees().gasPrice) /
MICRO_DROPS_PER_DROP +
1;
// FinishAfter time hasn't passed
env(escrow::finish(alice, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecWASM_REJECTED));
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta && txMeta->isFieldPresent(sfGasUsed)))
BEAST_EXPECTS(
txMeta->getFieldU32(sfGasUsed) == allowance,
std::to_string(txMeta->getFieldU32(sfGasUsed)));
if (BEAST_EXPECT(txMeta->isFieldPresent(sfWasmReturnCode)))
BEAST_EXPECTS(
txMeta->getFieldI32(sfWasmReturnCode) == -256,
std::to_string(txMeta->getFieldI32(sfWasmReturnCode)));
auto const sle = env.le(keylet::escrow(alice, seq));
if (BEAST_EXPECT(sle && sle->isFieldPresent(sfData)))
BEAST_EXPECTS(
checkVL(sle, sfData, "Data"),
strHex(sle->getFieldVL(sfData)));
}
}
void
testAllHostFunctions(FeatureBitset features)
{
testcase("Test all host functions");
using namespace jtx;
using namespace std::chrono;
// TODO: create wasm module for all host functions
static auto wasmHex = allHostFunctionsWasmHex;
Account const alice{"alice"};
Account const carol{"carol"};
{
Env env(*this, features);
// create escrow
env.fund(XRP(5000), alice, carol);
auto const seq = env.seq(alice);
BEAST_EXPECT(env.ownerCount(alice) == 0);
auto escrowCreate = escrow::create(alice, carol, XRP(1000));
XRPAmount txnFees =
env.current()->fees().base * 10 + wasmHex.size() / 2 * 5;
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::finish_time(env.now() + 11s),
escrow::cancel_time(env.now() + 100s),
escrow::data("1000000000"), // 1000 XRP in drops
fee(txnFees));
env.close();
if (BEAST_EXPECT(
env.ownerCount(alice) == (1 + wasmHex.size() / 2 / 500)))
{
env.require(balance(alice, XRP(4000) - txnFees));
env.require(balance(carol, XRP(5000)));
auto const allowance = 1'000'000;
XRPAmount const finishFee = env.current()->fees().base +
(allowance * env.current()->fees().gasPrice) /
MICRO_DROPS_PER_DROP +
1;
// FinishAfter time hasn't passed
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecNO_PERMISSION));
env.close();
env.close();
env.close();
// reduce the destination balance
env(pay(carol, alice, XRP(4500)));
env.close();
env.close();
env(escrow::finish(alice, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tesSUCCESS));
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta && txMeta->isFieldPresent(sfGasUsed)))
BEAST_EXPECTS(
txMeta->getFieldU32(sfGasUsed) == 38'571,
std::to_string(txMeta->getFieldU32(sfGasUsed)));
if (BEAST_EXPECT(txMeta->isFieldPresent(sfWasmReturnCode)))
BEAST_EXPECT(txMeta->getFieldI32(sfWasmReturnCode) == 1);
env.close();
BEAST_EXPECT(env.ownerCount(alice) == 0);
}
}
}
void
testKeyletHostFunctions(FeatureBitset features)
{
testcase("Test all keylet host functions");
using namespace jtx;
using namespace std::chrono;
// TODO: create wasm module for all host functions
static auto wasmHex = allKeyletsWasmHex;
Account const alice{"alice"};
Account const carol{"carol"};
{
Env env{*this};
env.fund(XRP(10000), alice, carol);
BEAST_EXPECT(env.seq(alice) == 4);
BEAST_EXPECT(env.ownerCount(alice) == 0);
// base objects that need to be created first
auto const tokenId =
token::getNextID(env, alice, 0, tfTransferable);
env(token::mint(alice, 0u), txflags(tfTransferable));
env(trust(alice, carol["USD"](1'000'000)));
env.close();
BEAST_EXPECT(env.seq(alice) == 6);
BEAST_EXPECT(env.ownerCount(alice) == 2);
// set up a bunch of objects to check their keylets
AMM amm(env, carol, XRP(10), carol["USD"](1000));
env(check::create(alice, carol, XRP(100)));
env(credentials::create(alice, alice, "termsandconditions"));
env(delegate::set(alice, carol, {"TrustSet"}));
env(deposit::auth(alice, carol));
env(did::set(alice), did::data("alice_did"));
env(escrow::create(alice, carol, XRP(100)),
escrow::finish_time(env.now() + 100s));
MPTTester mptTester{env, alice, {.fund = false}};
mptTester.create();
mptTester.authorize({.account = carol});
env(token::createOffer(carol, tokenId, XRP(100)),
token::owner(alice));
env(offer(alice, carol["GBP"](0.1), XRP(100)));
env(create(alice, carol, XRP(1000), 100s, alice.pk()));
pdomain::Credentials credentials{{alice, "first credential"}};
env(pdomain::setTx(alice, credentials));
env(signers(alice, 1, {{carol, 1}}));
env(ticket::create(alice, 1));
Vault vault{env};
auto [tx, _keylet] =
vault.create({.owner = alice, .asset = xrpIssue()});
env(tx);
env.close();
BEAST_EXPECTS(
env.ownerCount(alice) == 16,
std::to_string(env.ownerCount(alice)));
if (BEAST_EXPECTS(
env.seq(alice) == 20, std::to_string(env.seq(alice))))
{
auto const seq = env.seq(alice);
XRPAmount txnFees =
env.current()->fees().base * 10 + wasmHex.size() / 2 * 5;
env(escrow::create(alice, carol, XRP(1000)),
escrow::finish_function(wasmHex),
escrow::finish_time(env.now() + 2s),
escrow::cancel_time(env.now() + 100s),
fee(txnFees));
env.close();
env.close();
env.close();
auto const allowance = 137'926;
auto const finishFee = env.current()->fees().base +
(allowance * env.current()->fees().gasPrice) /
MICRO_DROPS_PER_DROP +
1;
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee));
env.close();
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta && txMeta->isFieldPresent(sfGasUsed)))
{
auto const gasUsed = txMeta->getFieldU32(sfGasUsed);
BEAST_EXPECTS(
gasUsed == allowance, std::to_string(gasUsed));
}
BEAST_EXPECTS(
env.ownerCount(alice) == 16,
std::to_string(env.ownerCount(alice)));
}
}
}
void
testWithFeats(FeatureBitset features)
{
testCreateFinishFunctionPreflight(features);
testFinishWasmFailures(features);
testFinishFunction(features);
testUpdateDataOnFailure(features);
// TODO: Update module with new host functions
testAllHostFunctions(features);
testKeyletHostFunctions(features);
}
public:
void
run() override
{
using namespace test::jtx;
FeatureBitset const all{testable_amendments()};
testWithFeats(all);
}
};
BEAST_DEFINE_TESTSUITE(EscrowSmart, app, ripple);
} // namespace test
} // namespace ripple

View File

@@ -17,11 +17,9 @@
*/
//==============================================================================
#include <test/app/wasm_fixtures/fixtures.h>
#include <test/jtx.h>
#include <xrpld/app/tx/applySteps.h>
#include <xrpld/app/wasm/WasmVM.h>
#include <xrpl/ledger/Dir.h>
#include <xrpl/protocol/Feature.h>
@@ -1703,763 +1701,6 @@ struct Escrow_test : public beast::unit_test::suite
}
}
void
testCreateFinishFunctionPreflight(FeatureBitset features)
{
testcase("Test preflight checks involving FinishFunction");
using namespace jtx;
using namespace std::chrono;
Account const alice{"alice"};
Account const carol{"carol"};
// Tests whether the ledger index is >= 5
// getLedgerSqn() >= 5}
static auto wasmHex = ledgerSqnWasmHex;
{
// featureSmartEscrow disabled
Env env(*this, features - featureSmartEscrow);
env.fund(XRP(5000), alice, carol);
XRPAmount const txnFees = env.current()->fees().base + 1000;
auto escrowCreate = escrow::create(alice, carol, XRP(1000));
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 100s),
fee(txnFees),
ter(temDISABLED));
env.close();
}
{
// FinishFunction > max length
Env env(
*this,
envconfig([](std::unique_ptr<Config> cfg) {
cfg->FEES.extension_size_limit = 10; // 10 bytes
return cfg;
}),
features);
XRPAmount const txnFees = env.current()->fees().base + 1000;
// create escrow
env.fund(XRP(5000), alice, carol);
auto escrowCreate = escrow::create(alice, carol, XRP(500));
// 11-byte string
std::string longWasmHex = "00112233445566778899AA";
env(escrowCreate,
escrow::finish_function(longWasmHex),
escrow::cancel_time(env.now() + 100s),
fee(txnFees),
ter(temMALFORMED));
env.close();
}
Env env(
*this,
envconfig([](std::unique_ptr<Config> cfg) {
cfg->START_UP = Config::FRESH;
return cfg;
}),
features);
XRPAmount const txnFees =
env.current()->fees().base * 10 + wasmHex.size() / 2 * 5;
// create escrow
env.fund(XRP(5000), alice, carol);
auto escrowCreate = escrow::create(alice, carol, XRP(500));
// Success situations
{
// FinishFunction + CancelAfter
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 20s),
fee(txnFees));
env.close();
}
{
// FinishFunction + Condition + CancelAfter
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 30s),
escrow::condition(escrow::cb1),
fee(txnFees));
env.close();
}
{
// FinishFunction + FinishAfter + CancelAfter
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 40s),
escrow::finish_time(env.now() + 2s),
fee(txnFees));
env.close();
}
{
// FinishFunction + FinishAfter + Condition + CancelAfter
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 50s),
escrow::condition(escrow::cb1),
escrow::finish_time(env.now() + 2s),
fee(txnFees));
env.close();
}
// Failure situations (i.e. all other combinations)
{
// only FinishFunction
env(escrowCreate,
escrow::finish_function(wasmHex),
fee(txnFees),
ter(temBAD_EXPIRATION));
env.close();
}
{
// FinishFunction + FinishAfter
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::finish_time(env.now() + 2s),
fee(txnFees),
ter(temBAD_EXPIRATION));
env.close();
}
{
// FinishFunction + Condition
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::condition(escrow::cb1),
fee(txnFees),
ter(temBAD_EXPIRATION));
env.close();
}
{
// FinishFunction + FinishAfter + Condition
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::condition(escrow::cb1),
escrow::finish_time(env.now() + 2s),
fee(txnFees),
ter(temBAD_EXPIRATION));
env.close();
}
{
// FinishFunction 0 length
env(escrowCreate,
escrow::finish_function(""),
escrow::cancel_time(env.now() + 60s),
fee(txnFees),
ter(temMALFORMED));
env.close();
}
{
// Not enough fees
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 70s),
fee(txnFees - 1),
ter(telINSUF_FEE_P));
env.close();
}
{
// FinishFunction nonexistent host function
// pub fn finish() -> bool {
// unsafe { host_lib::bad() >= 5 }
// }
auto const badWasmHex =
"0061736d010000000105016000017f02100108686f73745f6c696203626164"
"00000302010005030100100611027f00418080c0000b7f00418080c0000b07"
"2e04066d656d6f727902000666696e69736800010a5f5f646174615f656e64"
"03000b5f5f686561705f6261736503010a09010700100041044a0b004d0970"
"726f64756365727302086c616e6775616765010452757374000c70726f6365"
"737365642d6279010572757374631d312e38352e3120283465623136313235"
"3020323032352d30332d31352900490f7461726765745f6665617475726573"
"042b0f6d757461626c652d676c6f62616c732b087369676e2d6578742b0f72"
"65666572656e63652d74797065732b0a6d756c746976616c7565";
env(escrowCreate,
escrow::finish_function(badWasmHex),
escrow::cancel_time(env.now() + 100s),
fee(txnFees),
ter(temBAD_WASM));
env.close();
}
}
void
testFinishWasmFailures(FeatureBitset features)
{
testcase("EscrowFinish Smart Escrow failures");
using namespace jtx;
using namespace std::chrono;
Account const alice{"alice"};
Account const carol{"carol"};
// Tests whether the ledger index is >= 5
// getLedgerSqn() >= 5}
static auto wasmHex = ledgerSqnWasmHex;
{
// featureSmartEscrow disabled
Env env(*this, features - featureSmartEscrow);
env.fund(XRP(5000), alice, carol);
XRPAmount const txnFees =
env.current()->fees().base * 10 + wasmHex.size() / 2 * 5;
env(escrow::finish(carol, alice, 1),
fee(txnFees),
escrow::comp_allowance(4),
ter(temDISABLED));
env.close();
}
{
// ComputationAllowance > max compute limit
Env env(
*this,
envconfig([](std::unique_ptr<Config> cfg) {
cfg->FEES.extension_compute_limit = 1'000; // in gas
return cfg;
}),
features);
env.fund(XRP(5000), alice, carol);
// Run past the flag ledger so that a Fee change vote occurs and
// updates FeeSettings. (It also activates all supported
// amendments.)
for (auto i = env.current()->seq(); i <= 257; ++i)
env.close();
auto const allowance = 1'001;
env(escrow::finish(carol, alice, 1),
fee(env.current()->fees().base + allowance),
escrow::comp_allowance(allowance),
ter(temBAD_LIMIT));
}
Env env(*this, features);
// Run past the flag ledger so that a Fee change vote occurs and
// updates FeeSettings. (It also activates all supported
// amendments.)
for (auto i = env.current()->seq(); i <= 257; ++i)
env.close();
XRPAmount const txnFees =
env.current()->fees().base * 10 + wasmHex.size() / 2 * 5;
env.fund(XRP(5000), alice, carol);
// create escrow
auto const seq = env.seq(alice);
env(escrow::create(alice, carol, XRP(500)),
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 100s),
fee(txnFees));
env.close();
{
// no ComputationAllowance field
env(escrow::finish(carol, alice, seq),
ter(tefWASM_FIELD_NOT_INCLUDED));
}
{
// ComputationAllowance value of 0
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(0),
ter(temBAD_LIMIT));
}
{
// not enough fees
// This function takes 4 gas
// In testing, 1 gas costs 1 drop
auto const finishFee = env.current()->fees().base + 3;
env(escrow::finish(carol, alice, seq),
fee(finishFee),
escrow::comp_allowance(4),
ter(telINSUF_FEE_P));
}
{
// not enough gas
// This function takes 4 gas
// In testing, 1 gas costs 1 drop
auto const finishFee = env.current()->fees().base + 4;
env(escrow::finish(carol, alice, seq),
fee(finishFee),
escrow::comp_allowance(2),
ter(tecFAILED_PROCESSING));
}
{
// ComputationAllowance field included w/no FinishFunction on
// escrow
auto const seq2 = env.seq(alice);
env(escrow::create(alice, carol, XRP(500)),
escrow::finish_time(env.now() + 10s),
escrow::cancel_time(env.now() + 100s));
env.close();
auto const allowance = 100;
env(escrow::finish(carol, alice, seq2),
fee(env.current()->fees().base +
(allowance * env.current()->fees().gasPrice) /
MICRO_DROPS_PER_DROP +
1),
escrow::comp_allowance(allowance),
ter(tefNO_WASM));
}
}
void
testFinishFunction(FeatureBitset features)
{
testcase("Example escrow function");
using namespace jtx;
using namespace std::chrono;
Account const alice{"alice"};
Account const carol{"carol"};
// Tests whether the ledger index is >= 5
// getLedgerSqn() >= 5}
auto const& wasmHex = ledgerSqnWasmHex;
std::uint32_t const allowance = 66;
auto escrowCreate = escrow::create(alice, carol, XRP(1000));
auto [createFee, finishFee] = [&]() {
Env env(*this, features);
auto createFee =
env.current()->fees().base * 10 + wasmHex.size() / 2 * 5;
auto finishFee = env.current()->fees().base +
(allowance * env.current()->fees().gasPrice) /
MICRO_DROPS_PER_DROP +
1;
return std::make_pair(createFee, finishFee);
}();
{
// basic FinishFunction situation
Env env(*this, features);
// create escrow
env.fund(XRP(5000), alice, carol);
auto const seq = env.seq(alice);
BEAST_EXPECT(env.ownerCount(alice) == 0);
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::cancel_time(env.now() + 100s),
fee(createFee));
env.close();
if (BEAST_EXPECT(env.ownerCount(alice) == 2))
{
env.require(balance(alice, XRP(4000) - createFee));
env.require(balance(carol, XRP(5000)));
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecWASM_REJECTED));
env(escrow::finish(alice, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecWASM_REJECTED));
env(escrow::finish(alice, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecWASM_REJECTED));
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecWASM_REJECTED));
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecWASM_REJECTED));
env.close();
{
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed)))
BEAST_EXPECTS(
env.meta()->getFieldU32(sfGasUsed) == allowance,
std::to_string(env.meta()->getFieldU32(sfGasUsed)));
}
env(escrow::finish(alice, alice, seq),
fee(finishFee),
escrow::comp_allowance(allowance),
ter(tesSUCCESS));
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed)))
BEAST_EXPECTS(
txMeta->getFieldU32(sfGasUsed) == allowance,
std::to_string(txMeta->getFieldU32(sfGasUsed)));
if (BEAST_EXPECT(txMeta->isFieldPresent(sfWasmReturnCode)))
BEAST_EXPECTS(
txMeta->getFieldI32(sfWasmReturnCode) == 5,
std::to_string(txMeta->getFieldI32(sfWasmReturnCode)));
BEAST_EXPECT(env.ownerCount(alice) == 0);
}
}
{
// FinishFunction + Condition
Env env(*this, features);
env.fund(XRP(5000), alice, carol);
BEAST_EXPECT(env.ownerCount(alice) == 0);
auto const seq = env.seq(alice);
// create escrow
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::condition(escrow::cb1),
escrow::cancel_time(env.now() + 100s),
fee(createFee));
env.close();
auto const conditionFinishFee = finishFee +
env.current()->fees().base * (32 + (escrow::fb1.size() / 16));
if (BEAST_EXPECT(env.ownerCount(alice) == 2))
{
env.require(balance(alice, XRP(4000) - createFee));
env.require(balance(carol, XRP(5000)));
// no fulfillment provided, function fails
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecCRYPTOCONDITION_ERROR));
// fulfillment provided, function fails
env(escrow::finish(carol, alice, seq),
escrow::condition(escrow::cb1),
escrow::fulfillment(escrow::fb1),
escrow::comp_allowance(allowance),
fee(conditionFinishFee),
ter(tecWASM_REJECTED));
if (BEAST_EXPECT(env.meta()->isFieldPresent(sfGasUsed)))
BEAST_EXPECTS(
env.meta()->getFieldU32(sfGasUsed) == allowance,
std::to_string(env.meta()->getFieldU32(sfGasUsed)));
env.close();
// no fulfillment provided, function succeeds
env(escrow::finish(alice, alice, seq),
escrow::comp_allowance(allowance),
fee(conditionFinishFee),
ter(tecCRYPTOCONDITION_ERROR));
// wrong fulfillment provided, function succeeds
env(escrow::finish(alice, alice, seq),
escrow::condition(escrow::cb1),
escrow::fulfillment(escrow::fb2),
escrow::comp_allowance(allowance),
fee(conditionFinishFee),
ter(tecCRYPTOCONDITION_ERROR));
// fulfillment provided, function succeeds, tx succeeds
env(escrow::finish(alice, alice, seq),
escrow::condition(escrow::cb1),
escrow::fulfillment(escrow::fb1),
escrow::comp_allowance(allowance),
fee(conditionFinishFee),
ter(tesSUCCESS));
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed)))
BEAST_EXPECT(txMeta->getFieldU32(sfGasUsed) == allowance);
if (BEAST_EXPECT(txMeta->isFieldPresent(sfWasmReturnCode)))
BEAST_EXPECTS(
txMeta->getFieldI32(sfWasmReturnCode) == 6,
std::to_string(txMeta->getFieldI32(sfWasmReturnCode)));
env.close();
BEAST_EXPECT(env.ownerCount(alice) == 0);
}
}
{
// FinishFunction + FinishAfter
Env env(*this, features);
// create escrow
env.fund(XRP(5000), alice, carol);
auto const seq = env.seq(alice);
BEAST_EXPECT(env.ownerCount(alice) == 0);
auto const ts = env.now() + 97s;
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::finish_time(ts),
escrow::cancel_time(env.now() + 1000s),
fee(createFee));
env.close();
if (BEAST_EXPECT(env.ownerCount(alice) == 2))
{
env.require(balance(alice, XRP(4000) - createFee));
env.require(balance(carol, XRP(5000)));
// finish time hasn't passed, function fails
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee + 1),
ter(tecNO_PERMISSION));
env.close();
// finish time hasn't passed, function succeeds
for (; env.now() < ts; env.close())
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee + 2),
ter(tecNO_PERMISSION));
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee + 1),
ter(tesSUCCESS));
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed)))
BEAST_EXPECT(txMeta->getFieldU32(sfGasUsed) == allowance);
if (BEAST_EXPECT(txMeta->isFieldPresent(sfWasmReturnCode)))
BEAST_EXPECTS(
txMeta->getFieldI32(sfWasmReturnCode) == 13,
std::to_string(txMeta->getFieldI32(sfWasmReturnCode)));
BEAST_EXPECT(env.ownerCount(alice) == 0);
}
}
{
// FinishFunction + FinishAfter #2
Env env(*this, features);
// create escrow
env.fund(XRP(5000), alice, carol);
auto const seq = env.seq(alice);
BEAST_EXPECT(env.ownerCount(alice) == 0);
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::finish_time(env.now() + 2s),
escrow::cancel_time(env.now() + 100s),
fee(createFee));
// Don't close the ledger here
if (BEAST_EXPECT(env.ownerCount(alice) == 2))
{
env.require(balance(alice, XRP(4000) - createFee));
env.require(balance(carol, XRP(5000)));
// finish time hasn't passed, function fails
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecNO_PERMISSION));
env.close();
// finish time has passed, function fails
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecWASM_REJECTED));
if (BEAST_EXPECT(env.meta()->isFieldPresent(sfGasUsed)))
BEAST_EXPECTS(
env.meta()->getFieldU32(sfGasUsed) == allowance,
std::to_string(env.meta()->getFieldU32(sfGasUsed)));
env.close();
// finish time has passed, function succeeds, tx succeeds
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tesSUCCESS));
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed)))
BEAST_EXPECT(txMeta->getFieldU32(sfGasUsed) == allowance);
if (BEAST_EXPECT(txMeta->isFieldPresent(sfWasmReturnCode)))
BEAST_EXPECTS(
txMeta->getFieldI32(sfWasmReturnCode) == 6,
std::to_string(txMeta->getFieldI32(sfWasmReturnCode)));
env.close();
BEAST_EXPECT(env.ownerCount(alice) == 0);
}
}
}
void
testAllHostFunctions(FeatureBitset features)
{
testcase("Test all host functions");
using namespace jtx;
using namespace std::chrono;
// TODO: create wasm module for all host functions
static auto wasmHex = allHostFunctionsWasmHex;
Account const alice{"alice"};
Account const carol{"carol"};
{
Env env(*this, features);
// create escrow
env.fund(XRP(5000), alice, carol);
auto const seq = env.seq(alice);
BEAST_EXPECT(env.ownerCount(alice) == 0);
auto escrowCreate = escrow::create(alice, carol, XRP(1000));
XRPAmount txnFees =
env.current()->fees().base * 10 + wasmHex.size() / 2 * 5;
env(escrowCreate,
escrow::finish_function(wasmHex),
escrow::finish_time(env.now() + 11s),
escrow::cancel_time(env.now() + 100s),
escrow::data("1000000000"), // 1000 XRP in drops
fee(txnFees));
env.close();
if (BEAST_EXPECT(
env.ownerCount(alice) == (1 + wasmHex.size() / 2 / 500)))
{
env.require(balance(alice, XRP(4000) - txnFees));
env.require(balance(carol, XRP(5000)));
auto const allowance = 1'000'000;
XRPAmount const finishFee = env.current()->fees().base +
(allowance * env.current()->fees().gasPrice) /
MICRO_DROPS_PER_DROP +
1;
// FinishAfter time hasn't passed
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tecNO_PERMISSION));
env.close();
env.close();
env.close();
// reduce the destination balance
env(pay(carol, alice, XRP(4500)));
env.close();
env.close();
env(escrow::finish(alice, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee),
ter(tesSUCCESS));
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta && txMeta->isFieldPresent(sfGasUsed)))
BEAST_EXPECTS(
txMeta->getFieldU32(sfGasUsed) == 38'571,
std::to_string(txMeta->getFieldU32(sfGasUsed)));
if (BEAST_EXPECT(txMeta->isFieldPresent(sfWasmReturnCode)))
BEAST_EXPECT(txMeta->getFieldI32(sfWasmReturnCode) == 1);
env.close();
BEAST_EXPECT(env.ownerCount(alice) == 0);
}
}
}
void
testKeyletHostFunctions(FeatureBitset features)
{
testcase("Test all keylet host functions");
using namespace jtx;
using namespace std::chrono;
// TODO: create wasm module for all host functions
static auto wasmHex = allKeyletsWasmHex;
Account const alice{"alice"};
Account const carol{"carol"};
{
Env env{*this};
env.fund(XRP(10000), alice, carol);
BEAST_EXPECT(env.seq(alice) == 4);
BEAST_EXPECT(env.ownerCount(alice) == 0);
// base objects that need to be created first
auto const tokenId =
token::getNextID(env, alice, 0, tfTransferable);
env(token::mint(alice, 0u), txflags(tfTransferable));
env(trust(alice, carol["USD"](1'000'000)));
env.close();
BEAST_EXPECT(env.seq(alice) == 6);
BEAST_EXPECT(env.ownerCount(alice) == 2);
// set up a bunch of objects to check their keylets
AMM amm(env, carol, XRP(10), carol["USD"](1000));
env(check::create(alice, carol, XRP(100)));
env(credentials::create(alice, alice, "termsandconditions"));
env(delegate::set(alice, carol, {"TrustSet"}));
env(deposit::auth(alice, carol));
env(did::set(alice), did::data("alice_did"));
env(escrow::create(alice, carol, XRP(100)),
escrow::finish_time(env.now() + 100s));
MPTTester mptTester{env, alice, {.fund = false}};
mptTester.create();
mptTester.authorize({.account = carol});
env(token::createOffer(carol, tokenId, XRP(100)),
token::owner(alice));
env(offer(alice, carol["GBP"](0.1), XRP(100)));
env(create(alice, carol, XRP(1000), 100s, alice.pk()));
pdomain::Credentials credentials{{alice, "first credential"}};
env(pdomain::setTx(alice, credentials));
env(signers(alice, 1, {{carol, 1}}));
env(ticket::create(alice, 1));
Vault vault{env};
auto [tx, _keylet] =
vault.create({.owner = alice, .asset = xrpIssue()});
env(tx);
env.close();
BEAST_EXPECTS(
env.ownerCount(alice) == 16,
std::to_string(env.ownerCount(alice)));
if (BEAST_EXPECTS(
env.seq(alice) == 20, std::to_string(env.seq(alice))))
{
auto const seq = env.seq(alice);
XRPAmount txnFees =
env.current()->fees().base * 10 + wasmHex.size() / 2 * 5;
env(escrow::create(alice, carol, XRP(1000)),
escrow::finish_function(wasmHex),
escrow::finish_time(env.now() + 2s),
escrow::cancel_time(env.now() + 100s),
fee(txnFees));
env.close();
env.close();
env.close();
auto const allowance = 137'926;
auto const finishFee = env.current()->fees().base +
(allowance * env.current()->fees().gasPrice) /
MICRO_DROPS_PER_DROP +
1;
env(escrow::finish(carol, alice, seq),
escrow::comp_allowance(allowance),
fee(finishFee));
env.close();
auto const txMeta = env.meta();
if (BEAST_EXPECT(txMeta && txMeta->isFieldPresent(sfGasUsed)))
{
auto const gasUsed = txMeta->getFieldU32(sfGasUsed);
BEAST_EXPECTS(
gasUsed == allowance, std::to_string(gasUsed));
}
BEAST_EXPECTS(
env.ownerCount(alice) == 16,
std::to_string(env.ownerCount(alice)));
}
}
}
void
testWithFeats(FeatureBitset features)
{
@@ -2475,13 +1716,6 @@ struct Escrow_test : public beast::unit_test::suite
testConsequences(features);
testEscrowWithTickets(features);
testCredentials(features);
testCreateFinishFunctionPreflight(features);
testFinishWasmFailures(features);
testFinishFunction(features);
// TODO: Update module with new host functions
testAllHostFunctions(features);
testKeyletHostFunctions(features);
}
public:
@@ -2492,6 +1726,8 @@ public:
FeatureBitset const all{testable_amendments()};
testWithFeats(all);
testWithFeats(all - featureTokenEscrow);
testWithFeats(all - featureSmartEscrow);
testWithFeats(all - featureTokenEscrow - featureSmartEscrow);
testTags(all - fixIncludeKeyletFields);
}
};

View File

@@ -43,13 +43,17 @@ struct FeeSettingsFields
std::optional<XRPAmount> baseFeeDrops = std::nullopt;
std::optional<XRPAmount> reserveBaseDrops = std::nullopt;
std::optional<XRPAmount> reserveIncrementDrops = std::nullopt;
std::optional<std::uint32_t> extensionComputeLimit = std::nullopt;
std::optional<std::uint32_t> extensionSizeLimit = std::nullopt;
std::optional<std::uint32_t> gasPrice = std::nullopt;
};
STTx
createFeeTx(
Rules const& rules,
std::uint32_t seq,
FeeSettingsFields const& fields)
FeeSettingsFields const& fields,
bool forceAllFields = false)
{
auto fill = [&](auto& obj) {
obj.setAccountID(sfAccount, AccountID());
@@ -83,6 +87,17 @@ createFeeTx(
sfReferenceFeeUnits,
fields.referenceFeeUnits ? *fields.referenceFeeUnits : 0);
}
if (rules.enabled(featureSmartEscrow) || forceAllFields)
{
obj.setFieldU32(
sfExtensionComputeLimit,
fields.extensionComputeLimit ? *fields.extensionComputeLimit
: 0);
obj.setFieldU32(
sfExtensionSizeLimit,
fields.extensionSizeLimit ? *fields.extensionSizeLimit : 0);
obj.setFieldU32(sfGasPrice, fields.gasPrice ? *fields.gasPrice : 0);
}
};
return STTx(ttFEE, fill);
}
@@ -131,6 +146,12 @@ createInvalidFeeTx(
obj.setFieldU32(sfReserveIncrement, 50000);
obj.setFieldU32(sfReferenceFeeUnits, 10);
}
if (rules.enabled(featureSmartEscrow))
{
obj.setFieldU32(sfExtensionComputeLimit, 100 + uniqueValue);
obj.setFieldU32(sfExtensionSizeLimit, 200 + uniqueValue);
obj.setFieldU32(sfGasPrice, 300 + uniqueValue);
}
}
// If missingRequiredFields is true, we don't add the required fields
// (default behavior)
@@ -138,12 +159,12 @@ createInvalidFeeTx(
return STTx(ttFEE, fill);
}
bool
TER
applyFeeAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx)
{
auto const res =
apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal);
return res.ter == tesSUCCESS;
return res.ter;
}
bool
@@ -199,6 +220,25 @@ verifyFeeObject(
if (!checkEquality(sfReferenceFeeUnits, expected.referenceFeeUnits))
return false;
}
if (rules.enabled(featureSmartEscrow))
{
if (!checkEquality(
sfExtensionComputeLimit,
expected.extensionComputeLimit.value_or(0)))
return false;
if (!checkEquality(
sfExtensionSizeLimit, expected.extensionSizeLimit.value_or(0)))
return false;
if (!checkEquality(sfGasPrice, expected.gasPrice.value_or(0)))
return false;
}
else
{
if (feeObject->isFieldPresent(sfExtensionComputeLimit) ||
feeObject->isFieldPresent(sfExtensionSizeLimit) ||
feeObject->isFieldPresent(sfGasPrice))
return false;
}
return true;
}
@@ -359,7 +399,8 @@ class FeeVote_test : public beast::unit_test::suite
auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
OpenView accum(ledger.get());
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
BEAST_EXPECT(
isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
accum.apply(*ledger);
// Verify fee object was created/updated correctly
@@ -388,12 +429,76 @@ class FeeVote_test : public beast::unit_test::suite
auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
OpenView accum(ledger.get());
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
BEAST_EXPECT(
isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
accum.apply(*ledger);
// Verify fee object was created/updated correctly
BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields));
}
// Test with both XRPFees and SmartEscrow enabled
{
jtx::Env env(*this, jtx::testable_amendments());
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
// Create the next ledger to apply transaction to
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
FeeSettingsFields fields{
.baseFeeDrops = XRPAmount{10},
.reserveBaseDrops = XRPAmount{200000},
.reserveIncrementDrops = XRPAmount{50000},
.extensionComputeLimit = 100,
.extensionSizeLimit = 200,
.gasPrice = 300};
// Test successful fee transaction with new fields
auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
OpenView accum(ledger.get());
BEAST_EXPECT(
isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
accum.apply(*ledger);
// Verify fee object was created/updated correctly
BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields));
}
// Test that the Smart Escrow fields are rejected if the
// feature is disabled
{
jtx::Env env(
*this, jtx::testable_amendments() - featureSmartEscrow);
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
// Create the next ledger to apply transaction to
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
FeeSettingsFields fields{
.baseFeeDrops = XRPAmount{10},
.reserveBaseDrops = XRPAmount{200000},
.reserveIncrementDrops = XRPAmount{50000},
.extensionComputeLimit = 100,
.extensionSizeLimit = 200,
.gasPrice = 300};
// Test successful fee transaction with new fields
auto feeTx =
createFeeTx(ledger->rules(), ledger->seq(), fields, true);
OpenView accum(ledger.get());
BEAST_EXPECT(
!isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
}
}
void
@@ -420,12 +525,14 @@ class FeeVote_test : public beast::unit_test::suite
auto invalidTx = createInvalidFeeTx(
ledger->rules(), ledger->seq(), true, false, 1);
OpenView accum(ledger.get());
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
BEAST_EXPECT(
!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
// Test transaction with new format fields when XRPFees is disabled
auto disallowedTx = createInvalidFeeTx(
ledger->rules(), ledger->seq(), false, true, 2);
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, disallowedTx));
BEAST_EXPECT(
!isTesSuccess(applyFeeAndTestResult(env, accum, disallowedTx)));
}
{
@@ -445,12 +552,43 @@ class FeeVote_test : public beast::unit_test::suite
auto invalidTx = createInvalidFeeTx(
ledger->rules(), ledger->seq(), true, false, 3);
OpenView accum(ledger.get());
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
BEAST_EXPECT(
!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
// Test transaction with legacy fields when XRPFees is enabled
auto disallowedTx = createInvalidFeeTx(
ledger->rules(), ledger->seq(), false, true, 4);
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, disallowedTx));
BEAST_EXPECT(
!isTesSuccess(applyFeeAndTestResult(env, accum, disallowedTx)));
}
{
jtx::Env env(
*this,
jtx::testable_amendments() | featureXRPFees |
featureSmartEscrow);
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
// Create the next ledger to apply transaction to
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
// Test transaction with missing required new fields
auto invalidTx = createInvalidFeeTx(
ledger->rules(), ledger->seq(), true, false, 5);
OpenView accum(ledger.get());
BEAST_EXPECT(
!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
// Test transaction with legacy fields when XRPFees is enabled
auto disallowedTx = createInvalidFeeTx(
ledger->rules(), ledger->seq(), false, true, 6);
BEAST_EXPECT(
!isTesSuccess(applyFeeAndTestResult(env, accum, disallowedTx)));
}
}
@@ -489,7 +627,8 @@ class FeeVote_test : public beast::unit_test::suite
// But can be applied to a closed ledger
{
OpenView closedAccum(ledger.get());
BEAST_EXPECT(applyFeeAndTestResult(env, closedAccum, feeTx));
BEAST_EXPECT(
isTesSuccess(applyFeeAndTestResult(env, closedAccum, feeTx)));
}
}
@@ -516,7 +655,8 @@ class FeeVote_test : public beast::unit_test::suite
{
OpenView accum(ledger.get());
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx1));
BEAST_EXPECT(
isTesSuccess(applyFeeAndTestResult(env, accum, feeTx1)));
accum.apply(*ledger);
}
@@ -534,7 +674,8 @@ class FeeVote_test : public beast::unit_test::suite
{
OpenView accum(ledger.get());
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx2));
BEAST_EXPECT(
isTesSuccess(applyFeeAndTestResult(env, accum, feeTx2)));
accum.apply(*ledger);
}
@@ -570,7 +711,7 @@ class FeeVote_test : public beast::unit_test::suite
// The transaction should still succeed as long as other fields are
// valid
// The ledger sequence field is only used for informational purposes
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
}
void
@@ -596,7 +737,8 @@ class FeeVote_test : public beast::unit_test::suite
{
OpenView accum(ledger.get());
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx1));
BEAST_EXPECT(
isTesSuccess(applyFeeAndTestResult(env, accum, feeTx1)));
accum.apply(*ledger);
}
@@ -613,7 +755,8 @@ class FeeVote_test : public beast::unit_test::suite
{
OpenView accum(ledger.get());
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx2));
BEAST_EXPECT(
isTesSuccess(applyFeeAndTestResult(env, accum, feeTx2)));
accum.apply(*ledger);
}
@@ -649,7 +792,8 @@ class FeeVote_test : public beast::unit_test::suite
});
OpenView accum(ledger.get());
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
BEAST_EXPECT(
!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
}
void
@@ -836,6 +980,128 @@ class FeeVote_test : public beast::unit_test::suite
XRPAmount{setup.owner_reserve});
}
void
testDoVotingSmartEscrow()
{
testcase("doVoting with Smart Escrow");
using namespace jtx;
FeeSetup setup;
setup.reference_fee = 42;
setup.account_reserve = 1234567;
setup.owner_reserve = 7654321;
setup.extension_compute_limit = 100;
setup.extension_size_limit = 200;
setup.gas_price = 300;
Env env(
*this, testable_amendments() | featureXRPFees | featureSmartEscrow);
// establish what the current fees are
BEAST_EXPECT(
env.current()->fees().base == XRPAmount{UNIT_TEST_REFERENCE_FEE});
BEAST_EXPECT(env.current()->fees().reserve == XRPAmount{200'000'000});
BEAST_EXPECT(env.current()->fees().increment == XRPAmount{50'000'000});
BEAST_EXPECT(env.current()->fees().extensionComputeLimit == 0);
BEAST_EXPECT(env.current()->fees().extensionSizeLimit == 0);
BEAST_EXPECT(env.current()->fees().gasPrice == 0);
auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
// doVoting requires a flag ledger (every 256th ledger)
// We need to create a ledger at sequence 256 to make it a flag
// ledger
for (int i = 0; i < 256 - 1; ++i)
{
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
}
BEAST_EXPECT(ledger->isFlagLedger());
// Create some mock validations with fee votes
std::vector<std::shared_ptr<STValidation>> validations;
for (int i = 0; i < 5; i++)
{
auto sec = randomSecretKey();
auto pub = derivePublicKey(KeyType::secp256k1, sec);
auto val = std::make_shared<STValidation>(
env.app().timeKeeper().now(),
pub,
sec,
calcNodeID(pub),
[&](STValidation& v) {
v.setFieldU32(sfLedgerSequence, ledger->seq());
// Vote for different fees than current
v.setFieldAmount(
sfBaseFeeDrops, XRPAmount{setup.reference_fee});
v.setFieldAmount(
sfReserveBaseDrops, XRPAmount{setup.account_reserve});
v.setFieldAmount(
sfReserveIncrementDrops,
XRPAmount{setup.owner_reserve});
v.setFieldU32(
sfExtensionComputeLimit, setup.extension_compute_limit);
v.setFieldU32(
sfExtensionSizeLimit, setup.extension_size_limit);
v.setFieldU32(sfGasPrice, setup.gas_price);
});
if (i % 2)
val->setTrusted();
validations.push_back(val);
}
auto txSet = std::make_shared<SHAMap>(
SHAMapType::TRANSACTION, env.app().getNodeFamily());
// This should not throw since we have a flag ledger
feeVote->doVoting(ledger, validations, txSet);
auto const txs = getTxs(txSet);
BEAST_EXPECT(txs.size() == 1);
auto const& feeTx = txs[0];
BEAST_EXPECT(feeTx.getTxnType() == ttFEE);
BEAST_EXPECT(feeTx.getAccountID(sfAccount) == AccountID());
BEAST_EXPECT(feeTx.getFieldU32(sfLedgerSequence) == ledger->seq() + 1);
BEAST_EXPECT(feeTx.isFieldPresent(sfBaseFeeDrops));
BEAST_EXPECT(feeTx.isFieldPresent(sfReserveBaseDrops));
BEAST_EXPECT(feeTx.isFieldPresent(sfReserveIncrementDrops));
// The legacy fields should NOT be present
BEAST_EXPECT(!feeTx.isFieldPresent(sfBaseFee));
BEAST_EXPECT(!feeTx.isFieldPresent(sfReserveBase));
BEAST_EXPECT(!feeTx.isFieldPresent(sfReserveIncrement));
BEAST_EXPECT(!feeTx.isFieldPresent(sfReferenceFeeUnits));
// Check the values
BEAST_EXPECT(
feeTx.getFieldAmount(sfBaseFeeDrops) ==
XRPAmount{setup.reference_fee});
BEAST_EXPECT(
feeTx.getFieldAmount(sfReserveBaseDrops) ==
XRPAmount{setup.account_reserve});
BEAST_EXPECT(
feeTx.getFieldAmount(sfReserveIncrementDrops) ==
XRPAmount{setup.owner_reserve});
BEAST_EXPECT(
feeTx.getFieldU32(sfExtensionComputeLimit) ==
setup.extension_compute_limit);
BEAST_EXPECT(
feeTx.getFieldU32(sfExtensionSizeLimit) ==
setup.extension_size_limit);
BEAST_EXPECT(feeTx.getFieldU32(sfGasPrice) == setup.gas_price);
}
void
run() override
{
@@ -849,6 +1115,7 @@ class FeeVote_test : public beast::unit_test::suite
testSingleInvalidTransaction();
testDoValidation();
testDoVoting();
testDoVotingSmartEscrow();
}
};

View File

@@ -169,44 +169,6 @@ struct HostFuncImpl_test : public beast::unit_test::suite
BEAST_EXPECT(result.value() == env.current()->info().parentHash);
}
void
testGetLedgerAccountHash()
{
testcase("getLedgerAccountHash");
using namespace test::jtx;
Env env{*this};
OpenView ov{*env.current()};
ApplyContext ac = createApplyContext(env, ov);
auto const dummyEscrow =
keylet::escrow(env.master, env.seq(env.master));
WasmHostFunctionsImpl hfs(ac, dummyEscrow);
auto const result = hfs.getLedgerAccountHash();
if (BEAST_EXPECT(result.has_value()))
BEAST_EXPECT(result.value() == env.current()->info().accountHash);
}
void
testGetLedgerTransactionHash()
{
testcase("getLedgerTransactionHash");
using namespace test::jtx;
Env env{*this};
OpenView ov{*env.current()};
ApplyContext ac = createApplyContext(env, ov);
auto const dummyEscrow =
keylet::escrow(env.master, env.seq(env.master));
WasmHostFunctionsImpl hfs(ac, dummyEscrow);
auto const result = hfs.getLedgerTransactionHash();
if (BEAST_EXPECT(result.has_value()))
BEAST_EXPECT(result.value() == env.current()->info().txHash);
}
void
testGetBaseFee()
{
@@ -2900,7 +2862,7 @@ struct HostFuncImpl_test : public beast::unit_test::suite
void
testFloatNonIOU()
{
testcase("Float Xrp+Mpt");
testcase("float Xrp+Mpt");
using namespace test::jtx;
Env env{*this};
@@ -2962,6 +2924,7 @@ struct HostFuncImpl_test : public beast::unit_test::suite
void
testFloats()
{
testFloatTrace();
testFloatFromInt();
testFloatFromUint();
testFloatSet();
@@ -2974,7 +2937,6 @@ struct HostFuncImpl_test : public beast::unit_test::suite
testFloatPower();
testFloatLog();
testFloatNonIOU();
testFloatTrace();
}
void
@@ -2983,8 +2945,6 @@ struct HostFuncImpl_test : public beast::unit_test::suite
testGetLedgerSqn();
testGetParentLedgerTime();
testGetParentLedgerHash();
testGetLedgerAccountHash();
testGetLedgerTransactionHash();
testGetBaseFee();
testIsAmendmentEnabled();
testCacheLedgerObj();

View File

@@ -113,18 +113,6 @@ public:
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
{
@@ -649,18 +637,6 @@ struct PerfHostFunctions : public TestHostFunctions
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
{

View File

@@ -648,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 = 153'296;
auto const allowance = 152'154;
auto re = runEscrowWasm(
wasm, ESCROW_FUNCTION_NAME, {}, &hfs, allowance, env.journal);

View File

@@ -4,8 +4,8 @@
extern crate std;
use crate::host::{Error, Result, Result::Err, Result::Ok};
use xrpl_std::core::ledger_objects::current_escrow::CurrentEscrow;
use xrpl_std::core::ledger_objects::current_escrow::get_current_escrow;
use xrpl_std::core::ledger_objects::current_escrow::CurrentEscrow;
use xrpl_std::core::ledger_objects::ledger_object;
use xrpl_std::core::ledger_objects::traits::CurrentEscrowFields;
use xrpl_std::core::types::amount::asset::{Asset, IouAsset, XrpAsset};
@@ -13,7 +13,7 @@ use xrpl_std::core::types::amount::currency_code::CurrencyCode;
use xrpl_std::core::types::amount::mpt_id::MptId;
use xrpl_std::core::types::keylets;
use xrpl_std::host;
use xrpl_std::host::trace::{DataRepr, trace, trace_account, trace_data, trace_num};
use xrpl_std::host::trace::{trace, trace_account, trace_data, trace_num, DataRepr};
use xrpl_std::sfield;
#[unsafe(no_mangle)]

View File

@@ -6,10 +6,10 @@ version = 4
name = "codecov_tests"
version = "0.0.1"
dependencies = [
"xrpl-std",
"xrpl-wasm-std",
]
[[package]]
name = "xrpl-std"
name = "xrpl-wasm-std"
version = "0.5.1-devnet5"
source = "git+https://github.com/ripple/craft.git?branch=lastdevnet#6b20669b20561b9d0f09678f44ccbddb84ef9f47"
source = "git+https://github.com/ripple/craft.git?branch=main#638276c92d790f5b738faa9f42855f02a2c7c7dc"

View File

@@ -15,4 +15,4 @@ opt-level = 's'
panic = "abort"
[dependencies]
xrpl-std = { git = "https://github.com/ripple/craft.git", branch = "lastdevnet", package = "xrpl-std" }
xrpl-std = { git = "https://github.com/ripple/craft.git", branch = "main", package = "xrpl-wasm-std" }

View File

@@ -68,20 +68,6 @@ pub extern "C" fn finish() -> i32 {
"get_parent_ledger_hash",
);
});
with_buffer::<32, _, _>(|ptr, len| {
check_result(
unsafe { host::get_ledger_account_hash(ptr, len) },
32,
"get_ledger_account_hash",
);
});
with_buffer::<32, _, _>(|ptr, len| {
check_result(
unsafe { host::get_ledger_tx_hash(ptr, len) },
32,
"get_ledger_tx_hash",
);
});
check_result(unsafe { host::get_base_fee() }, 10, "get_base_fee");
let amendment_name: &[u8] = b"test_amendment";
let amendment_id: [u8; 32] = [1; 32];

View File

@@ -9859,314 +9859,308 @@ extern std::string const allKeyletsWasmHex =
extern std::string const codecovTestsWasmHex =
"0061736d0100000001570b60047f7f7f7f017f60057f7f7f7f7f017f60027f7f017f60067f"
"7f7f7f7f7f017f60077f7f7f7f7f7f7f017f6000017f60037f7f7f017f60017f017f60087f"
"7f7f7f7f7f7f7f017f60037f7f7e017f60047f7f7f7f0002da0d3e08686f73745f6c696205"
"7f7f7f7f7f7f7f017f60037f7f7e017f60047f7f7f7f0002990d3c08686f73745f6c696205"
"7472616365000108686f73745f6c69620974726163655f6e756d000908686f73745f6c6962"
"0e6765745f6c65646765725f73716e000508686f73745f6c6962166765745f706172656e74"
"5f6c65646765725f74696d65000508686f73745f6c6962166765745f706172656e745f6c65"
"646765725f68617368000208686f73745f6c6962176765745f6c65646765725f6163636f75"
"6e745f68617368000208686f73745f6c6962126765745f6c65646765725f74785f68617368"
"000208686f73745f6c69620c6765745f626173655f666565000508686f73745f6c69621161"
"6d656e646d656e745f656e61626c6564000208686f73745f6c69620c6765745f74785f6669"
"656c64000608686f73745f6c69620e6163636f756e745f6b65796c6574000008686f73745f"
"6c69621063616368655f6c65646765725f6f626a000608686f73745f6c69621c6765745f63"
"757272656e745f6c65646765725f6f626a5f6669656c64000608686f73745f6c6962146765"
"745f6c65646765725f6f626a5f6669656c64000008686f73745f6c6962136765745f74785f"
"6e65737465645f6669656c64000008686f73745f6c6962236765745f63757272656e745f6c"
"65646765725f6f626a5f6e65737465645f6669656c64000008686f73745f6c69621b676574"
"5f6c65646765725f6f626a5f6e65737465645f6669656c64000108686f73745f6c69621067"
"65745f74785f61727261795f6c656e000708686f73745f6c6962206765745f63757272656e"
"745f6c65646765725f6f626a5f61727261795f6c656e000708686f73745f6c696218676574"
"5f6c65646765725f6f626a5f61727261795f6c656e000208686f73745f6c6962176765745f"
"74785f6e65737465645f61727261795f6c656e000208686f73745f6c6962276765745f6375"
"7272656e745f6c65646765725f6f626a5f6e65737465645f61727261795f6c656e00020868"
"6f73745f6c69621f6765745f6c65646765725f6f626a5f6e65737465645f61727261795f6c"
"656e000608686f73745f6c69620b7570646174655f64617461000208686f73745f6c696213"
"636f6d707574655f7368613531325f68616c66000008686f73745f6c696209636865636b5f"
"736967000308686f73745f6c6962076765745f6e6674000308686f73745f6c69620e676574"
"5f6e66745f697373756572000008686f73745f6c69620d6765745f6e66745f7461786f6e00"
"0008686f73745f6c69620d6765745f6e66745f666c616773000208686f73745f6c69621467"
"65745f6e66745f7472616e736665725f666565000208686f73745f6c69620e6765745f6e66"
"745f73657269616c000008686f73745f6c69620d74726163655f6163636f756e7400000868"
"6f73745f6c69620c74726163655f616d6f756e74000008686f73745f6c69620f666c6f6174"
"5f66726f6d5f75696e74000108686f73745f6c69620b6c696e655f6b65796c657400080868"
"6f73745f6c69620a616d6d5f6b65796c6574000308686f73745f6c69621163726564656e74"
"69616c5f6b65796c6574000808686f73745f6c69620e6d70746f6b656e5f6b65796c657400"
"0308686f73745f6c69621274726163655f6f70617175655f666c6f6174000008686f73745f"
"6c69620d666c6f61745f636f6d70617265000008686f73745f6c696209666c6f61745f6164"
"64000408686f73745f6c69620e666c6f61745f7375627472616374000408686f73745f6c69"
"620e666c6f61745f6d756c7469706c79000408686f73745f6c69620c666c6f61745f646976"
"696465000408686f73745f6c69620a666c6f61745f726f6f74000308686f73745f6c696209"
"666c6f61745f706f77000308686f73745f6c696209666c6f61745f6c6f67000108686f7374"
"5f6c69620c636865636b5f6b65796c6574000108686f73745f6c69620f64656c6567617465"
"5f6b65796c6574000308686f73745f6c6962166465706f7369745f707265617574685f6b65"
"796c6574000308686f73745f6c69620a6469645f6b65796c6574000008686f73745f6c6962"
"0d657363726f775f6b65796c6574000108686f73745f6c6962136d70745f69737375616e63"
"655f6b65796c6574000108686f73745f6c6962106e66745f6f666665725f6b65796c657400"
"0108686f73745f6c69620c6f666665725f6b65796c6574000108686f73745f6c69620d6f72"
"61636c655f6b65796c6574000108686f73745f6c69620e7061796368616e5f6b65796c6574"
"000408686f73745f6c69621a7065726d697373696f6e65645f646f6d61696e5f6b65796c65"
"74000108686f73745f6c69620e7369676e6572735f6b65796c6574000008686f73745f6c69"
"620d7469636b65745f6b65796c6574000108686f73745f6c69620c7661756c745f6b65796c"
"657400010303020a0505030100110619037f01418080c0000b7f00419f9ec0000b7f0041a0"
"9ec0000b072e04066d656d6f727902000666696e697368003f0a5f5f646174615f656e6403"
"010b5f5f686561705f6261736503020ab02b02460002402000200147044020022003410041"
"00410010001a20004100480d01418b80c000410b2000ad1001000b200220032000ac10011a"
"0f0b418b80c000410b2000ac1001000be62a02087f027e230041f0016b22002400419680c0"
"00412341004100410010001a100241b9e00041b980c000410e103e100341b2920441c780c0"
"004116103e200041f0006a22054200370300200041e8006a22034200370300200041e0006a"
"2202420037030020004200370358200041d8006a220141201004412041a58cc0004116103e"
"20054200370300200342003703002002420037030020004200370358200141201005412041"
"bb8cc0004117103e2005420037030020034200370300200242003703002000420037035820"
"0141201006412041d28cc0004112103e1007410a41dd80c000410c103e200041186a428182"
"848890a0c08001370300200041106a428182848890a0c08001370300200041086a42818284"
"8890a0c080013703002000428182848890a0c0800137030041e980c000410e1008410141f7"
"80c0004111103e200041201008410141f780c0004111103e20034100360200200242003703"
"002000420037035802404181802020014114100922044114460440200041266a20002d005a"
"3a00002000200029005f3703c8012000200041e4006a2900003700cd01200041306a200029"
"00cd01370000200020002f01583b01242000200028005b360027200020002903c80137002b"
"20054200370300200342003703002002420037030020004200370358200041246a41142001"
"4120100a22054120470d012000413a6a20002d005a3a0000200041d0016a200041e7006a29"
"00002208370300200041d8016a200041ef006a2900002209370300200041c7006a20083700"
"00200041cf006a2009370000200041d7006a200041f7006a2d00003a0000200020002f0158"
"3b01382000200028005b36003b2000200029005f37003f200041386a41204100100b410141"
"8881c0004110103e2003410036020020024200370300200042003703584181802020014114"
"100c411441e48cc000411c103e200341003602002002420037030020004200370358410141"
"81802020014114100d411441808dc0004114103e024020012001410020016b41037122036a"
"22024f0d0020030440200321050340200141003a0000200141016a2101200541016b22050d"
"000b0b200341016b4107490d000340200141003a0000200141076a41003a0000200141066a"
"41003a0000200141056a41003a0000200141046a41003a0000200141036a41003a00002001"
"41026a41003a0000200141016a41003a0000200141086a22012002470d000b0b200241c400"
"20036b2203417c716a220120024b0440034020024100360200200241046a22022001490d00"
"0b0b024020012003410371220320016a22054f0d002003220204400340200141003a000020"
"0141016a2101200241016b22020d000b0b200341016b4107490d000340200141003a000020"
"0141076a41003a0000200141066a41003a0000200141056a41003a0000200141046a41003a"
"0000200141036a41003a0000200141026a41003a0000200141016a41003a0000200141086a"
"22012005470d000b0b2000418180203602c801410021010340200641c000490440200041d8"
"006a20066a200041c8016a20016a2d00003a0000200020002802980141016a220636029801"
"200141016a22014104470d010b0b200041d8016a22024100360200200041d0016a22044200"
"370300200042003703c801200041d8006a22012006200041c8016a22054114100e41144194"
"8dc0004113103e2002410036020020044200370300200042003703c8012001200028029801"
"20054114100f411441a78dc0004123103e2002410036020020044200370300200042003703"
"c80141012001200028029801200541141010411441ca8dc000411b103e4189803c10114120"
"419881c0004110103e4189803c1012412041a881c0004120103e41014189803c1013412041"
"c881c0004118103e20012000280298011014412041e081c0004117103e2001200028029801"
"1015412041f781c0004127103e4101200120002802980110164120419e82c000411f103e20"
"0041246a220341141017410041bd82c000410b103e200041e0016a22064200370300200242"
"0037030020044200370300200042003703c8012001200028029801200541201018412041e5"
"8dc0004113103e41c882c000410c41d482c000410b41df82c000410e1019410141ed82c000"
"4109103e200041b8016a200041186a290300370300200041b0016a200041106a2903003703"
"00200041a8016a200041086a290300370300200020002903003703a001200241003b010020"
"044200370300200042003703c80120034114200041a0016a2207412020054112101a411241"
"f88dc0004107103e2002410036020020044200370300200042003703c80120074120200541"
"14101b411441ff8dc000410e103e200041003602c8012007412020054104101c4104418d8e"
"c000410d103e20074120101d410841f682c000410d103e20074120101e410a418383c00041"
"14103e200041003602c8012007412020054104101f4104419a8ec000410e103e419783c000"
"410d200341141020412f41a483c000410d103e419783c000410d41b183c000410810214113"
"41b983c000410c103e417f41041004417141c583c000411e103e200041003602c801200541"
"7f1004417141a88ec000411e103e200041ca016a41003a0000200041003b01c80120054103"
"1004417d41c68ec0004124103e200041003602c8012005418094ebdc031004417341ea8ec0"
"004123103e419783c000410d200341141020412f41a483c000410d103e419783c000410d41"
"b183c00041081021411341b983c000410c103e200642003703002002420037030020044200"
"370300200042003703c801200041d894ebdc036a2207410820054120410010224173418d8f"
"c0004117103e200642003703002002420037030020044200370300200042003703c8012001"
"2000280298012005412041001022417141a48fc0004119103e41021011416f41e383c00041"
"1f103e417f20002802980110144171418284c000411f103e2001417f1014417141a184c000"
"411f103e20014181201014417441c084c0004120103e20072000280298011014417341e084"
"c000411f103e20072000280298014101100b417341ff84c0004118103e2001200028029801"
"4101100b4171419785c000411a103e20064200370300200242003703002004420037030020"
"0042003703c801200720002802980120054120100a417341bd8fc0004116103e2006420037"
"03002002420037030020044200370300200042003703c80120012000280298012005412010"
"0a417141d38fc0004118103e20064200370300200242003703002004420037030020004200"
"3703c80120034114200341142007200028029801200541201023417341eb8fc000411c103e"
"200642003703002002420037030020044200370300200042003703c8012003411420034114"
"20012000280298012005412010234171418790c000411e103e200642003703002002420037"
"030020044200370300200042003703c801418b9ec000411420072000280298012005412010"
"24417341a590c0004119103e20064200370300200242003703002004420037030020004200"
"3703c801418b9ec00041142001200028029801200541201024417141be90c000411f103e20"
"0642003703002002420037030020044200370300200042003703c801418b9ec000411441b1"
"85c0004114200541201024417141dd90c0004129103e200642003703002002420037030020"
"044200370300200042003703c80141c585c0004128418b9ec0004114200541201024417141"
"8691c0004125103e200041dc016a200041346a280100360200200041d4016a2000412c6a29"
"0100370200200020002901243702cc01200041808080083602c801200041003b01c0012005"
"4118418b9ec0004114200041c0016a220441021024417141ab91c000410e103e2007200028"
"029801422a1001417341ed85c0004111103e200041003b01c0014102200441021009416f41"
"b991c000411b103e200041003b01c001410220044102100c416f41d491c000412b103e2000"
"41003b01c0014101410220044102100d416f41ff91c0004123103e41021011416f41e383c0"
"00411f103e41021012416f41fe85c000412f103e410141021013416f41ad86c0004127103e"
"41e980c0004181201008417441d486c000411f103e41e980c00041c1001008417441f386c0"
"00411a103e200041003b01c001200141812020044102100e417441a292c0004121103e2000"
"41003b01c001200141812020044102100f417441c392c0004131103e200041003b01c00141"
"012001418120200441021010417441f492c0004129103e200141812010144174418d87c000"
"4125103e20014181201015417441b287c0004135103e410120014181201016417441e787c0"
"00412d103e200141812010174174419488c0004119103e419783c00041812041d482c00041"
"0b41df82c000410e1019417441ed82c0004109103e419783c000410d41d482c00041812041"
"df82c000410e1019417441ed82c0004109103e419783c000410d41d482c000410b41df82c0"
"004181201019417441ed82c0004109103e200041003b01c001200141812020044102101841"
"74419d93c0004121103e200041003b01c001418b9ec000418120418b9ec000411420044102"
"1024417441be93c0004118103e200041003b01c00120034114200341142001418120200441"
"021025417441d693c000411f103e200041003b01c001200541812020034114200441021026"
"417441f593c0004122103e419783c000410d200720002802980141001000417341ad88c000"
"410f103e200042d487b6f4c7d4b1c0003700c001419783c000410d200041c095ebdc036a22"
"0641081027417341bc88c000411c103e419783c000410d20072000280298011021417341d8"
"88c0004116103e20064108200441081028417341ee88c0004118103e200441082006410810"
"284173418689c0004118103e200041003b01ec012006410820044108200041ec016a220241"
"02410010294173419794c0004114103e200041003b01ec0120044108200641082002410241"
"001029417341ab94c0004114103e200041003b01ec01200641082004410820024102410010"
"2a417341bf94c0004119103e200041003b01ec012004410820064108200241024100102a41"
"7341d894c0004119103e200041003b01ec012006410820044108200241024100102b417341"
"f194c0004119103e200041003b01ec012004410820064108200241024100102b4173418a95"
"c0004119103e200041003b01ec012006410820044108200241024100102c417341a395c000"
"4117103e200041003b01ec012004410820064108200241024100102c417341ba95c0004117"
"103e200041003b01ec01200641084103200241024100102d417341d195c0004114103e2000"
"41003b01ec01200641084103200241024100102e417341e595c0004113103e200041003b01"
"ec0120064108200241024100102f417341f895c0004113103e20012000280298014100100b"
"4171419e89c0004123103e200041003b01ec0120034114200120002802980120024102101a"
"4171418b96c000411a103e200041003b01ec01200120002802980120024102101b417141a5"
"96c0004121103e200041003b01ec01200120002802980120024102101c417141c696c00041"
"20103e2001200028029801101d417141c189c0004120103e2001200028029801101e417141"
"e189c0004127103e200041003602ec01200120002802980120024104101f417141e696c000"
"4121103e200041003b01ec01200120002802980120024102100a4171418797c0004123103e"
"200041003b01ec0120012000280298014101200241021030417141aa97c0004121103e2000"
"41003b01ec01200120002802980122062003411420012006200241021025417141cb97c000"
"4127103e200041003b01ec0120034114200120002802980122062001200620024102102541"
"7141f297c0004127103e200041003b01ec0120012000280298012003411420024102103141"
"71419998c0004125103e200041003b01ec0120034114200120002802980120024102103141"
"7141be98c0004125103e200041003b01ec0120012000280298012003411420024102103241"
"7141e398c000412c103e200041003b01ec0120034114200120002802980120024102103241"
"71418f99c000412c103e200041003b01ec012001200028029801200241021033417141bb99"
"c000411f103e200041003b01ec0120012000280298014101200241021034417141da99c000"
"4122103e200041003b01ec0120012000280298012003411441b185c0004114200241021023"
"417141fc99c0004121103e200041003b01ec0120034114200120002802980141b185c00041"
"142002410210234171419d9ac0004121103e200041003b01ec012001200028029801410120"
"0241021035417141be9ac0004128103e200041003b01ec0120054118200120002802980120"
"0241021026417141e69ac0004123103e200041003b01ec0120012000280298014101200241"
"021036417141899bc0004125103e200041003b01ec01200120002802980141012002410210"
"37417141ae9bc0004121103e200041003b01ec012001200028029801410120024102103841"
"7141cf9bc0004122103e200041003b01ec0120012000280298012003411441012002410210"
"39417141f19bc0004124103e200041003b01ec012003411420012000280298014101200241"
"021039417141959cc0004124103e200041003b01ec01200120002802980141012002410210"
"3a417141b99cc000412f103e200041003b01ec01200120002802980120024102103b417141"
"e89cc0004123103e200041003b01ec012001200028029801410120024102103c4171418b9d"
"c0004122103e200041003b01ec012001200028029801410120024102103d417141ad9dc000"
"4121103e200041003b01ec01200120002802980141888ac000412020024102101a417141ce"
"9dc000411c103e419783c000410d20012000280298011020417141a88ac0004122103e4197"
"97abdd03410d41888ac000412041001000417341ca8ac0004110103e419797abdd03410d20"
"0441081027417341da8ac000411d103e419797abdd03410d200341141020417341f78ac000"
"4118103e419797abdd03410d41b183c000410810214173418f8bc0004117103e2001200028"
"029801200141812041001000417441a68bc000410e103e200141812042011001417441b48b"
"c0004112103e419783c000418120200441081027417441c68bc000411b103e419783c00041"
"8120200341141020417441e18bc0004116103e419783c00041812041b183c0004108102141"
"7441f78bc0004115103e419783c000410d200120002802980110214171418c8cc000411910"
"3e200041003b01ec01200120002802980120034114200241021026417141ea9dc000412110"
"3e200041f0016a240041010f0b418080c000410b417f20042004417f4e1bac1001000b4180"
"80c000410b417f20052005417f4e1bac1001000b0bf61d0200418080c0000bc5056572726f"
"725f636f64653d54455354204641494c45442424242424205354415254494e47205741534d"
"20455845435554494f4e2024242424246765745f6c65646765725f73716e6765745f706172"
"656e745f6c65646765725f74696d656765745f626173655f666565746573745f616d656e64"
"6d656e74616d656e646d656e745f656e61626c656463616368655f6c65646765725f6f626a"
"6765745f74785f61727261795f6c656e6765745f63757272656e745f6c65646765725f6f62"
"6a5f61727261795f6c656e6765745f6c65646765725f6f626a5f61727261795f6c656e6765"
"745f74785f6e65737465645f61727261795f6c656e6765745f63757272656e745f6c656467"
"65725f6f626a5f6e65737465645f61727261795f6c656e6765745f6c65646765725f6f626a"
"5f6e65737465645f61727261795f6c656e7570646174655f6461746174657374206d657373"
"61676574657374207075626b657974657374207369676e6174757265636865636b5f736967"
"6765745f6e66745f666c6167736765745f6e66745f7472616e736665725f66656574657374"
"696e6720747261636574726163655f6163636f756e74400000000000005f74726163655f61"
"6d6f756e746765745f706172656e745f6c65646765725f686173685f6e65675f7074726765"
"745f74785f61727261795f6c656e5f696e76616c69645f736669656c646765745f74785f6e"
"65737465645f61727261795f6c656e5f6e65675f7074726765745f74785f6e65737465645f"
"61727261795f6c656e5f6e65675f6c656e6765745f74785f6e65737465645f61727261795f"
"6c656e5f746f6f5f6c6f6e676765745f74785f6e65737465645f61727261795f6c656e5f70"
"74725f6f6f6263616368655f6c65646765725f6f626a5f7074725f6f6f6263616368655f6c"
"65646765725f6f626a5f77726f6e675f6c656e555344303030303030303030303030303030"
"30300041ed85c0000b9e1874726163655f6e756d5f6f6f625f7374726765745f6375727265"
"6e745f6c65646765725f6f626a5f61727261795f6c656e5f696e76616c69645f736669656c"
"646765745f6c65646765725f6f626a5f61727261795f6c656e5f696e76616c69645f736669"
"656c64616d656e646d656e745f656e61626c65645f746f6f5f6269675f736c696365616d65"
"6e646d656e745f656e61626c65645f746f6f5f6c6f6e676765745f74785f6e65737465645f"
"61727261795f6c656e5f746f6f5f6269675f736c6963656765745f63757272656e745f6c65"
"646765725f6f626a5f6e65737465645f61727261795f6c656e5f746f6f5f6269675f736c69"
"63656765745f6c65646765725f6f626a5f6e65737465645f61727261795f6c656e5f746f6f"
"5f6269675f736c6963657570646174655f646174615f746f6f5f6269675f736c6963657472"
"6163655f6f6f625f736c69636574726163655f6f70617175655f666c6f61745f6f6f625f73"
"6c69636574726163655f616d6f756e745f6f6f625f736c696365666c6f61745f636f6d7061"
"72655f6f6f625f736c69636531666c6f61745f636f6d706172655f6f6f625f736c69636532"
"63616368655f6c65646765725f6f626a5f77726f6e675f73697a655f75696e743235366765"
"745f6e66745f666c6167735f77726f6e675f73697a655f75696e743235366765745f6e6674"
"5f7472616e736665725f6665655f77726f6e675f73697a655f75696e743235363030303030"
"30303030303030303030303030303030303030303030303030303174726163655f6163636f"
"756e745f77726f6e675f73697a655f6163636f756e74696474726163655f6f6f625f737472"
"696e6774726163655f6f70617175655f666c6f61745f6f6f625f737472696e677472616365"
"5f6163636f756e745f6f6f625f737472696e6774726163655f616d6f756e745f6f6f625f73"
"7472696e6774726163655f746f6f5f6c6f6e6774726163655f6e756d5f746f6f5f6c6f6e67"
"74726163655f6f70617175655f666c6f61745f746f6f5f6c6f6e6774726163655f6163636f"
"756e745f746f6f5f6c6f6e6774726163655f616d6f756e745f746f6f5f6c6f6e6774726163"
"655f616d6f756e745f77726f6e675f6c656e6774686765745f706172656e745f6c65646765"
"725f686173686765745f6c65646765725f6163636f756e745f686173686765745f6c656467"
"65725f74785f686173686765745f63757272656e745f6c65646765725f6f626a5f6669656c"
"646765745f6c65646765725f6f626a5f6669656c646765745f74785f6e65737465645f6669"
"656c646765745f63757272656e745f6c65646765725f6f626a5f6e65737465645f6669656c"
"646765745f6c65646765725f6f626a5f6e65737465645f6669656c64636f6d707574655f73"
"68613531325f68616c666765745f6e66746765745f6e66745f6973737565726765745f6e66"
"745f7461786f6e6765745f6e66745f73657269616c6765745f706172656e745f6c65646765"
"725f686173685f6e65675f6c656e6765745f706172656e745f6c65646765725f686173685f"
"6275665f746f6f5f736d616c6c6765745f706172656e745f6c65646765725f686173685f6c"
"656e5f746f6f5f6c6f6e67666c6f61745f66726f6d5f75696e745f6c656e5f6f6f62666c6f"
"61745f66726f6d5f75696e745f77726f6e675f6c656e6163636f756e745f6b65796c65745f"
"6c656e5f6f6f626163636f756e745f6b65796c65745f77726f6e675f6c656e6c696e655f6b"
"65796c65745f6c656e5f6f6f625f63757272656e63796c696e655f6b65796c65745f77726f"
"6e675f6c656e5f63757272656e6379616d6d5f6b65796c65745f6c656e5f6f6f625f617373"
"657432616d6d5f6b65796c65745f6c656e5f77726f6e675f6c656e5f617373657432616d6d"
"5f6b65796c65745f6c656e5f77726f6e675f6e6f6e5f7872705f63757272656e63795f6c65"
"6e616d6d5f6b65796c65745f6c656e5f77726f6e675f7872705f63757272656e63795f6c65"
"6e616d6d5f6b65796c65745f6d70746765745f74785f6669656c645f696e76616c69645f73"
"6669656c646765745f63757272656e745f6c65646765725f6f626a5f6669656c645f696e76"
"616c69645f736669656c646765745f6c65646765725f6f626a5f6669656c645f696e76616c"
"69645f736669656c646765745f74785f6e65737465645f6669656c645f746f6f5f6269675f"
"736c6963656765745f63757272656e745f6c65646765725f6f626a5f6e65737465645f6669"
"656c645f746f6f5f6269675f736c6963656765745f6c65646765725f6f626a5f6e65737465"
"645f6669656c645f746f6f5f6269675f736c696365636f6d707574655f7368613531325f68"
"616c665f746f6f5f6269675f736c696365616d6d5f6b65796c65745f746f6f5f6269675f73"
"6c69636563726564656e7469616c5f6b65796c65745f746f6f5f6269675f736c6963656d70"
"746f6b656e5f6b65796c65745f746f6f5f6269675f736c6963655f6d70746964666c6f6174"
"5f6164645f6f6f625f736c69636531666c6f61745f6164645f6f6f625f736c69636532666c"
"6f61745f73756274726163745f6f6f625f736c69636531666c6f61745f7375627472616374"
"5f6f6f625f736c69636532666c6f61745f6d756c7469706c795f6f6f625f736c6963653166"
"6c6f61745f6d756c7469706c795f6f6f625f736c69636532666c6f61745f6469766964655f"
"6f6f625f736c69636531666c6f61745f6469766964655f6f6f625f736c69636532666c6f61"
"745f726f6f745f6f6f625f736c696365666c6f61745f706f775f6f6f625f736c696365666c"
"6f61745f6c6f675f6f6f625f736c6963656765745f6e66745f77726f6e675f73697a655f75"
"696e743235366765745f6e66745f6973737565725f77726f6e675f73697a655f75696e7432"
"35366765745f6e66745f7461786f6e5f77726f6e675f73697a655f75696e74323536676574"
"5f6e66745f73657269616c5f77726f6e675f73697a655f75696e743235366163636f756e74"
"5f6b65796c65745f77726f6e675f73697a655f6163636f756e746964636865636b5f6b6579"
"6c65745f77726f6e675f73697a655f6163636f756e74696463726564656e7469616c5f6b65"
"796c65745f77726f6e675f73697a655f6163636f756e7469643163726564656e7469616c5f"
"6b65796c65745f77726f6e675f73697a655f6163636f756e7469643264656c65676174655f"
"6b65796c65745f77726f6e675f73697a655f6163636f756e7469643164656c65676174655f"
"6b65796c65745f77726f6e675f73697a655f6163636f756e746964326465706f7369745f70"
"7265617574685f6b65796c65745f77726f6e675f73697a655f6163636f756e746964316465"
"706f7369745f707265617574685f6b65796c65745f77726f6e675f73697a655f6163636f75"
"6e746964326469645f6b65796c65745f77726f6e675f73697a655f6163636f756e74696465"
"7363726f775f6b65796c65745f77726f6e675f73697a655f6163636f756e7469646c696e65"
"5f6b65796c65745f77726f6e675f73697a655f6163636f756e746964316c696e655f6b6579"
"6c65745f77726f6e675f73697a655f6163636f756e746964326d70745f69737375616e6365"
"5f6b65796c65745f77726f6e675f73697a655f6163636f756e7469646d70746f6b656e5f6b"
"65796c65745f77726f6e675f73697a655f6163636f756e7469646e66745f6f666665725f6b"
"65796c65745f77726f6e675f73697a655f6163636f756e7469646f666665725f6b65796c65"
"745f77726f6e675f73697a655f6163636f756e7469646f7261636c655f6b65796c65745f77"
"726f6e675f73697a655f6163636f756e7469647061796368616e5f6b65796c65745f77726f"
"6e675f73697a655f6163636f756e746964317061796368616e5f6b65796c65745f77726f6e"
"675f73697a655f6163636f756e746964327065726d697373696f6e65645f646f6d61696e5f"
"6b65796c65745f77726f6e675f73697a655f6163636f756e7469647369676e6572735f6b65"
"796c65745f77726f6e675f73697a655f6163636f756e7469647469636b65745f6b65796c65"
"745f77726f6e675f73697a655f6163636f756e7469647661756c745f6b65796c65745f7772"
"6f6e675f73697a655f6163636f756e7469646765745f6e66745f77726f6e675f73697a655f"
"6163636f756e7469646d70746f6b656e5f6b65796c65745f6d707469645f77726f6e675f6c"
"656e677468004d0970726f64756365727302086c616e6775616765010452757374000c7072"
"6f6365737365642d6279010572757374631d312e39302e3020283131353965373863342032"
"3032352d30392d313429002c0f7461726765745f6665617475726573022b0f6d757461626c"
"652d676c6f62616c732b087369676e2d657874";
"646765725f68617368000208686f73745f6c69620c6765745f626173655f66656500050868"
"6f73745f6c696211616d656e646d656e745f656e61626c6564000208686f73745f6c69620c"
"6765745f74785f6669656c64000608686f73745f6c69620e6163636f756e745f6b65796c65"
"74000008686f73745f6c69621063616368655f6c65646765725f6f626a000608686f73745f"
"6c69621c6765745f63757272656e745f6c65646765725f6f626a5f6669656c64000608686f"
"73745f6c6962146765745f6c65646765725f6f626a5f6669656c64000008686f73745f6c69"
"62136765745f74785f6e65737465645f6669656c64000008686f73745f6c6962236765745f"
"63757272656e745f6c65646765725f6f626a5f6e65737465645f6669656c64000008686f73"
"745f6c69621b6765745f6c65646765725f6f626a5f6e65737465645f6669656c6400010868"
"6f73745f6c6962106765745f74785f61727261795f6c656e000708686f73745f6c69622067"
"65745f63757272656e745f6c65646765725f6f626a5f61727261795f6c656e000708686f73"
"745f6c6962186765745f6c65646765725f6f626a5f61727261795f6c656e000208686f7374"
"5f6c6962176765745f74785f6e65737465645f61727261795f6c656e000208686f73745f6c"
"6962276765745f63757272656e745f6c65646765725f6f626a5f6e65737465645f61727261"
"795f6c656e000208686f73745f6c69621f6765745f6c65646765725f6f626a5f6e65737465"
"645f61727261795f6c656e000608686f73745f6c69620b7570646174655f64617461000208"
"686f73745f6c696213636f6d707574655f7368613531325f68616c66000008686f73745f6c"
"696209636865636b5f736967000308686f73745f6c6962076765745f6e6674000308686f73"
"745f6c69620e6765745f6e66745f697373756572000008686f73745f6c69620d6765745f6e"
"66745f7461786f6e000008686f73745f6c69620d6765745f6e66745f666c61677300020868"
"6f73745f6c6962146765745f6e66745f7472616e736665725f666565000208686f73745f6c"
"69620e6765745f6e66745f73657269616c000008686f73745f6c69620d74726163655f6163"
"636f756e74000008686f73745f6c69620c74726163655f616d6f756e74000008686f73745f"
"6c69620f666c6f61745f66726f6d5f75696e74000108686f73745f6c69620b6c696e655f6b"
"65796c6574000808686f73745f6c69620a616d6d5f6b65796c6574000308686f73745f6c69"
"621163726564656e7469616c5f6b65796c6574000808686f73745f6c69620e6d70746f6b65"
"6e5f6b65796c6574000308686f73745f6c69621274726163655f6f70617175655f666c6f61"
"74000008686f73745f6c69620d666c6f61745f636f6d70617265000008686f73745f6c6962"
"09666c6f61745f616464000408686f73745f6c69620e666c6f61745f737562747261637400"
"0408686f73745f6c69620e666c6f61745f6d756c7469706c79000408686f73745f6c69620c"
"666c6f61745f646976696465000408686f73745f6c69620a666c6f61745f726f6f74000308"
"686f73745f6c696209666c6f61745f706f77000308686f73745f6c696209666c6f61745f6c"
"6f67000108686f73745f6c69620c636865636b5f6b65796c6574000108686f73745f6c6962"
"0f64656c65676174655f6b65796c6574000308686f73745f6c6962166465706f7369745f70"
"7265617574685f6b65796c6574000308686f73745f6c69620a6469645f6b65796c65740000"
"08686f73745f6c69620d657363726f775f6b65796c6574000108686f73745f6c6962136d70"
"745f69737375616e63655f6b65796c6574000108686f73745f6c6962106e66745f6f666665"
"725f6b65796c6574000108686f73745f6c69620c6f666665725f6b65796c6574000108686f"
"73745f6c69620d6f7261636c655f6b65796c6574000108686f73745f6c69620e7061796368"
"616e5f6b65796c6574000408686f73745f6c69621a7065726d697373696f6e65645f646f6d"
"61696e5f6b65796c6574000108686f73745f6c69620e7369676e6572735f6b65796c657400"
"0008686f73745f6c69620d7469636b65745f6b65796c6574000108686f73745f6c69620c76"
"61756c745f6b65796c657400010303020a0505030100110619037f01418080c0000b7f0041"
"f69dc0000b7f0041809ec0000b072e04066d656d6f727902000666696e697368003d0a5f5f"
"646174615f656e6403010b5f5f686561705f6261736503020ac12a02460002402000200147"
"04402002200341004100410010001a20004100480d01418b80c000410b2000ad1001000b20"
"0220032000ac10011a0f0b418b80c000410b2000ac1001000bf72902087f027e230041f001"
"6b22002400419680c000412341004100410010001a100241b9e00041b980c000410e103c10"
"0341b2920441c780c0004116103c200041f0006a22034200370300200041e8006a22044200"
"370300200041e0006a2202420037030020004200370358200041d8006a2201412010044120"
"41a58cc0004116103c1005410a41dd80c000410c103c200041186a428182848890a0c08001"
"370300200041106a428182848890a0c08001370300200041086a428182848890a0c0800137"
"03002000428182848890a0c0800137030041e980c000410e1006410141f780c0004111103c"
"200041201006410141f780c0004111103c2004410036020020024200370300200042003703"
"5841818020200141141007220541144604400240200041266a20002d005a3a000020002000"
"29005f3703c8012000200041e4006a2900003700cd01200041306a20002900cd0137000020"
"0020002f01583b01242000200028005b360027200020002903c80137002b20034200370300"
"200442003703002002420037030020004200370358200041246a4114200141201008220541"
"20470d002000413a6a20002d005a3a0000200041d0016a200041e7006a2900002208370300"
"200041d8016a200041ef006a2900002209370300200041c7006a2008370000200041cf006a"
"2009370000200041d7006a200041f7006a2d00003a0000200020002f01583b013820002000"
"28005b36003b2000200029005f37003f200041386a4120410010094101418881c000411010"
"3c2004410036020020024200370300200042003703584181802020014114100a411441bb8c"
"c000411c103c20044100360200200242003703002000420037035841014181802020014114"
"100b411441d78cc0004114103c02402001410020016b41037122046a220220014d0d002004"
"0440200421050340200141003a0000200141016a2101200541016b22050d000b0b20044101"
"6b4107490d000340200141003a0000200141076a41003a0000200141066a41003a00002001"
"41056a41003a0000200141046a41003a0000200141036a41003a0000200141026a41003a00"
"00200141016a41003a0000200141086a22012002470d000b0b200241c40020046b2204417c"
"716a220120024b0440034020024100360200200241046a22022001490d000b0b0240200120"
"04410371220420016a22054f0d002004220204400340200141003a0000200141016a210120"
"0241016b22020d000b0b200441016b4107490d000340200141003a0000200141076a41003a"
"0000200141066a41003a0000200141056a41003a0000200141046a41003a0000200141036a"
"41003a0000200141026a41003a0000200141016a41003a0000200141086a22012005470d00"
"0b0b2000418180203602c801410021010340200641c000490440200041d8006a20066a2000"
"41c8016a20016a2d00003a0000200020002802980141016a220636029801200141016a2201"
"4104470d010b0b200041d8016a22024100360200200041d0016a2203420037030020004200"
"3703c801200041d8006a22012006200041c8016a22054114100c411441eb8cc0004113103c"
"2002410036020020034200370300200042003703c801200120002802980120054114100d41"
"1441fe8cc0004123103c2002410036020020034200370300200042003703c8014101200120"
"002802980120054114100e411441a18dc000411b103c4189803c100f4120419881c0004110"
"103c4189803c1010412041a881c0004120103c41014189803c1011412041c881c000411810"
"3c20012000280298011012412041e081c0004117103c20012000280298011013412041f781"
"c0004127103c4101200120002802980110144120419e82c000411f103c200041246a220441"
"141015410041bd82c000410b103c200041e0016a2206420037030020024200370300200342"
"00370300200042003703c8012001200028029801200541201016412041bc8dc0004113103c"
"41c882c000410c41d482c000410b41df82c000410e1017410141ed82c0004109103c200041"
"b8016a200041186a290300370300200041b0016a200041106a290300370300200041a8016a"
"200041086a290300370300200020002903003703a001200241003b01002003420037030020"
"0042003703c80120044114200041a0016a22074120200541121018411241cf8dc000410710"
"3c2002410036020020034200370300200042003703c80120074120200541141019411441d6"
"8dc000410e103c200041003602c8012007412020054104101a410441e48dc000410d103c20"
"074120101b410841f682c000410d103c20074120101c410a418383c0004114103c20004100"
"3602c8012007412020054104101d410441f18dc000410e103c419783c000410d2004411410"
"1e412f41a483c000410d103c419783c000410d41b183c0004108101f411341b983c000410c"
"103c417f41041004417141c583c000411e103c200041003602c8012005417f1004417141ff"
"8dc000411e103c200041ca016a41003a0000200041003b01c801200541031004417d419d8e"
"c0004124103c200041003602c8012005418094ebdc031004417341c18ec0004123103c4197"
"83c000410d20044114101e412f41a483c000410d103c419783c000410d41b183c000410810"
"1f411341b983c000410c103c20064200370300200242003703002003420037030020004200"
"3703c801200041d894ebdc036a220741082005412041001020417341e48ec0004117103c20"
"0642003703002002420037030020034200370300200042003703c801200120002802980120"
"05412041001020417141fb8ec0004119103c4102100f416f41e383c000411f103c417f2000"
"2802980110124171418284c000411f103c2001417f1012417141a184c000411f103c200141"
"81201012417441c084c0004120103c20072000280298011012417341e084c000411f103c20"
"0720002802980141011009417341ff84c0004118103c200120002802980141011009417141"
"9785c000411a103c200642003703002002420037030020034200370300200042003703c801"
"2007200028029801200541201008417341948fc0004116103c200642003703002002420037"
"030020034200370300200042003703c8012001200028029801200541201008417141aa8fc0"
"004118103c200642003703002002420037030020034200370300200042003703c801200441"
"14200441142007200028029801200541201021417341c28fc000411c103c20064200370300"
"2002420037030020034200370300200042003703c801200441142004411420012000280298"
"01200541201021417141de8fc000411e103c20064200370300200242003703002003420037"
"0300200042003703c80141e29dc00041142007200028029801200541201022417341fc8fc0"
"004119103c200642003703002002420037030020034200370300200042003703c80141e29d"
"c000411420012000280298012005412010224171419590c000411f103c2006420037030020"
"02420037030020034200370300200042003703c80141e29dc000411441b185c00041142005"
"41201022417141b490c0004129103c20064200370300200242003703002003420037030020"
"0042003703c80141c585c000412841e29dc0004114200541201022417141dd90c000412510"
"3c200041dc016a200041346a280100360200200041d4016a2000412c6a2901003702002000"
"20002901243702cc01200041808080083602c801200041003b01c0012005411841e29dc000"
"4114200041c0016a2203410210224171418291c000410e103c2007200028029801422a1001"
"417341ed85c0004111103c200041003b01c0014102200341021007416f419091c000411b10"
"3c200041003b01c001410220034102100a416f41ab91c000412b103c200041003b01c00141"
"01410220034102100b416f41d691c0004123103c4102100f416f41e383c000411f103c4102"
"1010416f41fe85c000412f103c410141021011416f41ad86c0004127103c41e980c0004181"
"201006417441d486c000411f103c41e980c00041c1001006417441f386c000411a103c2000"
"41003b01c001200141812020034102100c417441f991c0004121103c200041003b01c00120"
"0141812020034102100d4174419a92c0004131103c200041003b01c0014101200141812020"
"034102100e417441cb92c0004129103c200141812010124174418d87c0004125103c200141"
"81201013417441b287c0004135103c410120014181201014417441e787c000412d103c2001"
"41812010154174419488c0004119103c419783c00041812041d482c000410b41df82c00041"
"0e1017417441ed82c0004109103c419783c000410d41d482c00041812041df82c000410e10"
"17417441ed82c0004109103c419783c000410d41d482c000410b41df82c000418120101741"
"7441ed82c0004109103c200041003b01c0012001418120200341021016417441f492c00041"
"21103c200041003b01c00141e29dc00041812041e29dc00041142003410210224174419593"
"c0004118103c200041003b01c00120044114200441142001418120200341021023417441ad"
"93c000411f103c200041003b01c001200541812020044114200341021024417441cc93c000"
"4122103c419783c000410d200720002802980141001000417341ad88c000410f103c200042"
"d487b6f4c7d4b1c0003700c001419783c000410d200041c095ebdc036a2206410810254173"
"41bc88c000411c103c419783c000410d2007200028029801101f417341d888c0004116103c"
"20064108200341081026417341ee88c0004118103c200341082006410810264173418689c0"
"004118103c200041003b01ec012006410820034108200041ec016a22024102410010274173"
"41ee93c0004114103c200041003b01ec012003410820064108200241024100102741734182"
"94c0004114103c200041003b01ec01200641082003410820024102410010284173419694c0"
"004119103c200041003b01ec0120034108200641082002410241001028417341af94c00041"
"19103c200041003b01ec0120064108200341082002410241001029417341c894c000411910"
"3c200041003b01ec0120034108200641082002410241001029417341e194c0004119103c20"
"0041003b01ec012006410820034108200241024100102a417341fa94c0004117103c200041"
"003b01ec012003410820064108200241024100102a4173419195c0004117103c200041003b"
"01ec01200641084103200241024100102b417341a895c0004114103c200041003b01ec0120"
"0641084103200241024100102c417341bc95c0004113103c200041003b01ec012006410820"
"0241024100102d417341cf95c0004113103c2001200028029801410010094171419e89c000"
"4123103c200041003b01ec01200441142001200028029801200241021018417141e295c000"
"411a103c200041003b01ec012001200028029801200241021019417141fc95c0004121103c"
"200041003b01ec01200120002802980120024102101a4171419d96c0004120103c20012000"
"28029801101b417141c189c0004120103c2001200028029801101c417141e189c000412710"
"3c200041003602ec01200120002802980120024104101d417141bd96c0004121103c200041"
"003b01ec012001200028029801200241021008417141de96c0004123103c200041003b01ec"
"012001200028029801410120024102102e4171418197c0004121103c200041003b01ec0120"
"0120002802980122062004411420012006200241021023417141a297c0004127103c200041"
"003b01ec01200441142001200028029801220620012006200241021023417141c997c00041"
"27103c200041003b01ec0120012000280298012004411420024102102f417141f097c00041"
"25103c200041003b01ec0120044114200120002802980120024102102f4171419598c00041"
"25103c200041003b01ec01200120002802980120044114200241021030417141ba98c00041"
"2c103c200041003b01ec01200441142001200028029801200241021030417141e698c00041"
"2c103c200041003b01ec0120012000280298012002410210314171419299c000411f103c20"
"0041003b01ec0120012000280298014101200241021032417141b199c0004122103c200041"
"003b01ec0120012000280298012004411441b185c0004114200241021021417141d399c000"
"4121103c200041003b01ec0120044114200120002802980141b185c0004114200241021021"
"417141f499c0004121103c200041003b01ec01200120002802980141012002410210334171"
"41959ac0004128103c200041003b01ec012005411820012000280298012002410210244171"
"41bd9ac0004123103c200041003b01ec0120012000280298014101200241021034417141e0"
"9ac0004125103c200041003b01ec0120012000280298014101200241021035417141859bc0"
"004121103c200041003b01ec0120012000280298014101200241021036417141a69bc00041"
"22103c200041003b01ec012001200028029801200441144101200241021037417141c89bc0"
"004124103c200041003b01ec012004411420012000280298014101200241021037417141ec"
"9bc0004124103c200041003b01ec0120012000280298014101200241021038417141909cc0"
"00412f103c200041003b01ec012001200028029801200241021039417141bf9cc000412310"
"3c200041003b01ec012001200028029801410120024102103a417141e29cc0004122103c20"
"0041003b01ec012001200028029801410120024102103b417141849dc0004121103c200041"
"003b01ec01200120002802980141888ac0004120200241021018417141a59dc000411c103c"
"419783c000410d2001200028029801101e417141a88ac0004122103c419797abdd03410d41"
"888ac000412041001000417341ca8ac0004110103c419797abdd03410d2003410810254173"
"41da8ac000411d103c419797abdd03410d20044114101e417341f78ac0004118103c419797"
"abdd03410d41b183c0004108101f4173418f8bc0004117103c200120002802980120014181"
"2041001000417441a68bc000410e103c200141812042011001417441b48bc0004112103c41"
"9783c000418120200341081025417441c68bc000411b103c419783c0004181202004411410"
"1e417441e18bc0004116103c419783c00041812041b183c0004108101f417441f78bc00041"
"15103c419783c000410d2001200028029801101f4171418c8cc0004119103c200041003b01"
"ec01200120002802980120044114200241021024417141c19dc0004121103c200041f0016a"
"240041010f0b0b418080c000410b417f20052005417f4e1bac1001000b0bcd1d0200418080"
"c0000bc5056572726f725f636f64653d54455354204641494c454424242424242053544152"
"54494e47205741534d20455845435554494f4e2024242424246765745f6c65646765725f73"
"716e6765745f706172656e745f6c65646765725f74696d656765745f626173655f66656574"
"6573745f616d656e646d656e74616d656e646d656e745f656e61626c656463616368655f6c"
"65646765725f6f626a6765745f74785f61727261795f6c656e6765745f63757272656e745f"
"6c65646765725f6f626a5f61727261795f6c656e6765745f6c65646765725f6f626a5f6172"
"7261795f6c656e6765745f74785f6e65737465645f61727261795f6c656e6765745f637572"
"72656e745f6c65646765725f6f626a5f6e65737465645f61727261795f6c656e6765745f6c"
"65646765725f6f626a5f6e65737465645f61727261795f6c656e7570646174655f64617461"
"74657374206d65737361676574657374207075626b657974657374207369676e6174757265"
"636865636b5f7369676765745f6e66745f666c6167736765745f6e66745f7472616e736665"
"725f66656574657374696e6720747261636574726163655f6163636f756e74400000000000"
"005f74726163655f616d6f756e746765745f706172656e745f6c65646765725f686173685f"
"6e65675f7074726765745f74785f61727261795f6c656e5f696e76616c69645f736669656c"
"646765745f74785f6e65737465645f61727261795f6c656e5f6e65675f7074726765745f74"
"785f6e65737465645f61727261795f6c656e5f6e65675f6c656e6765745f74785f6e657374"
"65645f61727261795f6c656e5f746f6f5f6c6f6e676765745f74785f6e65737465645f6172"
"7261795f6c656e5f7074725f6f6f6263616368655f6c65646765725f6f626a5f7074725f6f"
"6f6263616368655f6c65646765725f6f626a5f77726f6e675f6c656e555344303030303030"
"30303030303030303030300041ed85c0000bf51774726163655f6e756d5f6f6f625f737472"
"6765745f63757272656e745f6c65646765725f6f626a5f61727261795f6c656e5f696e7661"
"6c69645f736669656c646765745f6c65646765725f6f626a5f61727261795f6c656e5f696e"
"76616c69645f736669656c64616d656e646d656e745f656e61626c65645f746f6f5f626967"
"5f736c696365616d656e646d656e745f656e61626c65645f746f6f5f6c6f6e676765745f74"
"785f6e65737465645f61727261795f6c656e5f746f6f5f6269675f736c6963656765745f63"
"757272656e745f6c65646765725f6f626a5f6e65737465645f61727261795f6c656e5f746f"
"6f5f6269675f736c6963656765745f6c65646765725f6f626a5f6e65737465645f61727261"
"795f6c656e5f746f6f5f6269675f736c6963657570646174655f646174615f746f6f5f6269"
"675f736c69636574726163655f6f6f625f736c69636574726163655f6f70617175655f666c"
"6f61745f6f6f625f736c69636574726163655f616d6f756e745f6f6f625f736c696365666c"
"6f61745f636f6d706172655f6f6f625f736c69636531666c6f61745f636f6d706172655f6f"
"6f625f736c6963653263616368655f6c65646765725f6f626a5f77726f6e675f73697a655f"
"75696e743235366765745f6e66745f666c6167735f77726f6e675f73697a655f75696e7432"
"35366765745f6e66745f7472616e736665725f6665655f77726f6e675f73697a655f75696e"
"74323536303030303030303030303030303030303030303030303030303030303030303174"
"726163655f6163636f756e745f77726f6e675f73697a655f6163636f756e74696474726163"
"655f6f6f625f737472696e6774726163655f6f70617175655f666c6f61745f6f6f625f7374"
"72696e6774726163655f6163636f756e745f6f6f625f737472696e6774726163655f616d6f"
"756e745f6f6f625f737472696e6774726163655f746f6f5f6c6f6e6774726163655f6e756d"
"5f746f6f5f6c6f6e6774726163655f6f70617175655f666c6f61745f746f6f5f6c6f6e6774"
"726163655f6163636f756e745f746f6f5f6c6f6e6774726163655f616d6f756e745f746f6f"
"5f6c6f6e6774726163655f616d6f756e745f77726f6e675f6c656e6774686765745f706172"
"656e745f6c65646765725f686173686765745f63757272656e745f6c65646765725f6f626a"
"5f6669656c646765745f6c65646765725f6f626a5f6669656c646765745f74785f6e657374"
"65645f6669656c646765745f63757272656e745f6c65646765725f6f626a5f6e6573746564"
"5f6669656c646765745f6c65646765725f6f626a5f6e65737465645f6669656c64636f6d70"
"7574655f7368613531325f68616c666765745f6e66746765745f6e66745f69737375657267"
"65745f6e66745f7461786f6e6765745f6e66745f73657269616c6765745f706172656e745f"
"6c65646765725f686173685f6e65675f6c656e6765745f706172656e745f6c65646765725f"
"686173685f6275665f746f6f5f736d616c6c6765745f706172656e745f6c65646765725f68"
"6173685f6c656e5f746f6f5f6c6f6e67666c6f61745f66726f6d5f75696e745f6c656e5f6f"
"6f62666c6f61745f66726f6d5f75696e745f77726f6e675f6c656e6163636f756e745f6b65"
"796c65745f6c656e5f6f6f626163636f756e745f6b65796c65745f77726f6e675f6c656e6c"
"696e655f6b65796c65745f6c656e5f6f6f625f63757272656e63796c696e655f6b65796c65"
"745f77726f6e675f6c656e5f63757272656e6379616d6d5f6b65796c65745f6c656e5f6f6f"
"625f617373657432616d6d5f6b65796c65745f6c656e5f77726f6e675f6c656e5f61737365"
"7432616d6d5f6b65796c65745f6c656e5f77726f6e675f6e6f6e5f7872705f63757272656e"
"63795f6c656e616d6d5f6b65796c65745f6c656e5f77726f6e675f7872705f63757272656e"
"63795f6c656e616d6d5f6b65796c65745f6d70746765745f74785f6669656c645f696e7661"
"6c69645f736669656c646765745f63757272656e745f6c65646765725f6f626a5f6669656c"
"645f696e76616c69645f736669656c646765745f6c65646765725f6f626a5f6669656c645f"
"696e76616c69645f736669656c646765745f74785f6e65737465645f6669656c645f746f6f"
"5f6269675f736c6963656765745f63757272656e745f6c65646765725f6f626a5f6e657374"
"65645f6669656c645f746f6f5f6269675f736c6963656765745f6c65646765725f6f626a5f"
"6e65737465645f6669656c645f746f6f5f6269675f736c696365636f6d707574655f736861"
"3531325f68616c665f746f6f5f6269675f736c696365616d6d5f6b65796c65745f746f6f5f"
"6269675f736c69636563726564656e7469616c5f6b65796c65745f746f6f5f6269675f736c"
"6963656d70746f6b656e5f6b65796c65745f746f6f5f6269675f736c6963655f6d70746964"
"666c6f61745f6164645f6f6f625f736c69636531666c6f61745f6164645f6f6f625f736c69"
"636532666c6f61745f73756274726163745f6f6f625f736c69636531666c6f61745f737562"
"74726163745f6f6f625f736c69636532666c6f61745f6d756c7469706c795f6f6f625f736c"
"69636531666c6f61745f6d756c7469706c795f6f6f625f736c69636532666c6f61745f6469"
"766964655f6f6f625f736c69636531666c6f61745f6469766964655f6f6f625f736c696365"
"32666c6f61745f726f6f745f6f6f625f736c696365666c6f61745f706f775f6f6f625f736c"
"696365666c6f61745f6c6f675f6f6f625f736c6963656765745f6e66745f77726f6e675f73"
"697a655f75696e743235366765745f6e66745f6973737565725f77726f6e675f73697a655f"
"75696e743235366765745f6e66745f7461786f6e5f77726f6e675f73697a655f75696e7432"
"35366765745f6e66745f73657269616c5f77726f6e675f73697a655f75696e743235366163"
"636f756e745f6b65796c65745f77726f6e675f73697a655f6163636f756e74696463686563"
"6b5f6b65796c65745f77726f6e675f73697a655f6163636f756e74696463726564656e7469"
"616c5f6b65796c65745f77726f6e675f73697a655f6163636f756e7469643163726564656e"
"7469616c5f6b65796c65745f77726f6e675f73697a655f6163636f756e7469643264656c65"
"676174655f6b65796c65745f77726f6e675f73697a655f6163636f756e7469643164656c65"
"676174655f6b65796c65745f77726f6e675f73697a655f6163636f756e746964326465706f"
"7369745f707265617574685f6b65796c65745f77726f6e675f73697a655f6163636f756e74"
"6964316465706f7369745f707265617574685f6b65796c65745f77726f6e675f73697a655f"
"6163636f756e746964326469645f6b65796c65745f77726f6e675f73697a655f6163636f75"
"6e746964657363726f775f6b65796c65745f77726f6e675f73697a655f6163636f756e7469"
"646c696e655f6b65796c65745f77726f6e675f73697a655f6163636f756e746964316c696e"
"655f6b65796c65745f77726f6e675f73697a655f6163636f756e746964326d70745f697373"
"75616e63655f6b65796c65745f77726f6e675f73697a655f6163636f756e7469646d70746f"
"6b656e5f6b65796c65745f77726f6e675f73697a655f6163636f756e7469646e66745f6f66"
"6665725f6b65796c65745f77726f6e675f73697a655f6163636f756e7469646f666665725f"
"6b65796c65745f77726f6e675f73697a655f6163636f756e7469646f7261636c655f6b6579"
"6c65745f77726f6e675f73697a655f6163636f756e7469647061796368616e5f6b65796c65"
"745f77726f6e675f73697a655f6163636f756e746964317061796368616e5f6b65796c6574"
"5f77726f6e675f73697a655f6163636f756e746964327065726d697373696f6e65645f646f"
"6d61696e5f6b65796c65745f77726f6e675f73697a655f6163636f756e7469647369676e65"
"72735f6b65796c65745f77726f6e675f73697a655f6163636f756e7469647469636b65745f"
"6b65796c65745f77726f6e675f73697a655f6163636f756e7469647661756c745f6b65796c"
"65745f77726f6e675f73697a655f6163636f756e7469646765745f6e66745f77726f6e675f"
"73697a655f6163636f756e7469646d70746f6b656e5f6b65796c65745f6d707469645f7772"
"6f6e675f6c656e677468004d0970726f64756365727302086c616e67756167650104527573"
"74000c70726f6365737365642d6279010572757374631d312e38352e312028346562313631"
"32353020323032352d30332d313529002c0f7461726765745f6665617475726573022b0f6d"
"757461626c652d676c6f62616c732b087369676e2d657874";
extern std::string const floatTestsWasmHex =
"0061736d0100000001430860077f7f7f7f7f7f7f017f60057f7f7f7f7f017f60047f7f7f7f"
@@ -10330,3 +10324,21 @@ extern std::string const disabledFloatHex =
"6503050b5f5f686561705f6261736503060a5f5f686561705f656e640307"
"0d5f5f6d656d6f72795f6261736503080c5f5f7461626c655f6261736503"
"090a150202000b100043000000c54300200045921a41010b";
extern std::string const updateDataWasmHex =
"0061736d01000000010e0360027f7f017f6000006000017f02130103656e760b7570646174"
"655f64617461000003030201020503010002063f0a7f01419088040b7f004180080b7f0041"
"85080b7f004190080b7f00419088040b7f004180080b7f00419088040b7f00418080080b7f"
"0041000b7f0041010b07aa010c066d656d6f72790200115f5f7761736d5f63616c6c5f6374"
"6f727300010666696e69736800020c5f5f64736f5f68616e646c6503010a5f5f646174615f"
"656e6403020b5f5f737461636b5f6c6f7703030c5f5f737461636b5f6869676803040d5f5f"
"676c6f62616c5f6261736503050b5f5f686561705f6261736503060a5f5f686561705f656e"
"6403070d5f5f6d656d6f72795f6261736503080c5f5f7461626c655f6261736503090a3f02"
"02000b3a01017f230041106b220024002000410c6a4184082d00003a000020004180082800"
"00360208200041086a410410001a200041106a240041807e0b0b0b01004180080b04446174"
"61007f0970726f647563657273010c70726f6365737365642d62790105636c616e675f3139"
"2e312e352d776173692d73646b202868747470733a2f2f6769746875622e636f6d2f6c6c76"
"6d2f6c6c766d2d70726f6a6563742061623462356132646235383239353861663165653330"
"3861373930636664623432626432343732302900490f7461726765745f6665617475726573"
"042b0f6d757461626c652d676c6f62616c732b087369676e2d6578742b0f7265666572656e"
"63652d74797065732b0a6d756c746976616c7565";

View File

@@ -50,3 +50,5 @@ extern std::string const floatTestsWasmHex;
extern std::string const float0Hex;
extern std::string const disabledFloatHex;
extern std::string const updateDataWasmHex;

View File

@@ -0,0 +1,13 @@
#include <stdint.h>
int32_t
update_data(uint8_t const*, int32_t);
int
finish()
{
uint8_t buf[] = "Data";
update_data(buf, sizeof(buf) - 1);
return -256;
}

View File

@@ -137,7 +137,8 @@ EscrowCreate::calculateBaseFee(ReadView const& view, STTx const& tx)
bool
EscrowCreate::checkExtraFeatures(PreflightContext const& ctx)
{
if (ctx.tx.isFieldPresent(sfFinishFunction) &&
if ((ctx.tx.isFieldPresent(sfFinishFunction) ||
ctx.tx.isFieldPresent(sfData)) &&
!ctx.rules.enabled(featureSmartEscrow))
return false;
@@ -225,6 +226,22 @@ EscrowCreate::preflight(PreflightContext const& ctx)
return temDISABLED;
}
if (ctx.tx.isFieldPresent(sfData))
{
if (!ctx.tx.isFieldPresent(sfFinishFunction))
{
JLOG(ctx.j.debug())
<< "EscrowCreate with Data requires FinishFunction";
return temMALFORMED;
}
auto const data = ctx.tx.getFieldVL(sfData);
if (data.size() > maxWasmDataLength)
{
JLOG(ctx.j.debug()) << "EscrowCreate.Data bad size " << data.size();
return temMALFORMED;
}
}
if (ctx.tx.isFieldPresent(sfFinishFunction))
{
auto const code = ctx.tx.getFieldVL(sfFinishFunction);
@@ -1317,6 +1334,7 @@ EscrowFinish::doApply()
if (auto const& data = ledgerDataProvider.getData(); data.has_value())
{
slep->setFieldVL(sfData, makeSlice(*data));
ctx_.view().update(slep);
}
if (re.has_value())

View File

@@ -135,18 +135,6 @@ struct HostFunctions
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<Hash, HostFunctionError>
getLedgerAccountHash()
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<Hash, HostFunctionError>
getLedgerTransactionHash()
{
return Unexpected(HostFunctionError::INTERNAL);
}
virtual Expected<int32_t, HostFunctionError>
getBaseFee()
{

View File

@@ -99,12 +99,6 @@ public:
Expected<Hash, HostFunctionError>
getParentLedgerHash() override;
Expected<Hash, HostFunctionError>
getLedgerAccountHash() override;
Expected<Hash, HostFunctionError>
getLedgerTransactionHash() override;
Expected<int32_t, HostFunctionError>
getBaseFee() override;

View File

@@ -44,20 +44,6 @@ getParentLedgerHash_wrap(
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
using getLedgerAccountHash_proto = int32_t(uint8_t*, int32_t);
wasm_trap_t*
getLedgerAccountHash_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
using getLedgerTransactionHash_proto = int32_t(uint8_t*, int32_t);
wasm_trap_t*
getLedgerTransactionHash_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
using getBaseFee_proto = int32_t();
wasm_trap_t*
getBaseFee_wrap(

View File

@@ -55,18 +55,6 @@ WasmHostFunctionsImpl::getParentLedgerHash()
return ctx.view().info().parentHash;
}
Expected<Hash, HostFunctionError>
WasmHostFunctionsImpl::getLedgerAccountHash()
{
return ctx.view().info().accountHash;
}
Expected<Hash, HostFunctionError>
WasmHostFunctionsImpl::getLedgerTransactionHash()
{
return ctx.view().info().txHash;
}
Expected<int32_t, HostFunctionError>
WasmHostFunctionsImpl::getBaseFee()
{

View File

@@ -358,34 +358,6 @@ getParentLedgerHash_wrap(
runtime, params, results, hf->getParentLedgerHash(), index);
}
wasm_trap_t*
getLedgerAccountHash_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;
return returnResult(
runtime, params, results, hf->getLedgerAccountHash(), index);
}
wasm_trap_t*
getLedgerTransactionHash_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;
return returnResult(
runtime, params, results, hf->getLedgerTransactionHash(), index);
}
wasm_trap_t*
getBaseFee_wrap(
void* env,

View File

@@ -41,8 +41,6 @@ setCommonHostFunctions(HostFunctions* hfs, std::vector<WasmImportFunc>& i)
WASM_IMPORT_FUNC2(i, getLedgerSqn, "get_ledger_sqn", hfs, 60);
WASM_IMPORT_FUNC2(i, getParentLedgerTime, "get_parent_ledger_time", hfs, 60);
WASM_IMPORT_FUNC2(i, getParentLedgerHash, "get_parent_ledger_hash", hfs, 60);
WASM_IMPORT_FUNC2(i, getLedgerAccountHash, "get_ledger_account_hash", hfs, 60);
WASM_IMPORT_FUNC2(i, getLedgerTransactionHash, "get_ledger_tx_hash", hfs, 60);
WASM_IMPORT_FUNC2(i, getBaseFee, "get_base_fee", hfs, 60);
WASM_IMPORT_FUNC2(i, isAmendmentEnabled, "amendment_enabled", hfs, 100);