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