rippled
Env.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #ifndef RIPPLE_TEST_JTX_ENV_H_INCLUDED
21 #define RIPPLE_TEST_JTX_ENV_H_INCLUDED
22 
23 #include <ripple/app/ledger/Ledger.h>
24 #include <ripple/app/ledger/OpenLedger.h>
25 #include <ripple/app/main/Application.h>
26 #include <ripple/app/paths/Pathfinder.h>
27 #include <ripple/basics/Log.h>
28 #include <ripple/basics/chrono.h>
29 #include <ripple/beast/utility/Journal.h>
30 #include <ripple/core/Config.h>
31 #include <ripple/json/json_value.h>
32 #include <ripple/json/to_string.h>
33 #include <ripple/ledger/CachedSLEs.h>
34 #include <ripple/protocol/Feature.h>
35 #include <ripple/protocol/Indexes.h>
36 #include <ripple/protocol/Issue.h>
37 #include <ripple/protocol/STAmount.h>
38 #include <ripple/protocol/STObject.h>
39 #include <ripple/protocol/STTx.h>
40 #include <functional>
41 #include <string>
42 #include <test/jtx/AbstractClient.h>
43 #include <test/jtx/Account.h>
44 #include <test/jtx/JTx.h>
45 #include <test/jtx/ManualTimeKeeper.h>
46 #include <test/jtx/amount.h>
47 #include <test/jtx/envconfig.h>
48 #include <test/jtx/require.h>
49 #include <test/jtx/tags.h>
50 #include <test/unit_test/SuiteJournal.h>
51 #include <tuple>
52 #include <type_traits>
53 #include <unordered_map>
54 #include <utility>
55 #include <vector>
56 
57 namespace ripple {
58 namespace test {
59 namespace jtx {
60 
62 template <class... Args>
63 std::array<Account, 1 + sizeof...(Args)>
64 noripple(Account const& account, Args const&... args)
65 {
66  return {{account, args...}};
67 }
68 
69 inline FeatureBitset
71 {
72  static const FeatureBitset ids = [] {
73  auto const& sa = ripple::detail::supportedAmendments();
75  feats.reserve(sa.size());
76  for (auto const& s : sa)
77  {
78  if (auto const f = getRegisteredFeature(s))
79  feats.push_back(*f);
80  else
81  Throw<std::runtime_error>(
82  "Unknown feature: " + s + " in supportedAmendments.");
83  }
84  return FeatureBitset(feats);
85  }();
86  return ids;
87 }
88 
89 //------------------------------------------------------------------------------
90 
91 class SuiteLogs : public Logs
92 {
93  beast::unit_test::suite& suite_;
94 
95 public:
96  explicit SuiteLogs(beast::unit_test::suite& suite)
97  : Logs(beast::severities::kError), suite_(suite)
98  {
99  }
100 
101  ~SuiteLogs() override = default;
102 
105  std::string const& partition,
107  {
108  return std::make_unique<SuiteJournalSink>(partition, threshold, suite_);
109  }
110 };
111 
112 //------------------------------------------------------------------------------
113 
115 class Env
116 {
117 public:
118  beast::unit_test::suite& test;
119 
121 
122 private:
123  struct AppBundle
124  {
125  Application* app = nullptr;
130 
131  AppBundle() = default;
132  AppBundle(
133  beast::unit_test::suite& suite,
137  ~AppBundle();
138  };
139 
141 
142 public:
144 
145  Env() = delete;
146  Env&
147  operator=(Env const&) = delete;
148  Env(Env const&) = delete;
149 
164  // VFALCO Could wrap the suite::log in a Journal here
165  Env(beast::unit_test::suite& suite_,
167  FeatureBitset features,
168  std::unique_ptr<Logs> logs = nullptr,
170  : test(suite_)
171  , bundle_(suite_, std::move(config), std::move(logs), thresh)
172  , journal{bundle_.app->journal("Env")}
173  {
177  features, [&appFeats = app().config().features](uint256 const& f) {
178  appFeats.insert(f);
179  });
180  }
181 
195  Env(beast::unit_test::suite& suite_, FeatureBitset features)
196  : Env(suite_, envconfig(), features)
197  {
198  }
199 
212  Env(beast::unit_test::suite& suite_,
214  std::unique_ptr<Logs> logs = nullptr,
216  : Env(suite_,
217  std::move(config),
219  std::move(logs),
220  thresh)
221  {
222  }
223 
233  Env(beast::unit_test::suite& suite_) : Env(suite_, envconfig())
234  {
235  }
236 
237  virtual ~Env() = default;
238 
239  Application&
240  app()
241  {
242  return *bundle_.app;
243  }
244 
245  Application const&
246  app() const
247  {
248  return *bundle_.app;
249  }
250 
253  {
254  return *bundle_.timeKeeper;
255  }
256 
263  now()
264  {
265  return timeKeeper().now();
266  }
267 
271  {
272  return *bundle_.client;
273  }
274 
280  template <class... Args>
283  std::string const& cmd,
284  Args&&... args);
285 
286  template <class... Args>
288  rpc(std::string const& cmd, Args&&... args);
289 
299  current() const
300  {
301  return app().openLedger().current();
302  }
303 
312  closed();
313 
333  bool
334  close(
335  NetClock::time_point closeTime,
336  boost::optional<std::chrono::milliseconds> consensusDelay =
337  boost::none);
338 
346  template <class Rep, class Period>
347  bool
349  {
350  // VFALCO Is this the correct time?
351  return close(now() + elapsed);
352  }
353 
361  bool
363  {
364  // VFALCO Is this the correct time?
365  return close(std::chrono::seconds(5));
366  }
367 
371  void
372  trace(int howMany = -1)
373  {
374  trace_ = howMany;
375  }
376 
378  void
380  {
381  trace_ = 0;
382  }
383 
385  void
387  {
388  app().checkSigs(false);
389  }
390 
392  void
393  memoize(Account const& account);
394 
397  Account const&
398  lookup(AccountID const& id) const;
399 
400  Account const&
401  lookup(std::string const& base58ID) const;
408  balance(Account const& account) const;
409 
415  seq(Account const& account) const;
416 
420  // VFALCO NOTE This should return a unit-less amount
422  balance(Account const& account, Issue const& issue) const;
423 
428  le(Account const& account) const;
429 
434  le(Keylet const& k) const;
435 
437  template <class JsonValue, class... FN>
438  JTx
439  jt(JsonValue&& jv, FN const&... fN)
440  {
441  JTx jt(std::forward<JsonValue>(jv));
442  invoke(jt, fN...);
443  autofill(jt);
444  jt.stx = st(jt);
445  return jt;
446  }
447 
451  template <class JsonValue, class... FN>
453  json(JsonValue&& jv, FN const&... fN)
454  {
455  auto tj = jt(std::forward<JsonValue>(jv), fN...);
456  return std::move(tj.jv);
457  }
458 
464  template <class... Args>
465  void
466  require(Args const&... args)
467  {
468  jtx::required(args...)(*this);
469  }
470 
473  static std::pair<TER, bool>
474  parseResult(Json::Value const& jr);
475 
479  virtual void
480  submit(JTx const& jt);
481 
485  void
487 
491  void
492  postconditions(JTx const& jt, TER ter, bool didApply);
493 
496  template <class JsonValue, class... FN>
497  void
498  apply(JsonValue&& jv, FN const&... fN)
499  {
500  submit(jt(std::forward<JsonValue>(jv), fN...));
501  }
502 
503  template <class JsonValue, class... FN>
504  void
505  operator()(JsonValue&& jv, FN const&... fN)
506  {
507  apply(std::forward<JsonValue>(jv), fN...);
508  }
512  TER
513  ter() const
514  {
515  return ter_;
516  }
517 
527  meta();
528 
541  tx() const;
542 
543  void
544  enableFeature(uint256 const feature);
545 
546 private:
547  void
548  fund(bool setDefaultRipple, STAmount const& amount, Account const& account);
549 
550  void
551  fund_arg(STAmount const& amount, Account const& account)
552  {
553  fund(true, amount, account);
554  }
555 
556  template <std::size_t N>
557  void
558  fund_arg(STAmount const& amount, std::array<Account, N> const& list)
559  {
560  for (auto const& account : list)
561  fund(false, amount, account);
562  }
563 
564 public:
591  template <class Arg, class... Args>
592  void
593  fund(STAmount const& amount, Arg const& arg, Args const&... args)
594  {
595  fund_arg(amount, arg);
596  if constexpr (sizeof...(args) > 0)
597  fund(amount, args...);
598  }
599 
618  void
619  trust(STAmount const& amount, Account const& account);
620 
621  template <class... Accounts>
622  void
624  STAmount const& amount,
625  Account const& to0,
626  Account const& to1,
627  Accounts const&... toN)
628  {
629  trust(amount, to0);
630  trust(amount, to1, toN...);
631  }
634 protected:
635  int trace_ = 0;
639 
641  do_rpc(
642  std::vector<std::string> const& args,
644 
645  void
646  autofill_sig(JTx& jt);
647 
648  virtual void
649  autofill(JTx& jt);
650 
659  st(JTx const& jt);
660 
661  // Invoke funclets on stx
662  // Note: The STTx may not be modified
663  template <class... FN>
664  void
665  invoke(STTx& stx, FN const&... fN)
666  {
667  (fN(*this, stx), ...);
668  }
669 
670  // Invoke funclets on jt
671  template <class... FN>
672  void
673  invoke(JTx& jt, FN const&... fN)
674  {
675  (fN(*this, jt), ...);
676  }
677 
678  // Map of account IDs to Account
680 };
681 
682 template <class... Args>
686  std::string const& cmd,
687  Args&&... args)
688 {
689  return do_rpc(
690  std::vector<std::string>{cmd, std::forward<Args>(args)...}, headers);
691 }
692 
693 template <class... Args>
695 Env::rpc(std::string const& cmd, Args&&... args)
696 {
697  return rpc(
699  cmd,
700  std::forward<Args>(args)...);
701 }
702 
703 } // namespace jtx
704 } // namespace test
705 } // namespace ripple
706 
707 #endif
ripple::test::jtx::Env::AppBundle::app
Application * app
Definition: Env.h:125
ripple::test::jtx::Env::invoke
void invoke(STTx &stx, FN const &... fN)
Definition: Env.h:665
ripple::Application
Definition: Application.h:101
ripple::Application::checkSigs
virtual bool checkSigs() const =0
ripple::test::jtx::Env::Env
Env(beast::unit_test::suite &suite_, FeatureBitset features)
Create Env with default config and specified features.
Definition: Env.h:195
ripple::test::jtx::Env::autofill_sig
void autofill_sig(JTx &jt)
Definition: Env.cpp:378
ripple::test::jtx::SuiteLogs::suite_
beast::unit_test::suite & suite_
Definition: Env.h:93
ripple::test::jtx::Env::fund
void fund(STAmount const &amount, Arg const &arg, Args const &... args)
Create a new account with some XRP.
Definition: Env.h:593
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::OpenLedger::current
std::shared_ptr< OpenView const > current() const
Returns a view to the current open ledger.
Definition: OpenLedger.cpp:50
ripple::Issue
A currency issued by an account.
Definition: Issue.h:34
std::string
STL class.
std::shared_ptr
STL class.
utility
ripple::Logs
Manages partitions for logging.
Definition: Log.h:48
ripple::test::jtx::Env::map_
std::unordered_map< AccountID, Account > map_
Definition: Env.h:679
ripple::test::jtx::Env::ter_
TER ter_
Definition: Env.h:638
ripple::test::AbstractClient
Definition: AbstractClient.h:33
ripple::test::jtx::Env::AppBundle::client
std::unique_ptr< AbstractClient > client
Definition: Env.h:129
ripple::test::jtx::Env::tx
std::shared_ptr< STTx const > tx() const
Return the tx data for the last JTx.
Definition: Env.cpp:372
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
functional
ripple::test::jtx::Env::require
void require(Args const &... args)
Check a set of requirements.
Definition: Env.h:466
ripple::test::jtx::Env::apply
void apply(JsonValue &&jv, FN const &... fN)
Apply funclets and submit.
Definition: Env.h:498
ripple::test::jtx::Env::closed
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
Definition: Env.cpp:115
std::pair
std::vector::reserve
T reserve(T... args)
ripple::test::jtx::Env::fund_arg
void fund_arg(STAmount const &amount, std::array< Account, N > const &list)
Definition: Env.h:558
ripple::test::jtx::Env::AppBundle::AppBundle
AppBundle()=default
vector
ripple::test::jtx::Env::enableFeature
void enableFeature(uint256 const feature)
Definition: Env.cpp:455
ripple::test::jtx::Env::AppBundle::timeKeeper
ManualTimeKeeper * timeKeeper
Definition: Env.h:127
ripple::test::jtx::Env::txid_
uint256 txid_
Definition: Env.h:637
ripple::test::jtx::Env::AppBundle::~AppBundle
~AppBundle()
Definition: Env.cpp:95
ripple::test::jtx::JTx::stx
std::shared_ptr< STTx const > stx
Definition: JTx.h:49
ripple::test::jtx::Env::jt
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
Definition: Env.h:439
std::chrono::duration
ripple::test::jtx::Env::journal
const beast::Journal journal
Definition: Env.h:143
ripple::test::jtx::Env::notrace
void notrace()
Turn off JSON tracing.
Definition: Env.h:379
ripple::test::jtx::Env::disable_sigs
void disable_sigs()
Turn off signature checks.
Definition: Env.h:386
ripple::test::jtx::Env::timeKeeper
ManualTimeKeeper & timeKeeper()
Definition: Env.h:252
ripple::test::jtx::SuiteLogs::~SuiteLogs
~SuiteLogs() override=default
ripple::test::jtx::Env::sign_and_submit
void sign_and_submit(JTx const &jt, Json::Value params=Json::nullValue)
Use the submit RPC command with a provided JTx object.
Definition: Env.cpp:302
tuple
ripple::test::jtx::Env::AppBundle::thread
std::thread thread
Definition: Env.h:128
ripple::Pathfinder::initPathTable
static void initPathTable()
Definition: Pathfinder.cpp:1257
ripple::test::jtx::Env::balance
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
Definition: Env.cpp:174
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:240
ripple::test::jtx::envconfig
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:49
ripple::Application::openLedger
virtual OpenLedger & openLedger()=0
ripple::test::jtx::Env::bundle_
AppBundle bundle_
Definition: Env.h:140
ripple::test::jtx::Env::ter
TER ter() const
Return the TER for the last JTx.
Definition: Env.h:513
ripple::test::jtx::Env::trust
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Definition: Env.cpp:250
ripple::test::jtx::Env::st
std::shared_ptr< STTx const > st(JTx const &jt)
Create a STTx from a JTx The framework requires that JSON is valid.
Definition: Env.cpp:421
ripple::test::jtx::Env::Env
Env(beast::unit_test::suite &suite_, std::unique_ptr< Config > config, FeatureBitset features, std::unique_ptr< Logs > logs=nullptr, beast::severities::Severity thresh=beast::severities::kError)
Create Env using suite, Config pointer, and explicit features.
Definition: Env.h:165
ripple::test::jtx::Env::parseResult
static std::pair< TER, bool > parseResult(Json::Value const &jr)
Gets the TER result and didApply flag from a RPC Json result object.
Definition: Env.cpp:267
std::vector::push_back
T push_back(T... args)
ripple::test::ManualTimeKeeper
Definition: ManualTimeKeeper.h:29
ripple::base_uint< 256 >
ripple::test::jtx::SuiteLogs::SuiteLogs
SuiteLogs(beast::unit_test::suite &suite)
Definition: Env.h:96
ripple::test::jtx::Env::stopwatch_
TestStopwatch stopwatch_
Definition: Env.h:636
ripple::test::jtx::Env::meta
std::shared_ptr< STObject const > meta()
Return metadata for the last JTx.
Definition: Env.cpp:364
ripple::foreachFeature
void foreachFeature(FeatureBitset bs, F &&f)
Definition: Feature.h:340
ripple::test::jtx::Env::close
bool close(std::chrono::duration< Rep, Period > const &elapsed)
Close and advance the ledger.
Definition: Env.h:348
ripple::test::jtx::Env::operator()
void operator()(JsonValue &&jv, FN const &... fN)
Definition: Env.h:505
std::thread
STL class.
ripple::test::jtx::Env::trace
void trace(int howMany=-1)
Turn on JSON tracing.
Definition: Env.h:372
ripple::test::jtx::Env::postconditions
void postconditions(JTx const &jt, TER ter, bool didApply)
Check expected postconditions of JTx submission.
Definition: Env.cpp:340
ripple::TERSubset< CanCvtToTER >
ripple::test::jtx::SuiteLogs
Definition: Env.h:91
ripple::test::jtx::JTx
Execution context for applying a JSON transaction.
Definition: JTx.h:41
std::array
STL class.
ripple::test::jtx::Env::submit
virtual void submit(JTx const &jt)
Submit an existing JTx.
Definition: Env.cpp:279
ripple::STAmount
Definition: STAmount.h:42
std::chrono::time_point
ripple::STTx
Definition: STTx.h:42
ripple::test::jtx::Env::lookup
Account const & lookup(AccountID const &id) const
Returns the Account given the AccountID.
Definition: Env.cpp:156
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::test::jtx::supported_amendments
FeatureBitset supported_amendments()
Definition: Env.h:70
std::uint32_t
ripple::test::jtx::Account::master
static const Account master
The master account.
Definition: Account.h:47
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::test::jtx::Env::app
Application const & app() const
Definition: Env.h:246
ripple::test::jtx::Env::test
beast::unit_test::suite & test
Definition: Env.h:118
ripple::test::jtx::Env::invoke
void invoke(JTx &jt, FN const &... fN)
Definition: Env.h:673
ripple::test::jtx::required
require_t required(Args const &... args)
Compose many condition functors into one.
Definition: require.h:47
ripple::test::jtx::Env::client
AbstractClient & client()
Returns the connected client.
Definition: Env.h:270
ripple::detail::supportedAmendments
std::vector< std::string > const & supportedAmendments()
Amendments that this server supports, but doesn't enable by default.
Definition: Feature.cpp:81
beast::severities::kError
@ kError
Definition: Journal.h:38
ripple::Logs::threshold
beast::severities::Severity threshold() const
Definition: Log.cpp:150
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::jtx::Env::operator=
Env & operator=(Env const &)=delete
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::test::jtx::noripple
std::array< Account, 1+sizeof...(Args)> noripple(Account const &account, Args const &... args)
Designate accounts as no-ripple in Env::fund.
Definition: Env.h:64
ripple::test::jtx::Env::autofill
virtual void autofill(JTx &jt)
Definition: Env.cpp:401
ripple::test::jtx::Env::do_rpc
Json::Value do_rpc(std::vector< std::string > const &args, std::unordered_map< std::string, std::string > const &headers={})
Definition: Env.cpp:447
ripple::test::jtx::Env::now
NetClock::time_point now()
Returns the current Ripple Network Time.
Definition: Env.h:263
ripple::test::jtx::Env::close
bool close()
Close and advance the ledger.
Definition: Env.h:362
beast::severities::Severity
Severity
Severity level / threshold of a Journal message.
Definition: Journal.h:31
std
STL namespace.
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:219
ripple::test::jtx::Env::le
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
Definition: Env.cpp:207
ripple::test::jtx::Env::AppBundle::owned
std::unique_ptr< Application > owned
Definition: Env.h:126
ripple::test::jtx::Env::master
Account const & master
Definition: Env.h:120
Json::nullValue
@ nullValue
'null' value
Definition: json_value.h:36
ripple::FeatureBitset
Definition: Feature.h:156
ripple::test::jtx::Env::Env
Env(beast::unit_test::suite &suite_)
Create Env with only the current test suite.
Definition: Env.h:233
ripple::test::jtx::Env::~Env
virtual ~Env()=default
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::test::jtx::Env::fund_arg
void fund_arg(STAmount const &amount, Account const &account)
Definition: Env.h:551
ripple::test::ManualTimeKeeper::now
time_point now() const override
Returns the estimate of wall time, in network time.
Definition: ManualTimeKeeper.cpp:37
beast::manual_clock< std::chrono::steady_clock >
ripple::test::jtx::Env::memoize
void memoize(Account const &account)
Associate AccountID with account.
Definition: Env.cpp:150
ripple::test::jtx::Env::Env
Env()=delete
std::unique_ptr< beast::Journal::Sink >
unordered_map
ripple::test::jtx::SuiteLogs::makeSink
std::unique_ptr< beast::Journal::Sink > makeSink(std::string const &partition, beast::severities::Severity threshold) override
Definition: Env.h:104
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:216
type_traits
ripple::test::jtx::Env::current
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:299
ripple::test::jtx::Env::json
Json::Value json(JsonValue &&jv, FN const &... fN)
Create JSON from parameters.
Definition: Env.h:453
ripple::test::jtx::Env::trust
void trust(STAmount const &amount, Account const &to0, Account const &to1, Accounts const &... toN)
Definition: Env.h:623
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:115
ripple::test::jtx::Env::AppBundle
Definition: Env.h:123
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::jtx::PrettyAmount
Represents an XRP or IOU quantity This customizes the string conversion and supports XRP conversions ...
Definition: amount.h:73
ripple::test::jtx::Env::trace_
int trace_
Definition: Env.h:635
ripple::test::jtx::Env::Env
Env(beast::unit_test::suite &suite_, std::unique_ptr< Config > config, std::unique_ptr< Logs > logs=nullptr, beast::severities::Severity thresh=beast::severities::kError)
Create Env using suite and Config pointer.
Definition: Env.h:212
ripple::getRegisteredFeature
boost::optional< uint256 > getRegisteredFeature(std::string const &name)
Definition: Feature.cpp:143
beast
Definition: base_uint.h:585
string