rippled
Loading...
Searching...
No Matches
xchain_bridge.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 <test/jtx/Env.h>
21#include <test/jtx/attester.h>
22#include <test/jtx/xchain_bridge.h>
23
24#include <xrpl/json/json_value.h>
25#include <xrpl/protocol/Issue.h>
26#include <xrpl/protocol/SField.h>
27#include <xrpl/protocol/STBase.h>
28#include <xrpl/protocol/STInteger.h>
29#include <xrpl/protocol/STObject.h>
30#include <xrpl/protocol/TxFlags.h>
31#include <xrpl/protocol/XChainAttestations.h>
32#include <xrpl/protocol/jss.h>
33
34namespace ripple {
35namespace test {
36namespace jtx {
37
38// use this for creating a bridge for a transaction
41 Account const& lockingChainDoor,
42 Issue const& lockingChainIssue,
43 Account const& issuingChainDoor,
44 Issue const& issuingChainIssue)
45{
46 Json::Value jv;
47 jv[jss::LockingChainDoor] = lockingChainDoor.human();
48 jv[jss::LockingChainIssue] = to_json(lockingChainIssue);
49 jv[jss::IssuingChainDoor] = issuingChainDoor.human();
50 jv[jss::IssuingChainIssue] = to_json(issuingChainIssue);
51 return jv;
52}
53
54// use this for creating a bridge for a rpc query
57 Account const& lockingChainDoor,
58 Issue const& lockingChainIssue,
59 Account const& issuingChainDoor,
60 Issue const& issuingChainIssue)
61{
62 Json::Value jv;
63 jv[jss::LockingChainDoor] = lockingChainDoor.human();
64 jv[jss::LockingChainIssue] = to_json(lockingChainIssue);
65 jv[jss::IssuingChainDoor] = issuingChainDoor.human();
66 jv[jss::IssuingChainIssue] = to_json(issuingChainIssue);
67 return jv;
68}
69
72 Account const& acc,
73 Json::Value const& bridge,
74 STAmount const& reward,
75 std::optional<STAmount> const& minAccountCreate)
76{
77 Json::Value jv;
78
79 jv[jss::Account] = acc.human();
80 jv[sfXChainBridge.getJsonName()] = bridge;
81 jv[sfSignatureReward.getJsonName()] = reward.getJson(JsonOptions::none);
82 if (minAccountCreate)
83 jv[sfMinAccountCreateAmount.getJsonName()] =
84 minAccountCreate->getJson(JsonOptions::none);
85
86 jv[jss::TransactionType] = jss::XChainCreateBridge;
87 return jv;
88}
89
92 Account const& acc,
93 Json::Value const& bridge,
94 std::optional<STAmount> const& reward,
95 std::optional<STAmount> const& minAccountCreate)
96{
97 Json::Value jv;
98
99 jv[jss::Account] = acc.human();
100 jv[sfXChainBridge.getJsonName()] = bridge;
101 if (reward)
102 jv[sfSignatureReward.getJsonName()] =
103 reward->getJson(JsonOptions::none);
104 if (minAccountCreate)
105 jv[sfMinAccountCreateAmount.getJsonName()] =
106 minAccountCreate->getJson(JsonOptions::none);
107
108 jv[jss::TransactionType] = jss::XChainModifyBridge;
109 return jv;
110}
111
114 Account const& acc,
115 Json::Value const& bridge,
116 STAmount const& reward,
117 Account const& otherChainSource)
118{
119 Json::Value jv;
120
121 jv[jss::Account] = acc.human();
122 jv[sfXChainBridge.getJsonName()] = bridge;
123 jv[sfSignatureReward.getJsonName()] = reward.getJson(JsonOptions::none);
124 jv[sfOtherChainSource.getJsonName()] = otherChainSource.human();
125
126 jv[jss::TransactionType] = jss::XChainCreateClaimID;
127 return jv;
128}
129
132 Account const& acc,
133 Json::Value const& bridge,
134 std::uint32_t claimID,
135 AnyAmount const& amt,
136 std::optional<Account> const& dst)
137{
138 Json::Value jv;
139
140 jv[jss::Account] = acc.human();
141 jv[sfXChainBridge.getJsonName()] = bridge;
142 jv[sfXChainClaimID.getJsonName()] = claimID;
143 jv[jss::Amount] = amt.value.getJson(JsonOptions::none);
144 if (dst)
145 jv[sfOtherChainDestination.getJsonName()] = dst->human();
146
147 jv[jss::TransactionType] = jss::XChainCommit;
148 return jv;
149}
150
153 Account const& acc,
154 Json::Value const& bridge,
155 std::uint32_t claimID,
156 AnyAmount const& amt,
157 Account const& dst)
158{
159 Json::Value jv;
160
161 jv[sfAccount.getJsonName()] = acc.human();
162 jv[sfXChainBridge.getJsonName()] = bridge;
163 jv[sfXChainClaimID.getJsonName()] = claimID;
164 jv[sfDestination.getJsonName()] = dst.human();
165 jv[sfAmount.getJsonName()] = amt.value.getJson(JsonOptions::none);
166
167 jv[jss::TransactionType] = jss::XChainClaim;
168 return jv;
169}
170
173 Account const& acc,
174 Json::Value const& bridge,
175 Account const& dst,
176 AnyAmount const& amt,
177 AnyAmount const& reward)
178{
179 Json::Value jv;
180
181 jv[sfAccount.getJsonName()] = acc.human();
182 jv[sfXChainBridge.getJsonName()] = bridge;
183 jv[sfDestination.getJsonName()] = dst.human();
184 jv[sfAmount.getJsonName()] = amt.value.getJson(JsonOptions::none);
185 jv[sfSignatureReward.getJsonName()] =
187
188 jv[jss::TransactionType] = jss::XChainAccountCreateCommit;
189 return jv;
190}
191
194 jtx::Account const& submittingAccount,
195 Json::Value const& jvBridge,
196 jtx::Account const& sendingAccount,
197 jtx::AnyAmount const& sendingAmount,
198 jtx::Account const& rewardAccount,
199 bool wasLockingChainSend,
200 std::uint64_t claimID,
202 jtx::signer const& signer)
203{
204 STXChainBridge const stBridge(jvBridge);
205
206 auto const& pk = signer.account.pk();
207 auto const& sk = signer.account.sk();
208 auto const sig = sign_claim_attestation(
209 pk,
210 sk,
211 stBridge,
212 sendingAccount,
213 sendingAmount.value,
214 rewardAccount,
215 wasLockingChainSend,
216 claimID,
217 dst);
218
219 Json::Value result;
220
221 result[sfAccount.getJsonName()] = submittingAccount.human();
222 result[sfXChainBridge.getJsonName()] = jvBridge;
223
224 result[sfAttestationSignerAccount.getJsonName()] = signer.account.human();
225 result[sfPublicKey.getJsonName()] = strHex(pk.slice());
226 result[sfSignature.getJsonName()] = strHex(sig);
227 result[sfOtherChainSource.getJsonName()] = toBase58(sendingAccount);
228 result[sfAmount.getJsonName()] =
229 sendingAmount.value.getJson(JsonOptions::none);
230 result[sfAttestationRewardAccount.getJsonName()] = toBase58(rewardAccount);
231 result[sfWasLockingChainSend.getJsonName()] = wasLockingChainSend ? 1 : 0;
232
233 result[sfXChainClaimID.getJsonName()] =
234 STUInt64{claimID}.getJson(JsonOptions::none);
235 if (dst)
236 result[sfDestination.getJsonName()] = toBase58(*dst);
237
238 result[jss::TransactionType] = jss::XChainAddClaimAttestation;
239
240 return result;
241}
242
245 jtx::Account const& submittingAccount,
246 Json::Value const& jvBridge,
247 jtx::Account const& sendingAccount,
248 jtx::AnyAmount const& sendingAmount,
249 jtx::AnyAmount const& rewardAmount,
250 jtx::Account const& rewardAccount,
251 bool wasLockingChainSend,
252 std::uint64_t createCount,
253 jtx::Account const& dst,
254 jtx::signer const& signer)
255{
256 STXChainBridge const stBridge(jvBridge);
257
258 auto const& pk = signer.account.pk();
259 auto const& sk = signer.account.sk();
261 pk,
262 sk,
263 stBridge,
264 sendingAccount,
265 sendingAmount.value,
266 rewardAmount.value,
267 rewardAccount,
268 wasLockingChainSend,
269 createCount,
270 dst);
271
272 Json::Value result;
273
274 result[sfAccount.getJsonName()] = submittingAccount.human();
275 result[sfXChainBridge.getJsonName()] = jvBridge;
276
277 result[sfAttestationSignerAccount.getJsonName()] = signer.account.human();
278 result[sfPublicKey.getJsonName()] = strHex(pk.slice());
279 result[sfSignature.getJsonName()] = strHex(sig);
280 result[sfOtherChainSource.getJsonName()] = toBase58(sendingAccount);
281 result[sfAmount.getJsonName()] =
282 sendingAmount.value.getJson(JsonOptions::none);
283 result[sfAttestationRewardAccount.getJsonName()] = toBase58(rewardAccount);
284 result[sfWasLockingChainSend.getJsonName()] = wasLockingChainSend ? 1 : 0;
285
286 result[sfXChainAccountCreateCount.getJsonName()] =
287 STUInt64{createCount}.getJson(JsonOptions::none);
288 result[sfDestination.getJsonName()] = toBase58(dst);
289 result[sfSignatureReward.getJsonName()] =
290 rewardAmount.value.getJson(JsonOptions::none);
291
292 result[jss::TransactionType] = jss::XChainAddAccountCreateAttestation;
293
294 return result;
295}
296
299 jtx::Account const& submittingAccount,
300 Json::Value const& jvBridge,
301 jtx::Account const& sendingAccount,
302 jtx::AnyAmount const& sendingAmount,
303 std::vector<jtx::Account> const& rewardAccounts,
304 bool wasLockingChainSend,
305 std::uint64_t claimID,
308 std::size_t const numAtts,
309 std::size_t const fromIdx)
310{
311 assert(fromIdx + numAtts <= rewardAccounts.size());
312 assert(fromIdx + numAtts <= signers.size());
313 JValueVec vec;
314 vec.reserve(numAtts);
315 for (auto i = fromIdx; i < fromIdx + numAtts; ++i)
317 submittingAccount,
318 jvBridge,
319 sendingAccount,
320 sendingAmount,
321 rewardAccounts[i],
322 wasLockingChainSend,
323 claimID,
324 dst,
325 signers[i]));
326 return vec;
327}
328
331 jtx::Account const& submittingAccount,
332 Json::Value const& jvBridge,
333 jtx::Account const& sendingAccount,
334 jtx::AnyAmount const& sendingAmount,
335 jtx::AnyAmount const& rewardAmount,
336 std::vector<jtx::Account> const& rewardAccounts,
337 bool wasLockingChainSend,
338 std::uint64_t createCount,
339 jtx::Account const& dst,
341 std::size_t const numAtts,
342 std::size_t const fromIdx)
343{
344 assert(fromIdx + numAtts <= rewardAccounts.size());
345 assert(fromIdx + numAtts <= signers.size());
346 JValueVec vec;
347 vec.reserve(numAtts);
348 for (auto i = fromIdx; i < fromIdx + numAtts; ++i)
350 submittingAccount,
351 jvBridge,
352 sendingAccount,
353 sendingAmount,
354 rewardAmount,
355 rewardAccounts[i],
356 wasLockingChainSend,
357 createCount,
358 dst,
359 signers[i]));
360 return vec;
361}
362
364 : mcDoor("mcDoor")
365 , mcAlice("mcAlice")
366 , mcBob("mcBob")
367 , mcCarol("mcCarol")
368 , mcGw("mcGw")
369 , scDoor("scDoor")
370 , scAlice("scAlice")
371 , scBob("scBob")
372 , scCarol("scCarol")
373 , scGw("scGw")
374 , scAttester("scAttester")
375 , scReward("scReward")
376 , mcuDoor("mcuDoor")
377 , mcuAlice("mcuAlice")
378 , mcuBob("mcuBob")
379 , mcuCarol("mcuCarol")
380 , mcuGw("mcuGw")
381 , scuDoor("scuDoor")
382 , scuAlice("scuAlice")
383 , scuBob("scuBob")
384 , scuCarol("scuCarol")
385 , scuGw("scuGw")
386 , mcUSD(mcGw["USD"])
387 , scUSD(scGw["USD"])
388 , jvXRPBridgeRPC(
389 bridge_rpc(mcDoor, xrpIssue(), Account::master, xrpIssue()))
390 , jvb(bridge(mcDoor, xrpIssue(), Account::master, xrpIssue()))
391 , jvub(bridge(mcuDoor, xrpIssue(), Account::master, xrpIssue()))
392 , features(testable_amendments() | FeatureBitset{featureXChainBridge})
393 , signers([] {
394 constexpr int numSigners = UT_XCHAIN_DEFAULT_NUM_SIGNERS;
395 std::vector<signer> result;
396 result.reserve(numSigners);
397 for (int i = 0; i < numSigners; ++i)
398 {
399 using namespace std::literals;
400 auto const a = Account(
401 "signer_"s + std::to_string(i),
403 result.emplace_back(a);
404 }
405 return result;
406 }())
407 , alt_signers([] {
408 constexpr int numSigners = UT_XCHAIN_DEFAULT_NUM_SIGNERS;
409 std::vector<signer> result;
410 result.reserve(numSigners);
411 for (int i = 0; i < numSigners; ++i)
412 {
413 using namespace std::literals;
414 auto const a = Account(
415 "alt_signer_"s + std::to_string(i),
416 (i % 2) ? KeyType::ed25519 : KeyType::secp256k1);
417 result.emplace_back(a);
418 }
419 return result;
420 }())
421 , payee([&] {
423 r.reserve(signers.size());
424 for (int i = 0, e = signers.size(); i != e; ++i)
425 {
426 r.push_back(scReward);
427 }
428 return r;
429 }())
430 , payees([&] {
432 r.reserve(signers.size());
433 for (int i = 0, e = signers.size(); i != e; ++i)
434 {
435 using namespace std::literals;
436 auto const a = Account("reward_"s + std::to_string(i));
437 r.push_back(a);
438 }
439 return r;
440 }())
442 , reward(XRP(1))
443 , split_reward_quorum(
444 divide(reward, STAmount(UT_XCHAIN_DEFAULT_QUORUM), reward.issue()))
445 , split_reward_everyone(divide(
446 reward,
448 reward.issue()))
449 , tiny_reward(drops(37))
450 , tiny_reward_split((divide(
451 tiny_reward,
452 STAmount(UT_XCHAIN_DEFAULT_QUORUM),
453 tiny_reward.issue())))
454 , tiny_reward_remainder(
455 tiny_reward -
456 multiply(
457 tiny_reward_split,
458 STAmount(UT_XCHAIN_DEFAULT_QUORUM),
459 tiny_reward.issue()))
460 , one_xrp(XRP(1))
461 , xrp_dust(divide(one_xrp, STAmount(10000), one_xrp.issue()))
462{
463}
464
465void
467{
468 STAmount xrp_funds{XRP(10000)};
469 mcEnv.fund(xrp_funds, mcDoor, mcAlice, mcBob, mcCarol, mcGw);
470
471 // Signer's list must match the attestation signers
472 mcEnv(jtx::signers(mcDoor, signers.size(), signers));
473
474 // create XRP bridges in both direction
475 auto const reward = XRP(1);
476 STAmount const minCreate = XRP(20);
477
478 mcEnv(bridge_create(mcDoor, jvb, reward, minCreate));
479 mcEnv.close();
480}
481
482void
484{
485 STAmount xrp_funds{XRP(10000)};
486 scEnv.fund(
488
489 // Signer's list must match the attestation signers
491
492 // create XRP bridges in both direction
493 auto const reward = XRP(1);
494 STAmount const minCreate = XRP(20);
495
496 scEnv(bridge_create(Account::master, jvb, reward, minCreate));
497 scEnv.close();
498}
499
500void
506} // namespace jtx
507} // namespace test
508} // namespace ripple
Represents a JSON value.
Definition json_value.h:149
UInt size() const
Number of values in array or object.
A currency issued by an account.
Definition Issue.h:33
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Definition STAmount.cpp:795
Immutable cryptographic account descriptor.
Definition Account.h:39
PublicKey const & pk() const
Return the public key.
Definition Account.h:94
static Account const master
The master account.
Definition Account.h:48
SecretKey const & sk() const
Return the secret key.
Definition Account.h:101
std::string const & human() const
Returns the human readable public key.
Definition Account.h:118
A transaction testing environment.
Definition Env.h:121
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:121
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:289
Set the regular signature on a JTx.
Definition sig.h:35
T emplace_back(T... args)
constexpr std::size_t UT_XCHAIN_DEFAULT_QUORUM
Json::Value create_account_attestation(jtx::Account const &submittingAccount, Json::Value const &jvBridge, jtx::Account const &sendingAccount, jtx::AnyAmount const &sendingAmount, jtx::AnyAmount const &rewardAmount, jtx::Account const &rewardAccount, bool wasLockingChainSend, std::uint64_t createCount, jtx::Account const &dst, jtx::signer const &signer)
JValueVec claim_attestations(jtx::Account const &submittingAccount, Json::Value const &jvBridge, jtx::Account const &sendingAccount, jtx::AnyAmount const &sendingAmount, std::vector< jtx::Account > const &rewardAccounts, bool wasLockingChainSend, std::uint64_t claimID, std::optional< jtx::Account > const &dst, std::vector< jtx::signer > const &signers, std::size_t const numAtts, std::size_t const fromIdx)
Json::Value bridge_create(Account const &acc, Json::Value const &bridge, STAmount const &reward, std::optional< STAmount > const &minAccountCreate)
Json::Value claim_attestation(jtx::Account const &submittingAccount, Json::Value const &jvBridge, jtx::Account const &sendingAccount, jtx::AnyAmount const &sendingAmount, jtx::Account const &rewardAccount, bool wasLockingChainSend, std::uint64_t claimID, std::optional< jtx::Account > const &dst, jtx::signer const &signer)
Json::Value bridge(Account const &lockingChainDoor, Issue const &lockingChainIssue, Account const &issuingChainDoor, Issue const &issuingChainIssue)
Json::Value signers(Account const &account, std::uint32_t quorum, std::vector< signer > const &v)
Definition multisign.cpp:34
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Json::Value sidechain_xchain_account_create(Account const &acc, Json::Value const &bridge, Account const &dst, AnyAmount const &amt, AnyAmount const &reward)
Json::Value xchain_claim(Account const &acc, Json::Value const &bridge, std::uint32_t claimID, AnyAmount const &amt, Account const &dst)
constexpr std::size_t UT_XCHAIN_DEFAULT_NUM_SIGNERS
JValueVec create_account_attestations(jtx::Account const &submittingAccount, Json::Value const &jvBridge, jtx::Account const &sendingAccount, jtx::AnyAmount const &sendingAmount, jtx::AnyAmount const &rewardAmount, std::vector< jtx::Account > const &rewardAccounts, bool wasLockingChainSend, std::uint64_t createCount, jtx::Account const &dst, std::vector< jtx::signer > const &signers, std::size_t const numAtts, std::size_t const fromIdx)
FeatureBitset testable_amendments()
Definition Env.h:74
Json::Value xchain_create_claim_id(Account const &acc, Json::Value const &bridge, STAmount const &reward, Account const &otherChainSource)
Json::Value bridge_modify(Account const &acc, Json::Value const &bridge, std::optional< STAmount > const &reward, std::optional< STAmount > const &minAccountCreate)
Buffer sign_claim_attestation(PublicKey const &pk, SecretKey const &sk, STXChainBridge const &bridge, AccountID const &sendingAccount, STAmount const &sendingAmount, AccountID const &rewardAccount, bool wasLockingChainSend, std::uint64_t claimID, std::optional< AccountID > const &dst)
Definition attester.cpp:32
Json::Value xchain_commit(Account const &acc, Json::Value const &bridge, std::uint32_t claimID, AnyAmount const &amt, std::optional< Account > const &dst)
Buffer sign_create_account_attestation(PublicKey const &pk, SecretKey const &sk, STXChainBridge const &bridge, AccountID const &sendingAccount, STAmount const &sendingAmount, STAmount const &rewardAmount, AccountID const &rewardAccount, bool wasLockingChainSend, std::uint64_t createCount, AccountID const &dst)
Definition attester.cpp:55
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:111
Json::Value bridge_rpc(Account const &lockingChainDoor, Issue const &lockingChainIssue, Account const &issuingChainDoor, Issue const &issuingChainIssue)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
Definition Issue.h:115
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
STAmount divide(STAmount const &amount, Rate const &rate)
Definition Rate2.cpp:93
STAmount multiply(STAmount const &amount, Rate const &rate)
Definition Rate2.cpp:53
Json::Value to_json(Asset const &asset)
Definition Asset.h:123
std::string strHex(FwdIt begin, FwdIt end)
Definition strHex.h:30
KeyType
Definition KeyType.h:28
T push_back(T... args)
T reserve(T... args)
Amount specifier with an option for any issuer.
std::vector< signer > const signers
void createBridgeObjects(Env &mcEnv, Env &scEnv)
A signer in a SignerList.
Definition multisign.h:39
T to_string(T... args)