mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
add sfData preflight checks + tests (#5839)
This commit is contained in:
@@ -1730,6 +1730,14 @@ struct Escrow_test : public beast::unit_test::suite
|
||||
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();
|
||||
}
|
||||
|
||||
{
|
||||
@@ -1757,6 +1765,44 @@ struct Escrow_test : public beast::unit_test::suite
|
||||
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) {
|
||||
@@ -2286,6 +2332,72 @@ struct Escrow_test : public beast::unit_test::suite
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -2478,6 +2590,7 @@ struct Escrow_test : public beast::unit_test::suite
|
||||
testCreateFinishFunctionPreflight(features);
|
||||
testFinishWasmFailures(features);
|
||||
testFinishFunction(features);
|
||||
testUpdateDataOnFailure(features);
|
||||
|
||||
// TODO: Update module with new host functions
|
||||
testAllHostFunctions(features);
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -10330,3 +10330,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";
|
||||
|
||||
@@ -50,3 +50,5 @@ extern std::string const floatTestsWasmHex;
|
||||
extern std::string const float0Hex;
|
||||
|
||||
extern std::string const disabledFloatHex;
|
||||
|
||||
extern std::string const updateDataWasmHex;
|
||||
|
||||
13
src/test/app/wasm_fixtures/updateData.c
Normal file
13
src/test/app/wasm_fixtures/updateData.c
Normal 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;
|
||||
}
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user