mirror of
https://github.com/XRPLF/clio.git
synced 2025-12-06 17:27:58 +00:00
feat: Add Support Credentials for Clio (#1712)
Rippled PR: [here](https://github.com/XRPLF/rippled/pull/5103)
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
@@ -48,6 +49,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
@@ -540,7 +542,7 @@ CreateCheckLedgerObject(std::string_view account, std::string_view dest)
|
||||
}
|
||||
|
||||
ripple::STObject
|
||||
CreateDepositPreauthLedgerObject(std::string_view account, std::string_view auth)
|
||||
CreateDepositPreauthLedgerObjectByAuth(std::string_view account, std::string_view auth)
|
||||
{
|
||||
ripple::STObject depositPreauth(ripple::sfLedgerEntry);
|
||||
depositPreauth.setFieldU16(ripple::sfLedgerEntryType, ripple::ltDEPOSIT_PREAUTH);
|
||||
@@ -553,6 +555,27 @@ CreateDepositPreauthLedgerObject(std::string_view account, std::string_view auth
|
||||
return depositPreauth;
|
||||
}
|
||||
|
||||
ripple::STObject
|
||||
CreateDepositPreauthLedgerObjectByAuthCredentials(
|
||||
std::string_view account,
|
||||
std::string_view issuer,
|
||||
std::string_view credType
|
||||
)
|
||||
{
|
||||
ripple::STObject depositPreauth(ripple::sfLedgerEntry);
|
||||
depositPreauth.setFieldU16(ripple::sfLedgerEntryType, ripple::ltDEPOSIT_PREAUTH);
|
||||
depositPreauth.setAccountID(ripple::sfAccount, GetAccountIDWithString(account));
|
||||
depositPreauth.setFieldArray(
|
||||
ripple::sfAuthorizeCredentials,
|
||||
CreateAuthCredentialArray(std::vector<std::string_view>{issuer}, std::vector<std::string_view>{credType})
|
||||
);
|
||||
depositPreauth.setFieldU32(ripple::sfFlags, 0);
|
||||
depositPreauth.setFieldU64(ripple::sfOwnerNode, 0);
|
||||
depositPreauth.setFieldH256(ripple::sfPreviousTxnID, ripple::uint256{});
|
||||
depositPreauth.setFieldU32(ripple::sfPreviousTxnLgrSeq, 0);
|
||||
return depositPreauth;
|
||||
}
|
||||
|
||||
data::NFT
|
||||
CreateNFT(std::string_view tokenID, std::string_view account, ripple::LedgerIndex seq, ripple::Blob uri, bool isBurned)
|
||||
{
|
||||
@@ -1192,3 +1215,47 @@ CreateOracleObject(
|
||||
|
||||
return ledgerObject;
|
||||
}
|
||||
|
||||
// acc2 issue credential for acc1 so acc2 is issuer
|
||||
ripple::STObject
|
||||
CreateCredentialObject(
|
||||
std::string_view acc1,
|
||||
std::string_view acc2,
|
||||
std::string_view credType,
|
||||
bool accept,
|
||||
std::optional<uint32_t> expiration
|
||||
)
|
||||
{
|
||||
ripple::STObject credObj(ripple::sfCredential);
|
||||
credObj.setFieldU16(ripple::sfLedgerEntryType, ripple::ltCREDENTIAL);
|
||||
credObj.setFieldVL(ripple::sfCredentialType, ripple::Blob{credType.begin(), credType.end()});
|
||||
credObj.setAccountID(ripple::sfSubject, GetAccountIDWithString(acc1));
|
||||
credObj.setAccountID(ripple::sfIssuer, GetAccountIDWithString(acc2));
|
||||
if (expiration.has_value())
|
||||
credObj.setFieldU32(ripple::sfExpiration, expiration.value());
|
||||
|
||||
if (accept) {
|
||||
credObj.setFieldU32(ripple::sfFlags, ripple::lsfAccepted);
|
||||
} else {
|
||||
credObj.setFieldU32(ripple::sfFlags, 0);
|
||||
}
|
||||
credObj.setFieldU64(ripple::sfSubjectNode, 0);
|
||||
credObj.setFieldU64(ripple::sfIssuerNode, 0);
|
||||
credObj.setFieldH256(ripple::sfPreviousTxnID, ripple::uint256{});
|
||||
credObj.setFieldU32(ripple::sfPreviousTxnLgrSeq, 0);
|
||||
return credObj;
|
||||
}
|
||||
|
||||
ripple::STArray
|
||||
CreateAuthCredentialArray(std::vector<std::string_view> issuer, std::vector<std::string_view> credType)
|
||||
{
|
||||
ripple::STArray arr;
|
||||
ASSERT(issuer.size() == credType.size(), "issuer and credtype vector must be same length");
|
||||
for (std::size_t i = 0; i < issuer.size(); ++i) {
|
||||
auto credential = ripple::STObject::makeInnerObject(ripple::sfCredential);
|
||||
credential.setAccountID(ripple::sfIssuer, GetAccountIDWithString(issuer[i]));
|
||||
credential.setFieldVL(ripple::sfCredentialType, ripple::strUnHex(std::string(credType[i])).value());
|
||||
arr.push_back(credential);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "data/Types.hpp"
|
||||
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
@@ -268,7 +269,14 @@ CreateEscrowLedgerObject(std::string_view account, std::string_view dest);
|
||||
CreateCheckLedgerObject(std::string_view account, std::string_view dest);
|
||||
|
||||
[[nodiscard]] ripple::STObject
|
||||
CreateDepositPreauthLedgerObject(std::string_view account, std::string_view auth);
|
||||
CreateDepositPreauthLedgerObjectByAuth(std::string_view account, std::string_view auth);
|
||||
|
||||
[[nodiscard]] ripple::STObject
|
||||
CreateDepositPreauthLedgerObjectByAuthCredentials(
|
||||
std::string_view account,
|
||||
std::string_view issuer,
|
||||
std::string_view credType
|
||||
);
|
||||
|
||||
[[nodiscard]] data::NFT
|
||||
CreateNFT(
|
||||
@@ -435,3 +443,15 @@ CreateOracleSetTxWithMetadata(
|
||||
bool created,
|
||||
std::string_view previousTxnId
|
||||
);
|
||||
|
||||
[[nodiscard]] ripple::STObject
|
||||
CreateCredentialObject(
|
||||
std::string_view acc1,
|
||||
std::string_view acc2,
|
||||
std::string_view credType,
|
||||
bool accept = true,
|
||||
std::optional<uint32_t> expiration = std::nullopt
|
||||
);
|
||||
|
||||
[[nodiscard]] ripple::STArray
|
||||
CreateAuthCredentialArray(std::vector<std::string_view> issuer, std::vector<std::string_view> credType);
|
||||
|
||||
@@ -67,6 +67,7 @@ target_sources(
|
||||
rpc/handlers/AMMInfoTests.cpp
|
||||
rpc/handlers/BookChangesTests.cpp
|
||||
rpc/handlers/BookOffersTests.cpp
|
||||
rpc/handlers/CredentialHelpersTests.cpp
|
||||
rpc/handlers/DefaultProcessorTests.cpp
|
||||
rpc/handlers/DepositAuthorizedTests.cpp
|
||||
rpc/handlers/FeatureTests.cpp
|
||||
|
||||
@@ -30,10 +30,12 @@
|
||||
|
||||
#include <boost/asio/impl/spawn.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/ErrorCodes.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
@@ -47,6 +49,7 @@
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
153
tests/unit/rpc/handlers/CredentialHelpersTests.cpp
Normal file
153
tests/unit/rpc/handlers/CredentialHelpersTests.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2024, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and 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 "rpc/CredentialHelpers.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "rpc/JS.hpp"
|
||||
#include "util/AsioContextTestFixture.hpp"
|
||||
#include "util/MockBackendTestFixture.hpp"
|
||||
#include "util/MockPrometheus.hpp"
|
||||
#include "util/TestObject.hpp"
|
||||
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
#include <xrpl/protocol/STObject.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
using namespace rpc;
|
||||
using namespace testing;
|
||||
|
||||
constexpr static auto Account = "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn";
|
||||
constexpr static auto Account2 = "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun";
|
||||
constexpr static auto Index1 = "E6DBAFC99223B42257915A63DFC6B0C032D4070F9A574B255AD97466726FC321";
|
||||
constexpr static auto CredentialID = "c7a14f6b9d5d4a9cb9c223a61b8e5c7df58e8b7ad1c6b4f8e7a321fa4e5b4c9d";
|
||||
constexpr static std::string_view CredentialType = "credType";
|
||||
|
||||
TEST(CreateAuthCredentialsTest, UniqueCredentials)
|
||||
{
|
||||
ripple::STArray credentials;
|
||||
auto const cred1 = CreateCredentialObject(Account, Account2, CredentialType);
|
||||
auto const cred2 = CreateCredentialObject(Account2, Account, CredentialType);
|
||||
|
||||
credentials.push_back(cred1);
|
||||
credentials.push_back(cred2);
|
||||
|
||||
auto const result = credentials::createAuthCredentials(credentials);
|
||||
|
||||
// Validate that the result contains the correct set of credentials
|
||||
ASSERT_EQ(result.size(), 2);
|
||||
|
||||
auto const cred1Type = cred1.getFieldVL(ripple::sfCredentialType);
|
||||
auto const cred2Type = cred2.getFieldVL(ripple::sfCredentialType);
|
||||
|
||||
auto const expected_cred1 =
|
||||
std::make_pair(cred1.getAccountID(ripple::sfIssuer), ripple::Slice{cred1Type.data(), cred1Type.size()});
|
||||
auto const expected_cred2 =
|
||||
std::make_pair(cred2.getAccountID(ripple::sfIssuer), ripple::Slice{cred2Type.data(), cred2Type.size()});
|
||||
|
||||
EXPECT_TRUE(result.count(expected_cred1));
|
||||
EXPECT_TRUE(result.count(expected_cred2));
|
||||
}
|
||||
|
||||
TEST(ParseAuthorizeCredentialsTest, ValidCredentialsArray)
|
||||
{
|
||||
boost::json::array credentials;
|
||||
boost::json::object credential1;
|
||||
credential1[JS(issuer)] = Account;
|
||||
credential1[JS(credential_type)] = ripple::strHex(CredentialType);
|
||||
|
||||
credentials.push_back(credential1);
|
||||
ripple::STArray const parsedCredentials = credentials::parseAuthorizeCredentials(credentials);
|
||||
|
||||
ASSERT_EQ(parsedCredentials.size(), 1);
|
||||
|
||||
ripple::STObject const& cred = parsedCredentials[0];
|
||||
ASSERT_TRUE(cred.isFieldPresent(ripple::sfIssuer));
|
||||
ASSERT_TRUE(cred.isFieldPresent(ripple::sfCredentialType));
|
||||
|
||||
auto const expectedIssuer =
|
||||
*ripple::parseBase58<ripple::AccountID>(static_cast<std::string>(credential1[JS(issuer)].as_string()));
|
||||
auto const expectedCredentialType =
|
||||
ripple::strUnHex(static_cast<std::string>(credential1[JS(credential_type)].as_string())).value();
|
||||
|
||||
EXPECT_EQ(cred.getAccountID(ripple::sfIssuer), expectedIssuer);
|
||||
EXPECT_EQ(cred.getFieldVL(ripple::sfCredentialType), expectedCredentialType);
|
||||
}
|
||||
|
||||
class CredentialHelperTest : public util::prometheus::WithPrometheus,
|
||||
public MockBackendTest,
|
||||
public SyncAsioContextTest {};
|
||||
|
||||
TEST_F(CredentialHelperTest, GetInvalidCredentialArray)
|
||||
{
|
||||
boost::json::array credentialsArray = {CredentialID};
|
||||
auto const info = CreateLedgerHeader(Index1, 30);
|
||||
|
||||
boost::asio::spawn(ctx, [&](boost::asio::yield_context yield) {
|
||||
auto const ret =
|
||||
credentials::fetchCredentialArray(credentialsArray, GetAccountIDWithString(Account), *backend, info, yield);
|
||||
ASSERT_FALSE(ret.has_value());
|
||||
auto const status = ret.error();
|
||||
EXPECT_EQ(status, RippledError::rpcBAD_CREDENTIALS);
|
||||
EXPECT_EQ(status.message, "credentials don't exist.");
|
||||
});
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(CredentialHelperTest, GetValidCredentialArray)
|
||||
{
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(Index1, 30);
|
||||
auto const credLedgerObject = CreateCredentialObject(Account, Account2, CredentialType, true);
|
||||
|
||||
ON_CALL(*backend, doFetchLedgerObject(_, _, _)).WillByDefault(Return(credLedgerObject.getSerializer().peekData()));
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(1);
|
||||
|
||||
boost::json::array credentialsArray = {CredentialID};
|
||||
|
||||
ripple::STArray expectedAuthCreds;
|
||||
ripple::STObject credential(ripple::sfCredential);
|
||||
credential.setAccountID(ripple::sfIssuer, GetAccountIDWithString(Account2));
|
||||
credential.setFieldVL(ripple::sfCredentialType, ripple::Blob{std::begin(CredentialType), std::end(CredentialType)});
|
||||
expectedAuthCreds.push_back(std::move(credential));
|
||||
|
||||
boost::asio::spawn(ctx, [&](boost::asio::yield_context yield) {
|
||||
auto const result = credentials::fetchCredentialArray(
|
||||
credentialsArray, GetAccountIDWithString(Account), *backend, ledgerHeader, yield
|
||||
);
|
||||
ASSERT_TRUE(result.has_value());
|
||||
EXPECT_EQ(result.value(), expectedAuthCreds);
|
||||
});
|
||||
ctx.run();
|
||||
}
|
||||
@@ -28,24 +28,34 @@
|
||||
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <optional>
|
||||
#include <ranges>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
constexpr static auto ACCOUNT = "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn";
|
||||
constexpr static auto ACCOUNT2 = "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun";
|
||||
constexpr static auto LEDGERHASH = "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A652";
|
||||
constexpr static auto INDEX1 = "1B8590C01B0006EDFA9ED60296DD052DC5E90F99659B25014D08E1BC983515BC";
|
||||
constexpr static auto INDEX2 = "1B8590C01B0006EDFA9ED60296DD052DC5E90F99659B25014D08E1BC983515B1";
|
||||
constexpr static auto Account = "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn";
|
||||
constexpr static auto Account2 = "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun";
|
||||
constexpr static auto LedgerHash = "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A652";
|
||||
constexpr static auto Index1 = "1B8590C01B0006EDFA9ED60296DD052DC5E90F99659B25014D08E1BC983515BC";
|
||||
constexpr static auto Index2 = "1B8590C01B0006EDFA9ED60296DD052DC5E90F99659B25014D08E1BC983515B1";
|
||||
constexpr static std::string_view CredentialType = "credType";
|
||||
constexpr static auto CredentialHash = "F245428267E6177AEEFDD4FEA3533285712A4B1091CF82A7EA7BC39A62C3FB1A";
|
||||
|
||||
constexpr static auto RANGEMIN = 10;
|
||||
constexpr static auto RANGEMAX = 30;
|
||||
constexpr static auto RangeMin = 10;
|
||||
constexpr static auto RangeMax = 30;
|
||||
|
||||
using namespace rpc;
|
||||
namespace json = boost::json;
|
||||
@@ -156,6 +166,38 @@ generateTestValuesForParametersTest()
|
||||
"invalidParams",
|
||||
"ledgerIndexMalformed",
|
||||
},
|
||||
{
|
||||
"CredentialsNotArray",
|
||||
R"({
|
||||
"source_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"destination_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"credentials": "x"
|
||||
})",
|
||||
"invalidParams",
|
||||
"Invalid parameters.",
|
||||
},
|
||||
{
|
||||
"CredentialsNotStringsInArray",
|
||||
R"({
|
||||
"source_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"destination_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_hash": "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A652",
|
||||
"credentials": [123]
|
||||
})",
|
||||
"invalidParams",
|
||||
"Item is not a valid uint256 type.",
|
||||
},
|
||||
{
|
||||
"CredentialsNotHexedStringInArray",
|
||||
R"({
|
||||
"source_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"destination_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_hash": "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A652",
|
||||
"credentials": ["234", "432"]
|
||||
})",
|
||||
"invalidParams",
|
||||
"Item is not a valid uint256 type.",
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -184,10 +226,10 @@ TEST_P(DepositAuthorizedParameterTest, InvalidParams)
|
||||
|
||||
TEST_F(RPCDepositAuthorizedTest, LedgerNotExistViaIntSequence)
|
||||
{
|
||||
backend->setRange(RANGEMIN, RANGEMAX);
|
||||
backend->setRange(RangeMin, RangeMax);
|
||||
|
||||
EXPECT_CALL(*backend, fetchLedgerBySequence).Times(1);
|
||||
ON_CALL(*backend, fetchLedgerBySequence(RANGEMAX, _)).WillByDefault(Return(std::nullopt));
|
||||
ON_CALL(*backend, fetchLedgerBySequence(RangeMax, _)).WillByDefault(Return(std::nullopt));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{DepositAuthorizedHandler{backend}};
|
||||
@@ -197,9 +239,9 @@ TEST_F(RPCDepositAuthorizedTest, LedgerNotExistViaIntSequence)
|
||||
"destination_account": "{}",
|
||||
"ledger_index": {}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
RANGEMAX
|
||||
Account,
|
||||
Account2,
|
||||
RangeMax
|
||||
));
|
||||
|
||||
auto const output = handler.process(req, Context{yield});
|
||||
@@ -213,10 +255,10 @@ TEST_F(RPCDepositAuthorizedTest, LedgerNotExistViaIntSequence)
|
||||
|
||||
TEST_F(RPCDepositAuthorizedTest, LedgerNotExistViaStringSequence)
|
||||
{
|
||||
backend->setRange(RANGEMIN, RANGEMAX);
|
||||
backend->setRange(RangeMin, RangeMax);
|
||||
|
||||
EXPECT_CALL(*backend, fetchLedgerBySequence).Times(1);
|
||||
ON_CALL(*backend, fetchLedgerBySequence(RANGEMAX, _)).WillByDefault(Return(std::nullopt));
|
||||
ON_CALL(*backend, fetchLedgerBySequence(RangeMax, _)).WillByDefault(Return(std::nullopt));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{DepositAuthorizedHandler{backend}};
|
||||
@@ -226,9 +268,9 @@ TEST_F(RPCDepositAuthorizedTest, LedgerNotExistViaStringSequence)
|
||||
"destination_account": "{}",
|
||||
"ledger_index": "{}"
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
RANGEMAX
|
||||
Account,
|
||||
Account2,
|
||||
RangeMax
|
||||
));
|
||||
|
||||
auto const output = handler.process(req, Context{yield});
|
||||
@@ -242,10 +284,10 @@ TEST_F(RPCDepositAuthorizedTest, LedgerNotExistViaStringSequence)
|
||||
|
||||
TEST_F(RPCDepositAuthorizedTest, LedgerNotExistViaHash)
|
||||
{
|
||||
backend->setRange(RANGEMIN, RANGEMAX);
|
||||
backend->setRange(RangeMin, RangeMax);
|
||||
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash).Times(1);
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LEDGERHASH}, _)).WillByDefault(Return(std::nullopt));
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillByDefault(Return(std::nullopt));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{DepositAuthorizedHandler{backend}};
|
||||
@@ -255,9 +297,9 @@ TEST_F(RPCDepositAuthorizedTest, LedgerNotExistViaHash)
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}"
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
LEDGERHASH
|
||||
Account,
|
||||
Account2,
|
||||
LedgerHash
|
||||
));
|
||||
|
||||
auto const output = handler.process(req, Context{yield});
|
||||
@@ -273,9 +315,9 @@ TEST_F(RPCDepositAuthorizedTest, SourceAccountDoesNotExist)
|
||||
{
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(LEDGERHASH, 30);
|
||||
auto ledgerHeader = CreateLedgerHeader(LedgerHash, 30);
|
||||
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LEDGERHASH}, _)).WillByDefault(Return(ledgerHeader));
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillByDefault(Return(ledgerHeader));
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash).Times(1);
|
||||
|
||||
ON_CALL(*backend, doFetchLedgerObject).WillByDefault(Return(std::optional<Blob>{}));
|
||||
@@ -287,9 +329,9 @@ TEST_F(RPCDepositAuthorizedTest, SourceAccountDoesNotExist)
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}"
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
LEDGERHASH
|
||||
Account,
|
||||
Account2,
|
||||
LedgerHash
|
||||
));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
@@ -308,14 +350,14 @@ TEST_F(RPCDepositAuthorizedTest, DestinationAccountDoesNotExist)
|
||||
{
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(LEDGERHASH, 30);
|
||||
auto ledgerHeader = CreateLedgerHeader(LedgerHash, 30);
|
||||
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LEDGERHASH}, _)).WillByDefault(Return(ledgerHeader));
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillByDefault(Return(ledgerHeader));
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash).Times(1);
|
||||
|
||||
auto const accountRoot = CreateAccountRootObject(ACCOUNT, 0, 2, 200, 2, INDEX1, 2);
|
||||
auto const accountRoot = CreateAccountRootObject(Account, 0, 2, 200, 2, Index1, 2);
|
||||
ON_CALL(*backend, doFetchLedgerObject(_, _, _)).WillByDefault(Return(accountRoot.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(ACCOUNT2)).key, _, _))
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account2)).key, _, _))
|
||||
.WillByDefault(Return(std::optional<Blob>{}));
|
||||
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(2);
|
||||
@@ -326,9 +368,9 @@ TEST_F(RPCDepositAuthorizedTest, DestinationAccountDoesNotExist)
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}"
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
LEDGERHASH
|
||||
Account,
|
||||
Account2,
|
||||
LedgerHash
|
||||
));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
@@ -357,12 +399,12 @@ TEST_F(RPCDepositAuthorizedTest, AccountsAreEqual)
|
||||
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(LEDGERHASH, 30);
|
||||
auto ledgerHeader = CreateLedgerHeader(LedgerHash, 30);
|
||||
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LEDGERHASH}, _)).WillByDefault(Return(ledgerHeader));
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillByDefault(Return(ledgerHeader));
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash).Times(1);
|
||||
|
||||
auto const accountRoot = CreateAccountRootObject(ACCOUNT, 0, 2, 200, 2, INDEX1, 2);
|
||||
auto const accountRoot = CreateAccountRootObject(Account, 0, 2, 200, 2, Index1, 2);
|
||||
ON_CALL(*backend, doFetchLedgerObject).WillByDefault(Return(accountRoot.getSerializer().peekData()));
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(2);
|
||||
|
||||
@@ -372,9 +414,9 @@ TEST_F(RPCDepositAuthorizedTest, AccountsAreEqual)
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}"
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT,
|
||||
LEDGERHASH
|
||||
Account,
|
||||
Account,
|
||||
LedgerHash
|
||||
));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
@@ -400,17 +442,17 @@ TEST_F(RPCDepositAuthorizedTest, DifferentAccountsNoDepositAuthFlag)
|
||||
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(LEDGERHASH, 30);
|
||||
auto ledgerHeader = CreateLedgerHeader(LedgerHash, 30);
|
||||
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LEDGERHASH}, _)).WillByDefault(Return(ledgerHeader));
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillByDefault(Return(ledgerHeader));
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash).Times(1);
|
||||
|
||||
auto const account1Root = CreateAccountRootObject(ACCOUNT, 0, 2, 200, 2, INDEX1, 2);
|
||||
auto const account2Root = CreateAccountRootObject(ACCOUNT2, 0, 2, 200, 2, INDEX2, 2);
|
||||
auto const account1Root = CreateAccountRootObject(Account, 0, 2, 200, 2, Index1, 2);
|
||||
auto const account2Root = CreateAccountRootObject(Account2, 0, 2, 200, 2, Index2, 2);
|
||||
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(ACCOUNT)).key, _, _))
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account)).key, _, _))
|
||||
.WillByDefault(Return(account1Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(ACCOUNT2)).key, _, _))
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account2)).key, _, _))
|
||||
.WillByDefault(Return(account2Root.getSerializer().peekData()));
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(2);
|
||||
|
||||
@@ -420,9 +462,9 @@ TEST_F(RPCDepositAuthorizedTest, DifferentAccountsNoDepositAuthFlag)
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}"
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
LEDGERHASH
|
||||
Account,
|
||||
Account2,
|
||||
LedgerHash
|
||||
));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
@@ -448,18 +490,18 @@ TEST_F(RPCDepositAuthorizedTest, DifferentAccountsWithDepositAuthFlagReturnsFals
|
||||
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(LEDGERHASH, 30);
|
||||
auto ledgerHeader = CreateLedgerHeader(LedgerHash, 30);
|
||||
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LEDGERHASH}, _)).WillByDefault(Return(ledgerHeader));
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillByDefault(Return(ledgerHeader));
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash).Times(1);
|
||||
|
||||
auto const account1Root = CreateAccountRootObject(ACCOUNT, 0, 2, 200, 2, INDEX1, 2);
|
||||
auto const account2Root = CreateAccountRootObject(ACCOUNT2, ripple::lsfDepositAuth, 2, 200, 2, INDEX2, 2);
|
||||
auto const account1Root = CreateAccountRootObject(Account, 0, 2, 200, 2, Index1, 2);
|
||||
auto const account2Root = CreateAccountRootObject(Account2, ripple::lsfDepositAuth, 2, 200, 2, Index2, 2);
|
||||
|
||||
ON_CALL(*backend, doFetchLedgerObject(_, _, _)).WillByDefault(Return(std::nullopt));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(ACCOUNT)).key, _, _))
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account)).key, _, _))
|
||||
.WillByDefault(Return(account1Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(ACCOUNT2)).key, _, _))
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account2)).key, _, _))
|
||||
.WillByDefault(Return(account2Root.getSerializer().peekData()));
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(3);
|
||||
|
||||
@@ -469,9 +511,9 @@ TEST_F(RPCDepositAuthorizedTest, DifferentAccountsWithDepositAuthFlagReturnsFals
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}"
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
LEDGERHASH
|
||||
Account,
|
||||
Account2,
|
||||
LedgerHash
|
||||
));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
@@ -497,18 +539,18 @@ TEST_F(RPCDepositAuthorizedTest, DifferentAccountsWithDepositAuthFlagReturnsTrue
|
||||
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(LEDGERHASH, 30);
|
||||
auto ledgerHeader = CreateLedgerHeader(LedgerHash, 30);
|
||||
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LEDGERHASH}, _)).WillByDefault(Return(ledgerHeader));
|
||||
ON_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillByDefault(Return(ledgerHeader));
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash).Times(1);
|
||||
|
||||
auto const account1Root = CreateAccountRootObject(ACCOUNT, 0, 2, 200, 2, INDEX1, 2);
|
||||
auto const account2Root = CreateAccountRootObject(ACCOUNT2, ripple::lsfDepositAuth, 2, 200, 2, INDEX2, 2);
|
||||
auto const account1Root = CreateAccountRootObject(Account, 0, 2, 200, 2, Index1, 2);
|
||||
auto const account2Root = CreateAccountRootObject(Account2, ripple::lsfDepositAuth, 2, 200, 2, Index2, 2);
|
||||
|
||||
ON_CALL(*backend, doFetchLedgerObject(_, _, _)).WillByDefault(Return(std::optional<Blob>{{1, 2, 3}}));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(ACCOUNT)).key, _, _))
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account)).key, _, _))
|
||||
.WillByDefault(Return(account1Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(ACCOUNT2)).key, _, _))
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account2)).key, _, _))
|
||||
.WillByDefault(Return(account2Root.getSerializer().peekData()));
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(3);
|
||||
|
||||
@@ -518,9 +560,9 @@ TEST_F(RPCDepositAuthorizedTest, DifferentAccountsWithDepositAuthFlagReturnsTrue
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}"
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
LEDGERHASH
|
||||
Account,
|
||||
Account2,
|
||||
LedgerHash
|
||||
));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
@@ -531,3 +573,380 @@ TEST_F(RPCDepositAuthorizedTest, DifferentAccountsWithDepositAuthFlagReturnsTrue
|
||||
EXPECT_EQ(*output.result, json::parse(expectedOut));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCDepositAuthorizedTest, CredentialAcceptedAndNotExpiredReturnsTrue)
|
||||
{
|
||||
static auto const expectedOut = fmt::format(
|
||||
R"({{
|
||||
"ledger_hash": "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A652",
|
||||
"ledger_index": 30,
|
||||
"validated": true,
|
||||
"deposit_authorized": true,
|
||||
"source_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"destination_account": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun",
|
||||
"credentials": ["{}"]
|
||||
}})",
|
||||
CredentialHash // CREDENTIALHASH should match credentialIndex
|
||||
);
|
||||
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(LedgerHash, 30);
|
||||
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto const account1Root = CreateAccountRootObject(Account, 0, 2, 200, 2, Index1, 2);
|
||||
auto const account2Root = CreateAccountRootObject(Account2, ripple::lsfDepositAuth, 2, 200, 2, Index2, 2);
|
||||
auto const credential = CreateCredentialObject(Account, Account2, CredentialType);
|
||||
auto const credentialIndex = ripple::keylet::credential(
|
||||
GetAccountIDWithString(Account),
|
||||
GetAccountIDWithString(Account2),
|
||||
ripple::Slice(CredentialType.data(), CredentialType.size())
|
||||
)
|
||||
.key;
|
||||
|
||||
ON_CALL(*backend, doFetchLedgerObject(_, _, _)).WillByDefault(Return(std::optional<Blob>{{1, 2, 3}}));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account)).key, _, _))
|
||||
.WillByDefault(Return(account1Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account2)).key, _, _))
|
||||
.WillByDefault(Return(account2Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(credentialIndex, _, _))
|
||||
.WillByDefault(Return(credential.getSerializer().peekData()));
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(4);
|
||||
|
||||
auto const input = json::parse(fmt::format(
|
||||
R"({{
|
||||
"source_account": "{}",
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}",
|
||||
"credentials": ["{}"]
|
||||
}})",
|
||||
Account,
|
||||
Account2,
|
||||
LedgerHash,
|
||||
ripple::strHex(credentialIndex)
|
||||
));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{DepositAuthorizedHandler{backend}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ(*output.result, json::parse(expectedOut));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCDepositAuthorizedTest, CredentialNotAuthorizedReturnsFalse)
|
||||
{
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(LedgerHash, 30);
|
||||
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto const account1Root = CreateAccountRootObject(Account, 0, 2, 200, 2, Index1, 2);
|
||||
auto const account2Root = CreateAccountRootObject(Account2, ripple::lsfDepositAuth, 2, 200, 2, Index2, 2);
|
||||
auto const credential = CreateCredentialObject(Account, Account2, CredentialType, false);
|
||||
auto const credentialIndex = ripple::keylet::credential(
|
||||
GetAccountIDWithString(Account),
|
||||
GetAccountIDWithString(Account2),
|
||||
ripple::Slice(CredentialType.data(), CredentialType.size())
|
||||
)
|
||||
.key;
|
||||
|
||||
ON_CALL(*backend, doFetchLedgerObject(_, _, _)).WillByDefault(Return(std::optional<Blob>{{1, 2, 3}}));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account)).key, _, _))
|
||||
.WillByDefault(Return(account1Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account2)).key, _, _))
|
||||
.WillByDefault(Return(account2Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(credentialIndex, _, _))
|
||||
.WillByDefault(Return(credential.getSerializer().peekData()));
|
||||
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(3);
|
||||
|
||||
auto const input = json::parse(fmt::format(
|
||||
R"({{
|
||||
"source_account": "{}",
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}",
|
||||
"credentials": ["{}"]
|
||||
}})",
|
||||
Account,
|
||||
Account2,
|
||||
LedgerHash,
|
||||
ripple::strHex(credentialIndex)
|
||||
));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{DepositAuthorizedHandler{backend}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
|
||||
ASSERT_FALSE(output);
|
||||
auto const err = rpc::makeError(output.result.error());
|
||||
EXPECT_EQ(err.at("error").as_string(), "badCredentials");
|
||||
EXPECT_EQ(err.at("error_message").as_string(), "credentials aren't accepted");
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCDepositAuthorizedTest, CredentialExpiredReturnsFalse)
|
||||
{
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(LedgerHash, 30, 100);
|
||||
|
||||
// set parent close time to 500 seconds
|
||||
ledgerHeader.parentCloseTime = ripple::NetClock::time_point{std::chrono::seconds{500}};
|
||||
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto const account1Root = CreateAccountRootObject(Account, 0, 2, 200, 2, Index1, 2);
|
||||
auto const account2Root = CreateAccountRootObject(Account2, ripple::lsfDepositAuth, 2, 200, 2, Index2, 2);
|
||||
|
||||
// credential expire time is 23 seconds, so credential will fail
|
||||
auto const expiredCredential = CreateCredentialObject(Account, Account2, CredentialType, true, 23);
|
||||
|
||||
auto const credentialIndex = ripple::keylet::credential(
|
||||
GetAccountIDWithString(Account),
|
||||
GetAccountIDWithString(Account2),
|
||||
ripple::Slice(CredentialType.data(), CredentialType.size())
|
||||
)
|
||||
.key;
|
||||
|
||||
ON_CALL(*backend, doFetchLedgerObject(_, _, _)).WillByDefault(Return(std::optional<Blob>{{1, 2, 3}}));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account)).key, _, _))
|
||||
.WillByDefault(Return(account1Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account2)).key, _, _))
|
||||
.WillByDefault(Return(account2Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(credentialIndex, _, _))
|
||||
.WillByDefault(Return(expiredCredential.getSerializer().peekData()));
|
||||
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(3);
|
||||
|
||||
auto const input = json::parse(fmt::format(
|
||||
R"({{
|
||||
"source_account": "{}",
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}",
|
||||
"credentials": ["{}"]
|
||||
}})",
|
||||
Account,
|
||||
Account2,
|
||||
LedgerHash,
|
||||
ripple::strHex(credentialIndex)
|
||||
));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{DepositAuthorizedHandler{backend}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
|
||||
ASSERT_FALSE(output);
|
||||
auto const err = rpc::makeError(output.result.error());
|
||||
EXPECT_EQ(err.at("error").as_string(), "badCredentials");
|
||||
EXPECT_EQ(err.at("error_message").as_string(), "credentials are expired");
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCDepositAuthorizedTest, DuplicateCredentialsReturnsFalse)
|
||||
{
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(LedgerHash, 30, 34);
|
||||
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto const account1Root = CreateAccountRootObject(Account, 0, 2, 200, 2, Index1, 2);
|
||||
auto const account2Root = CreateAccountRootObject(Account2, ripple::lsfDepositAuth, 2, 200, 2, Index2, 2);
|
||||
auto const credential = CreateCredentialObject(Account, Account2, CredentialType);
|
||||
auto const credentialIndex = ripple::keylet::credential(
|
||||
GetAccountIDWithString(Account),
|
||||
GetAccountIDWithString(Account2),
|
||||
ripple::Slice(CredentialType.data(), CredentialType.size())
|
||||
)
|
||||
.key;
|
||||
|
||||
ON_CALL(*backend, doFetchLedgerObject(_, _, _)).WillByDefault(Return(std::optional<Blob>{{1, 2, 3}}));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account)).key, _, _))
|
||||
.WillByDefault(Return(account1Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account2)).key, _, _))
|
||||
.WillByDefault(Return(account2Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(credentialIndex, _, _))
|
||||
.WillByDefault(Return(credential.getSerializer().peekData()));
|
||||
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(3);
|
||||
|
||||
auto const input = json::parse(fmt::format(
|
||||
R"({{
|
||||
"source_account": "{}",
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}",
|
||||
"credentials": ["{}", "{}"]
|
||||
}})",
|
||||
Account,
|
||||
Account2,
|
||||
LedgerHash,
|
||||
ripple::strHex(credentialIndex),
|
||||
ripple::strHex(credentialIndex)
|
||||
));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{DepositAuthorizedHandler{backend}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
|
||||
ASSERT_FALSE(output);
|
||||
auto const err = rpc::makeError(output.result.error());
|
||||
EXPECT_EQ(err.at("error").as_string(), "badCredentials");
|
||||
EXPECT_EQ(err.at("error_message").as_string(), "duplicates in credentials.");
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCDepositAuthorizedTest, NoElementsInCredentialsReturnsFalse)
|
||||
{
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(LedgerHash, 30, 34);
|
||||
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto const account1Root = CreateAccountRootObject(Account, 0, 2, 200, 2, Index1, 2);
|
||||
auto const account2Root = CreateAccountRootObject(Account2, ripple::lsfDepositAuth, 2, 200, 2, Index2, 2);
|
||||
|
||||
ON_CALL(*backend, doFetchLedgerObject(_, _, _)).WillByDefault(Return(std::optional<Blob>{{1, 2, 3}}));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account)).key, _, _))
|
||||
.WillByDefault(Return(account1Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account2)).key, _, _))
|
||||
.WillByDefault(Return(account2Root.getSerializer().peekData()));
|
||||
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(2);
|
||||
|
||||
auto const input = json::parse(fmt::format(
|
||||
R"({{
|
||||
"source_account": "{}",
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}",
|
||||
"credentials": []
|
||||
}})",
|
||||
Account,
|
||||
Account2,
|
||||
LedgerHash
|
||||
));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{DepositAuthorizedHandler{backend}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
|
||||
ASSERT_FALSE(output);
|
||||
auto const err = rpc::makeError(output.result.error());
|
||||
EXPECT_EQ(err.at("error").as_string(), "invalidParams");
|
||||
EXPECT_EQ(err.at("error_message").as_string(), "credential array has no elements.");
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCDepositAuthorizedTest, MoreThanMaxNumberOfCredentialsReturnsFalse)
|
||||
{
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(LedgerHash, 30, 34);
|
||||
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto const account1Root = CreateAccountRootObject(Account, 0, 2, 200, 2, Index1, 2);
|
||||
auto const account2Root = CreateAccountRootObject(Account2, ripple::lsfDepositAuth, 2, 200, 2, Index2, 2);
|
||||
auto const credential = CreateCredentialObject(Account, Account2, CredentialType);
|
||||
auto const credentialIndex = ripple::keylet::credential(
|
||||
GetAccountIDWithString(Account),
|
||||
GetAccountIDWithString(Account2),
|
||||
ripple::Slice(CredentialType.data(), CredentialType.size())
|
||||
)
|
||||
.key;
|
||||
|
||||
ON_CALL(*backend, doFetchLedgerObject(_, _, _)).WillByDefault(Return(std::optional<Blob>{{1, 2, 3}}));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account)).key, _, _))
|
||||
.WillByDefault(Return(account1Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account2)).key, _, _))
|
||||
.WillByDefault(Return(account2Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(credentialIndex, _, _))
|
||||
.WillByDefault(Return(credential.getSerializer().peekData()));
|
||||
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(2);
|
||||
|
||||
std::vector<std::string> credentials(9, ripple::strHex(credentialIndex));
|
||||
|
||||
auto const input = json::parse(fmt::format(
|
||||
R"({{
|
||||
"source_account": "{}",
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}",
|
||||
"credentials": [{}]
|
||||
}})",
|
||||
Account,
|
||||
Account2,
|
||||
LedgerHash,
|
||||
fmt::join(
|
||||
credentials | std::views::transform([](std::string const& cred) { return fmt::format("\"{}\"", cred); }),
|
||||
", "
|
||||
)
|
||||
));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{DepositAuthorizedHandler{backend}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
|
||||
ASSERT_FALSE(output);
|
||||
auto const err = rpc::makeError(output.result.error());
|
||||
EXPECT_EQ(err.at("error").as_string(), "invalidParams");
|
||||
EXPECT_EQ(err.at("error_message").as_string(), "credential array too long.");
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCDepositAuthorizedTest, DifferenSubjectAccountForCredentialReturnsFalse)
|
||||
{
|
||||
backend->setRange(10, 30);
|
||||
|
||||
auto ledgerHeader = CreateLedgerHeader(LedgerHash, 30);
|
||||
|
||||
EXPECT_CALL(*backend, fetchLedgerByHash(ripple::uint256{LedgerHash}, _)).WillOnce(Return(ledgerHeader));
|
||||
|
||||
auto const account1Root = CreateAccountRootObject(Account, 0, 2, 200, 2, Index1, 2);
|
||||
auto const account2Root = CreateAccountRootObject(Account2, ripple::lsfDepositAuth, 2, 200, 2, Index2, 2);
|
||||
|
||||
// reverse the subject and issuer account. Now subject is ACCOUNT2
|
||||
auto const credential = CreateCredentialObject(Account2, Account, CredentialType);
|
||||
auto const credentialIndex = ripple::keylet::credential(
|
||||
GetAccountIDWithString(Account2),
|
||||
GetAccountIDWithString(Account),
|
||||
ripple::Slice(CredentialType.data(), CredentialType.size())
|
||||
)
|
||||
.key;
|
||||
|
||||
ON_CALL(*backend, doFetchLedgerObject(_, _, _)).WillByDefault(Return(std::optional<Blob>{{1, 2, 3}}));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account)).key, _, _))
|
||||
.WillByDefault(Return(account1Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::account(GetAccountIDWithString(Account2)).key, _, _))
|
||||
.WillByDefault(Return(account2Root.getSerializer().peekData()));
|
||||
ON_CALL(*backend, doFetchLedgerObject(credentialIndex, _, _))
|
||||
.WillByDefault(Return(credential.getSerializer().peekData()));
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(3);
|
||||
|
||||
auto const input = json::parse(fmt::format(
|
||||
R"({{
|
||||
"source_account": "{}",
|
||||
"destination_account": "{}",
|
||||
"ledger_hash": "{}",
|
||||
"credentials": ["{}"]
|
||||
}})",
|
||||
Account,
|
||||
Account2,
|
||||
LedgerHash,
|
||||
ripple::strHex(credentialIndex)
|
||||
));
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{DepositAuthorizedHandler{backend}};
|
||||
auto const output = handler.process(input, Context{yield});
|
||||
|
||||
ASSERT_FALSE(output);
|
||||
auto const err = rpc::makeError(output.result.error());
|
||||
EXPECT_EQ(err.at("error").as_string(), "badCredentials");
|
||||
EXPECT_EQ(err.at("error_message").as_string(), "credentials don't belong to the root account");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include "data/Types.hpp"
|
||||
#include "rpc/CredentialHelpers.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "rpc/common/AnyHandler.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
@@ -29,6 +30,8 @@
|
||||
#include <boost/asio/executor_work_guard.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/value_to.hpp>
|
||||
@@ -36,6 +39,8 @@
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
@@ -49,6 +54,7 @@
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -66,6 +72,7 @@ constexpr static auto LEDGERHASH = "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A
|
||||
constexpr static auto TOKENID = "000827103B94ECBB7BF0A0A6ED62B3607801A27B65F4679F4AD1D4850000C0EA";
|
||||
constexpr static auto NFTID = "00010000A7CAD27B688D14BA1A9FA5366554D6ADCF9CE0875B974D9F00000004";
|
||||
constexpr static auto TXNID = "05FB0EB4B899F056FA095537C5817163801F544BAFCEA39C995D76DB4D16F9DD";
|
||||
constexpr static auto CREDENTIALTYPE = "4B5943";
|
||||
|
||||
class RPCLedgerEntryTest : public HandlerBaseTest {};
|
||||
|
||||
@@ -200,6 +207,206 @@ generateTestValuesForParametersTest()
|
||||
"authorizedNotString"
|
||||
},
|
||||
|
||||
ParamTestCaseBundle{
|
||||
"InvalidDepositPreauthJsonAuthorizeCredentialsNotArray",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"deposit_preauth": {{
|
||||
"owner": "{}",
|
||||
"authorized_credentials": "asdf"
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT
|
||||
),
|
||||
"malformedRequest",
|
||||
"authorized_credentials not array"
|
||||
},
|
||||
|
||||
ParamTestCaseBundle{
|
||||
"DepositPreauthBothAuthAndAuthCredentialsDoesNotExists",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"deposit_preauth": {{
|
||||
"owner": "{}"
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT
|
||||
),
|
||||
"malformedRequest",
|
||||
"Must have one of authorized or authorized_credentials."
|
||||
},
|
||||
|
||||
ParamTestCaseBundle{
|
||||
"DepositPreauthBothAuthAndAuthCredentialsExists",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"deposit_preauth": {{
|
||||
"owner": "{}",
|
||||
"authorized": "{}",
|
||||
"authorized_credentials": [
|
||||
{{
|
||||
"issuer": "{}",
|
||||
"credential_type": "{}"
|
||||
}}
|
||||
]
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
ACCOUNT3,
|
||||
CREDENTIALTYPE
|
||||
),
|
||||
"malformedRequest",
|
||||
"Must have one of authorized or authorized_credentials."
|
||||
},
|
||||
|
||||
ParamTestCaseBundle{
|
||||
"DepositPreauthEmptyAuthorizeCredentials",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"deposit_preauth": {{
|
||||
"owner": "{}",
|
||||
"authorized_credentials": [
|
||||
]
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT
|
||||
),
|
||||
"malformedAuthorizedCredentials",
|
||||
"Requires at least one element in authorized_credentials array"
|
||||
},
|
||||
|
||||
ParamTestCaseBundle{
|
||||
"DepositPreauthAuthorizeCredentialsMissingCredentialType",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"deposit_preauth": {{
|
||||
"owner": "{}",
|
||||
"authorized_credentials": [
|
||||
{{
|
||||
"issuer": "{}"
|
||||
}}
|
||||
]
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Field 'CredentialType' is required but missing."
|
||||
},
|
||||
|
||||
ParamTestCaseBundle{
|
||||
"DepositPreauthAuthorizeCredentialsMissingIssuer",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"deposit_preauth": {{
|
||||
"owner": "{}",
|
||||
"authorized_credentials": [
|
||||
{{
|
||||
"credential_type": "{}"
|
||||
}}
|
||||
]
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
CREDENTIALTYPE
|
||||
),
|
||||
"malformedRequest",
|
||||
"Field 'Issuer' is required but missing."
|
||||
},
|
||||
|
||||
ParamTestCaseBundle{
|
||||
"DepositPreauthAuthorizeCredentialsIncorrectCredentialType",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"deposit_preauth": {{
|
||||
"owner": "{}",
|
||||
"authorized_credentials": [
|
||||
{{
|
||||
"issuer": "{}",
|
||||
"credential_type": 432
|
||||
}}
|
||||
]
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2
|
||||
),
|
||||
"invalidParams",
|
||||
"credential_type NotString"
|
||||
},
|
||||
|
||||
ParamTestCaseBundle{
|
||||
"DepositPreauthAuthorizeCredentialsCredentialTypeNotHex",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"deposit_preauth": {{
|
||||
"owner": "{}",
|
||||
"authorized_credentials": [
|
||||
{{
|
||||
"issuer": "{}",
|
||||
"credential_type": "hello world"
|
||||
}}
|
||||
]
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedAuthorizedCredentials",
|
||||
"credential_type NotHexString"
|
||||
},
|
||||
|
||||
ParamTestCaseBundle{
|
||||
"DepositPreauthAuthorizeCredentialsCredentialTypeEmpty",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"deposit_preauth": {{
|
||||
"owner": "{}",
|
||||
"authorized_credentials": [
|
||||
{{
|
||||
"issuer": "{}",
|
||||
"credential_type": ""
|
||||
}}
|
||||
]
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedAuthorizedCredentials",
|
||||
"credential_type is empty"
|
||||
},
|
||||
|
||||
ParamTestCaseBundle{
|
||||
"DepositPreauthDuplicateAuthorizeCredentials",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"deposit_preauth": {{
|
||||
"owner": "{}",
|
||||
"authorized_credentials": [
|
||||
{{
|
||||
"issuer": "{}",
|
||||
"credential_type": "{}"
|
||||
}},
|
||||
{{
|
||||
"issuer": "{}",
|
||||
"credential_type": "{}"
|
||||
}}
|
||||
]
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
CREDENTIALTYPE,
|
||||
ACCOUNT2,
|
||||
CREDENTIALTYPE
|
||||
),
|
||||
"malformedAuthorizedCredentials",
|
||||
"duplicates in credentials."
|
||||
},
|
||||
|
||||
ParamTestCaseBundle{
|
||||
"InvalidTicketType",
|
||||
R"({
|
||||
@@ -1759,6 +1966,29 @@ generateTestValuesForParametersTest()
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"CredentialInvalidSubjectType",
|
||||
R"({
|
||||
"credential": {
|
||||
"subject": 123
|
||||
}
|
||||
})",
|
||||
"malformedAddress",
|
||||
"Malformed address."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"CredentialInvalidIssuerType",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"credential": {{
|
||||
"issuer": ["{}"]
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"InvalidMPTIssuanceStringIndex",
|
||||
R"({
|
||||
@@ -1806,6 +2036,37 @@ generateTestValuesForParametersTest()
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"CredentialInvalidCredentialType",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"credential": {{
|
||||
"subject": "{}",
|
||||
"issuer": "{}",
|
||||
"credential_type": 1234
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"CredentialMissingIssuerField",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"credential": {{
|
||||
"subject": "{}",
|
||||
"credential_type": "1234"
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
ParamTestCaseBundle{
|
||||
"InvalidMPTokenAccount",
|
||||
fmt::format(
|
||||
@@ -1828,7 +2089,7 @@ generateTestValuesForParametersTest()
|
||||
),
|
||||
"malformedRequest",
|
||||
"Malformed request."
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2068,7 +2329,7 @@ generateTestValuesForNormalPathTest()
|
||||
INDEX1
|
||||
),
|
||||
ripple::uint256{INDEX1},
|
||||
CreateDepositPreauthLedgerObject(ACCOUNT, ACCOUNT2)
|
||||
CreateDepositPreauthLedgerObjectByAuth(ACCOUNT, ACCOUNT2)
|
||||
},
|
||||
NormalPathTestBundle{
|
||||
"AccountRoot",
|
||||
@@ -2155,7 +2416,7 @@ generateTestValuesForNormalPathTest()
|
||||
CreateEscrowLedgerObject(ACCOUNT, ACCOUNT2)
|
||||
},
|
||||
NormalPathTestBundle{
|
||||
"DepositPreauth",
|
||||
"DepositPreauthByAuth",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"binary": true,
|
||||
@@ -2168,7 +2429,58 @@ generateTestValuesForNormalPathTest()
|
||||
ACCOUNT2
|
||||
),
|
||||
ripple::keylet::depositPreauth(account1, account2).key,
|
||||
CreateDepositPreauthLedgerObject(ACCOUNT, ACCOUNT2)
|
||||
CreateDepositPreauthLedgerObjectByAuth(ACCOUNT, ACCOUNT2)
|
||||
},
|
||||
NormalPathTestBundle{
|
||||
"DepositPreauthByAuthCredentials",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"binary": true,
|
||||
"deposit_preauth": {{
|
||||
"owner": "{}",
|
||||
"authorized_credentials": [
|
||||
{{
|
||||
"issuer": "{}",
|
||||
"credential_type": "{}"
|
||||
}}
|
||||
]
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
CREDENTIALTYPE
|
||||
),
|
||||
ripple::keylet::depositPreauth(
|
||||
account1,
|
||||
credentials::createAuthCredentials(CreateAuthCredentialArray(
|
||||
std::vector<std::string_view>{ACCOUNT2}, std::vector<std::string_view>{CREDENTIALTYPE}
|
||||
))
|
||||
)
|
||||
.key,
|
||||
CreateDepositPreauthLedgerObjectByAuthCredentials(ACCOUNT, ACCOUNT2, CREDENTIALTYPE)
|
||||
},
|
||||
NormalPathTestBundle{
|
||||
"Credentials",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"binary": true,
|
||||
"credential": {{
|
||||
"subject": "{}",
|
||||
"issuer": "{}",
|
||||
"credential_type": "{}"
|
||||
}}
|
||||
}})",
|
||||
ACCOUNT,
|
||||
ACCOUNT2,
|
||||
CREDENTIALTYPE
|
||||
),
|
||||
ripple::keylet::credential(
|
||||
account1,
|
||||
account2,
|
||||
ripple::Slice(ripple::strUnHex(CREDENTIALTYPE)->data(), ripple::strUnHex(CREDENTIALTYPE)->size())
|
||||
)
|
||||
.key,
|
||||
CreateCredentialObject(ACCOUNT, ACCOUNT2, CREDENTIALTYPE)
|
||||
},
|
||||
NormalPathTestBundle{
|
||||
"RippleState",
|
||||
|
||||
@@ -55,6 +55,7 @@ TEST(LedgerUtilsTests, LedgerObjectTypeList)
|
||||
JS(mpt_issuance),
|
||||
JS(mptoken),
|
||||
JS(oracle),
|
||||
JS(credential),
|
||||
JS(nunl)
|
||||
};
|
||||
|
||||
@@ -86,6 +87,7 @@ TEST(LedgerUtilsTests, AccountOwnedTypeList)
|
||||
JS(xchain_owned_create_account_claim_id),
|
||||
JS(did),
|
||||
JS(oracle),
|
||||
JS(credential),
|
||||
JS(mpt_issuance),
|
||||
JS(mptoken)
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user