From 1fa15b1a76e1dbcbea1381c4353886ab52543342 Mon Sep 17 00:00:00 2001 From: Shawn Xie <shawnxie920@gmail.com> Date: Mon, 9 Sep 2024 12:40:12 -0400 Subject: [PATCH] MPT amount base 10 --- src/libxrpl/protocol/STInteger.cpp | 35 ++++++++++++++++++++------- src/libxrpl/protocol/STParsedJSON.cpp | 6 ++++- src/test/app/MPToken_test.cpp | 16 ++++++------ src/test/jtx/impl/mpt.cpp | 13 +--------- src/test/jtx/mpt.h | 2 +- 5 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/libxrpl/protocol/STInteger.cpp b/src/libxrpl/protocol/STInteger.cpp index 7b7420006f9..df42443aadd 100644 --- a/src/libxrpl/protocol/STInteger.cpp +++ b/src/libxrpl/protocol/STInteger.cpp @@ -61,7 +61,8 @@ STUInt8::getText() const } template <> -Json::Value STUInt8::getJson(JsonOptions) const +Json::Value +STUInt8::getJson(JsonOptions) const { if (getFName() == sfTransactionResult) { @@ -118,7 +119,8 @@ STUInt16::getText() const } template <> -Json::Value STUInt16::getJson(JsonOptions) const +Json::Value +STUInt16::getJson(JsonOptions) const { if (getFName() == sfLedgerEntryType) { @@ -164,7 +166,8 @@ STUInt32::getText() const } template <> -Json::Value STUInt32::getJson(JsonOptions) const +Json::Value +STUInt32::getJson(JsonOptions) const { return value_; } @@ -192,13 +195,27 @@ STUInt64::getText() const } template <> -Json::Value STUInt64::getJson(JsonOptions) const +Json::Value +STUInt64::getJson(JsonOptions) const { - std::string str(16, 0); - auto ret = std::to_chars(str.data(), str.data() + str.size(), value_, 16); - assert(ret.ec == std::errc()); - str.resize(std::distance(str.data(), ret.ptr)); - return str; + auto convertToString = [](uint64_t const value, int const base) { + std::string str( + base == 10 ? 20 : 16, 0); // Allocate space depending on base + auto ret = + std::to_chars(str.data(), str.data() + str.size(), value, base); + assert(ret.ec == std::errc()); + str.resize(std::distance(str.data(), ret.ptr)); + return str; + }; + + if (auto const& fName = getFName(); fName == sfMaximumAmount || + fName == sfOutstandingAmount || fName == sfLockedAmount || + fName == sfMPTAmount) + { + return convertToString(value_, 10); // Convert to base 10 + } + + return convertToString(value_, 16); // Convert to base 16 } } // namespace ripple diff --git a/src/libxrpl/protocol/STParsedJSON.cpp b/src/libxrpl/protocol/STParsedJSON.cpp index 92044334431..3db15d1eb39 100644 --- a/src/libxrpl/protocol/STParsedJSON.cpp +++ b/src/libxrpl/protocol/STParsedJSON.cpp @@ -398,8 +398,12 @@ parseLeaf( std::uint64_t val; + // if the field is amount, serialize as base 10 auto [p, ec] = std::from_chars( - str.data(), str.data() + str.size(), val, 16); + str.data(), + str.data() + str.size(), + val, + (field == sfMaximumAmount) ? 10 : 16); if (ec != std::errc() || (p != str.data() + str.size())) Throw<std::invalid_argument>("invalid data"); diff --git a/src/test/app/MPToken_test.cpp b/src/test/app/MPToken_test.cpp index 0cac8811366..b1789158987 100644 --- a/src/test/app/MPToken_test.cpp +++ b/src/test/app/MPToken_test.cpp @@ -53,7 +53,7 @@ class MPToken_test : public beast::unit_test::suite // tries to set a txfee while not enabling in the flag mptAlice.create( - {.maxAmt = 100, + {.maxAmt = "100", .assetScale = 0, .transferFee = 1, .metadata = "test", @@ -61,7 +61,7 @@ class MPToken_test : public beast::unit_test::suite // tries to set a txfee greater than max mptAlice.create( - {.maxAmt = 100, + {.maxAmt = "100", .assetScale = 0, .transferFee = maxTransferFee + 1, .metadata = "test", @@ -70,7 +70,7 @@ class MPToken_test : public beast::unit_test::suite // tries to set a txfee while not enabling transfer mptAlice.create( - {.maxAmt = 100, + {.maxAmt = "100", .assetScale = 0, .transferFee = maxTransferFee, .metadata = "test", @@ -78,7 +78,7 @@ class MPToken_test : public beast::unit_test::suite // empty metadata returns error mptAlice.create( - {.maxAmt = 100, + {.maxAmt = "100", .assetScale = 0, .transferFee = 0, .metadata = "", @@ -86,7 +86,7 @@ class MPToken_test : public beast::unit_test::suite // MaximumAmout of 0 returns error mptAlice.create( - {.maxAmt = 0, + {.maxAmt = "0", .assetScale = 1, .transferFee = 1, .metadata = "test", @@ -94,7 +94,7 @@ class MPToken_test : public beast::unit_test::suite // MaximumAmount larger than 63 bit returns error mptAlice.create( - {.maxAmt = 0xFFFFFFFFFFFFFFF0ull, + {.maxAmt = "18446744073709551600", .assetScale = 0, .transferFee = 0, .metadata = "test", @@ -116,7 +116,7 @@ class MPToken_test : public beast::unit_test::suite Env env{*this, features}; MPTTester mptAlice(env, alice); mptAlice.create( - {.maxAmt = 0x7FFFFFFFFFFFFFFF, + {.maxAmt = "9223372036854775807", .assetScale = 1, .transferFee = 10, .metadata = "123", @@ -781,7 +781,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {&bob}}); mptAlice.create( - {.maxAmt = 100, + {.maxAmt = "100", .ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); diff --git a/src/test/jtx/impl/mpt.cpp b/src/test/jtx/impl/mpt.cpp index 88f206796bf..1e051a8092a 100644 --- a/src/test/jtx/impl/mpt.cpp +++ b/src/test/jtx/impl/mpt.cpp @@ -25,15 +25,6 @@ namespace ripple { namespace test { namespace jtx { -static std::array<std::uint8_t, 8> -uint64ToByteArray(std::uint64_t value) -{ - value = boost::endian::native_to_big(value); - std::array<std::uint8_t, 8> result; - std::memcpy(result.data(), &value, sizeof(value)); - return result; -} - void mptflags::operator()(Env& env) const { @@ -105,10 +96,8 @@ MPTTester::create(const MPTCreate& arg) jv[sfTransferFee.jsonName] = *arg.transferFee; if (arg.metadata) jv[sfMPTokenMetadata.jsonName] = strHex(*arg.metadata); - - // convert maxAmt to hex string, since json doesn't accept 64-bit int if (arg.maxAmt) - jv[sfMaximumAmount.jsonName] = strHex(uint64ToByteArray(*arg.maxAmt)); + jv[sfMaximumAmount.jsonName] = *arg.maxAmt; if (submit(arg, jv) != tesSUCCESS) { // Verify issuance doesn't exist diff --git a/src/test/jtx/mpt.h b/src/test/jtx/mpt.h index e96b73f039a..78b09a03923 100644 --- a/src/test/jtx/mpt.h +++ b/src/test/jtx/mpt.h @@ -97,7 +97,7 @@ struct MPTConstr struct MPTCreate { - std::optional<std::int64_t> maxAmt = std::nullopt; + std::optional<std::string> maxAmt = std::nullopt; std::optional<std::uint8_t> assetScale = std::nullopt; std::optional<std::uint16_t> transferFee = std::nullopt; std::optional<std::string> metadata = std::nullopt;