Merge branch 'ripple/wamr' into ripple/wamr-host-functions

This commit is contained in:
Mayukha Vadari
2025-09-26 16:37:25 -04:00
committed by GitHub
13 changed files with 287 additions and 81 deletions

View File

@@ -72,8 +72,10 @@ class STCurrency;
STYPE(STI_VL, 7) \
STYPE(STI_ACCOUNT, 8) \
STYPE(STI_NUMBER, 9) \
STYPE(STI_INT32, 10) \
STYPE(STI_INT64, 11) \
\
/* 10-13 are reserved */ \
/* 12-13 are reserved */ \
STYPE(STI_OBJECT, 14) \
STYPE(STI_ARRAY, 15) \
\
@@ -356,6 +358,9 @@ using SF_UINT256 = TypedField<STBitString<256>>;
using SF_UINT384 = TypedField<STBitString<384>>;
using SF_UINT512 = TypedField<STBitString<512>>;
using SF_INT32 = TypedField<STInteger<std::int32_t>>;
using SF_INT64 = TypedField<STInteger<std::int64_t>>;
using SF_ACCOUNT = TypedField<STAccount>;
using SF_AMOUNT = TypedField<STAmount>;
using SF_ISSUE = TypedField<STIssue>;

View File

@@ -81,6 +81,8 @@ using STUInt16 = STInteger<std::uint16_t>;
using STUInt32 = STInteger<std::uint32_t>;
using STUInt64 = STInteger<std::uint64_t>;
using STInt32 = STInteger<std::int32_t>;
template <typename Integer>
inline STInteger<Integer>::STInteger(Integer v) : value_(v)
{

View File

@@ -231,6 +231,8 @@ public:
getFieldH192(SField const& field) const;
uint256
getFieldH256(SField const& field) const;
std::int32_t
getFieldI32(SField const& field) const;
AccountID
getAccountID(SField const& field) const;
@@ -365,6 +367,8 @@ public:
void
setFieldH256(SField const& field, uint256 const&);
void
setFieldI32(SField const& field, std::int32_t);
void
setFieldVL(SField const& field, Blob const&);
void
setFieldVL(SField const& field, Slice const&);

View File

@@ -208,6 +208,12 @@ TYPED_SFIELD(sfAssetsMaximum, NUMBER, 3)
TYPED_SFIELD(sfAssetsTotal, NUMBER, 4)
TYPED_SFIELD(sfLossUnrealized, NUMBER, 5)
// int32
// NOTE: Do not use `sfDummyInt32`. It's so far the only use of INT32
// in this file and has been defined here for test only.
// TODO: Replace `sfDummyInt32` with actually useful field.
TYPED_SFIELD(sfDummyInt32, INT32, 1) // for tests only
// currency amount (common)
TYPED_SFIELD(sfAmount, AMOUNT, 1)
TYPED_SFIELD(sfBalance, AMOUNT, 2)

View File

@@ -249,4 +249,33 @@ STUInt64::getJson(JsonOptions) const
return convertToString(value_, 16); // Convert to base 16
}
//------------------------------------------------------------------------------
template <>
STInteger<std::int32_t>::STInteger(SerialIter& sit, SField const& name)
: STInteger(name, sit.get32())
{
}
template <>
SerializedTypeID
STInt32::getSType() const
{
return STI_INT32;
}
template <>
std::string
STInt32::getText() const
{
return std::to_string(value_);
}
template <>
Json::Value
STInt32::getJson(JsonOptions) const
{
return value_;
}
} // namespace ripple

View File

