mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-24 04:25:50 +00:00
most of float_sto done, some bug fixing still to do
This commit is contained in:
@@ -559,6 +559,56 @@ get_free_slot(hook::HookContext& hookCtx)
|
|||||||
return slot_into;
|
return slot_into;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cu_ptr is a pointer into memory, bounds check is assumed to have already happened
|
||||||
|
inline
|
||||||
|
std::optional<Currency> parseCurrency(
|
||||||
|
uint8_t* cu_ptr, uint32_t cu_len)
|
||||||
|
{
|
||||||
|
if (cu_len == 20)
|
||||||
|
{
|
||||||
|
// normal 20 byte currency
|
||||||
|
return Currency::fromVoid(cu_ptr);
|
||||||
|
}
|
||||||
|
else if (cu_len == 3)
|
||||||
|
{
|
||||||
|
// 3 byte ascii currency
|
||||||
|
// need to check what data is in these three bytes, to ensure ISO4217 compliance
|
||||||
|
auto const validateChar = [](uint8_t c) -> bool
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(c >= 'a' && c <= 'z') ||
|
||||||
|
(c >= 'A' && c <= 'Z') ||
|
||||||
|
(c >= '0' && c <= '9') ||
|
||||||
|
c == '?' || c == '!' || c == '@' ||
|
||||||
|
c == '#' || c == '$' || c == '%' ||
|
||||||
|
c == '^' || c == '&' || c == '*' ||
|
||||||
|
c == '<' || c == '>' || c == '(' ||
|
||||||
|
c == ')' || c == '{' || c == '}' ||
|
||||||
|
c == '[' || c == ']' || c == '|';
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!validateChar(*((uint8_t*)(cu_ptr + 0U))) ||
|
||||||
|
!validateChar(*((uint8_t*)(cu_ptr + 1U))) ||
|
||||||
|
!validateChar(*((uint8_t*)(cu_ptr + 2U))))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
uint8_t cur_buf[20] =
|
||||||
|
{
|
||||||
|
0,0,0,0,
|
||||||
|
0,0,0,0,
|
||||||
|
0,0,0,0,
|
||||||
|
*((uint8_t*)(cu_ptr + 0U)),
|
||||||
|
*((uint8_t*)(cu_ptr + 1U)),
|
||||||
|
*((uint8_t*)(cu_ptr + 2U)),
|
||||||
|
0,0,0,0,0
|
||||||
|
};
|
||||||
|
return Currency::fromVoid(cur_buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
hook::
|
hook::
|
||||||
computeHookStateOwnerCount(uint32_t hookStateCount)
|
computeHookStateOwnerCount(uint32_t hookStateCount)
|
||||||
@@ -2639,48 +2689,9 @@ DEFINE_HOOK_FUNCTION(
|
|||||||
if (hi_len != 20 || lo_len != 20)
|
if (hi_len != 20 || lo_len != 20)
|
||||||
return INVALID_ARGUMENT;
|
return INVALID_ARGUMENT;
|
||||||
|
|
||||||
std::optional<Currency> cur;
|
std::optional<Currency> cur =
|
||||||
if (cu_len == 20)
|
parseCurrency(memory + cu_ptr, cu_len);
|
||||||
{
|
if (!cur)
|
||||||
// normal 20 byte currency
|
|
||||||
cur = Currency::fromVoid(memory + cu_ptr);
|
|
||||||
}
|
|
||||||
else if (cu_len == 3)
|
|
||||||
{
|
|
||||||
// 3 byte ascii currency
|
|
||||||
// need to check what data is in these three bytes, to ensure ISO4217 compliance
|
|
||||||
auto const validateChar = [](uint8_t c) -> bool
|
|
||||||
{
|
|
||||||
return
|
|
||||||
(c >= 'a' && c <= 'z') ||
|
|
||||||
(c >= 'A' && c <= 'Z') ||
|
|
||||||
(c >= '0' && c <= '9') ||
|
|
||||||
c == '?' || c == '!' || c == '@' ||
|
|
||||||
c == '#' || c == '$' || c == '%' ||
|
|
||||||
c == '^' || c == '&' || c == '*' ||
|
|
||||||
c == '<' || c == '>' || c == '(' ||
|
|
||||||
c == ')' || c == '{' || c == '}' ||
|
|
||||||
c == '[' || c == ']' || c == '|';
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!validateChar(*((uint8_t*)(cu_ptr + memory + 0U))) ||
|
|
||||||
!validateChar(*((uint8_t*)(cu_ptr + memory + 1U))) ||
|
|
||||||
!validateChar(*((uint8_t*)(cu_ptr + memory + 2U))))
|
|
||||||
return INVALID_ARGUMENT;
|
|
||||||
|
|
||||||
uint8_t cur_buf[20] =
|
|
||||||
{
|
|
||||||
0,0,0,0,
|
|
||||||
0,0,0,0,
|
|
||||||
0,0,0,0,
|
|
||||||
*((uint8_t*)(cu_ptr + memory + 0U)),
|
|
||||||
*((uint8_t*)(cu_ptr + memory + 1U)),
|
|
||||||
*((uint8_t*)(cu_ptr + memory + 2U)),
|
|
||||||
0,0,0,0,0
|
|
||||||
};
|
|
||||||
cur = Currency::fromVoid(cur_buf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return INVALID_ARGUMENT;
|
return INVALID_ARGUMENT;
|
||||||
|
|
||||||
auto kl = ripple::keylet::line(
|
auto kl = ripple::keylet::line(
|
||||||
@@ -4372,6 +4383,51 @@ DEFINE_HOOK_FUNCTION(
|
|||||||
int64_t float1, uint32_t field_code)
|
int64_t float1, uint32_t field_code)
|
||||||
{
|
{
|
||||||
HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx, hookCtx on current stack
|
HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx, hookCtx on current stack
|
||||||
|
|
||||||
|
std::optional<Currency> currency;
|
||||||
|
std::optional<AccountID> issuer;
|
||||||
|
|
||||||
|
// bounds and argument checks
|
||||||
|
if (NOT_IN_BOUNDS(write_ptr, write_len, memory_length))
|
||||||
|
return OUT_OF_BOUNDS;
|
||||||
|
|
||||||
|
if (cread_len == 0)
|
||||||
|
{
|
||||||
|
if (cread_ptr != 0)
|
||||||
|
return INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cread_len != 20 && cread_len != 3)
|
||||||
|
return INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
if (NOT_IN_BOUNDS(cread_ptr, cread_len, memory_length))
|
||||||
|
return OUT_OF_BOUNDS;
|
||||||
|
|
||||||
|
currency = parseCurrency(memory + cread_ptr, cread_len);
|
||||||
|
|
||||||
|
if (!currency)
|
||||||
|
return INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iread_len == 0)
|
||||||
|
{
|
||||||
|
if (iread_ptr != 0)
|
||||||
|
return INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (iread_len != 20)
|
||||||
|
return INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
if (NOT_IN_BOUNDS(iread_ptr, iread_len, memory_length))
|
||||||
|
return OUT_OF_BOUNDS;
|
||||||
|
|
||||||
|
issuer = AccountID::fromVoid(memory + iread_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RETURN_IF_INVALID_FLOAT(float1);
|
RETURN_IF_INVALID_FLOAT(float1);
|
||||||
|
|
||||||
uint16_t field = field_code & 0xFFFFU;
|
uint16_t field = field_code & 0xFFFFU;
|
||||||
@@ -4389,24 +4445,23 @@ DEFINE_HOOK_FUNCTION(
|
|||||||
|
|
||||||
int64_t bytes_written = 0;
|
int64_t bytes_written = 0;
|
||||||
|
|
||||||
if (NOT_IN_BOUNDS(write_ptr, write_len, memory_length))
|
if (issuer && !currency)
|
||||||
return OUT_OF_BOUNDS;
|
|
||||||
|
|
||||||
if (!is_xrp && !is_short && (cread_ptr == 0 && cread_len == 0 && iread_ptr == 0 && iread_len == 0))
|
|
||||||
return INVALID_ARGUMENT;
|
return INVALID_ARGUMENT;
|
||||||
|
|
||||||
if (!is_xrp && !is_short)
|
if (!issuer && currency)
|
||||||
|
return INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
if (issuer)
|
||||||
{
|
{
|
||||||
if (NOT_IN_BOUNDS(cread_ptr, cread_len, memory_length) ||
|
if (is_xrp)
|
||||||
NOT_IN_BOUNDS(iread_ptr, iread_len, memory_length))
|
|
||||||
return OUT_OF_BOUNDS;
|
|
||||||
|
|
||||||
if (cread_len != 20 || iread_len != 20)
|
|
||||||
return INVALID_ARGUMENT;
|
return INVALID_ARGUMENT;
|
||||||
|
if (is_short)
|
||||||
|
return INVALID_ARGUMENT;
|
||||||
|
|
||||||
bytes_needed += 40;
|
bytes_needed += 40;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else if (!is_xrp && !is_short)
|
||||||
|
return INVALID_ARGUMENT;
|
||||||
|
|
||||||
if (bytes_needed > write_len)
|
if (bytes_needed > write_len)
|
||||||
return TOO_SMALL;
|
return TOO_SMALL;
|
||||||
@@ -4446,18 +4501,18 @@ DEFINE_HOOK_FUNCTION(
|
|||||||
uint8_t out[8];
|
uint8_t out[8];
|
||||||
if (is_xrp)
|
if (is_xrp)
|
||||||
{
|
{
|
||||||
// we need to normalize to exp -6
|
int32_t shift = -(exp);
|
||||||
while (exp < -6)
|
|
||||||
{
|
|
||||||
man /= 10;
|
|
||||||
exp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (exp > -6)
|
if (shift > 15)
|
||||||
{
|
return 0;
|
||||||
man *= 10;
|
|
||||||
exp--;
|
if (shift < 0)
|
||||||
}
|
return XFL_OVERFLOW;
|
||||||
|
|
||||||
|
if (shift > 0)
|
||||||
|
man /= power_of_ten[shift];
|
||||||
|
|
||||||
|
std::cout << "man: " << man << "\n";
|
||||||
|
|
||||||
out[0] = (neg ? 0b00000000U : 0b01000000U);
|
out[0] = (neg ? 0b00000000U : 0b01000000U);
|
||||||
out[0] += (uint8_t)((man >> 56U) & 0b111111U);
|
out[0] += (uint8_t)((man >> 56U) & 0b111111U);
|
||||||
@@ -4562,11 +4617,9 @@ DEFINE_HOOK_FUNCTION(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_xrp = (((*upto) & 0b10000000U) == 0);
|
||||||
bool is_negative = (((*upto) & 0b01000000U) == 0);
|
bool is_negative = (((*upto) & 0b01000000U) == 0);
|
||||||
int32_t exponent = (((*upto++) & 0b00111111U)) << 2U;
|
|
||||||
exponent += ((*upto)>>6U);
|
|
||||||
exponent -= 97;
|
|
||||||
uint64_t mantissa = (((uint64_t)(*upto++)) & 0b00111111U) << 48U;
|
uint64_t mantissa = (((uint64_t)(*upto++)) & 0b00111111U) << 48U;
|
||||||
mantissa += ((uint64_t)*upto++) << 40U;
|
mantissa += ((uint64_t)*upto++) << 40U;
|
||||||
mantissa += ((uint64_t)*upto++) << 32U;
|
mantissa += ((uint64_t)*upto++) << 32U;
|
||||||
@@ -4574,6 +4627,19 @@ DEFINE_HOOK_FUNCTION(
|
|||||||
mantissa += ((uint64_t)*upto++) << 16U;
|
mantissa += ((uint64_t)*upto++) << 16U;
|
||||||
mantissa += ((uint64_t)*upto++) << 8U;
|
mantissa += ((uint64_t)*upto++) << 8U;
|
||||||
mantissa += ((uint64_t)*upto++);
|
mantissa += ((uint64_t)*upto++);
|
||||||
|
|
||||||
|
int32_t exponent = 0;
|
||||||
|
|
||||||
|
if (is_xrp)
|
||||||
|
{
|
||||||
|
// exponent remains 0
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
exponent = (((*upto++) & 0b00111111U)) << 2U;
|
||||||
|
exponent += ((*upto)>>6U);
|
||||||
|
exponent -= 97;
|
||||||
|
}
|
||||||
|
|
||||||
if (mantissa == 0)
|
if (mantissa == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -3504,6 +3504,130 @@ public:
|
|||||||
void
|
void
|
||||||
test_float_sto()
|
test_float_sto()
|
||||||
{
|
{
|
||||||
|
testcase("Test float_sto");
|
||||||
|
using namespace jtx;
|
||||||
|
Env env{*this, supported_amendments()};
|
||||||
|
|
||||||
|
auto const alice = Account{"alice"};
|
||||||
|
auto const bob = Account{"bob"};
|
||||||
|
env.fund(XRP(10000), alice);
|
||||||
|
env.fund(XRP(10000), bob);
|
||||||
|
|
||||||
|
{
|
||||||
|
TestHook hook = wasm[R"[test.hook](
|
||||||
|
#include <stdint.h>
|
||||||
|
extern int32_t _g (uint32_t id, uint32_t maxiter);
|
||||||
|
#define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1)
|
||||||
|
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||||
|
extern int64_t rollback (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||||
|
extern int64_t hook_account (uint32_t, uint32_t);
|
||||||
|
extern int64_t float_sto (
|
||||||
|
uint32_t write_ptr,
|
||||||
|
uint32_t write_len,
|
||||||
|
uint32_t cread_ptr,
|
||||||
|
uint32_t cread_len,
|
||||||
|
uint32_t iread_ptr,
|
||||||
|
uint32_t iread_len,
|
||||||
|
int64_t float1,
|
||||||
|
uint32_t field_code
|
||||||
|
);
|
||||||
|
int64_t float_sto_set (
|
||||||
|
uint32_t read_ptr,
|
||||||
|
uint32_t read_len
|
||||||
|
);
|
||||||
|
#define OUT_OF_BOUNDS (-1)
|
||||||
|
#define INVALID_FLOAT (-10024)
|
||||||
|
#define INVALID_ARGUMENT (-7)
|
||||||
|
#define TOO_SMALL (-4)
|
||||||
|
#define XFL_OVERFLOW (-30)
|
||||||
|
#define ASSERT(x)\
|
||||||
|
if (!(x))\
|
||||||
|
rollback((uint32_t)#x, sizeof(#x), __LINE__);
|
||||||
|
|
||||||
|
#define SBUF(x) x, sizeof(x)
|
||||||
|
#define sfAmount ((6U << 16U) + 1U)
|
||||||
|
uint8_t cur1[3] = {'U','S','D'};
|
||||||
|
|
||||||
|
#define BUFFER_EQUAL_20(buf1, buf2)\
|
||||||
|
(\
|
||||||
|
*(((uint64_t*)(buf1)) + 0) == *(((uint64_t*)(buf2)) + 0) &&\
|
||||||
|
*(((uint64_t*)(buf1)) + 1) == *(((uint64_t*)(buf2)) + 1) &&\
|
||||||
|
*(((uint32_t*)(buf1)) + 4) == *(((uint32_t*)(buf2)) + 4))
|
||||||
|
|
||||||
|
int64_t hook(uint32_t reserved )
|
||||||
|
{
|
||||||
|
_g(1,1);
|
||||||
|
uint8_t cur2[20];
|
||||||
|
for (int i =0; GUARD(20), i < 20; ++i)
|
||||||
|
cur2[i] = i;
|
||||||
|
|
||||||
|
uint8_t iss[20];
|
||||||
|
ASSERT(hook_account(SBUF(iss)) == 20);
|
||||||
|
|
||||||
|
uint8_t buf[48];
|
||||||
|
|
||||||
|
// the three buffers must be bounds checked
|
||||||
|
ASSERT(float_sto(1000000, 50, 0,0,0,0,0,0) == OUT_OF_BOUNDS);
|
||||||
|
ASSERT(float_sto(0, 1000000, 0,0,0,0,0,0) == OUT_OF_BOUNDS);
|
||||||
|
ASSERT(float_sto(SBUF(buf), 1000000, 50, 0,0,0,0) == OUT_OF_BOUNDS);
|
||||||
|
ASSERT(float_sto(SBUF(buf), 0, 1000000, 0,0,0,0) == OUT_OF_BOUNDS);
|
||||||
|
ASSERT(float_sto(SBUF(buf), 0,0, 1000000, 50, 0,0) == OUT_OF_BOUNDS);
|
||||||
|
ASSERT(float_sto(SBUF(buf), 0,0, 0, 1000000, 0,0) == OUT_OF_BOUNDS);
|
||||||
|
|
||||||
|
// zero issuer/currency pointers must be accompanied by 0 length
|
||||||
|
ASSERT(float_sto(SBUF(buf), 0, 1, 0,0, 0,0) == INVALID_ARGUMENT);
|
||||||
|
ASSERT(float_sto(SBUF(buf), 0, 0, 0,1, 0,0) == INVALID_ARGUMENT);
|
||||||
|
|
||||||
|
// zero issuer/currency lengths mus tbe accompanied by 0 pointers
|
||||||
|
ASSERT(float_sto(SBUF(buf), 1, 0, 0,0, 0,0) == INVALID_ARGUMENT);
|
||||||
|
ASSERT(float_sto(SBUF(buf), 0, 0, 1,0, 0,0) == INVALID_ARGUMENT);
|
||||||
|
|
||||||
|
// issuer without currency is invalid
|
||||||
|
ASSERT(float_sto(SBUF(buf), 0,0, SBUF(iss), 0, sfAmount) == INVALID_ARGUMENT);
|
||||||
|
|
||||||
|
// currency without issuer is invalid
|
||||||
|
ASSERT(float_sto(SBUF(buf), SBUF(cur1), 0,0, 0, sfAmount) == INVALID_ARGUMENT);
|
||||||
|
|
||||||
|
// currency and issuer with field code 0 = XRP is invalid
|
||||||
|
ASSERT(float_sto(SBUF(buf), SBUF(cur1), SBUF(iss), 0, 0) == INVALID_ARGUMENT);
|
||||||
|
|
||||||
|
// invalid XFL
|
||||||
|
ASSERT(float_sto(SBUF(buf), SBUF(cur2), SBUF(iss), -1, sfAmount) == INVALID_FLOAT);
|
||||||
|
|
||||||
|
// valid XFL, currency and issuer
|
||||||
|
{
|
||||||
|
// currency and issuer with field code not XRP is valid (XFL = 1234567.0)
|
||||||
|
ASSERT(float_sto(SBUF(buf), SBUF(cur2), SBUF(iss), 6198187654261802496ULL, sfAmount) == 48);
|
||||||
|
|
||||||
|
// check the output contains the correct currency code
|
||||||
|
ASSERT(BUFFER_EQUAL_20(buf + 28, cur2));
|
||||||
|
|
||||||
|
// check the output contains the correct issuer
|
||||||
|
ASSERT(BUFFER_EQUAL_20(buf + 8, iss));
|
||||||
|
|
||||||
|
// check the field code is correct
|
||||||
|
ASSERT(buf[0] == 0x61U); // sfAmount
|
||||||
|
|
||||||
|
// reverse the operation and check the XFL amount is correct
|
||||||
|
ASSERT(float_sto_set(SBUF(buf)) == 6198187654261802496ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// RH TODO: xrp and short
|
||||||
|
|
||||||
|
return accept(0,0,0);
|
||||||
|
|
||||||
|
}
|
||||||
|
)[test.hook]"];
|
||||||
|
|
||||||
|
env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0),
|
||||||
|
M("set float_sto"),
|
||||||
|
HSFEE);
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
env(pay(bob, alice, XRP(1)), M("test float_sto"), fee(XRP(1)));
|
||||||
|
env.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -9134,7 +9258,7 @@ public:
|
|||||||
|
|
||||||
test_state(); //
|
test_state(); //
|
||||||
test_state_foreign(); //
|
test_state_foreign(); //
|
||||||
test_state_foreign_set();
|
test_state_foreign_set(); //
|
||||||
test_state_set(); //
|
test_state_set(); //
|
||||||
|
|
||||||
test_sto_emplace(); //
|
test_sto_emplace(); //
|
||||||
|
|||||||
Reference in New Issue
Block a user