mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
add more hook unit tests, and test wasm checker
This commit is contained in:
@@ -31,6 +31,107 @@ using TestHook = std::vector<uint8_t> const&;
|
||||
|
||||
class SetHook_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
|
||||
void
|
||||
testHooksDisabled()
|
||||
{
|
||||
testcase("Check for disabled amendment");
|
||||
using namespace jtx;
|
||||
Env env{*this, supported_amendments() - featureHooks};
|
||||
auto const alice = Account{"alice"};
|
||||
env.fund(XRP(10000), alice);
|
||||
// RH TODO: does it matter that passing malformed txn here gives back temMALFORMED (and not disabled)?
|
||||
env(ripple::test::jtx::hook(alice, {{hso(accept_wasm)}}, 0), ter(temDISABLED));
|
||||
}
|
||||
|
||||
//Json::Value
|
||||
//hook(Account const& account, std::optional<std::vector<Json::Value>> hooks, std::uint32_t flags);
|
||||
|
||||
//Json::Value
|
||||
//hso(std::vector<uint8_t> wasmBytes, uint64_t hookOn = 0, uint256 ns = beast::zero, uint8_t apiversion = 0);
|
||||
|
||||
void
|
||||
testMalformedTxStructure()
|
||||
{
|
||||
testcase("Checks malformed transactions");
|
||||
using namespace jtx;
|
||||
Env env{*this, supported_amendments()};
|
||||
|
||||
auto const alice = Account{"alice"};
|
||||
env.fund(XRP(10000), alice);
|
||||
|
||||
// Must have a "Hooks" field
|
||||
env(ripple::test::jtx::hook(alice, {}, 0), ter(temMALFORMED));
|
||||
|
||||
// Must have at least one non-empty subfield
|
||||
env(ripple::test::jtx::hook(alice, {{}}, 0), ter(temMALFORMED));
|
||||
|
||||
// Must have fewer than 5 entries
|
||||
env(ripple::test::jtx::hook(alice, {{
|
||||
hso(accept_wasm),
|
||||
hso(accept_wasm),
|
||||
hso(accept_wasm),
|
||||
hso(accept_wasm),
|
||||
hso(accept_wasm)}}, 0), ter(temMALFORMED));
|
||||
|
||||
// If createcode present must be less than 64kib
|
||||
{
|
||||
std::vector<uint8_t> longbin(0x10000U, 0xFFU);
|
||||
env(ripple::test::jtx::hook(alice, {{hso(longbin)}}, 0), ter(temMALFORMED));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Json::Value jv;
|
||||
|
||||
jv[jss::Account] = alice.human();
|
||||
jv[jss::TransactionType] = jss::SetHook;
|
||||
jv[jss::Flags] = 0;
|
||||
jv[jss::Hooks] =
|
||||
Json::Value{Json::arrayValue};
|
||||
|
||||
Json::Value iv;
|
||||
|
||||
iv[jss::CreateCode] = std::string(65536, 'F');
|
||||
iv[jss::HookOn] = "0000000000000000";
|
||||
iv[jss::HookNamespace] = to_string(uint256{beast::zero});
|
||||
iv[jss::HookApiVersion] = Json::Value{0};
|
||||
|
||||
jv[jss::Hooks][i][jss::Hook] = iv;
|
||||
env(jv, ter(temMALFORMED));
|
||||
*/
|
||||
void
|
||||
testMalformedWasm()
|
||||
{
|
||||
testcase("Checks malformed hook binaries");
|
||||
using namespace jtx;
|
||||
Env env{*this, supported_amendments()};
|
||||
|
||||
auto const alice = Account{"alice"};
|
||||
env.fund(XRP(10000), alice);
|
||||
|
||||
// Must import guard
|
||||
env(ripple::test::jtx::hook(alice, {{hso(noguard_wasm)}}, 0), ter(temMALFORMED));
|
||||
|
||||
// Must only contain hook and cbak
|
||||
env(ripple::test::jtx::hook(alice, {{hso(illegalfunc_wasm)}}, 0), ter(temMALFORMED));
|
||||
}
|
||||
|
||||
// Trivial single hook
|
||||
//env(ripple::test::jtx::hook(alice, {{hso(accept_wasm)}}, 0));
|
||||
|
||||
// RH TODO
|
||||
void
|
||||
run() override
|
||||
{
|
||||
//testTicketSetHook(); // RH TODO
|
||||
testHooksDisabled();
|
||||
testMalformedTxStructure();
|
||||
testMalformedWasm();
|
||||
}
|
||||
|
||||
private:
|
||||
TestHook
|
||||
accept_wasm =
|
||||
@@ -41,55 +142,64 @@ private:
|
||||
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
int64_t hook(uint32_t reserved )
|
||||
{
|
||||
accept(0,0,0);
|
||||
return accept(0,0,0);
|
||||
_g(1,1);
|
||||
}
|
||||
)[test.hook]"
|
||||
];
|
||||
public:
|
||||
|
||||
TestHook
|
||||
noguard_wasm =
|
||||
wasm[
|
||||
R"[test.hook](
|
||||
#include <stdint.h>
|
||||
extern int32_t _g (uint32_t id, uint32_t maxiter);
|
||||
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
int64_t hook(uint32_t reserved )
|
||||
{
|
||||
return accept(0,0,0);
|
||||
}
|
||||
)[test.hook]"
|
||||
];
|
||||
|
||||
TestHook
|
||||
illegalfunc_wasm =
|
||||
wasm[
|
||||
R"[test.hook](
|
||||
#include <stdint.h>
|
||||
extern int32_t _g (uint32_t id, uint32_t maxiter);
|
||||
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
int64_t hook(uint32_t reserved )
|
||||
{
|
||||
return accept(0,0,0);
|
||||
}
|
||||
void otherfunc()
|
||||
{
|
||||
_g(1,1);
|
||||
}
|
||||
)[test.hook]"
|
||||
];
|
||||
|
||||
TestHook
|
||||
long_wasm =
|
||||
wasm[
|
||||
R"[test.hook](
|
||||
#include <stdint.h>
|
||||
extern int32_t _g (uint32_t id, uint32_t maxiter);
|
||||
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
#define SBUF(x) (uint32_t)(x), sizeof(x)
|
||||
#define M_REPEAT_10(X) X X X X X X X X X X
|
||||
#define M_REPEAT_100(X) M_REPEAT_10(M_REPEAT_10(X))
|
||||
#define M_REPEAT_1000(X) M_REPEAT_100(M_REPEAT_10(X))
|
||||
int64_t hook(uint32_t reserved )
|
||||
{
|
||||
char ret[] = M_REPEAT_1000("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz01234567890123");
|
||||
return accept(SBUF(ret), 0);
|
||||
}
|
||||
)[test.hook]"
|
||||
];
|
||||
|
||||
|
||||
void
|
||||
testHooksDisabled()
|
||||
{
|
||||
testcase("SetHook checks for disabled amendment");
|
||||
using namespace jtx;
|
||||
Env env{*this, supported_amendments() - featureHooks};
|
||||
auto const alice = Account{"alice"};
|
||||
env.fund(XRP(10000), alice);
|
||||
env(ripple::test::jtx::hook(alice, {}, 0), ter(temDISABLED));
|
||||
}
|
||||
|
||||
void
|
||||
testMalformedTransaction()
|
||||
{
|
||||
testcase("SetHook checks for malformed transactions");
|
||||
using namespace jtx;
|
||||
Env env{*this, supported_amendments()};
|
||||
|
||||
auto const alice = Account{"alice"};
|
||||
env.fund(XRP(10000), alice);
|
||||
|
||||
|
||||
// Must have a "Hooks" field
|
||||
env(ripple::test::jtx::hook(alice, {}, 0), ter(temMALFORMED));
|
||||
|
||||
// Must have at least one non-empty subfield
|
||||
env(ripple::test::jtx::hook(alice, {{}}, 0), ter(temMALFORMED));
|
||||
|
||||
// Trivial single hook
|
||||
env(ripple::test::jtx::hook(alice, {{hso(accept_wasm)}}, 0));
|
||||
|
||||
// RH TODO
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
//testTicketSetHook(); // RH TODO
|
||||
testHooksDisabled();
|
||||
testMalformedTransaction();
|
||||
}
|
||||
};
|
||||
BEAST_DEFINE_TESTSUITE(SetHook, tx, ripple);
|
||||
} // namespace test
|
||||
|
||||
@@ -14,12 +14,12 @@ std::map<std::string, std::vector<uint8_t>> wasm = {' > SetHook_wasm.h
|
||||
cat SetHook_test.cpp | tr '\n' '\f' |
|
||||
grep -Po 'R"\[test\.hook\](.*?)\[test\.hook\]"' |
|
||||
sed -E 's/R"\[test\.hook\]\(//g' |
|
||||
sed -E 's/\)\[test\.hook\]"[\f \t]*//g' |
|
||||
sed -E 's/\)\[test\.hook\]"[\f \t]*/\/*end*\//g' |
|
||||
while read -r line
|
||||
do
|
||||
echo -n '{ R"[test.hook](' >> SetHook_wasm.h
|
||||
# tr '\f' '\n' <<< $line >> SetHook_wasm.h
|
||||
cat <<< $line | tr -d '\n' | tr '\f' '\n' >> SetHook_wasm.h
|
||||
cat <<< $line | sed -E 's/.{7}$//g' | tr -d '\n' | tr '\f' '\n' >> SetHook_wasm.h
|
||||
echo ')[test.hook]",' >> SetHook_wasm.h
|
||||
echo "{" >> SetHook_wasm.h
|
||||
wasmcc -x c /dev/stdin -o /dev/stdout -O2 -Wl,--allow-undefined <<< `tr '\f' '\n' <<< $line` |
|
||||
|
||||
12
src/test/app/check_test_hooks.sh
Executable file
12
src/test/app/check_test_hooks.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
ERRORS="0"
|
||||
cat SetHook_wasm.h | tr -d '\n' | grep -Po '{[0-9A-FUx, ]*}' | tr -d ' ,{}U' | sed -E 's/0x//g' |
|
||||
while read -r line
|
||||
do
|
||||
xxd -r -p <<< $line | wasm-objdump -d -
|
||||
if [ "$?" -gt "0" ]
|
||||
then
|
||||
ERRORS=`echo $ERRORS + 1 | bc`
|
||||
fi
|
||||
done
|
||||
echo "Errors decompiling: $ERRORS"
|
||||
@@ -32,7 +32,7 @@ Json::Value
|
||||
hook(Account const& account, std::optional<std::vector<Json::Value>> hooks, std::uint32_t flags);
|
||||
|
||||
Json::Value
|
||||
hso(std::vector<uint8_t> wasmBytes, uint64_t hookOn = 0, uint256 ns = beast::zero, uint8_t apiversion = 0);
|
||||
hso(std::vector<uint8_t> const& wasmBytes, uint64_t hookOn = 0, uint256 ns = beast::zero, uint8_t apiversion = 0);
|
||||
|
||||
} // namespace jtx
|
||||
} // namespace test
|
||||
|
||||
@@ -65,8 +65,11 @@ inline std::string uint64_hex(uint64_t x)
|
||||
}
|
||||
|
||||
Json::Value
|
||||
hso(std::vector<uint8_t> wasmBytes, uint64_t hookOn, uint256 ns, uint8_t apiversion)
|
||||
hso(std::vector<uint8_t> const& wasmBytes, uint64_t hookOn, uint256 ns, uint8_t apiversion)
|
||||
{
|
||||
if (wasmBytes.size() == 0)
|
||||
throw std::runtime_error("empty hook wasm passed to hso()");
|
||||
|
||||
Json::Value jv;
|
||||
jv[jss::CreateCode] = strHex(wasmBytes);
|
||||
jv[jss::HookOn] = uint64_hex(hookOn);
|
||||
|
||||
Reference in New Issue
Block a user