rippled
Loading...
Searching...
No Matches
DepositAuthorized.cpp
1#include <xrpld/rpc/Context.h>
2#include <xrpld/rpc/detail/RPCLedgerHelpers.h>
3
4#include <xrpl/ledger/ReadView.h>
5#include <xrpl/ledger/helpers/CredentialHelpers.h>
6#include <xrpl/protocol/ErrorCodes.h>
7#include <xrpl/protocol/Indexes.h>
8#include <xrpl/protocol/RPCErr.h>
9#include <xrpl/protocol/jss.h>
10
11namespace xrpl {
12
13// {
14// source_account : <ident>
15// destination_account : <ident>
16// ledger_hash : <ledger>
17// ledger_index : <ledger_index>
18// credentials : [<credentialID>,...]
19// }
20
23{
24 Json::Value const& params = context.params;
25
26 // Validate source_account.
27 if (!params.isMember(jss::source_account))
28 return RPC::missing_field_error(jss::source_account);
29 if (!params[jss::source_account].isString())
30 {
31 return RPC::make_error(
32 rpcINVALID_PARAMS, RPC::expected_field_message(jss::source_account, "a string"));
33 }
34
35 auto srcID = parseBase58<AccountID>(params[jss::source_account].asString());
36 if (!srcID)
38 auto const srcAcct{srcID.value()};
39
40 // Validate destination_account.
41 if (!params.isMember(jss::destination_account))
42 return RPC::missing_field_error(jss::destination_account);
43 if (!params[jss::destination_account].isString())
44 {
45 return RPC::make_error(
46 rpcINVALID_PARAMS, RPC::expected_field_message(jss::destination_account, "a string"));
47 }
48
49 auto dstID = parseBase58<AccountID>(params[jss::destination_account].asString());
50 if (!dstID)
52 auto const dstAcct{dstID.value()};
53
54 // Validate ledger.
56 Json::Value result = RPC::lookupLedger(ledger, context);
57
58 if (!ledger)
59 return result;
60
61 // If source account is not in the ledger it can't be authorized.
62 if (!ledger->exists(keylet::account(srcAcct)))
63 {
65 return result;
66 }
67
68 // If destination account is not in the ledger you can't deposit to it, eh?
69 auto const sleDest = ledger->read(keylet::account(dstAcct));
70 if (!sleDest)
71 {
73 return result;
74 }
75
76 bool const reqAuth = ((sleDest->getFlags() & lsfDepositAuth) != 0u) && (srcAcct != dstAcct);
77 bool const credentialsPresent = params.isMember(jss::credentials);
78
81 if (credentialsPresent)
82 {
83 auto const& creds(params[jss::credentials]);
84 if (!creds.isArray() || !creds)
85 {
86 return RPC::make_error(
89 jss::credentials, "is non-empty array of CredentialID(hash256)"));
90 }
91 if (creds.size() > maxCredentialsArraySize)
92 {
93 return RPC::make_error(
94 rpcINVALID_PARAMS, RPC::expected_field_message(jss::credentials, "array too long"));
95 }
96
97 lifeExtender.reserve(creds.size());
98 for (auto const& jo : creds)
99 {
100 if (!jo.isString())
101 {
102 return RPC::make_error(
105 jss::credentials, "an array of CredentialID(hash256)"));
106 }
107
108 uint256 credH;
109 auto const credS = jo.asString();
110 if (!credH.parseHex(credS))
111 {
112 return RPC::make_error(
115 jss::credentials, "an array of CredentialID(hash256)"));
116 }
117
118 std::shared_ptr<SLE const> sleCred = ledger->read(keylet::credential(credH));
119 if (!sleCred)
120 {
121 RPC::inject_error(rpcBAD_CREDENTIALS, "credentials don't exist", result);
122 return result;
123 }
124
125 if ((sleCred->getFlags() & lsfAccepted) == 0u)
126 {
127 RPC::inject_error(rpcBAD_CREDENTIALS, "credentials aren't accepted", result);
128 return result;
129 }
130
131 if (credentials::checkExpired(sleCred, ledger->header().parentCloseTime))
132 {
133 RPC::inject_error(rpcBAD_CREDENTIALS, "credentials are expired", result);
134 return result;
135 }
136
137 if ((*sleCred)[sfSubject] != srcAcct)
138 {
140 rpcBAD_CREDENTIALS, "credentials doesn't belong to the root account", result);
141 return result;
142 }
143
144 auto [it, ins] = sorted.emplace((*sleCred)[sfIssuer], (*sleCred)[sfCredentialType]);
145 if (!ins)
146 {
147 RPC::inject_error(rpcBAD_CREDENTIALS, "duplicates in credentials", result);
148 return result;
149 }
150 lifeExtender.push_back(std::move(sleCred));
151 }
152 }
153
154 // If the two accounts are the same OR if that flag is
155 // not set, then the deposit should be fine.
156 bool depositAuthorized = true;
157 if (reqAuth)
158 {
159 depositAuthorized = ledger->exists(keylet::depositPreauth(dstAcct, srcAcct)) ||
160 (credentialsPresent && ledger->exists(keylet::depositPreauth(dstAcct, sorted)));
161 }
162
163 result[jss::source_account] = params[jss::source_account].asString();
164 result[jss::destination_account] = params[jss::destination_account].asString();
165 if (credentialsPresent)
166 result[jss::credentials] = params[jss::credentials];
167
168 result[jss::deposit_authorized] = depositAuthorized;
169 return result;
170}
171
172} // namespace xrpl
Represents a JSON value.
Definition json_value.h:130
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:476
T emplace(T... args)
std::string expected_field_message(std::string const &name, std::string const &type)
Definition ErrorCodes.h:285
Json::Value missing_field_error(std::string const &name)
Definition ErrorCodes.h:231
void inject_error(error_code_i code, Json::Value &json)
Add or update the json update to reflect the error code.
Status lookupLedger(std::shared_ptr< ReadView const > &ledger, JsonContext const &context, Json::Value &result)
Looks up a ledger from a request and fills a Json::Value with ledger data.
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
bool checkExpired(std::shared_ptr< SLE const > const &sleCredential, NetClock::time_point const &closed)
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Definition Indexes.cpp:307
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:165
Keylet credential(AccountID const &subject, AccountID const &issuer, Slice const &credType) noexcept
Definition Indexes.cpp:498
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::size_t constexpr maxCredentialsArraySize
The maximum number of credentials can be passed in array.
Definition Protocol.h:224
Json::Value rpcError(error_code_i iError)
Definition RPCErr.cpp:12
Json::Value doDepositAuthorized(RPC::JsonContext &)
@ rpcBAD_CREDENTIALS
Definition ErrorCodes.h:132
@ rpcSRC_ACT_NOT_FOUND
Definition ErrorCodes.h:102
@ rpcDST_ACT_NOT_FOUND
Definition ErrorCodes.h:85
@ rpcINVALID_PARAMS
Definition ErrorCodes.h:64
@ rpcACT_MALFORMED
Definition ErrorCodes.h:70
T push_back(T... args)
T reserve(T... args)
Json::Value params
Definition Context.h:43