@@ -647,6 +647,12 @@ STObject::getFieldH256(SField const& field) const
return getFieldByValue<STUInt256>(field);
}
std::int32_t
STObject::getFieldI32(SField const& field) const
{
return getFieldByValue<STInt32>(field);
}
AccountID
STObject::getAccountID(SField const& field) const
{
@@ -761,6 +767,12 @@ STObject::setFieldH256(SField const& field, uint256 const& v)
setFieldUsingSetValue<STUInt256>(field, v);
}
void
STObject::setFieldI32(SField const& field, std::int32_t v)
{
setFieldUsingSetValue<STInt32>(field, v);
}
void
STObject::setFieldV256(SField const& field, STVector256 const& v)
{

View File

@@ -563,30 +563,6 @@ parseLeaf(
break;
}
case STI_UINT192: {
if (!value.isString())
{
error = bad_type(json_name, fieldName);
return ret;
}
uint192 num;
if (auto const s = value.asString(); !num.parseHex(s))
{
if (!s.empty())
{
error = invalid_data(json_name, fieldName);
return ret;
}
num.zero();
}
ret = detail::make_stvar<STUInt192>(field, num);
break;
}
case STI_UINT160: {
if (!value.isString())
{
@@ -611,6 +587,30 @@ parseLeaf(
break;
}
case STI_UINT192: {
if (!value.isString())
{
error = bad_type(json_name, fieldName);
return ret;
}
uint192 num;
if (auto const s = value.asString(); !num.parseHex(s))
{
if (!s.empty())
{
error = invalid_data(json_name, fieldName);
return ret;
}
num.zero();
}
ret = detail::make_stvar<STUInt192>(field, num);
break;
}
case STI_UINT256: {
if (!value.isString())
{
@@ -635,6 +635,52 @@ parseLeaf(
break;
}
case STI_INT32:
try
{
if (value.isString())
{
ret = detail::make_stvar<STInt32>(
field,
beast::lexicalCastThrow<std::int32_t>(
value.asString()));
}
else if (value.isInt())
{
// future-proofing - a static assert failure if the JSON
// library ever supports larger ints
// In such case, we will need additional bounds checks here
static_assert(
std::is_same_v<decltype(value.asInt()), std::int32_t>);
ret = detail::make_stvar<STInt32>(field, value.asInt());
}
else if (value.isUInt())
{
auto const uintValue = value.asUInt();
if (uintValue >
static_cast<std::uint32_t>(
std::numeric_limits<std::int32_t>::max()))
{
error = out_of_range(json_name, fieldName);
return ret;
}
ret = detail::make_stvar<STInt32>(
field, static_cast<std::int32_t>(uintValue));
}
else
{
error = bad_type(json_name, fieldName);
return ret;
}
}
catch (std::exception const&)
{
error = invalid_data(json_name, fieldName);
return ret;
}
break;
case STI_VL:
if (!value.isString())
{
@@ -1120,8 +1166,7 @@ parseArray(
Json::Value const objectFields(json[i][objectName]);
std::stringstream ss;
ss << json_name << "."
<< "[" << i << "]." << objectName;
ss << json_name << "." << "[" << i << "]." << objectName;
auto ret = parseObject(
ss.str(), objectFields, nameField, depth + 1, error);

View File

@@ -208,6 +208,9 @@ STVar::constructST(SerializedTypeID id, int depth, Args&&... args)
case STI_UINT256:
construct<STUInt256>(std::forward<Args>(args)...);
return;
case STI_INT32:
construct<STInt32>(std::forward<Args>(args)...);
return;
case STI_VECTOR256:
construct<STVector256>(std::forward<Args>(args)...);
return;

View File

@@ -83,6 +83,12 @@ Serializer::addInteger(std::uint64_t i)
{
return add64(i);
}
template <>
int
Serializer::addInteger(std::int32_t i)
{
return add32(i);
}
int
Serializer::addRaw(Blob const& vector)

View File

@@ -122,10 +122,27 @@ struct STAccount_test : public beast::unit_test::suite
}
}
void
testAccountID()
{
auto const s = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
if (auto const parsed = parseBase58<AccountID>(s); BEAST_EXPECT(parsed))
{
BEAST_EXPECT(toBase58(*parsed) == s);
}
{
auto const s =
"âabcd1rNxp4h8apvRis6mJf9Sh8C6iRxfrDWNâabcdAVâ\xc2\x80\xc2\x8f";
BEAST_EXPECT(!parseBase58<AccountID>(s));
}
}
void
run() override
{
testSTAccount();
testAccountID();
}
};

View File

@@ -30,6 +30,7 @@ struct STInteger_test : public beast::unit_test::suite
void
testUInt8()
{
testcase("UInt8");
STUInt8 u8(255);
BEAST_EXPECT(u8.value() == 255);
BEAST_EXPECT(u8.getText() == "255");
@@ -56,6 +57,7 @@ struct STInteger_test : public beast::unit_test::suite
void
testUInt16()
{
testcase("UInt16");
STUInt16 u16(65535);
BEAST_EXPECT(u16.value() == 65535);
BEAST_EXPECT(u16.getText() == "65535");
@@ -80,6 +82,7 @@ struct STInteger_test : public beast::unit_test::suite
void
testUInt32()
{
testcase("UInt32");
STUInt32 u32(4'294'967'295u);
BEAST_EXPECT(u32.value() == 4'294'967'295u);
BEAST_EXPECT(u32.getText() == "4294967295");
@@ -102,6 +105,7 @@ struct STInteger_test : public beast::unit_test::suite
void
testUInt64()
{
testcase("UInt64");
STUInt64 u64(0xFFFFFFFFFFFFFFFFull);
BEAST_EXPECT(u64.value() == 0xFFFFFFFFFFFFFFFFull);
BEAST_EXPECT(u64.getText() == "18446744073709551615");
@@ -120,6 +124,29 @@ struct STInteger_test : public beast::unit_test::suite
u64_2.getJson(JsonOptions::none) == "18446744073709551615");
}
void
testInt32()
{
testcase("Int32");
{
int const minInt32 = -2147483648;
STInt32 i32(minInt32);
BEAST_EXPECT(i32.value() == minInt32);
BEAST_EXPECT(i32.getText() == "-2147483648");
BEAST_EXPECT(i32.getSType() == STI_INT32);
BEAST_EXPECT(i32.getJson(JsonOptions::none) == minInt32);
}
{
int const maxInt32 = 2147483647;
STInt32 i32(maxInt32);
BEAST_EXPECT(i32.value() == maxInt32);
BEAST_EXPECT(i32.getText() == "2147483647");
BEAST_EXPECT(i32.getSType() == STI_INT32);
BEAST_EXPECT(i32.getJson(JsonOptions::none) == maxInt32);
}
}
void
run() override
{
@@ -127,6 +154,7 @@ struct STInteger_test : public beast::unit_test::suite
testUInt16();
testUInt32();
testUInt64();
testInt32();
}
};

View File

@@ -736,6 +736,107 @@ class STParsedJSON_test : public beast::unit_test::suite
}
}
void
testInt32()
{
testcase("Int32");
{
Json::Value j;
int const minInt32 = -2147483648;
j[sfDummyInt32] = minInt32;
STParsedJSONObject obj("Test", j);
BEAST_EXPECT(obj.object.has_value());
if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32)))
BEAST_EXPECT(obj.object->getFieldI32(sfDummyInt32) == minInt32);
}
// max value
{
Json::Value j;
int const maxInt32 = 2147483647;
j[sfDummyInt32] = maxInt32;
STParsedJSONObject obj("Test", j);
BEAST_EXPECT(obj.object.has_value());
if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32)))
BEAST_EXPECT(obj.object->getFieldI32(sfDummyInt32) == maxInt32);
}
// max uint value
{
Json::Value j;
unsigned int const maxUInt32 = 2147483647u;
j[sfDummyInt32] = maxUInt32;
STParsedJSONObject obj("Test", j);
BEAST_EXPECT(obj.object.has_value());
if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32)))
BEAST_EXPECT(
obj.object->getFieldI32(sfDummyInt32) ==
static_cast<int32_t>(maxUInt32));
}
// Test with string value
{
Json::Value j;
j[sfDummyInt32] = "2147483647";
STParsedJSONObject obj("Test", j);
BEAST_EXPECT(obj.object.has_value());
if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32)))
BEAST_EXPECT(
obj.object->getFieldI32(sfDummyInt32) == 2147483647u);
}
// Test with string negative value
{
Json::Value j;
int value = -2147483648;
j[sfDummyInt32] = std::to_string(value);
STParsedJSONObject obj("Test", j);
BEAST_EXPECT(obj.object.has_value());
if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32)))
BEAST_EXPECT(obj.object->getFieldI32(sfDummyInt32) == value);
}
// Test out of range value for int32 (negative)
{
Json::Value j;
j[sfDummyInt32] = "-2147483649";
STParsedJSONObject obj("Test", j);
BEAST_EXPECT(!obj.object.has_value());
}
// Test out of range value for int32 (positive)
{
Json::Value j;
j[sfDummyInt32] = 2147483648u;
STParsedJSONObject obj("Test", j);
BEAST_EXPECT(!obj.object.has_value());
}
// Test string value out of range
{
Json::Value j;
j[sfDummyInt32] = "2147483648";
STParsedJSONObject obj("Test", j);
BEAST_EXPECT(!obj.object.has_value());
}
// Test bad_type (arrayValue)
{
Json::Value j;
j[sfDummyInt32] = Json::Value(Json::arrayValue);
STParsedJSONObject obj("Test", j);
BEAST_EXPECT(!obj.object.has_value());
}
// Test bad_type (objectValue)
{
Json::Value j;
j[sfDummyInt32] = Json::Value(Json::objectValue);
STParsedJSONObject obj("Test", j);
BEAST_EXPECT(!obj.object.has_value());
}
}
void
testBlob()
{
@@ -1338,8 +1439,7 @@ class STParsedJSON_test : public beast::unit_test::suite
issueJson["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
j[sfAsset] = issueJson;
STParsedJSONObject obj("Test", j);
if (BEAST_EXPECTS(
obj.object.has_value(), obj.error.toStyledString()))
if (BEAST_EXPECT(obj.object.has_value()))
{
BEAST_EXPECT(obj.object->isFieldPresent(sfAsset));
auto const& issueField = (*obj.object)[sfAsset];
@@ -2235,6 +2335,7 @@ class STParsedJSON_test : public beast::unit_test::suite
testUInt160();
testUInt192();
testUInt256();
testInt32();
testBlob();
testVector256();
testAccount();

View File

@@ -1,52 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 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 <xrpl/beast/unit_test.h>
#include <xrpl/protocol/UintTypes.h>
namespace ripple {
struct types_test : public beast::unit_test::suite
{
void
testAccountID()
{
auto const s = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
if (auto const parsed = parseBase58<AccountID>(s); BEAST_EXPECT(parsed))
{
BEAST_EXPECT(toBase58(*parsed) == s);
}
{
auto const s =
"âabcd1rNxp4h8apvRis6mJf9Sh8C6iRxfrDWNâabcdAVâ\xc2\x80\xc2\x8f";
BEAST_EXPECT(!parseBase58<AccountID>(s));
}
}
void
run() override
{
testAccountID();
}
};
BEAST_DEFINE_TESTSUITE(types, protocol, ripple);
} // namespace ripple