rippled
MultiSign_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5  Permission to use, copy, modify, and/or distribute this software for any
6  purpose with or without fee is hereby granted, provided that the above
7  copyright notice and this permission notice appear in all copies.
8  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16 //==============================================================================
17 
18 #include <ripple/core/ConfigSections.h>
19 #include <ripple/protocol/Feature.h>
20 #include <ripple/protocol/jss.h>
21 #include <test/jtx.h>
22 
23 namespace ripple {
24 namespace test {
25 
26 class MultiSign_test : public beast::unit_test::suite
27 {
28  // Unfunded accounts to use for phantom signing.
37 
38 public:
39  void
41  {
42  testcase("No Reserve");
43 
44  using namespace jtx;
45  Env env{*this, features};
46  Account const alice{"alice", KeyType::secp256k1};
47 
48  // The reserve required for a signer list changes with the passage
49  // of featureMultiSignReserve. Make the required adjustments.
50  bool const reserve1{features[featureMultiSignReserve]};
51 
52  // Pay alice enough to meet the initial reserve, but not enough to
53  // meet the reserve for a SignerListSet.
54  auto const fee = env.current()->fees().base;
55  auto const smallSignersReserve = reserve1 ? XRP(250) : XRP(350);
56  env.fund(smallSignersReserve - drops(1), alice);
57  env.close();
58  env.require(owners(alice, 0));
59 
60  {
61  // Attach a signer list to alice. Should fail.
62  Json::Value smallSigners = signers(alice, 1, {{bogie, 1}});
63  env(smallSigners, ter(tecINSUFFICIENT_RESERVE));
64  env.close();
65  env.require(owners(alice, 0));
66 
67  // Fund alice enough to set the signer list, then attach signers.
68  env(pay(env.master, alice, fee + drops(1)));
69  env.close();
70  env(smallSigners);
71  env.close();
72  env.require(owners(alice, reserve1 ? 1 : 3));
73  }
74  {
75  // Pay alice enough to almost make the reserve for the biggest
76  // possible list.
77  auto const addReserveBigSigners = reserve1 ? XRP(0) : XRP(350);
78  env(pay(env.master, alice, addReserveBigSigners + fee - drops(1)));
79 
80  // Replace with the biggest possible signer list. Should fail.
81  Json::Value bigSigners = signers(
82  alice,
83  1,
84  {{bogie, 1},
85  {demon, 1},
86  {ghost, 1},
87  {haunt, 1},
88  {jinni, 1},
89  {phase, 1},
90  {shade, 1},
91  {spook, 1}});
92  env(bigSigners, ter(tecINSUFFICIENT_RESERVE));
93  env.close();
94  env.require(owners(alice, reserve1 ? 1 : 3));
95 
96  // Fund alice one more drop (plus the fee) and succeed.
97  env(pay(env.master, alice, fee + drops(1)));
98  env.close();
99  env(bigSigners);
100  env.close();
101  env.require(owners(alice, reserve1 ? 1 : 10));
102  }
103  // Remove alice's signer list and get the owner count back.
104  env(signers(alice, jtx::none));
105  env.close();
106  env.require(owners(alice, 0));
107  }
108 
109  void
111  {
112  testcase("SignerListSet");
113 
114  using namespace jtx;
115  Env env{*this, features};
116  Account const alice{"alice", KeyType::ed25519};
117  env.fund(XRP(1000), alice);
118 
119  // Add alice as a multisigner for herself. Should fail.
120  env(signers(alice, 1, {{alice, 1}}), ter(temBAD_SIGNER));
121 
122  // Add a signer with a weight of zero. Should fail.
123  env(signers(alice, 1, {{bogie, 0}}), ter(temBAD_WEIGHT));
124 
125  // Add a signer where the weight is too big. Should fail since
126  // the weight field is only 16 bits. The jtx framework can't do
127  // this kind of test, so it's commented out.
128  // env(signers(alice, 1, { { bogie, 0x10000} }), ter
129  // (temBAD_WEIGHT));
130 
131  // Add the same signer twice. Should fail.
132  env(signers(
133  alice,
134  1,
135  {{bogie, 1},
136  {demon, 1},
137  {ghost, 1},
138  {haunt, 1},
139  {jinni, 1},
140  {phase, 1},
141  {demon, 1},
142  {spook, 1}}),
143  ter(temBAD_SIGNER));
144 
145  // Set a quorum of zero. Should fail.
146  env(signers(alice, 0, {{bogie, 1}}), ter(temMALFORMED));
147 
148  // Make a signer list where the quorum can't be met. Should fail.
149  env(signers(
150  alice,
151  9,
152  {{bogie, 1},
153  {demon, 1},
154  {ghost, 1},
155  {haunt, 1},
156  {jinni, 1},
157  {phase, 1},
158  {shade, 1},
159  {spook, 1}}),
160  ter(temBAD_QUORUM));
161 
162  // Make a signer list that's too big. Should fail.
163  Account const spare("spare", KeyType::secp256k1);
164  env(signers(
165  alice,
166  1,
167  {{bogie, 1},
168  {demon, 1},
169  {ghost, 1},
170  {haunt, 1},
171  {jinni, 1},
172  {phase, 1},
173  {shade, 1},
174  {spook, 1},
175  {spare, 1}}),
176  ter(temMALFORMED));
177 
178  env.close();
179  env.require(owners(alice, 0));
180  }
181 
182  void
184  {
185  testcase("Phantom Signers");
186 
187  using namespace jtx;
188  Env env{*this, features};
189  Account const alice{"alice", KeyType::ed25519};
190  env.fund(XRP(1000), alice);
191  env.close();
192 
193  // Attach phantom signers to alice and use them for a transaction.
194  env(signers(alice, 1, {{bogie, 1}, {demon, 1}}));
195  env.close();
196  env.require(owners(alice, features[featureMultiSignReserve] ? 1 : 4));
197 
198  // This should work.
199  auto const baseFee = env.current()->fees().base;
200  std::uint32_t aliceSeq = env.seq(alice);
201  env(noop(alice), msig(bogie, demon), fee(3 * baseFee));
202  env.close();
203  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
204 
205  // Either signer alone should work.
206  aliceSeq = env.seq(alice);
207  env(noop(alice), msig(bogie), fee(2 * baseFee));
208  env.close();
209  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
210 
211  aliceSeq = env.seq(alice);
212  env(noop(alice), msig(demon), fee(2 * baseFee));
213  env.close();
214  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
215 
216  // Duplicate signers should fail.
217  aliceSeq = env.seq(alice);
218  env(noop(alice), msig(demon, demon), fee(3 * baseFee), ter(temINVALID));
219  env.close();
220  BEAST_EXPECT(env.seq(alice) == aliceSeq);
221 
222  // A non-signer should fail.
223  aliceSeq = env.seq(alice);
224  env(noop(alice),
225  msig(bogie, spook),
226  fee(3 * baseFee),
228  env.close();
229  BEAST_EXPECT(env.seq(alice) == aliceSeq);
230 
231  // Don't meet the quorum. Should fail.
232  env(signers(alice, 2, {{bogie, 1}, {demon, 1}}));
233  aliceSeq = env.seq(alice);
234  env(noop(alice), msig(bogie), fee(2 * baseFee), ter(tefBAD_QUORUM));
235  env.close();
236  BEAST_EXPECT(env.seq(alice) == aliceSeq);
237 
238  // Meet the quorum. Should succeed.
239  aliceSeq = env.seq(alice);
240  env(noop(alice), msig(bogie, demon), fee(3 * baseFee));
241  env.close();
242  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
243  }
244 
245  void
247  {
248  testcase("Fee");
249 
250  using namespace jtx;
251  Env env{*this, features};
252  Account const alice{"alice", KeyType::ed25519};
253  env.fund(XRP(1000), alice);
254  env.close();
255 
256  // Attach maximum possible number of signers to alice.
257  env(signers(
258  alice,
259  1,
260  {{bogie, 1},
261  {demon, 1},
262  {ghost, 1},
263  {haunt, 1},
264  {jinni, 1},
265  {phase, 1},
266  {shade, 1},
267  {spook, 1}}));
268  env.close();
269  env.require(owners(alice, features[featureMultiSignReserve] ? 1 : 10));
270 
271  // This should work.
272  auto const baseFee = env.current()->fees().base;
273  std::uint32_t aliceSeq = env.seq(alice);
274  env(noop(alice), msig(bogie), fee(2 * baseFee));
275  env.close();
276 
277  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
278 
279  // This should fail because the fee is too small.
280  aliceSeq = env.seq(alice);
281  env(noop(alice),
282  msig(bogie),
283  fee((2 * baseFee) - 1),
285  env.close();
286 
287  BEAST_EXPECT(env.seq(alice) == aliceSeq);
288 
289  // This should work.
290  aliceSeq = env.seq(alice);
291  env(noop(alice),
293  fee(9 * baseFee));
294  env.close();
295 
296  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
297 
298  // This should fail because the fee is too small.
299  aliceSeq = env.seq(alice);
300  env(noop(alice),
302  fee((9 * baseFee) - 1),
304  env.close();
305 
306  BEAST_EXPECT(env.seq(alice) == aliceSeq);
307  }
308 
309  void
311  {
312  testcase("Misordered Signers");
313 
314  using namespace jtx;
315  Env env{*this, features};
316  Account const alice{"alice", KeyType::ed25519};
317  env.fund(XRP(1000), alice);
318  env.close();
319 
320  // The signatures in a transaction must be submitted in sorted order.
321  // Make sure the transaction fails if they are not.
322  env(signers(alice, 1, {{bogie, 1}, {demon, 1}}));
323  env.close();
324  env.require(owners(alice, features[featureMultiSignReserve] ? 1 : 4));
325 
326  msig phantoms{bogie, demon};
327  std::reverse(phantoms.signers.begin(), phantoms.signers.end());
328  std::uint32_t const aliceSeq = env.seq(alice);
329  env(noop(alice), phantoms, ter(temINVALID));
330  env.close();
331  BEAST_EXPECT(env.seq(alice) == aliceSeq);
332  }
333 
334  void
336  {
337  testcase("Master Signers");
338 
339  using namespace jtx;
340  Env env{*this, features};
341  Account const alice{"alice", KeyType::ed25519};
342  Account const becky{"becky", KeyType::secp256k1};
343  Account const cheri{"cheri", KeyType::ed25519};
344  env.fund(XRP(1000), alice, becky, cheri);
345  env.close();
346 
347  // For a different situation, give alice a regular key but don't use it.
348  Account const alie{"alie", KeyType::secp256k1};
349  env(regkey(alice, alie));
350  env.close();
351  std::uint32_t aliceSeq = env.seq(alice);
352  env(noop(alice), sig(alice));
353  env(noop(alice), sig(alie));
354  env.close();
355  BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
356 
357  // Attach signers to alice
358  env(signers(alice, 4, {{becky, 3}, {cheri, 4}}), sig(alice));
359  env.close();
360  env.require(owners(alice, features[featureMultiSignReserve] ? 1 : 4));
361 
362  // Attempt a multisigned transaction that meets the quorum.
363  auto const baseFee = env.current()->fees().base;
364  aliceSeq = env.seq(alice);
365  env(noop(alice), msig(cheri), fee(2 * baseFee));
366  env.close();
367  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
368 
369  // If we don't meet the quorum the transaction should fail.
370  aliceSeq = env.seq(alice);
371  env(noop(alice), msig(becky), fee(2 * baseFee), ter(tefBAD_QUORUM));
372  env.close();
373  BEAST_EXPECT(env.seq(alice) == aliceSeq);
374 
375  // Give becky and cheri regular keys.
376  Account const beck{"beck", KeyType::ed25519};
377  env(regkey(becky, beck));
378  Account const cher{"cher", KeyType::ed25519};
379  env(regkey(cheri, cher));
380  env.close();
381 
382  // becky's and cheri's master keys should still work.
383  aliceSeq = env.seq(alice);
384  env(noop(alice), msig(becky, cheri), fee(3 * baseFee));
385  env.close();
386  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
387  }
388 
389  void
391  {
392  testcase("Regular Signers");
393 
394  using namespace jtx;
395  Env env{*this, features};
396  Account const alice{"alice", KeyType::secp256k1};
397  Account const becky{"becky", KeyType::ed25519};
398  Account const cheri{"cheri", KeyType::secp256k1};
399  env.fund(XRP(1000), alice, becky, cheri);
400  env.close();
401 
402  // Attach signers to alice.
403  env(signers(alice, 1, {{becky, 1}, {cheri, 1}}), sig(alice));
404 
405  // Give everyone regular keys.
406  Account const alie{"alie", KeyType::ed25519};
407  env(regkey(alice, alie));
408  Account const beck{"beck", KeyType::secp256k1};
409  env(regkey(becky, beck));
410  Account const cher{"cher", KeyType::ed25519};
411  env(regkey(cheri, cher));
412  env.close();
413 
414  // Disable cheri's master key to mix things up.
415  env(fset(cheri, asfDisableMaster), sig(cheri));
416  env.close();
417 
418  // Attempt a multisigned transaction that meets the quorum.
419  auto const baseFee = env.current()->fees().base;
420  std::uint32_t aliceSeq = env.seq(alice);
421  env(noop(alice), msig(msig::Reg{cheri, cher}), fee(2 * baseFee));
422  env.close();
423  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
424 
425  // cheri should not be able to multisign using her master key.
426  aliceSeq = env.seq(alice);
427  env(noop(alice),
428  msig(cheri),
429  fee(2 * baseFee),
431  env.close();
432  BEAST_EXPECT(env.seq(alice) == aliceSeq);
433 
434  // becky should be able to multisign using either of her keys.
435  aliceSeq = env.seq(alice);
436  env(noop(alice), msig(becky), fee(2 * baseFee));
437  env.close();
438  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
439 
440  aliceSeq = env.seq(alice);
441  env(noop(alice), msig(msig::Reg{becky, beck}), fee(2 * baseFee));
442  env.close();
443  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
444 
445  // Both becky and cheri should be able to sign using regular keys.
446  aliceSeq = env.seq(alice);
447  env(noop(alice),
448  fee(3 * baseFee),
449  msig(msig::Reg{becky, beck}, msig::Reg{cheri, cher}));
450  env.close();
451  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
452  }
453 
454  void
456  {
457  testcase("Regular Signers Using submit_multisigned");
458 
459  using namespace jtx;
460  Env env(
461  *this,
463  cfg->loadFromString("[" SECTION_SIGNING_SUPPORT "]\ntrue");
464  return cfg;
465  }),
466  features);
467  Account const alice{"alice", KeyType::secp256k1};
468  Account const becky{"becky", KeyType::ed25519};
469  Account const cheri{"cheri", KeyType::secp256k1};
470  env.fund(XRP(1000), alice, becky, cheri);
471  env.close();
472 
473  // Attach signers to alice.
474  env(signers(alice, 2, {{becky, 1}, {cheri, 1}}), sig(alice));
475 
476  // Give everyone regular keys.
477  Account const beck{"beck", KeyType::secp256k1};
478  env(regkey(becky, beck));
479  Account const cher{"cher", KeyType::ed25519};
480  env(regkey(cheri, cher));
481  env.close();
482 
483  // Disable cheri's master key to mix things up.
484  env(fset(cheri, asfDisableMaster), sig(cheri));
485  env.close();
486 
487  auto const baseFee = env.current()->fees().base;
488  std::uint32_t aliceSeq;
489 
490  // these represent oft-repeated setup for input json below
491  auto setup_tx = [&]() -> Json::Value {
492  Json::Value jv;
493  jv[jss::tx_json][jss::Account] = alice.human();
494  jv[jss::tx_json][jss::TransactionType] = jss::AccountSet;
495  jv[jss::tx_json][jss::Fee] = (8 * baseFee).jsonClipped();
496  jv[jss::tx_json][jss::Sequence] = env.seq(alice);
497  jv[jss::tx_json][jss::SigningPubKey] = "";
498  return jv;
499  };
500  auto cheri_sign = [&](Json::Value& jv) {
501  jv[jss::account] = cheri.human();
502  jv[jss::key_type] = "ed25519";
503  jv[jss::passphrase] = cher.name();
504  };
505  auto becky_sign = [&](Json::Value& jv) {
506  jv[jss::account] = becky.human();
507  jv[jss::secret] = beck.name();
508  };
509 
510  {
511  // Attempt a multisigned transaction that meets the quorum.
512  // using sign_for and submit_multisigned
513  aliceSeq = env.seq(alice);
514  Json::Value jv_one = setup_tx();
515  cheri_sign(jv_one);
516  auto jrr =
517  env.rpc("json", "sign_for", to_string(jv_one))[jss::result];
518  BEAST_EXPECT(jrr[jss::status] == "success");
519 
520  // for the second sign_for, use the returned tx_json with
521  // first signer info
522  Json::Value jv_two;
523  jv_two[jss::tx_json] = jrr[jss::tx_json];
524  becky_sign(jv_two);
525  jrr = env.rpc("json", "sign_for", to_string(jv_two))[jss::result];
526  BEAST_EXPECT(jrr[jss::status] == "success");
527 
528  Json::Value jv_submit;
529  jv_submit[jss::tx_json] = jrr[jss::tx_json];
530  jrr = env.rpc(
531  "json",
532  "submit_multisigned",
533  to_string(jv_submit))[jss::result];
534  BEAST_EXPECT(jrr[jss::status] == "success");
535  env.close();
536  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
537  }
538 
539  {
540  // failure case -- SigningPubKey not empty
541  aliceSeq = env.seq(alice);
542  Json::Value jv_one = setup_tx();
543  jv_one[jss::tx_json][jss::SigningPubKey] =
544  strHex(alice.pk().slice());
545  cheri_sign(jv_one);
546  auto jrr =
547  env.rpc("json", "sign_for", to_string(jv_one))[jss::result];
548  BEAST_EXPECT(jrr[jss::status] == "error");
549  BEAST_EXPECT(jrr[jss::error] == "invalidParams");
550  BEAST_EXPECT(
551  jrr[jss::error_message] ==
552  "When multi-signing 'tx_json.SigningPubKey' must be empty.");
553  }
554 
555  {
556  // failure case - bad fee
557  aliceSeq = env.seq(alice);
558  Json::Value jv_one = setup_tx();
559  jv_one[jss::tx_json][jss::Fee] = -1;
560  cheri_sign(jv_one);
561  auto jrr =
562  env.rpc("json", "sign_for", to_string(jv_one))[jss::result];
563  BEAST_EXPECT(jrr[jss::status] == "success");
564 
565  // for the second sign_for, use the returned tx_json with
566  // first signer info
567  Json::Value jv_two;
568  jv_two[jss::tx_json] = jrr[jss::tx_json];
569  becky_sign(jv_two);
570  jrr = env.rpc("json", "sign_for", to_string(jv_two))[jss::result];
571  BEAST_EXPECT(jrr[jss::status] == "success");
572 
573  Json::Value jv_submit;
574  jv_submit[jss::tx_json] = jrr[jss::tx_json];
575  jrr = env.rpc(
576  "json",
577  "submit_multisigned",
578  to_string(jv_submit))[jss::result];
579  BEAST_EXPECT(jrr[jss::status] == "error");
580  BEAST_EXPECT(jrr[jss::error] == "invalidParams");
581  BEAST_EXPECT(
582  jrr[jss::error_message] ==
583  "Invalid Fee field. Fees must be greater than zero.");
584  }
585 
586  {
587  // failure case - bad fee v2
588  aliceSeq = env.seq(alice);
589  Json::Value jv_one = setup_tx();
590  jv_one[jss::tx_json][jss::Fee] =
591  alice["USD"](10).value().getFullText();
592  cheri_sign(jv_one);
593  auto jrr =
594  env.rpc("json", "sign_for", to_string(jv_one))[jss::result];
595  BEAST_EXPECT(jrr[jss::status] == "success");
596 
597  // for the second sign_for, use the returned tx_json with
598  // first signer info
599  Json::Value jv_two;
600  jv_two[jss::tx_json] = jrr[jss::tx_json];
601  becky_sign(jv_two);
602  jrr = env.rpc("json", "sign_for", to_string(jv_two))[jss::result];
603  BEAST_EXPECT(jrr[jss::status] == "success");
604 
605  Json::Value jv_submit;
606  jv_submit[jss::tx_json] = jrr[jss::tx_json];
607  jrr = env.rpc(
608  "json",
609  "submit_multisigned",
610  to_string(jv_submit))[jss::result];
611  BEAST_EXPECT(jrr[jss::status] == "error");
612  BEAST_EXPECT(jrr[jss::error] == "internal");
613  BEAST_EXPECT(jrr[jss::error_message] == "Internal error.");
614  }
615 
616  {
617  // cheri should not be able to multisign using her master key.
618  aliceSeq = env.seq(alice);
619  Json::Value jv = setup_tx();
620  jv[jss::account] = cheri.human();
621  jv[jss::secret] = cheri.name();
622  auto jrr = env.rpc("json", "sign_for", to_string(jv))[jss::result];
623  BEAST_EXPECT(jrr[jss::status] == "error");
624  BEAST_EXPECT(jrr[jss::error] == "masterDisabled");
625  env.close();
626  BEAST_EXPECT(env.seq(alice) == aliceSeq);
627  }
628 
629  {
630  // Unlike cheri, becky should also be able to sign using her master
631  // key
632  aliceSeq = env.seq(alice);
633  Json::Value jv_one = setup_tx();
634  cheri_sign(jv_one);
635  auto jrr =
636  env.rpc("json", "sign_for", to_string(jv_one))[jss::result];
637  BEAST_EXPECT(jrr[jss::status] == "success");
638 
639  // for the second sign_for, use the returned tx_json with
640  // first signer info
641  Json::Value jv_two;
642  jv_two[jss::tx_json] = jrr[jss::tx_json];
643  jv_two[jss::account] = becky.human();
644  jv_two[jss::key_type] = "ed25519";
645  jv_two[jss::passphrase] = becky.name();
646  jrr = env.rpc("json", "sign_for", to_string(jv_two))[jss::result];
647  BEAST_EXPECT(jrr[jss::status] == "success");
648 
649  Json::Value jv_submit;
650  jv_submit[jss::tx_json] = jrr[jss::tx_json];
651  jrr = env.rpc(
652  "json",
653  "submit_multisigned",
654  to_string(jv_submit))[jss::result];
655  BEAST_EXPECT(jrr[jss::status] == "success");
656  env.close();
657  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
658  }
659 
660  {
661  // check for bad or bogus accounts in the tx
662  Json::Value jv = setup_tx();
663  jv[jss::tx_json][jss::Account] = "DEADBEEF";
664  cheri_sign(jv);
665  auto jrr = env.rpc("json", "sign_for", to_string(jv))[jss::result];
666  BEAST_EXPECT(jrr[jss::status] == "error");
667  BEAST_EXPECT(jrr[jss::error] == "srcActMalformed");
668 
669  Account const jimmy{"jimmy"};
670  jv[jss::tx_json][jss::Account] = jimmy.human();
671  jrr = env.rpc("json", "sign_for", to_string(jv))[jss::result];
672  BEAST_EXPECT(jrr[jss::status] == "error");
673  BEAST_EXPECT(jrr[jss::error] == "srcActNotFound");
674  }
675 
676  {
677  aliceSeq = env.seq(alice);
678  Json::Value jv = setup_tx();
679  jv[jss::tx_json][sfSigners.fieldName] =
681  becky_sign(jv);
682  auto jrr = env.rpc(
683  "json", "submit_multisigned", to_string(jv))[jss::result];
684  BEAST_EXPECT(jrr[jss::status] == "error");
685  BEAST_EXPECT(jrr[jss::error] == "invalidParams");
686  BEAST_EXPECT(
687  jrr[jss::error_message] ==
688  "tx_json.Signers array may not be empty.");
689  env.close();
690  BEAST_EXPECT(env.seq(alice) == aliceSeq);
691  }
692  }
693 
694  void
696  {
697  testcase("Heterogenious Signers");
698 
699  using namespace jtx;
700  Env env{*this, features};
701  Account const alice{"alice", KeyType::secp256k1};
702  Account const becky{"becky", KeyType::ed25519};
703  Account const cheri{"cheri", KeyType::secp256k1};
704  Account const daria{"daria", KeyType::ed25519};
705  env.fund(XRP(1000), alice, becky, cheri, daria);
706  env.close();
707 
708  // alice uses a regular key with the master disabled.
709  Account const alie{"alie", KeyType::secp256k1};
710  env(regkey(alice, alie));
711  env(fset(alice, asfDisableMaster), sig(alice));
712 
713  // becky is master only without a regular key.
714 
715  // cheri has a regular key, but leaves the master key enabled.
716  Account const cher{"cher", KeyType::secp256k1};
717  env(regkey(cheri, cher));
718 
719  // daria has a regular key and disables her master key.
720  Account const dari{"dari", KeyType::ed25519};
721  env(regkey(daria, dari));
722  env(fset(daria, asfDisableMaster), sig(daria));
723  env.close();
724 
725  // Attach signers to alice.
726  env(signers(alice, 1, {{becky, 1}, {cheri, 1}, {daria, 1}, {jinni, 1}}),
727  sig(alie));
728  env.close();
729  env.require(owners(alice, features[featureMultiSignReserve] ? 1 : 6));
730 
731  // Each type of signer should succeed individually.
732  auto const baseFee = env.current()->fees().base;
733  std::uint32_t aliceSeq = env.seq(alice);
734  env(noop(alice), msig(becky), fee(2 * baseFee));
735  env.close();
736  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
737 
738  aliceSeq = env.seq(alice);
739  env(noop(alice), msig(cheri), fee(2 * baseFee));
740  env.close();
741  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
742 
743  aliceSeq = env.seq(alice);
744  env(noop(alice), msig(msig::Reg{cheri, cher}), fee(2 * baseFee));
745  env.close();
746  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
747 
748  aliceSeq = env.seq(alice);
749  env(noop(alice), msig(msig::Reg{daria, dari}), fee(2 * baseFee));
750  env.close();
751  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
752 
753  aliceSeq = env.seq(alice);
754  env(noop(alice), msig(jinni), fee(2 * baseFee));
755  env.close();
756  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
757 
758  // Should also work if all signers sign.
759  aliceSeq = env.seq(alice);
760  env(noop(alice),
761  fee(5 * baseFee),
762  msig(becky, msig::Reg{cheri, cher}, msig::Reg{daria, dari}, jinni));
763  env.close();
764  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
765 
766  // Require all signers to sign.
767  env(signers(
768  alice,
769  0x3FFFC,
770  {{becky, 0xFFFF},
771  {cheri, 0xFFFF},
772  {daria, 0xFFFF},
773  {jinni, 0xFFFF}}),
774  sig(alie));
775  env.close();
776  env.require(owners(alice, features[featureMultiSignReserve] ? 1 : 6));
777 
778  aliceSeq = env.seq(alice);
779  env(noop(alice),
780  fee(9 * baseFee),
781  msig(becky, msig::Reg{cheri, cher}, msig::Reg{daria, dari}, jinni));
782  env.close();
783  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
784 
785  // Try cheri with both key types.
786  aliceSeq = env.seq(alice);
787  env(noop(alice),
788  fee(5 * baseFee),
789  msig(becky, cheri, msig::Reg{daria, dari}, jinni));
790  env.close();
791  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
792 
793  // Makes sure the maximum allowed number of signers works.
794  env(signers(
795  alice,
796  0x7FFF8,
797  {{becky, 0xFFFF},
798  {cheri, 0xFFFF},
799  {daria, 0xFFFF},
800  {haunt, 0xFFFF},
801  {jinni, 0xFFFF},
802  {phase, 0xFFFF},
803  {shade, 0xFFFF},
804  {spook, 0xFFFF}}),
805  sig(alie));
806  env.close();
807  env.require(owners(alice, features[featureMultiSignReserve] ? 1 : 10));
808 
809  aliceSeq = env.seq(alice);
810  env(noop(alice),
811  fee(9 * baseFee),
812  msig(
813  becky,
814  msig::Reg{cheri, cher},
815  msig::Reg{daria, dari},
816  haunt,
817  jinni,
818  phase,
819  shade,
820  spook));
821  env.close();
822  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
823 
824  // One signer short should fail.
825  aliceSeq = env.seq(alice);
826  env(noop(alice),
827  msig(becky, cheri, haunt, jinni, phase, shade, spook),
828  fee(8 * baseFee),
829  ter(tefBAD_QUORUM));
830  env.close();
831  BEAST_EXPECT(env.seq(alice) == aliceSeq);
832 
833  // Remove alice's signer list and get the owner count back.
834  env(signers(alice, jtx::none), sig(alie));
835  env.close();
836  env.require(owners(alice, 0));
837  }
838 
839  // We want to always leave an account signable. Make sure the that we
840  // disallow removing the last way a transaction may be signed.
841  void
843  {
844  testcase("Key Disable");
845 
846  using namespace jtx;
847  Env env{*this, features};
848  Account const alice{"alice", KeyType::ed25519};
849  env.fund(XRP(1000), alice);
850 
851  // There are three negative tests we need to make:
852  // M0. A lone master key cannot be disabled.
853  // R0. A lone regular key cannot be removed.
854  // L0. A lone signer list cannot be removed.
855  //
856  // Additionally, there are 6 positive tests we need to make:
857  // M1. The master key can be disabled if there's a regular key.
858  // M2. The master key can be disabled if there's a signer list.
859  //
860  // R1. The regular key can be removed if there's a signer list.
861  // R2. The regular key can be removed if the master key is enabled.
862  //
863  // L1. The signer list can be removed if the master key is enabled.
864  // L2. The signer list can be removed if there's a regular key.
865 
866  // Master key tests.
867  // M0: A lone master key cannot be disabled.
868  env(fset(alice, asfDisableMaster),
869  sig(alice),
871 
872  // Add a regular key.
873  Account const alie{"alie", KeyType::ed25519};
874  env(regkey(alice, alie));
875 
876  // M1: The master key can be disabled if there's a regular key.
877  env(fset(alice, asfDisableMaster), sig(alice));
878 
879  // R0: A lone regular key cannot be removed.
880  env(regkey(alice, disabled), sig(alie), ter(tecNO_ALTERNATIVE_KEY));
881 
882  // Add a signer list.
883  env(signers(alice, 1, {{bogie, 1}}), sig(alie));
884 
885  // R1: The regular key can be removed if there's a signer list.
886  env(regkey(alice, disabled), sig(alie));
887 
888  // L0: A lone signer list cannot be removed.
889  auto const baseFee = env.current()->fees().base;
890  env(signers(alice, jtx::none),
891  msig(bogie),
892  fee(2 * baseFee),
894 
895  // Enable the master key.
896  env(fclear(alice, asfDisableMaster), msig(bogie), fee(2 * baseFee));
897 
898  // L1: The signer list can be removed if the master key is enabled.
899  env(signers(alice, jtx::none), msig(bogie), fee(2 * baseFee));
900 
901  // Add a signer list.
902  env(signers(alice, 1, {{bogie, 1}}), sig(alice));
903 
904  // M2: The master key can be disabled if there's a signer list.
905  env(fset(alice, asfDisableMaster), sig(alice));
906 
907  // Add a regular key.
908  env(regkey(alice, alie), msig(bogie), fee(2 * baseFee));
909 
910  // L2: The signer list can be removed if there's a regular key.
911  env(signers(alice, jtx::none), sig(alie));
912 
913  // Enable the master key.
914  env(fclear(alice, asfDisableMaster), sig(alie));
915 
916  // R2: The regular key can be removed if the master key is enabled.
917  env(regkey(alice, disabled), sig(alie));
918  }
919 
920  // Verify that the first regular key can be made for free using the
921  // master key, but not when multisigning.
922  void
924  {
925  testcase("Regular Key");
926 
927  using namespace jtx;
928  Env env{*this, features};
929  Account const alice{"alice", KeyType::secp256k1};
930  env.fund(XRP(1000), alice);
931 
932  // Give alice a regular key with a zero fee. Should succeed. Once.
933  Account const alie{"alie", KeyType::ed25519};
934  env(regkey(alice, alie), sig(alice), fee(0));
935 
936  // Try it again and creating the regular key for free should fail.
937  Account const liss{"liss", KeyType::secp256k1};
938  env(regkey(alice, liss), sig(alice), fee(0), ter(telINSUF_FEE_P));
939 
940  // But paying to create a regular key should succeed.
941  env(regkey(alice, liss), sig(alice));
942 
943  // In contrast, trying to multisign for a regular key with a zero
944  // fee should always fail. Even the first time.
945  Account const becky{"becky", KeyType::ed25519};
946  env.fund(XRP(1000), becky);
947 
948  env(signers(becky, 1, {{alice, 1}}), sig(becky));
949  env(regkey(becky, alie), msig(alice), fee(0), ter(telINSUF_FEE_P));
950 
951  // Using the master key to sign for a regular key for free should
952  // still work.
953  env(regkey(becky, alie), sig(becky), fee(0));
954  }
955 
956  // See if every kind of transaction can be successfully multi-signed.
957  void
959  {
960  testcase("Transaction Types");
961 
962  using namespace jtx;
963  Env env{*this, features};
964  Account const alice{"alice", KeyType::secp256k1};
965  Account const becky{"becky", KeyType::ed25519};
966  Account const zelda{"zelda", KeyType::secp256k1};
967  Account const gw{"gw"};
968  auto const USD = gw["USD"];
969  env.fund(XRP(1000), alice, becky, zelda, gw);
970  env.close();
971 
972  // alice uses a regular key with the master disabled.
973  Account const alie{"alie", KeyType::secp256k1};
974  env(regkey(alice, alie));
975  env(fset(alice, asfDisableMaster), sig(alice));
976 
977  // Attach signers to alice.
978  env(signers(alice, 2, {{becky, 1}, {bogie, 1}}), sig(alie));
979  env.close();
980  int const signerListOwners{features[featureMultiSignReserve] ? 1 : 4};
981  env.require(owners(alice, signerListOwners + 0));
982 
983  // Multisign a ttPAYMENT.
984  auto const baseFee = env.current()->fees().base;
985  std::uint32_t aliceSeq = env.seq(alice);
986  env(pay(alice, env.master, XRP(1)),
987  msig(becky, bogie),
988  fee(3 * baseFee));
989  env.close();
990  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
991 
992  // Multisign a ttACCOUNT_SET.
993  aliceSeq = env.seq(alice);
994  env(noop(alice), msig(becky, bogie), fee(3 * baseFee));
995  env.close();
996  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
997 
998  // Multisign a ttREGULAR_KEY_SET.
999  aliceSeq = env.seq(alice);
1000  Account const ace{"ace", KeyType::secp256k1};
1001  env(regkey(alice, ace), msig(becky, bogie), fee(3 * baseFee));
1002  env.close();
1003  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1004 
1005  // Multisign a ttTRUST_SET
1006  env(trust("alice", USD(100)),
1007  msig(becky, bogie),
1008  fee(3 * baseFee),
1009  require(lines("alice", 1)));
1010  env.close();
1011  env.require(owners(alice, signerListOwners + 1));
1012 
1013  // Multisign a ttOFFER_CREATE transaction.
1014  env(pay(gw, alice, USD(50)));
1015  env.close();
1016  env.require(balance(alice, USD(50)));
1017  env.require(balance(gw, alice["USD"](-50)));
1018 
1019  std::uint32_t const offerSeq = env.seq(alice);
1020  env(offer(alice, XRP(50), USD(50)),
1021  msig(becky, bogie),
1022  fee(3 * baseFee));
1023  env.close();
1024  env.require(owners(alice, signerListOwners + 2));
1025 
1026  // Now multisign a ttOFFER_CANCEL canceling the offer we just created.
1027  {
1028  aliceSeq = env.seq(alice);
1029  Json::Value cancelOffer;
1030  cancelOffer[jss::Account] = alice.human();
1031  cancelOffer[jss::OfferSequence] = offerSeq;
1032  cancelOffer[jss::TransactionType] = jss::OfferCancel;
1033  env(cancelOffer,
1034  seq(aliceSeq),
1035  msig(becky, bogie),
1036  fee(3 * baseFee));
1037  env.close();
1038  BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1039  env.require(owners(alice, signerListOwners + 1));
1040  }
1041 
1042  // Multisign a ttSIGNER_LIST_SET.
1043  env(signers(alice, 3, {{becky, 1}, {bogie, 1}, {demon, 1}}),
1044  msig(becky, bogie),
1045  fee(3 * baseFee));
1046  env.close();
1047  env.require(owners(alice, features[featureMultiSignReserve] ? 2 : 6));
1048  }
1049 
1050  void
1052  {
1053  testcase("Bad Signature Text");
1054 
1055  // Verify that the text returned for signature failures is correct.
1056  using namespace jtx;
1057 
1058  Env env{*this, features};
1059 
1060  // lambda that submits an STTx and returns the resulting JSON.
1061  auto submitSTTx = [&env](STTx const& stx) {
1062  Json::Value jvResult;
1063  jvResult[jss::tx_blob] = strHex(stx.getSerializer().slice());
1064  return env.rpc("json", "submit", to_string(jvResult));
1065  };
1066 
1067  Account const alice{"alice"};
1068  env.fund(XRP(1000), alice);
1069  env(signers(alice, 1, {{bogie, 1}, {demon, 1}}), sig(alice));
1070 
1071  auto const baseFee = env.current()->fees().base;
1072  {
1073  // Single-sign, but leave an empty SigningPubKey.
1074  JTx tx = env.jt(noop(alice), sig(alice));
1075  STTx local = *(tx.stx);
1076  local.setFieldVL(sfSigningPubKey, Blob()); // Empty SigningPubKey
1077  auto const info = submitSTTx(local);
1078  BEAST_EXPECT(
1079  info[jss::result][jss::error_exception] ==
1080  "fails local checks: Empty SigningPubKey.");
1081  }
1082  {
1083  // Single-sign, but invalidate the signature.
1084  JTx tx = env.jt(noop(alice), sig(alice));
1085  STTx local = *(tx.stx);
1086  // Flip some bits in the signature.
1087  auto badSig = local.getFieldVL(sfTxnSignature);
1088  badSig[20] ^= 0xAA;
1089  local.setFieldVL(sfTxnSignature, badSig);
1090  // Signature should fail.
1091  auto const info = submitSTTx(local);
1092  BEAST_EXPECT(
1093  info[jss::result][jss::error_exception] ==
1094  "fails local checks: Invalid signature.");
1095  }
1096  {
1097  // Single-sign, but invalidate the sequence number.
1098  JTx tx = env.jt(noop(alice), sig(alice));
1099  STTx local = *(tx.stx);
1100  // Flip some bits in the signature.
1101  auto seq = local.getFieldU32(sfSequence);
1102  local.setFieldU32(sfSequence, seq + 1);
1103  // Signature should fail.
1104  auto const info = submitSTTx(local);
1105  BEAST_EXPECT(
1106  info[jss::result][jss::error_exception] ==
1107  "fails local checks: Invalid signature.");
1108  }
1109  {
1110  // Multisign, but leave a nonempty sfSigningPubKey.
1111  JTx tx = env.jt(noop(alice), fee(2 * baseFee), msig(bogie));
1112  STTx local = *(tx.stx);
1113  local[sfSigningPubKey] = alice.pk(); // Insert sfSigningPubKey
1114  auto const info = submitSTTx(local);
1115  BEAST_EXPECT(
1116  info[jss::result][jss::error_exception] ==
1117  "fails local checks: Cannot both single- and multi-sign.");
1118  }
1119  {
1120  // Both multi- and single-sign with an empty SigningPubKey.
1121  JTx tx = env.jt(noop(alice), fee(2 * baseFee), msig(bogie));
1122  STTx local = *(tx.stx);
1123  local.sign(alice.pk(), alice.sk());
1124  local.setFieldVL(sfSigningPubKey, Blob()); // Empty SigningPubKey
1125  auto const info = submitSTTx(local);
1126  BEAST_EXPECT(
1127  info[jss::result][jss::error_exception] ==
1128  "fails local checks: Cannot both single- and multi-sign.");
1129  }
1130  {
1131  // Multisign but invalidate one of the signatures.
1132  JTx tx = env.jt(noop(alice), fee(2 * baseFee), msig(bogie));
1133  STTx local = *(tx.stx);
1134  // Flip some bits in the signature.
1135  auto& signer = local.peekFieldArray(sfSigners).back();
1136  auto badSig = signer.getFieldVL(sfTxnSignature);
1137  badSig[20] ^= 0xAA;
1138  signer.setFieldVL(sfTxnSignature, badSig);
1139  // Signature should fail.
1140  auto const info = submitSTTx(local);
1141  BEAST_EXPECT(
1142  info[jss::result][jss::error_exception].asString().find(
1143  "Invalid signature on account r") != std::string::npos);
1144  }
1145  {
1146  // Multisign with an empty signers array should fail.
1147  JTx tx = env.jt(noop(alice), fee(2 * baseFee), msig(bogie));
1148  STTx local = *(tx.stx);
1149  local.peekFieldArray(sfSigners).clear(); // Empty Signers array.
1150  auto const info = submitSTTx(local);
1151  BEAST_EXPECT(
1152  info[jss::result][jss::error_exception] ==
1153  "fails local checks: Invalid Signers array size.");
1154  }
1155  {
1156  // Multisign 9 times should fail.
1157  JTx tx = env.jt(
1158  noop(alice),
1159  fee(2 * baseFee),
1160  msig(
1161  bogie,
1162  bogie,
1163  bogie,
1164  bogie,
1165  bogie,
1166  bogie,
1167  bogie,
1168  bogie,
1169  bogie));
1170  STTx local = *(tx.stx);
1171  auto const info = submitSTTx(local);
1172  BEAST_EXPECT(
1173  info[jss::result][jss::error_exception] ==
1174  "fails local checks: Invalid Signers array size.");
1175  }
1176  {
1177  // The account owner may not multisign for themselves.
1178  JTx tx = env.jt(noop(alice), fee(2 * baseFee), msig(alice));
1179  STTx local = *(tx.stx);
1180  auto const info = submitSTTx(local);
1181  BEAST_EXPECT(
1182  info[jss::result][jss::error_exception] ==
1183  "fails local checks: Invalid multisigner.");
1184  }
1185  {
1186  // No duplicate multisignatures allowed.
1187  JTx tx = env.jt(noop(alice), fee(2 * baseFee), msig(bogie, bogie));
1188  STTx local = *(tx.stx);
1189  auto const info = submitSTTx(local);
1190  BEAST_EXPECT(
1191  info[jss::result][jss::error_exception] ==
1192  "fails local checks: Duplicate Signers not allowed.");
1193  }
1194  {
1195  // Multisignatures must be submitted in sorted order.
1196  JTx tx = env.jt(noop(alice), fee(2 * baseFee), msig(bogie, demon));
1197  STTx local = *(tx.stx);
1198  // Unsort the Signers array.
1199  auto& signers = local.peekFieldArray(sfSigners);
1200  std::reverse(signers.begin(), signers.end());
1201  // Signature should fail.
1202  auto const info = submitSTTx(local);
1203  BEAST_EXPECT(
1204  info[jss::result][jss::error_exception] ==
1205  "fails local checks: Unsorted Signers array.");
1206  }
1207  }
1208 
1209  void
1211  {
1212  testcase("No Multisigners");
1213 
1214  using namespace jtx;
1215  Env env{*this, features};
1216  Account const alice{"alice", KeyType::ed25519};
1217  Account const becky{"becky", KeyType::secp256k1};
1218  env.fund(XRP(1000), alice, becky);
1219  env.close();
1220 
1221  auto const baseFee = env.current()->fees().base;
1222  env(noop(alice),
1223  msig(becky, demon),
1224  fee(3 * baseFee),
1226  }
1227 
1228  void
1230  {
1231  testcase("Multisigning multisigner");
1232 
1233  // Set up a signer list where one of the signers has both the
1234  // master disabled and no regular key (because that signer is
1235  // exclusively multisigning). That signer should no longer be
1236  // able to successfully sign the signer list.
1237 
1238  using namespace jtx;
1239  Env env{*this, features};
1240  Account const alice{"alice", KeyType::ed25519};
1241  Account const becky{"becky", KeyType::secp256k1};
1242  env.fund(XRP(1000), alice, becky);
1243  env.close();
1244 
1245  // alice sets up a signer list with becky as a signer.
1246  env(signers(alice, 1, {{becky, 1}}));
1247  env.close();
1248 
1249  // becky sets up her signer list.
1250  env(signers(becky, 1, {{bogie, 1}, {demon, 1}}));
1251  env.close();
1252 
1253  // Because becky has not (yet) disabled her master key, she can
1254  // multisign a transaction for alice.
1255  auto const baseFee = env.current()->fees().base;
1256  env(noop(alice), msig(becky), fee(2 * baseFee));
1257  env.close();
1258 
1259  // Now becky disables her master key.
1260  env(fset(becky, asfDisableMaster));
1261  env.close();
1262 
1263  // Since becky's master key is disabled she can no longer
1264  // multisign for alice.
1265  env(noop(alice),
1266  msig(becky),
1267  fee(2 * baseFee),
1269  env.close();
1270 
1271  // Becky cannot 2-level multisign for alice. 2-level multisigning
1272  // is not supported.
1273  env(noop(alice),
1274  msig(msig::Reg{becky, bogie}),
1275  fee(2 * baseFee),
1277  env.close();
1278 
1279  // Verify that becky cannot sign with a regular key that she has
1280  // not yet enabled.
1281  Account const beck{"beck", KeyType::ed25519};
1282  env(noop(alice),
1283  msig(msig::Reg{becky, beck}),
1284  fee(2 * baseFee),
1286  env.close();
1287 
1288  // Once becky gives herself the regular key, she can sign for alice
1289  // using that regular key.
1290  env(regkey(becky, beck), msig(demon), fee(2 * baseFee));
1291  env.close();
1292 
1293  env(noop(alice), msig(msig::Reg{becky, beck}), fee(2 * baseFee));
1294  env.close();
1295 
1296  // The presence of becky's regular key does not influence whether she
1297  // can 2-level multisign; it still won't work.
1298  env(noop(alice),
1299  msig(msig::Reg{becky, demon}),
1300  fee(2 * baseFee),
1302  env.close();
1303  }
1304 
1305  void
1307  {
1308  testcase("sign_for Hash");
1309 
1310  // Make sure that the "hash" field returned by the "sign_for" RPC
1311  // command matches the hash returned when that command is sent
1312  // through "submit_multisigned". Make sure that hash also locates
1313  // the transaction in the ledger.
1314  using namespace jtx;
1315  Account const alice{"alice", KeyType::ed25519};
1316 
1317  Env env(
1318  *this,
1320  cfg->loadFromString("[" SECTION_SIGNING_SUPPORT "]\ntrue");
1321  return cfg;
1322  }),
1323  features);
1324  env.fund(XRP(1000), alice);
1325  env.close();
1326 
1327  env(signers(alice, 2, {{bogie, 1}, {ghost, 1}}));
1328  env.close();
1329 
1330  // Use sign_for to sign a transaction where alice pays 10 XRP to
1331  // masterpassphrase.
1332  auto const baseFee = env.current()->fees().base;
1333  Json::Value jvSig1;
1334  jvSig1[jss::account] = bogie.human();
1335  jvSig1[jss::secret] = bogie.name();
1336  jvSig1[jss::tx_json][jss::Account] = alice.human();
1337  jvSig1[jss::tx_json][jss::Amount] = 10000000;
1338  jvSig1[jss::tx_json][jss::Destination] = env.master.human();
1339  jvSig1[jss::tx_json][jss::Fee] = (3 * baseFee).jsonClipped();
1340  jvSig1[jss::tx_json][jss::Sequence] = env.seq(alice);
1341  jvSig1[jss::tx_json][jss::TransactionType] = jss::Payment;
1342 
1343  Json::Value jvSig2 = env.rpc("json", "sign_for", to_string(jvSig1));
1344  BEAST_EXPECT(jvSig2[jss::result][jss::status].asString() == "success");
1345 
1346  // Save the hash with one signature for use later.
1347  std::string const hash1 =
1348  jvSig2[jss::result][jss::tx_json][jss::hash].asString();
1349 
1350  // Add the next signature and sign again.
1351  jvSig2[jss::result][jss::account] = ghost.human();
1352  jvSig2[jss::result][jss::secret] = ghost.name();
1353  Json::Value jvSubmit =
1354  env.rpc("json", "sign_for", to_string(jvSig2[jss::result]));
1355  BEAST_EXPECT(
1356  jvSubmit[jss::result][jss::status].asString() == "success");
1357 
1358  // Save the hash with two signatures for use later.
1359  std::string const hash2 =
1360  jvSubmit[jss::result][jss::tx_json][jss::hash].asString();
1361  BEAST_EXPECT(hash1 != hash2);
1362 
1363  // Submit the result of the two signatures.
1364  Json::Value jvResult = env.rpc(
1365  "json", "submit_multisigned", to_string(jvSubmit[jss::result]));
1366  BEAST_EXPECT(
1367  jvResult[jss::result][jss::status].asString() == "success");
1368  BEAST_EXPECT(
1369  jvResult[jss::result][jss::engine_result].asString() ==
1370  "tesSUCCESS");
1371 
1372  // The hash from the submit should be the same as the hash from the
1373  // second signing.
1374  BEAST_EXPECT(
1375  hash2 == jvResult[jss::result][jss::tx_json][jss::hash].asString());
1376  env.close();
1377 
1378  // The transaction we just submitted should now be available and
1379  // validated.
1380  Json::Value jvTx = env.rpc("tx", hash2);
1381  BEAST_EXPECT(jvTx[jss::result][jss::status].asString() == "success");
1382  BEAST_EXPECT(jvTx[jss::result][jss::validated].asString() == "true");
1383  BEAST_EXPECT(
1384  jvTx[jss::result][jss::meta][sfTransactionResult.jsonName]
1385  .asString() == "tesSUCCESS");
1386  }
1387 
1388  void
1390  {
1391  testcase("Amendment Transition");
1392 
1393  // The OwnerCount associated with a SignerList changes once the
1394  // featureMultiSignReserve amendment goes live. Create a couple
1395  // of signer lists before and after the amendment goes live and
1396  // verify that the OwnerCount is managed properly for all of them.
1397  using namespace jtx;
1398  Account const alice{"alice", KeyType::secp256k1};
1399  Account const becky{"becky", KeyType::ed25519};
1400  Account const cheri{"cheri", KeyType::secp256k1};
1401  Account const daria{"daria", KeyType::ed25519};
1402 
1404  env.fund(XRP(1000), alice, becky, cheri, daria);
1405  env.close();
1406 
1407  // Give alice and becky signer lists before the amendment goes live.
1408  env(signers(alice, 1, {{bogie, 1}}));
1409  env(signers(
1410  becky,
1411  1,
1412  {{bogie, 1},
1413  {demon, 1},
1414  {ghost, 1},
1415  {haunt, 1},
1416  {jinni, 1},
1417  {phase, 1},
1418  {shade, 1},
1419  {spook, 1}}));
1420  env.close();
1421 
1422  env.require(owners(alice, 3));
1423  env.require(owners(becky, 10));
1424 
1425  // Enable the amendment.
1426  env.enableFeature(featureMultiSignReserve);
1427  env.close();
1428 
1429  // Give cheri and daria signer lists after the amendment goes live.
1430  env(signers(cheri, 1, {{bogie, 1}}));
1431  env(signers(
1432  daria,
1433  1,
1434  {{bogie, 1},
1435  {demon, 1},
1436  {ghost, 1},
1437  {haunt, 1},
1438  {jinni, 1},
1439  {phase, 1},
1440  {shade, 1},
1441  {spook, 1}}));
1442  env.close();
1443 
1444  env.require(owners(alice, 3));
1445  env.require(owners(becky, 10));
1446  env.require(owners(cheri, 1));
1447  env.require(owners(daria, 1));
1448 
1449  // Delete becky's signer list; her OwnerCount should drop to zero.
1450  // Replace alice's signer list; her OwnerCount should drop to one.
1451  env(signers(becky, jtx::none));
1452  env(signers(
1453  alice,
1454  1,
1455  {{bogie, 1},
1456  {demon, 1},
1457  {ghost, 1},
1458  {haunt, 1},
1459  {jinni, 1},
1460  {phase, 1},
1461  {shade, 1},
1462  {spook, 1}}));
1463  env.close();
1464 
1465  env.require(owners(alice, 1));
1466  env.require(owners(becky, 0));
1467  env.require(owners(cheri, 1));
1468  env.require(owners(daria, 1));
1469 
1470  // Delete the three remaining signer lists. Everybody's OwnerCount
1471  // should now be zero.
1472  env(signers(alice, jtx::none));
1473  env(signers(cheri, jtx::none));
1474  env(signers(daria, jtx::none));
1475  env.close();
1476 
1477  env.require(owners(alice, 0));
1478  env.require(owners(becky, 0));
1479  env.require(owners(cheri, 0));
1480  env.require(owners(daria, 0));
1481  }
1482 
1483  void
1485  {
1486  testcase("Signers With Tickets");
1487 
1488  using namespace jtx;
1489  Env env{*this, features};
1490  Account const alice{"alice", KeyType::ed25519};
1491  env.fund(XRP(2000), alice);
1492  env.close();
1493 
1494  // If featureTicketBatch is not enabled expect massive failures.
1495  BEAST_EXPECT(features[featureTicketBatch]);
1496 
1497  // Create a few tickets that alice can use up.
1498  std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
1499  env(ticket::create(alice, 20));
1500  env.close();
1501  std::uint32_t const aliceSeq = env.seq(alice);
1502 
1503  // Attach phantom signers to alice using a ticket.
1504  env(signers(alice, 1, {{bogie, 1}, {demon, 1}}),
1505  ticket::use(aliceTicketSeq++));
1506  env.close();
1507  env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1508  BEAST_EXPECT(env.seq(alice) == aliceSeq);
1509 
1510  // This should work.
1511  auto const baseFee = env.current()->fees().base;
1512  env(noop(alice),
1513  msig(bogie, demon),
1514  fee(3 * baseFee),
1515  ticket::use(aliceTicketSeq++));
1516  env.close();
1517  env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1518  BEAST_EXPECT(env.seq(alice) == aliceSeq);
1519 
1520  // Should also be able to remove the signer list using a ticket.
1521  env(signers(alice, jtx::none), ticket::use(aliceTicketSeq++));
1522  env.close();
1523  env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
1524  BEAST_EXPECT(env.seq(alice) == aliceSeq);
1525  }
1526 
1527  void
1529  {
1530  test_noReserve(features);
1531  test_signerListSet(features);
1532  test_phantomSigners(features);
1533  test_fee(features);
1534  test_misorderedSigners(features);
1535  test_masterSigners(features);
1536  test_regularSigners(features);
1538  test_heterogeneousSigners(features);
1539  test_keyDisable(features);
1540  test_regKey(features);
1541  test_txTypes(features);
1542  test_badSignatureText(features);
1543  test_noMultiSigners(features);
1544  test_multisigningMultisigner(features);
1545  test_signForHash(features);
1546  test_signersWithTickets(features);
1547  }
1548 
1549  void
1550  run() override
1551  {
1552  using namespace jtx;
1553  auto const all = supported_amendments() | featureTicketBatch;
1554 
1555  // The reserve required on a signer list changes based on.
1556  // featureMultiSignReserve. Test both with and without.
1560  }
1561 };
1562 
1563 BEAST_DEFINE_TESTSUITE(MultiSign, app, ripple);
1564 
1565 } // namespace test
1566 } // namespace ripple
ripple::test::MultiSign_test::haunt
const jtx::Account haunt
Definition: MultiSign_test.cpp:32
ripple::test::jtx::Account::name
std::string const & name() const
Return the name.
Definition: Account.h:78
ripple::test::jtx::noop
Json::Value noop(Account const &account)
The null transaction.
Definition: noop.h:31
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
ripple::Blob
std::vector< unsigned char > Blob
Storage for linear binary data.
Definition: Blob.h:30
ripple::test::MultiSign_test
Definition: MultiSign_test.cpp:26
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
std::string
STL class.
ripple::test::jtx::none
static const none_t none
Definition: tags.h:34
ripple::test::jtx::drops
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Definition: amount.h:241
ripple::test::MultiSign_test::ghost
const jtx::Account ghost
Definition: MultiSign_test.cpp:31
ripple::test::jtx::ter
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition: ter.h:33
ripple::sfSigners
const SField sfSigners(access, STI_ARRAY, 3, "Signers", SField::sMD_Default, SField::notSigning)
Definition: SField.h:517
ripple::test::jtx::owners
Match the number of items in the account's owner directory.
Definition: owners.h:69
ripple::test::MultiSign_test::test_misorderedSigners
void test_misorderedSigners(FeatureBitset features)
Definition: MultiSign_test.cpp:310
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
ripple::TxSearched::all
@ all
ripple::test::jtx::balance
A balance matches.
Definition: balance.h:38
ripple::sfSigningPubKey
const SF_Blob sfSigningPubKey(access, STI_VL, 3, "SigningPubKey")
Definition: SField.h:460
ripple::sfSequence
const SF_U32 sfSequence(access, STI_UINT32, 4, "Sequence")
Definition: SField.h:356
ripple::test::jtx::trust
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition: trust.cpp:30
ripple::SField::fieldName
const std::string fieldName
Definition: SField.h:129
ripple::test::jtx::JTx::stx
std::shared_ptr< STTx const > stx
Definition: JTx.h:49
ripple::test::jtx::require
Check a set of conditions.
Definition: require.h:63
ripple::test::jtx::Account::human
std::string const & human() const
Returns the human readable public key.
Definition: Account.h:109
ripple::featureMultiSignReserve
const uint256 featureMultiSignReserve
Definition: Feature.cpp:177
ripple::test::jtx::msig::Reg
Definition: multisign.h:61
ripple::test::MultiSign_test::test_multisigningMultisigner
void test_multisigningMultisigner(FeatureBitset features)
Definition: MultiSign_test.cpp:1229
std::reverse
T reverse(T... args)
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:42
ripple::STObject::setFieldVL
void setFieldVL(SField const &field, Blob const &)
Definition: STObject.cpp:668
ripple::STObject::getFieldVL
Blob getFieldVL(SField const &field) const
Definition: STObject.cpp:568
ripple::test::jtx::envconfig
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:49
ripple::test::MultiSign_test::test_signersWithTickets
void test_signersWithTickets(FeatureBitset features)
Definition: MultiSign_test.cpp:1484
ripple::SField::jsonName
const Json::StaticString jsonName
Definition: SField.h:133
ripple::test::jtx::msig
Set a multisignature on a JTx.
Definition: multisign.h:58
ripple::test::jtx::signer
A signer in a SignerList.
Definition: multisign.h:34
ripple::FeatureBitset::base
std::bitset< detail::FeatureCollections::numFeatures()> base
Definition: Feature.h:159
ripple::test::MultiSign_test::test_txTypes
void test_txTypes(FeatureBitset features)
Definition: MultiSign_test.cpp:958
ripple::tefBAD_QUORUM
@ tefBAD_QUORUM
Definition: TER.h:157
ripple::KeyType::ed25519
@ ed25519
ripple::test::jtx::ticket::use
Set a ticket sequence on a JTx.
Definition: ticket.h:47
ripple::temBAD_QUORUM
@ temBAD_QUORUM
Definition: TER.h:111
ripple::STArray::clear
void clear()
Definition: STArray.h:149
ripple::tecNO_ALTERNATIVE_KEY
@ tecNO_ALTERNATIVE_KEY
Definition: TER.h:257
ripple::test::MultiSign_test::demon
const jtx::Account demon
Definition: MultiSign_test.cpp:30
ripple::STObject::peekFieldArray
STArray & peekFieldArray(SField const &field)
Definition: STObject.cpp:418
ripple::tefMASTER_DISABLED
@ tefMASTER_DISABLED
Definition: TER.h:154
ripple::temBAD_SIGNER
@ temBAD_SIGNER
Definition: TER.h:110
ripple::test::jtx::JTx
Execution context for applying a JSON transaction.
Definition: JTx.h:41
ripple::test::MultiSign_test::test_regularSigners
void test_regularSigners(FeatureBitset features)
Definition: MultiSign_test.cpp:390
ripple::test::jtx::fset
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition: flags.cpp:28
ripple::test::MultiSign_test::test_fee
void test_fee(FeatureBitset features)
Definition: MultiSign_test.cpp:246
ripple::telINSUF_FEE_P
@ telINSUF_FEE_P
Definition: TER.h:56
ripple::sfTxnSignature
const SF_Blob sfTxnSignature(access, STI_VL, 4, "TxnSignature", SField::sMD_Default, SField::notSigning)
Definition: SField.h:461
ripple::test::MultiSign_test::test_amendmentTransition
void test_amendmentTransition()
Definition: MultiSign_test.cpp:1389
ripple::STTx
Definition: STTx.h:42
ripple::test::MultiSign_test::spook
const jtx::Account spook
Definition: MultiSign_test.cpp:36
ripple::test::jtx::supported_amendments
FeatureBitset supported_amendments()
Definition: Env.h:70
std::uint32_t
ripple::test::jtx::sig
Set the regular signature on a JTx.
Definition: sig.h:33
ripple::test::MultiSign_test::test_signForHash
void test_signForHash(FeatureBitset features)
Definition: MultiSign_test.cpp:1306
ripple::test::jtx::Env::seq
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Definition: Env.cpp:198
ripple::STTx::sign
void sign(PublicKey const &publicKey, SecretKey const &secretKey)
Definition: STTx.cpp:180
ripple::test::jtx::fclear
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition: flags.h:40
ripple::test::MultiSign_test::test_noReserve
void test_noReserve(FeatureBitset features)
Definition: MultiSign_test.cpp:40
ripple::test::jtx::fee
Set the fee on a JTx.
Definition: fee.h:34
ripple::STArray::back
STObject & back()
Definition: STArray.h:83
ripple::KeyType::secp256k1
@ secp256k1
ripple::test::MultiSign_test::test_regKey
void test_regKey(FeatureBitset features)
Definition: MultiSign_test.cpp:923
ripple::test::MultiSign_test::testAll
void testAll(FeatureBitset features)
Definition: MultiSign_test.cpp:1528
ripple::asfDisableMaster
const std::uint32_t asfDisableMaster
Definition: TxFlags.h:68
ripple::test::jtx::seq
Set the sequence number on a JTx.
Definition: seq.h:32
ripple::tefNOT_MULTI_SIGNING
@ tefNOT_MULTI_SIGNING
Definition: TER.h:158
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::MultiSign_test::test_badSignatureText
void test_badSignatureText(FeatureBitset features)
Definition: MultiSign_test.cpp:1051
ripple::test::MultiSign_test::test_phantomSigners
void test_phantomSigners(FeatureBitset features)
Definition: MultiSign_test.cpp:183
ripple::test::MultiSign_test::run
void run() override
Definition: MultiSign_test.cpp:1550
ripple::test::MultiSign_test::test_heterogeneousSigners
void test_heterogeneousSigners(FeatureBitset features)
Definition: MultiSign_test.cpp:695
ripple::test::MultiSign_test::shade
const jtx::Account shade
Definition: MultiSign_test.cpp:35
ripple::test::jtx::pay
Json::Value pay(Account const &account, Account const &to, AnyAmount amount)
Create a payment.
Definition: pay.cpp:29
ripple::test::MultiSign_test::test_keyDisable
void test_keyDisable(FeatureBitset features)
Definition: MultiSign_test.cpp:842
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:121
ripple::test::MultiSign_test::test_regularSignersUsingSubmitMulti
void test_regularSignersUsingSubmitMulti(FeatureBitset features)
Definition: MultiSign_test.cpp:455
ripple::test::jtx::regkey
Json::Value regkey(Account const &account, disabled_t)
Disable the regular key.
Definition: regkey.cpp:28
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:219
ripple::test::jtx::Env::master
Account const & master
Definition: Env.h:120
ripple::sfTransactionResult
const SF_U8 sfTransactionResult(access, STI_UINT8, 3, "TransactionResult")
Definition: SField.h:341
ripple::test::MultiSign_test::jinni
const jtx::Account jinni
Definition: MultiSign_test.cpp:33
ripple::FeatureBitset
Definition: Feature.h:156
ripple::tecINSUFFICIENT_RESERVE
@ tecINSUFFICIENT_RESERVE
Definition: TER.h:268
ripple::featureTicketBatch
const uint256 featureTicketBatch
Definition: Feature.cpp:189
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::test::MultiSign_test::test_masterSigners
void test_masterSigners(FeatureBitset features)
Definition: MultiSign_test.cpp:335
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:67
ripple::temMALFORMED
@ temMALFORMED
Definition: TER.h:82
ripple::STObject::getFieldU32
std::uint32_t getFieldU32(SField const &field) const
Definition: STObject.cpp:532
ripple::test::MultiSign_test::test_signerListSet
void test_signerListSet(FeatureBitset features)
Definition: MultiSign_test.cpp:110
std::unique_ptr
STL class.
ripple::STObject::setFieldU32
void setFieldU32(SField const &field, std::uint32_t)
Definition: STObject.cpp:632
ripple::test::jtx::Env::current
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:299
ripple::test::MultiSign_test::bogie
const jtx::Account bogie
Definition: MultiSign_test.cpp:29
ripple::test::MultiSign_test::phase
const jtx::Account phase
Definition: MultiSign_test.cpp:34
ripple::temBAD_WEIGHT
@ temBAD_WEIGHT
Definition: TER.h:112
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:115
ripple::temINVALID
@ temINVALID
Definition: TER.h:105
ripple::test::jtx::Env::rpc
Json::Value rpc(std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition: Env.h:684
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::test::MultiSign_test::test_noMultiSigners
void test_noMultiSigners(FeatureBitset features)
Definition: MultiSign_test.cpp:1210
ripple::test::jtx::owner_count
Definition: owners.h:49
ripple::tefBAD_SIGNATURE
@ tefBAD_SIGNATURE
Definition: TER.h:156
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469