rippled
Loading...
Searching...
No Matches
PaymentChannelClaim.cpp
1#include <xrpl/ledger/ApplyView.h>
2#include <xrpl/ledger/View.h>
3#include <xrpl/ledger/helpers/CredentialHelpers.h>
4#include <xrpl/protocol/Feature.h>
5#include <xrpl/protocol/Indexes.h>
6#include <xrpl/protocol/PayChan.h>
7#include <xrpl/protocol/PublicKey.h>
8#include <xrpl/protocol/TxFlags.h>
9#include <xrpl/tx/transactors/payment_channel/PaymentChannelClaim.h>
10
11#include <libxrpl/tx/transactors/payment_channel/PaymentChannelHelpers.h>
12
13namespace xrpl {
14
15bool
17{
18 return !ctx.tx.isFieldPresent(sfCredentialIDs) || ctx.rules.enabled(featureCredentials);
19}
20
23{
24 return tfPaymentChannelClaimMask;
25}
26
29{
30 auto const bal = ctx.tx[~sfBalance];
31 if (bal && (!isXRP(*bal) || *bal <= beast::zero))
32 return temBAD_AMOUNT;
33
34 auto const amt = ctx.tx[~sfAmount];
35 if (amt && (!isXRP(*amt) || *amt <= beast::zero))
36 return temBAD_AMOUNT;
37
38 if (bal && amt && *bal > *amt)
39 return temBAD_AMOUNT;
40
41 {
42 auto const flags = ctx.tx.getFlags();
43
44 if (((flags & tfClose) != 0u) && ((flags & tfRenew) != 0u))
45 return temMALFORMED;
46 }
47
48 if (auto const sig = ctx.tx[~sfSignature])
49 {
50 if (!(ctx.tx[~sfPublicKey] && bal))
51 return temMALFORMED;
52
53 // Check the signature
54 // The signature isn't needed if txAccount == src, but if it's
55 // present, check it
56
57 auto const reqBalance = bal->xrp();
58 auto const authAmt = amt ? amt->xrp() : reqBalance;
59
60 if (reqBalance > authAmt)
61 return temBAD_AMOUNT;
62
63 Keylet const k(ltPAYCHAN, ctx.tx[sfChannel]);
64 if (!publicKeyType(ctx.tx[sfPublicKey]))
65 return temMALFORMED;
66
67 PublicKey const pk(ctx.tx[sfPublicKey]);
68 Serializer msg;
69 serializePayChanAuthorization(msg, k.key, authAmt);
70 if (!verify(pk, msg.slice(), *sig))
71 return temBAD_SIGNATURE;
72 }
73
74 if (auto const err = credentials::checkFields(ctx.tx, ctx.j); !isTesSuccess(err))
75 return err;
76
77 return tesSUCCESS;
78}
79
80TER
82{
83 if (!ctx.view.rules().enabled(featureCredentials))
84 return Transactor::preclaim(ctx);
85
86 if (auto const err = credentials::valid(ctx.tx, ctx.view, ctx.tx[sfAccount], ctx.j);
87 !isTesSuccess(err))
88 return err;
89
90 return tesSUCCESS;
91}
92
93TER
95{
96 Keylet const k(ltPAYCHAN, ctx_.tx[sfChannel]);
97 auto const slep = ctx_.view().peek(k);
98 if (!slep)
99 return tecNO_TARGET;
100
101 AccountID const src = (*slep)[sfAccount];
102 AccountID const dst = (*slep)[sfDestination];
103 AccountID const txAccount = ctx_.tx[sfAccount];
104
105 auto const curExpiration = (*slep)[~sfExpiration];
106 {
107 auto const cancelAfter = (*slep)[~sfCancelAfter];
108 auto const closeTime = ctx_.view().header().parentCloseTime.time_since_epoch().count();
109 if ((cancelAfter && closeTime >= *cancelAfter) ||
110 (curExpiration && closeTime >= *curExpiration))
111 return closeChannel(slep, ctx_.view(), k.key, ctx_.registry.get().getJournal("View"));
112 }
113
114 if (txAccount != src && txAccount != dst)
115 return tecNO_PERMISSION;
116
117 if (ctx_.tx[~sfBalance])
118 {
119 auto const chanBalance = slep->getFieldAmount(sfBalance).xrp();
120 auto const chanFunds = slep->getFieldAmount(sfAmount).xrp();
121 auto const reqBalance = ctx_.tx[sfBalance].xrp();
122
123 if (txAccount == dst && !ctx_.tx[~sfSignature])
124 return temBAD_SIGNATURE;
125
126 if (ctx_.tx[~sfSignature])
127 {
128 PublicKey const pk((*slep)[sfPublicKey]);
129 if (ctx_.tx[sfPublicKey] != pk)
130 return temBAD_SIGNER;
131 }
132
133 if (reqBalance > chanFunds)
134 return tecUNFUNDED_PAYMENT;
135
136 if (reqBalance <= chanBalance)
137 {
138 // nothing requested
139 return tecUNFUNDED_PAYMENT;
140 }
141
142 auto const sled = ctx_.view().peek(keylet::account(dst));
143 if (!sled)
144 return tecNO_DST;
145
146 if (auto err =
147 verifyDepositPreauth(ctx_.tx, ctx_.view(), txAccount, dst, sled, ctx_.journal);
148 !isTesSuccess(err))
149 return err;
150
151 (*slep)[sfBalance] = ctx_.tx[sfBalance];
152 XRPAmount const reqDelta = reqBalance - chanBalance;
153 XRPL_ASSERT(
154 reqDelta >= beast::zero, "xrpl::PaymentChannelClaim::doApply : minimum balance delta");
155 (*sled)[sfBalance] = (*sled)[sfBalance] + reqDelta;
156 ctx_.view().update(sled);
157 ctx_.view().update(slep);
158 }
159
160 if ((ctx_.tx.getFlags() & tfRenew) != 0u)
161 {
162 if (src != txAccount)
163 return tecNO_PERMISSION;
164 (*slep)[~sfExpiration] = std::nullopt;
165 ctx_.view().update(slep);
166 }
167
168 if ((ctx_.tx.getFlags() & tfClose) != 0u)
169 {
170 // Channel will close immediately if dry or the receiver closes
171 if (dst == txAccount || (*slep)[sfBalance] == (*slep)[sfAmount])
172 return closeChannel(slep, ctx_.view(), k.key, ctx_.registry.get().getJournal("View"));
173
174 auto const settleExpiration =
176 (*slep)[sfSettleDelay];
177
178 if (!curExpiration || *curExpiration > settleExpiration)
179 {
180 (*slep)[~sfExpiration] = settleExpiration;
181 ctx_.view().update(slep);
182 }
183 }
184
185 return tesSUCCESS;
186}
187
188} // namespace xrpl
STTx const & tx
std::reference_wrapper< ServiceRegistry > registry
beast::Journal const journal
ApplyView & view()
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
static bool checkExtraFeatures(PreflightContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
A public key.
Definition PublicKey.h:42
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual LedgerHeader const & header() const =0
Returns information about the ledger.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:120
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:456
std::uint32_t getFlags() const
Definition STObject.cpp:509
Slice slice() const noexcept
Definition Serializer.h:44
static TER preclaim(PreclaimContext const &ctx)
Definition Transactor.h:202
ApplyContext & ctx_
Definition Transactor.h:112
T is_same_v
NotTEC checkFields(STTx const &tx, beast::Journal j)
TER valid(STTx const &tx, ReadView const &view, AccountID const &src, beast::Journal j)
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:165
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
bool isXRP(AccountID const &c)
Definition AccountID.h:70
TER verifyDepositPreauth(STTx const &tx, ApplyView &view, AccountID const &src, AccountID const &dst, std::shared_ptr< SLE const > const &sleDst, beast::Journal j)
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig) noexcept
Verify a signature on a message.
void serializePayChanAuthorization(Serializer &msg, uint256 const &key, XRPAmount const &amt)
Definition PayChan.h:11
TER closeChannel(std::shared_ptr< SLE > const &slep, ApplyView &view, uint256 const &key, beast::Journal j)
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
@ temMALFORMED
Definition TER.h:67
@ temBAD_AMOUNT
Definition TER.h:69
@ temBAD_SIGNATURE
Definition TER.h:85
@ temBAD_SIGNER
Definition TER.h:95
bool isTesSuccess(TER x) noexcept
Definition TER.h:651
@ tecUNFUNDED_PAYMENT
Definition TER.h:266
@ tecNO_TARGET
Definition TER.h:285
@ tecNO_PERMISSION
Definition TER.h:286
@ tecNO_DST
Definition TER.h:271
@ tesSUCCESS
Definition TER.h:225
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:19
uint256 key
Definition Keylet.h:20
NetClock::time_point parentCloseTime
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:57
ReadView const & view
Definition Transactor.h:60
beast::Journal const j
Definition Transactor.h:65
State information when preflighting a tx.
Definition Transactor.h:14
beast::Journal const j
Definition Transactor.h:21
T time_since_epoch(T... args)