xrpld
Loading...
Searching...
No Matches
xchain_bridge.cpp
1#include <test/jtx/xchain_bridge.h>
2
3#include <test/jtx/Account.h>
4#include <test/jtx/Env.h>
5#include <test/jtx/amount.h>
6#include <test/jtx/attester.h>
7#include <test/jtx/multisign.h>
8
9#include <xrpl/basics/strHex.h>
10#include <xrpl/json/json_value.h>
11#include <xrpl/protocol/AccountID.h>
12#include <xrpl/protocol/Feature.h>
13#include <xrpl/protocol/Issue.h>
14#include <xrpl/protocol/KeyType.h>
15#include <xrpl/protocol/SField.h>
16#include <xrpl/protocol/STAmount.h>
17#include <xrpl/protocol/STBase.h>
18#include <xrpl/protocol/STInteger.h>
19#include <xrpl/protocol/jss.h>
20
21#include <cassert>
22#include <cstddef>
23#include <cstdint>
24#include <optional>
25#include <string>
26#include <vector>
27
28namespace xrpl::test::jtx {
29
30// use this for creating a bridge for a transaction
31json::Value
33 Account const& lockingChainDoor,
34 Issue const& lockingChainIssue,
35 Account const& issuingChainDoor,
36 Issue const& issuingChainIssue)
37{
38 json::Value jv;
39 jv[jss::LockingChainDoor] = lockingChainDoor.human();
40 jv[jss::LockingChainIssue] = toJson(lockingChainIssue);
41 jv[jss::IssuingChainDoor] = issuingChainDoor.human();
42 jv[jss::IssuingChainIssue] = toJson(issuingChainIssue);
43 return jv;
44}
45
46// use this for creating a bridge for a rpc query
49 Account const& lockingChainDoor,
50 Issue const& lockingChainIssue,
51 Account const& issuingChainDoor,
52 Issue const& issuingChainIssue)
53{
54 json::Value jv;
55 jv[jss::LockingChainDoor] = lockingChainDoor.human();
56 jv[jss::LockingChainIssue] = toJson(lockingChainIssue);
57 jv[jss::IssuingChainDoor] = issuingChainDoor.human();
58 jv[jss::IssuingChainIssue] = toJson(issuingChainIssue);
59 return jv;
60}
61
64 Account const& acc,
65 json::Value const& bridge,
66 STAmount const& reward,
67 std::optional<STAmount> const& minAccountCreate)
68{
69 json::Value jv;
70
71 jv[jss::Account] = acc.human();
72 jv[sfXChainBridge.getJsonName()] = bridge;
73 jv[sfSignatureReward.getJsonName()] = reward.getJson(JsonOptions::Values::None);
74 if (minAccountCreate)
75 {
76 jv[sfMinAccountCreateAmount.getJsonName()] =
77 minAccountCreate->getJson(JsonOptions::Values::None);
78 }
79
80 jv[jss::TransactionType] = jss::XChainCreateBridge;
81 return jv;
82}
83
86 Account const& acc,
87 json::Value const& bridge,
88 std::optional<STAmount> const& reward,
89 std::optional<STAmount> const& minAccountCreate)
90{
91 json::Value jv;
92
93 jv[jss::Account] = acc.human();
94 jv[sfXChainBridge.getJsonName()] = bridge;
95 if (reward)
96 jv[sfSignatureReward.getJsonName()] = reward->getJson(JsonOptions::Values::None);
97 if (minAccountCreate)
98 {
99 jv[sfMinAccountCreateAmount.getJsonName()] =
100 minAccountCreate->getJson(JsonOptions::Values::None);
101 }
102
103 jv[jss::TransactionType] = jss::XChainModifyBridge;
104 return jv;
105}
106
109 Account const& acc,
110 json::Value const& bridge,
111 STAmount const& reward,
112 Account const& otherChainSource)
113{
114 json::Value jv;
115
116 jv[jss::Account] = acc.human();
117 jv[sfXChainBridge.getJsonName()] = bridge;
118 jv[sfSignatureReward.getJsonName()] = reward.getJson(JsonOptions::Values::None);
119 jv[sfOtherChainSource.getJsonName()] = otherChainSource.human();
120
121 jv[jss::TransactionType] = jss::XChainCreateClaimID;
122 return jv;
123}
124
127 Account const& acc,
128 json::Value const& bridge,
129 std::uint32_t claimID,
130 AnyAmount const& amt,
131 std::optional<Account> const& dst)
132{
133 json::Value jv;
134
135 jv[jss::Account] = acc.human();
136 jv[sfXChainBridge.getJsonName()] = bridge;
137 jv[sfXChainClaimID.getJsonName()] = claimID;
138 jv[jss::Amount] = amt.value.getJson(JsonOptions::Values::None);
139 if (dst)
140 jv[sfOtherChainDestination.getJsonName()] = dst->human();
141
142 jv[jss::TransactionType] = jss::XChainCommit;
143 return jv;
144}
145
148 Account const& acc,
149 json::Value const& bridge,
150 std::uint32_t claimID,
151 AnyAmount const& amt,
152 Account const& dst)
153{
154 json::Value jv;
155
156 jv[sfAccount.getJsonName()] = acc.human();
157 jv[sfXChainBridge.getJsonName()] = bridge;
158 jv[sfXChainClaimID.getJsonName()] = claimID;
159 jv[sfDestination.getJsonName()] = dst.human();
160 jv[sfAmount.getJsonName()] = amt.value.getJson(JsonOptions::Values::None);
161
162 jv[jss::TransactionType] = jss::XChainClaim;
163 return jv;
164}
165
168 Account const& acc,
169 json::Value const& bridge,
170 Account const& dst,
171 AnyAmount const& amt,
172 AnyAmount const& reward)
173{
174 json::Value jv;
175
176 jv[sfAccount.getJsonName()] = acc.human();
177 jv[sfXChainBridge.getJsonName()] = bridge;
178 jv[sfDestination.getJsonName()] = dst.human();
179 jv[sfAmount.getJsonName()] = amt.value.getJson(JsonOptions::Values::None);
180 jv[sfSignatureReward.getJsonName()] = reward.value.getJson(JsonOptions::Values::None);
181
182 jv[jss::TransactionType] = jss::XChainAccountCreateCommit;
183 return jv;
184}
185
188 jtx::Account const& submittingAccount,
189 json::Value const& jvBridge,
190 jtx::Account const& sendingAccount,
191 jtx::AnyAmount const& sendingAmount,
192 jtx::Account const& rewardAccount,
193 bool wasLockingChainSend,
196 jtx::Signer const& signer)
197{
198 STXChainBridge const stBridge(jvBridge);
199
200 auto const& pk = signer.account.pk();
201 auto const& sk = signer.account.sk();
202 auto const sig = signClaimAttestation(
203 pk,
204 sk,
205 stBridge,
206 sendingAccount,
207 sendingAmount.value,
208 rewardAccount,
209 wasLockingChainSend,
210 claimID,
211 dst);
212
213 json::Value result;
214
215 result[sfAccount.getJsonName()] = submittingAccount.human();
216 result[sfXChainBridge.getJsonName()] = jvBridge;
217
218 result[sfAttestationSignerAccount.getJsonName()] = signer.account.human();
219 result[sfPublicKey.getJsonName()] = strHex(pk.slice());
220 result[sfSignature.getJsonName()] = strHex(sig);
221 result[sfOtherChainSource.getJsonName()] = toBase58(sendingAccount);
222 result[sfAmount.getJsonName()] = sendingAmount.value.getJson(JsonOptions::Values::None);
223 result[sfAttestationRewardAccount.getJsonName()] = toBase58(rewardAccount);
224 result[sfWasLockingChainSend.getJsonName()] = wasLockingChainSend ? 1 : 0;
225
226 result[sfXChainClaimID.getJsonName()] = STUInt64{claimID}.getJson(JsonOptions::Values::None);
227 if (dst)
228 result[sfDestination.getJsonName()] = toBase58(*dst);
229
230 result[jss::TransactionType] = jss::XChainAddClaimAttestation;
231
232 return result;
233}
234
237 jtx::Account const& submittingAccount,
238 json::Value const& jvBridge,
239 jtx::Account const& sendingAccount,
240 jtx::AnyAmount const& sendingAmount,
241 jtx::AnyAmount const& rewardAmount,
242 jtx::Account const& rewardAccount,
243 bool wasLockingChainSend,
244 std::uint64_t createCount,
245 jtx::Account const& dst,
246 jtx::Signer const& signer)
247{
248 STXChainBridge const stBridge(jvBridge);
249
250 auto const& pk = signer.account.pk();
251 auto const& sk = signer.account.sk();
252 auto const sig = jtx::signCreateAccountAttestation(
253 pk,
254 sk,
255 stBridge,
256 sendingAccount,
257 sendingAmount.value,
258 rewardAmount.value,
259 rewardAccount,
260 wasLockingChainSend,
261 createCount,
262 dst);
263
264 json::Value result;
265
266 result[sfAccount.getJsonName()] = submittingAccount.human();
267 result[sfXChainBridge.getJsonName()] = jvBridge;
268
269 result[sfAttestationSignerAccount.getJsonName()] = signer.account.human();
270 result[sfPublicKey.getJsonName()] = strHex(pk.slice());
271 result[sfSignature.getJsonName()] = strHex(sig);
272 result[sfOtherChainSource.getJsonName()] = toBase58(sendingAccount);
273 result[sfAmount.getJsonName()] = sendingAmount.value.getJson(JsonOptions::Values::None);
274 result[sfAttestationRewardAccount.getJsonName()] = toBase58(rewardAccount);
275 result[sfWasLockingChainSend.getJsonName()] = wasLockingChainSend ? 1 : 0;
276
277 result[sfXChainAccountCreateCount.getJsonName()] =
278 STUInt64{createCount}.getJson(JsonOptions::Values::None);
279 result[sfDestination.getJsonName()] = toBase58(dst);
280 result[sfSignatureReward.getJsonName()] = rewardAmount.value.getJson(JsonOptions::Values::None);
281
282 result[jss::TransactionType] = jss::XChainAddAccountCreateAttestation;
283
284 return result;
285}
286
289 jtx::Account const& submittingAccount,
290 json::Value const& jvBridge,
291 jtx::Account const& sendingAccount,
292 jtx::AnyAmount const& sendingAmount,
293 std::vector<jtx::Account> const& rewardAccounts,
294 bool wasLockingChainSend,
295 std::uint64_t claimID,
298 std::size_t const numAtts,
299 std::size_t const fromIdx)
300{
301 assert(fromIdx + numAtts <= rewardAccounts.size());
302 assert(fromIdx + numAtts <= signers.size());
303 JValueVec vec;
304 vec.reserve(numAtts);
305 for (auto i = fromIdx; i < fromIdx + numAtts; ++i)
306 {
308 submittingAccount,
309 jvBridge,
310 sendingAccount,
311 sendingAmount,
312 rewardAccounts[i],
313 wasLockingChainSend,
314 claimID,
315 dst,
316 signers[i]));
317 }
318 return vec;
319}
320
323 jtx::Account const& submittingAccount,
324 json::Value const& jvBridge,
325 jtx::Account const& sendingAccount,
326 jtx::AnyAmount const& sendingAmount,
327 jtx::AnyAmount const& rewardAmount,
328 std::vector<jtx::Account> const& rewardAccounts,
329 bool wasLockingChainSend,
330 std::uint64_t createCount,
331 jtx::Account const& dst,
333 std::size_t const numAtts,
334 std::size_t const fromIdx)
335{
336 assert(fromIdx + numAtts <= rewardAccounts.size());
337 assert(fromIdx + numAtts <= signers.size());
338 JValueVec vec;
339 vec.reserve(numAtts);
340 for (auto i = fromIdx; i < fromIdx + numAtts; ++i)
341 {
343 submittingAccount,
344 jvBridge,
345 sendingAccount,
346 sendingAmount,
347 rewardAmount,
348 rewardAccounts[i],
349 wasLockingChainSend,
350 createCount,
351 dst,
352 signers[i]));
353 }
354 return vec;
355}
356
358 : mcDoor("mcDoor")
359 , mcAlice("mcAlice")
360 , mcBob("mcBob")
361 , mcCarol("mcCarol")
362 , mcGw("mcGw")
363 , scDoor("scDoor")
364 , scAlice("scAlice")
365 , scBob("scBob")
366 , scCarol("scCarol")
367 , scGw("scGw")
368 , scAttester("scAttester")
369 , scReward("scReward")
370 , mcuDoor("mcuDoor")
371 , mcuAlice("mcuAlice")
372 , mcuBob("mcuBob")
373 , mcuCarol("mcuCarol")
374 , mcuGw("mcuGw")
375 , scuDoor("scuDoor")
376 , scuAlice("scuAlice")
377 , scuBob("scuBob")
378 , scuCarol("scuCarol")
379 , scuGw("scuGw")
380 , mcUSD(mcGw["USD"])
381 , scUSD(scGw["USD"])
383 , jvb(bridge(mcDoor, xrpIssue(), Account::kMaster, xrpIssue()))
384 , jvub(bridge(mcuDoor, xrpIssue(), Account::kMaster, xrpIssue()))
385 , features(testableAmendments() | FeatureBitset{featureXChainBridge})
386 , signers([] {
387 static constexpr int kNumSigners = kUtXchainDefaultNumSigners;
388 std::vector<Signer> result;
389 result.reserve(kNumSigners);
390 for (int i = 0; i < kNumSigners; ++i)
391 {
392 using namespace std::literals;
393 auto const a = Account(
394 "signer_"s + std::to_string(i), (i % 2) ? KeyType::Ed25519 : KeyType::Secp256k1);
395 result.emplace_back(a);
396 }
397 return result;
398 }())
399 , altSigners([] {
400 static constexpr int kNumSigners = kUtXchainDefaultNumSigners;
401 std::vector<Signer> result;
402 result.reserve(kNumSigners);
403 for (int i = 0; i < kNumSigners; ++i)
404 {
405 using namespace std::literals;
406 auto const a = Account(
407 "alt_signer_"s + std::to_string(i),
409 result.emplace_back(a);
410 }
411 return result;
412 }())
413 , payee([&] {
415 r.reserve(signers.size());
416 for (int i = 0, e = signers.size(); i != e; ++i)
417 {
418 r.push_back(scReward);
419 }
420 return r;
421 }())
422 , payees([&] {
423 std::vector<Account> r;
424 r.reserve(signers.size());
425 for (int i = 0, e = signers.size(); i != e; ++i)
426 {
427 using namespace std::literals;
428 auto const a = Account("reward_"s + std::to_string(i));
429 r.push_back(a);
430 }
431 return r;
432 }())
433 , reward(XRP(1))
434 , splitRewardQuorum(divide(reward, STAmount(kUtXchainDefaultQuorum), reward.get<Issue>()))
435 , splitRewardEveryone(divide(reward, STAmount(kUtXchainDefaultNumSigners), reward.get<Issue>()))
436 , tinyReward(drops(37))
437 , tinyRewardSplit(
438 (divide(tinyReward, STAmount(kUtXchainDefaultQuorum), tinyReward.get<Issue>())))
439 , tinyRewardRemainder(
440 tinyReward -
441 multiply(tinyRewardSplit, STAmount(kUtXchainDefaultQuorum), tinyReward.get<Issue>()))
442 , oneXrp(XRP(1))
443 , xrpDust(divide(oneXrp, STAmount(10000), oneXrp.get<Issue>()))
444{
445}
446
447void
449{
450 STAmount const xrpFunds{XRP(10000)};
451 mcEnv.fund(xrpFunds, mcDoor, mcAlice, mcBob, mcCarol, mcGw);
452
453 // Signer's list must match the attestation signers
454 mcEnv(jtx::signers(mcDoor, signers.size(), signers));
455
456 // create XRP bridges in both direction
457 auto const reward = XRP(1);
458 STAmount const minCreate = XRP(20);
459
460 mcEnv(bridgeCreate(mcDoor, jvb, reward, minCreate));
461 mcEnv.close();
462}
463
464void
466{
467 STAmount const xrpFunds{XRP(10000)};
468 scEnv.fund(xrpFunds, scDoor, scAlice, scBob, scCarol, scGw, scAttester, scReward);
469
470 // Signer's list must match the attestation signers
472
473 // create XRP bridges in both direction
474 auto const reward = XRP(1);
475 STAmount const minCreate = XRP(20);
476
477 scEnv(bridgeCreate(Account::kMaster, jvb, reward, minCreate));
478 scEnv.close();
479}
480
481void
487} // namespace xrpl::test::jtx
Represents a JSON value.
Definition json_value.h:130
UInt size() const
Number of values in array or object.
A currency issued by an account.
Definition Issue.h:13
json::Value getJson(JsonOptions=JsonOptions::Values::None) const override
Definition STAmount.cpp:734
Immutable cryptographic account descriptor.
Definition jtx/Account.h:17
SecretKey const & sk() const
Return the secret key.
Definition jtx/Account.h:75
std::string const & human() const
Returns the human readable public key.
Definition jtx/Account.h:92
PublicKey const & pk() const
Return the public key.
Definition jtx/Account.h:68
static Account const kMaster
The master account.
Definition jtx/Account.h:26
A transaction testing environment.
Definition Env.h:143
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:133
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:296
T emplace_back(T... args)
Buffer signClaimAttestation(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:16
std::vector< json::Value > JValueVec
json::Value sidechainXchainAccountCreate(Account const &acc, json::Value const &bridge, Account const &dst, AnyAmount const &amt, AnyAmount const &reward)
json::Value bridgeRpc(Account const &lockingChainDoor, Issue const &lockingChainIssue, Account const &issuingChainDoor, Issue const &issuingChainIssue)
XrpT const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:92
json::Value xchainCommit(Account const &acc, json::Value const &bridge, std::uint32_t claimID, AnyAmount const &amt, std::optional< Account > const &dst)
FeatureBitset testableAmendments()
Definition Env.h:76
json::Value bridgeCreate(Account const &acc, json::Value const &bridge, STAmount const &reward, std::optional< STAmount > const &minAccountCreate)
json::Value bridge(Account const &lockingChainDoor, Issue const &lockingChainIssue, Account const &issuingChainDoor, Issue const &issuingChainIssue)
constexpr std::size_t kUtXchainDefaultNumSigners
JValueVec claimAttestations(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)
Buffer signCreateAccountAttestation(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:33
json::Value claimAttestation(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 createAccountAttestation(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)
json::Value xchainClaim(Account const &acc, json::Value const &bridge, std::uint32_t claimID, AnyAmount const &amt, Account const &dst)
constexpr std::size_t kUtXchainDefaultQuorum
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
json::Value bridgeModify(Account const &acc, json::Value const &bridge, std::optional< STAmount > const &reward, std::optional< STAmount > const &minAccountCreate)
json::Value xchainCreateClaimId(Account const &acc, json::Value const &bridge, STAmount const &reward, Account const &otherChainSource)
json::Value signers(Account const &account, std::uint32_t quorum, std::vector< Signer > const &v)
Definition multisign.cpp:31
JValueVec createAccountAttestations(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)
STAmount divide(STAmount const &amount, Rate const &rate)
Definition Rate2.cpp:69
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
Definition Issue.h:97
std::string strHex(FwdIt begin, FwdIt end)
Definition strHex.h:10
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:93
STInteger< std::uint64_t > STUInt64
Definition STInteger.h:62
json::Value toJson(Asset const &asset)
Definition Asset.h:157
STAmount multiply(STAmount const &amount, Number const &frac, Number::RoundingMode rm)
T push_back(T... args)
T reserve(T... args)
T size(T... args)
std::uint64_t claimID(json::Value const &jvb)
Amount specifier with an option for any issuer.
A signer in a SignerList.
Definition multisign.h:17
void createBridgeObjects(Env &mcEnv, Env &scEnv)
std::vector< Signer > const signers
T to_string(T... args)