rippled
Loading...
Searching...
No Matches
XChainAttestations.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2022 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpl/basics/Buffer.h>
21#include <xrpl/basics/Slice.h>
22#include <xrpl/basics/contract.h>
23#include <xrpl/json/json_value.h>
24#include <xrpl/protocol/AccountID.h>
25#include <xrpl/protocol/PublicKey.h>
26#include <xrpl/protocol/SField.h>
27#include <xrpl/protocol/STAccount.h>
28#include <xrpl/protocol/STAmount.h>
29#include <xrpl/protocol/STArray.h>
30#include <xrpl/protocol/STObject.h>
31#include <xrpl/protocol/SecretKey.h>
32#include <xrpl/protocol/Serializer.h>
33#include <xrpl/protocol/XChainAttestations.h>
34#include <xrpl/protocol/json_get_or_throw.h>
35#include <xrpl/protocol/jss.h>
36
37#include <cstdint>
38#include <optional>
39#include <stdexcept>
40#include <tuple>
41#include <utility>
42#include <vector>
43
44namespace ripple {
45namespace Attestations {
46
48 AccountID attestationSignerAccount_,
49 PublicKey const& publicKey_,
50 Buffer signature_,
51 AccountID const& sendingAccount_,
52 STAmount const& sendingAmount_,
53 AccountID const& rewardAccount_,
54 bool wasLockingChainSend_)
55 : attestationSignerAccount{attestationSignerAccount_}
56 , publicKey{publicKey_}
57 , signature{std::move(signature_)}
58 , sendingAccount{sendingAccount_}
59 , sendingAmount{sendingAmount_}
60 , rewardAccount{rewardAccount_}
61 , wasLockingChainSend{wasLockingChainSend_}
62{
63}
64
65bool
67 AttestationBase const& lhs,
68 AttestationBase const& rhs)
69{
70 return std::tie(
72 lhs.publicKey,
73 lhs.signature,
75 lhs.sendingAmount,
76 lhs.rewardAccount,
80 rhs.publicKey,
81 rhs.signature,
83 rhs.sendingAmount,
84 rhs.rewardAccount,
86}
87
88bool
100
101bool
103{
106}
107
109 : attestationSignerAccount{o[sfAttestationSignerAccount]}
110 , publicKey{o[sfPublicKey]}
111 , signature{o[sfSignature]}
112 , sendingAccount{o[sfAccount]}
113 , sendingAmount{o[sfAmount]}
114 , rewardAccount{o[sfAttestationRewardAccount]}
115 , wasLockingChainSend{bool(o[sfWasLockingChainSend])}
116{
117}
118
120 : attestationSignerAccount{Json::getOrThrow<AccountID>(
121 v,
122 sfAttestationSignerAccount)}
123 , publicKey{Json::getOrThrow<PublicKey>(v, sfPublicKey)}
124 , signature{Json::getOrThrow<Buffer>(v, sfSignature)}
125 , sendingAccount{Json::getOrThrow<AccountID>(v, sfAccount)}
126 , sendingAmount{Json::getOrThrow<STAmount>(v, sfAmount)}
127 , rewardAccount{Json::getOrThrow<AccountID>(v, sfAttestationRewardAccount)}
128 , wasLockingChainSend{Json::getOrThrow<bool>(v, sfWasLockingChainSend)}
129{
130}
131
132void
134{
135 o[sfAttestationSignerAccount] = attestationSignerAccount;
136 o[sfPublicKey] = publicKey;
137 o[sfSignature] = signature;
138 o[sfAmount] = sendingAmount;
139 o[sfAccount] = sendingAccount;
140 o[sfAttestationRewardAccount] = rewardAccount;
141 o[sfWasLockingChainSend] = wasLockingChainSend;
142}
143
145 AccountID attestationSignerAccount_,
146 PublicKey const& publicKey_,
147 Buffer signature_,
148 AccountID const& sendingAccount_,
149 STAmount const& sendingAmount_,
150 AccountID const& rewardAccount_,
151 bool wasLockingChainSend_,
152 std::uint64_t claimID_,
153 std::optional<AccountID> const& dst_)
155 attestationSignerAccount_,
156 publicKey_,
157 std::move(signature_),
158 sendingAccount_,
159 sendingAmount_,
160 rewardAccount_,
161 wasLockingChainSend_)
162 , claimID{claimID_}
163 , dst{dst_}
164{
165}
166
168 STXChainBridge const& bridge,
169 AccountID attestationSignerAccount_,
170 PublicKey const& publicKey_,
171 SecretKey const& secretKey_,
172 AccountID const& sendingAccount_,
173 STAmount const& sendingAmount_,
174 AccountID const& rewardAccount_,
175 bool wasLockingChainSend_,
176 std::uint64_t claimID_,
177 std::optional<AccountID> const& dst_)
179 attestationSignerAccount_,
180 publicKey_,
181 Buffer{},
182 sendingAccount_,
183 sendingAmount_,
184 rewardAccount_,
185 wasLockingChainSend_,
186 claimID_,
187 dst_}
188{
189 auto const toSign = message(bridge);
190 signature = sign(publicKey_, secretKey_, makeSlice(toSign));
191}
192
194 : AttestationBase(o), claimID{o[sfXChainClaimID]}, dst{o[~sfDestination]}
195{
196}
197
199 : AttestationBase{v}
200 , claimID{Json::getOrThrow<std::uint64_t>(v, sfXChainClaimID)}
201{
202 if (v.isMember(sfDestination.getJsonName()))
203 dst = Json::getOrThrow<AccountID>(v, sfDestination);
204}
205
208{
209 STObject o =
210 STObject::makeInnerObject(sfXChainClaimAttestationCollectionElement);
211 addHelper(o);
212 o[sfXChainClaimID] = claimID;
213 if (dst)
214 o[sfDestination] = *dst;
215 return o;
216}
217
220 STXChainBridge const& bridge,
221 AccountID const& sendingAccount,
222 STAmount const& sendingAmount,
223 AccountID const& rewardAccount,
224 bool wasLockingChainSend,
225 std::uint64_t claimID,
226 std::optional<AccountID> const& dst)
227{
229 // Serialize in SField order to make python serializers easier to write
230 o[sfXChainClaimID] = claimID;
231 o[sfAmount] = sendingAmount;
232 if (dst)
233 o[sfDestination] = *dst;
234 o[sfOtherChainSource] = sendingAccount;
235 o[sfAttestationRewardAccount] = rewardAccount;
236 o[sfWasLockingChainSend] = wasLockingChainSend ? 1 : 0;
237 o[sfXChainBridge] = bridge;
238
239 Serializer s;
240 o.add(s);
241
242 return std::move(s.modData());
243}
244
247{
249 bridge,
254 claimID,
255 dst);
256}
257
258bool
263
264bool
266{
267 return AttestationClaim::sameEventHelper(*this, rhs) &&
268 tie(claimID, dst) == tie(rhs.claimID, rhs.dst);
269}
270
271bool
273{
274 return AttestationClaim::equalHelper(lhs, rhs) &&
275 tie(lhs.claimID, lhs.dst) == tie(rhs.claimID, rhs.dst);
276}
277
279 : AttestationBase(o)
280 , createCount{o[sfXChainAccountCreateCount]}
281 , toCreate{o[sfDestination]}
282 , rewardAmount{o[sfSignatureReward]}
283{
284}
285
287 : AttestationBase{v}
288 , createCount{Json::getOrThrow<std::uint64_t>(
289 v,
290 sfXChainAccountCreateCount)}
291 , toCreate{Json::getOrThrow<AccountID>(v, sfDestination)}
292 , rewardAmount{Json::getOrThrow<STAmount>(v, sfSignatureReward)}
293{
294}
295
297 AccountID attestationSignerAccount_,
298 PublicKey const& publicKey_,
299 Buffer signature_,
300 AccountID const& sendingAccount_,
301 STAmount const& sendingAmount_,
302 STAmount const& rewardAmount_,
303 AccountID const& rewardAccount_,
304 bool wasLockingChainSend_,
305 std::uint64_t createCount_,
306 AccountID const& toCreate_)
308 attestationSignerAccount_,
309 publicKey_,
310 std::move(signature_),
311 sendingAccount_,
312 sendingAmount_,
313 rewardAccount_,
314 wasLockingChainSend_)
315 , createCount{createCount_}
316 , toCreate{toCreate_}
317 , rewardAmount{rewardAmount_}
318{
319}
320
322 STXChainBridge const& bridge,
323 AccountID attestationSignerAccount_,
324 PublicKey const& publicKey_,
325 SecretKey const& secretKey_,
326 AccountID const& sendingAccount_,
327 STAmount const& sendingAmount_,
328 STAmount const& rewardAmount_,
329 AccountID const& rewardAccount_,
330 bool wasLockingChainSend_,
331 std::uint64_t createCount_,
332 AccountID const& toCreate_)
334 attestationSignerAccount_,
335 publicKey_,
336 Buffer{},
337 sendingAccount_,
338 sendingAmount_,
339 rewardAmount_,
340 rewardAccount_,
341 wasLockingChainSend_,
342 createCount_,
343 toCreate_}
344{
345 auto const toSign = message(bridge);
346 signature = sign(publicKey_, secretKey_, makeSlice(toSign));
347}
348
351{
353 sfXChainCreateAccountAttestationCollectionElement);
354 addHelper(o);
355
356 o[sfXChainAccountCreateCount] = createCount;
357 o[sfDestination] = toCreate;
358 o[sfSignatureReward] = rewardAmount;
359
360 return o;
361}
362
365 STXChainBridge const& bridge,
366 AccountID const& sendingAccount,
367 STAmount const& sendingAmount,
368 STAmount const& rewardAmount,
369 AccountID const& rewardAccount,
370 bool wasLockingChainSend,
371 std::uint64_t createCount,
372 AccountID const& dst)
373{
375 // Serialize in SField order to make python serializers easier to write
376 o[sfXChainAccountCreateCount] = createCount;
377 o[sfAmount] = sendingAmount;
378 o[sfSignatureReward] = rewardAmount;
379 o[sfDestination] = dst;
380 o[sfOtherChainSource] = sendingAccount;
381 o[sfAttestationRewardAccount] = rewardAccount;
382 o[sfWasLockingChainSend] = wasLockingChainSend ? 1 : 0;
383 o[sfXChainBridge] = bridge;
384
385 Serializer s;
386 o.add(s);
387
388 return std::move(s.modData());
389}
390
404
405bool
407{
409}
410
411bool
413{
418
419bool
421 AttestationCreateAccount const& lhs,
422 AttestationCreateAccount const& rhs)
423{
424 return AttestationCreateAccount::equalHelper(lhs, rhs) &&
425 std::tie(lhs.createCount, lhs.toCreate, lhs.rewardAmount) ==
426 std::tie(rhs.createCount, rhs.toCreate, rhs.rewardAmount);
427}
428
429} // namespace Attestations
430
431SField const& XChainClaimAttestation::ArrayFieldName{sfXChainClaimAttestations};
433 sfXChainCreateAccountAttestations};
434
436 AccountID const& keyAccount_,
437 PublicKey const& publicKey_,
438 STAmount const& amount_,
439 AccountID const& rewardAccount_,
440 bool wasLockingChainSend_,
441 std::optional<AccountID> const& dst_)
442 : keyAccount(keyAccount_)
443 , publicKey(publicKey_)
444 , amount(sfAmount, amount_)
445 , rewardAccount(rewardAccount_)
446 , wasLockingChainSend(wasLockingChainSend_)
447 , dst(dst_)
448{
449}
450
452 STAccount const& keyAccount_,
453 PublicKey const& publicKey_,
454 STAmount const& amount_,
455 STAccount const& rewardAccount_,
456 bool wasLockingChainSend_,
457 std::optional<STAccount> const& dst_)
459 keyAccount_.value(),
460 publicKey_,
461 amount_,
462 rewardAccount_.value(),
463 wasLockingChainSend_,
464 dst_ ? std::optional<AccountID>{dst_->value()} : std::nullopt}
465{
466}
467
468XChainClaimAttestation::XChainClaimAttestation(STObject const& o)
470 o[sfAttestationSignerAccount],
471 PublicKey{o[sfPublicKey]},
472 o[sfAmount],
473 o[sfAttestationRewardAccount],
474 o[sfWasLockingChainSend] != 0,
475 o[~sfDestination]} {};
476
479 Json::getOrThrow<AccountID>(v, sfAttestationSignerAccount),
480 Json::getOrThrow<PublicKey>(v, sfPublicKey),
481 Json::getOrThrow<STAmount>(v, sfAmount),
482 Json::getOrThrow<AccountID>(v, sfAttestationRewardAccount),
483 Json::getOrThrow<bool>(v, sfWasLockingChainSend),
484 std::nullopt}
485{
486 if (v.isMember(sfDestination.getJsonName()))
487 dst = Json::getOrThrow<AccountID>(v, sfDestination);
488};
489
493 claimAtt.attestationSignerAccount,
494 claimAtt.publicKey,
495 claimAtt.sendingAmount,
496 claimAtt.rewardAccount,
497 claimAtt.wasLockingChainSend,
498 claimAtt.dst}
499{
500}
501
504{
505 STObject o = STObject::makeInnerObject(sfXChainClaimProofSig);
506 o[sfAttestationSignerAccount] =
507 STAccount{sfAttestationSignerAccount, keyAccount};
508 o[sfPublicKey] = publicKey;
509 o[sfAmount] = STAmount{sfAmount, amount};
510 o[sfAttestationRewardAccount] =
511 STAccount{sfAttestationRewardAccount, rewardAccount};
512 o[sfWasLockingChainSend] = wasLockingChainSend;
513 if (dst)
514 o[sfDestination] = STAccount{sfDestination, *dst};
515 return o;
516}
517
518bool
520{
521 return std::tie(
522 lhs.keyAccount,
523 lhs.publicKey,
524 lhs.amount,
525 lhs.rewardAccount,
527 lhs.dst) ==
528 std::tie(
529 rhs.keyAccount,
530 rhs.publicKey,
531 rhs.amount,
532 rhs.rewardAccount,
534 rhs.dst);
535}
536
539 : amount{att.sendingAmount}
540 , wasLockingChainSend{att.wasLockingChainSend}
541 , dst{att.dst}
542{
543}
544
556
557//------------------------------------------------------------------------------
558
560 AccountID const& keyAccount_,
561 PublicKey const& publicKey_,
562 STAmount const& amount_,
563 STAmount const& rewardAmount_,
564 AccountID const& rewardAccount_,
565 bool wasLockingChainSend_,
566 AccountID const& dst_)
567 : keyAccount(keyAccount_)
568 , publicKey(publicKey_)
569 , amount(sfAmount, amount_)
570 , rewardAmount(sfSignatureReward, rewardAmount_)
571 , rewardAccount(rewardAccount_)
572 , wasLockingChainSend(wasLockingChainSend_)
573 , dst(dst_)
574{
575}
576
578 STObject const& o)
580 o[sfAttestationSignerAccount],
581 PublicKey{o[sfPublicKey]},
582 o[sfAmount],
583 o[sfSignatureReward],
584 o[sfAttestationRewardAccount],
585 o[sfWasLockingChainSend] != 0,
586 o[sfDestination]} {};
587
588XChainCreateAccountAttestation ::XChainCreateAccountAttestation(
589 Json::Value const& v)
591 Json::getOrThrow<AccountID>(v, sfAttestationSignerAccount),
592 Json::getOrThrow<PublicKey>(v, sfPublicKey),
593 Json::getOrThrow<STAmount>(v, sfAmount),
594 Json::getOrThrow<STAmount>(v, sfSignatureReward),
595 Json::getOrThrow<AccountID>(v, sfAttestationRewardAccount),
596 Json::getOrThrow<bool>(v, sfWasLockingChainSend),
597 Json::getOrThrow<AccountID>(v, sfDestination)}
598{
599}
600
604 createAtt.attestationSignerAccount,
605 createAtt.publicKey,
606 createAtt.sendingAmount,
607 createAtt.rewardAmount,
608 createAtt.rewardAccount,
609 createAtt.wasLockingChainSend,
610 createAtt.toCreate}
611{
612}
613
616{
617 STObject o = STObject::makeInnerObject(sfXChainCreateAccountProofSig);
618
619 o[sfAttestationSignerAccount] =
620 STAccount{sfAttestationSignerAccount, keyAccount};
621 o[sfPublicKey] = publicKey;
622 o[sfAmount] = STAmount{sfAmount, amount};
623 o[sfSignatureReward] = STAmount{sfSignatureReward, rewardAmount};
624 o[sfAttestationRewardAccount] =
625 STAccount{sfAttestationRewardAccount, rewardAccount};
626 o[sfWasLockingChainSend] = wasLockingChainSend;
627 o[sfDestination] = STAccount{sfDestination, dst};
628
629 return o;
630}
631
634 : amount{att.sendingAmount}
635 , rewardAmount(att.rewardAmount)
636 , wasLockingChainSend{att.wasLockingChainSend}
637 , dst{att.toCreate}
638{
639}
640
652
653bool
657{
658 return std::tie(
659 lhs.keyAccount,
660 lhs.publicKey,
661 lhs.amount,
662 lhs.rewardAmount,
663 lhs.rewardAccount,
665 lhs.dst) ==
666 std::tie(
667 rhs.keyAccount,
668 rhs.publicKey,
669 rhs.amount,
670 rhs.rewardAmount,
671 rhs.rewardAccount,
673 rhs.dst);
674}
675
676//------------------------------------------------------------------------------
677//
678template <class TAttestation>
681 : attestations_{std::move(atts)}
682{
683}
684
685template <class TAttestation>
686typename XChainAttestationsBase<TAttestation>::AttCollection::const_iterator
688{
689 return attestations_.begin();
690}
691
692template <class TAttestation>
695{
696 return attestations_.end();
697}
698
699template <class TAttestation>
702{
703 return attestations_.begin();
704}
705
706template <class TAttestation>
709{
710 return attestations_.end();
711}
712
713template <class TAttestation>
715 Json::Value const& v)
716{
717 if (!v.isObject())
718 {
719 Throw<std::runtime_error>(
720 "XChainAttestationsBase can only be specified with an 'object' "
721 "Json value");
722 }
723
724 attestations_ = [&] {
725 auto const jAtts = v[jss::attestations];
726
727 if (jAtts.size() > maxAttestations)
728 Throw<std::runtime_error>(
729 "XChainAttestationsBase exceeded max number of attestations");
730
732 r.reserve(jAtts.size());
733 for (auto const& a : jAtts)
734 r.emplace_back(a);
735 return r;
736 }();
737}
738
739template <class TAttestation>
741{
742 if (arr.size() > maxAttestations)
743 Throw<std::runtime_error>(
744 "XChainAttestationsBase exceeded max number of attestations");
745
746 attestations_.reserve(arr.size());
747 for (auto const& o : arr)
748 attestations_.emplace_back(o);
749}
750
751template <class TAttestation>
754{
755 STArray r{TAttestation::ArrayFieldName, attestations_.size()};
756 for (auto const& e : attestations_)
757 r.emplace_back(e.toSTObject());
758 return r;
759}
760
763
764} // namespace ripple
Represents a JSON value.
Definition json_value.h:149
bool isObject() const
bool isMember(char const *key) const
Return true if the object has a member named key.
Like std::vector<char> but better.
Definition Buffer.h:36
A public key.
Definition PublicKey.h:62
size_type size() const
Definition STArray.h:248
static STObject makeInnerObject(SField const &name)
Definition STObject.cpp:95
A secret key.
Definition SecretKey.h:38
AttCollection::const_iterator end() const
AttCollection::const_iterator begin() const
T emplace_back(T... args)
T is_same_v
JSON (JavaScript Object Notation).
Definition json_errors.h:25
bool operator==(AttestationClaim const &lhs, AttestationClaim const &rhs)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical=true) noexcept
Verify a signature on a message.
bool isLegalNet(STAmount const &value)
Definition STAmount.h:600
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &message)
Generate a signature for a message.
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition Slice.h:244
SField const sfGeneric
constexpr bool operator==(base_uint< Bits, Tag > const &lhs, base_uint< Bits, Tag > const &rhs)
Definition base_uint.h:585
STL namespace.
T reserve(T... args)
static bool equalHelper(AttestationBase const &lhs, AttestationBase const &rhs)
virtual std::vector< std::uint8_t > message(STXChainBridge const &bridge) const =0
AttestationBase(AccountID attestationSignerAccount_, PublicKey const &publicKey_, Buffer signature_, AccountID const &sendingAccount_, STAmount const &sendingAmount_, AccountID const &rewardAccount_, bool wasLockingChainSend_)
static bool sameEventHelper(AttestationBase const &lhs, AttestationBase const &rhs)
bool verify(STXChainBridge const &bridge) const
bool sameEvent(AttestationClaim const &rhs) const
AttestationClaim(AccountID attestationSignerAccount_, PublicKey const &publicKey_, Buffer signature_, AccountID const &sendingAccount_, STAmount const &sendingAmount_, AccountID const &rewardAccount_, bool wasLockingChainSend_, std::uint64_t claimID_, std::optional< AccountID > const &dst_)
static std::vector< std::uint8_t > message(STXChainBridge const &bridge, AccountID const &sendingAccount, STAmount const &sendingAmount, AccountID const &rewardAccount, bool wasLockingChainSend, std::uint64_t claimID, std::optional< AccountID > const &dst)
static std::vector< std::uint8_t > message(STXChainBridge const &bridge, AccountID const &sendingAccount, STAmount const &sendingAmount, STAmount const &rewardAmount, AccountID const &rewardAccount, bool wasLockingChainSend, std::uint64_t createCount, AccountID const &dst)
bool sameEvent(AttestationCreateAccount const &rhs) const
AttestationMatch match(MatchFields const &rhs) const
static SField const & ArrayFieldName
std::optional< AccountID > dst
XChainClaimAttestation(AccountID const &keyAccount_, PublicKey const &publicKey_, STAmount const &amount_, AccountID const &rewardAccount_, bool wasLockingChainSend_, std::optional< AccountID > const &dst)
XChainCreateAccountAttestation(AccountID const &keyAccount_, PublicKey const &publicKey_, STAmount const &amount_, STAmount const &rewardAmount_, AccountID const &rewardAccount_, bool wasLockingChainSend_, AccountID const &dst_)
AttestationMatch match(MatchFields const &rhs) const
friend bool operator==(XChainCreateAccountAttestation const &lhs, XChainCreateAccountAttestation const &rhs)
T tie(T... args)
T value(T... args)