20 #include <ripple/app/ledger/Ledger.h>
21 #include <ripple/app/ledger/AcceptedLedger.h>
22 #include <ripple/app/ledger/InboundLedgers.h>
23 #include <ripple/app/ledger/LedgerMaster.h>
24 #include <ripple/consensus/LedgerTiming.h>
25 #include <ripple/app/ledger/LedgerToJson.h>
26 #include <ripple/app/ledger/OrderBookDB.h>
27 #include <ripple/app/ledger/PendingSaves.h>
28 #include <ripple/app/ledger/TransactionMaster.h>
29 #include <ripple/app/main/Application.h>
30 #include <ripple/app/misc/HashRouter.h>
31 #include <ripple/app/misc/LoadFeeTrack.h>
32 #include <ripple/app/misc/NetworkOPs.h>
33 #include <ripple/basics/contract.h>
34 #include <ripple/basics/Log.h>
35 #include <ripple/basics/StringUtilities.h>
36 #include <ripple/core/Config.h>
37 #include <ripple/core/DatabaseCon.h>
38 #include <ripple/core/JobQueue.h>
39 #include <ripple/core/SociDB.h>
40 #include <ripple/json/to_string.h>
41 #include <ripple/nodestore/Database.h>
42 #include <ripple/protocol/digest.h>
43 #include <ripple/protocol/Indexes.h>
44 #include <ripple/protocol/jss.h>
45 #include <ripple/protocol/PublicKey.h>
46 #include <ripple/protocol/SecretKey.h>
47 #include <ripple/protocol/HashPrefix.h>
48 #include <ripple/protocol/UintTypes.h>
49 #include <ripple/beast/core/LexicalCast.h>
50 #include <boost/optional.hpp>
79 :
public sles_type::iter_base
103 equal (base_type
const& impl)
const override
105 auto const& other =
dynamic_cast<
107 return iter_ == other.iter_;
119 auto const item = *
iter_;
121 return std::make_shared<SLE const>(
129 :
public txs_type::iter_base
155 equal (base_type
const& impl)
const override
157 auto const& other =
dynamic_cast<
159 return iter_ == other.iter_;
171 auto const item = *
iter_;
203 sle->setFieldAmount(
sfBalance, info_.drops);
207 if (! amendments.empty())
210 sle->setFieldV256 (
sfAmendments, STVector256{amendments});
215 setImmutable(config);
227 info.txHash, family))
229 info.accountHash, family))
230 , rules_ (config.features)
239 JLOG (j.
warn()) <<
"Don't have TX root for ledger";
246 JLOG (j.
warn()) <<
"Don't have AS root for ledger";
269 prevLedger.stateMap_->family()))
270 , stateMap_ (prevLedger.stateMap_->snapShot (true))
271 , fees_(prevLedger.fees_)
272 , rules_(prevLedger.rules_)
302 info.txHash, family))
304 info.accountHash, family))
321 info_.seq = ledgerSeq;
322 info_.closeTime = closeTime;
348 bool correctCloseTime,
Config const& config)
362 return stateMap_->addItem(std::move(item),
false,
false);
371 return std::make_shared<STTx const>(sit);
407 boost::optional<uint256>
409 boost::optional<uint256>
const& last)
const
414 if (last && item->key() >= last)
422 if (k.
key == beast::zero)
431 auto sle = std::make_shared<SLE>(
433 item->size()}, item->key());
445 return std::make_unique<sles_iter_impl>(
stateMap_->begin());
452 return std::make_unique<sles_iter_impl>(
stateMap_->end());
459 return std::make_unique<sles_iter_impl>(stateMap_->upper_bound(key));
466 return std::make_unique<txs_iter_impl>(!
open(),
txMap_->begin());
473 return std::make_unique<txs_iter_impl>(!
open(),
txMap_->end());
479 return txMap_->hasItem (key);
488 txMap_->peekItem(key);
495 return { std::move(result.first),
496 std::move(result.second) };
503 boost::optional<digest_type>
508 if (! stateMap_->peekItem(key,
digest))
510 return digest.as_uint256();
519 LogicError(
"Ledger::rawErase: key not found");
532 std::move(item),
false,
false))
533 LogicError(
"Ledger::rawInsert: key already exists");
546 std::move(item),
false,
false))
547 LogicError(
"Ledger::rawReplace: key not found");
560 metaData->getDataLength () + 16);
561 s.
addVL (txn->peekData ());
562 s.
addVL (metaData->peekData ());
566 (std::move(item),
true,
true))
586 if (sle->getFieldIndex (
sfBaseFee) != -1)
631 auto sle = std::make_shared<SLE>(
632 SerialIter{value->data(), value->size()}, value->key());
655 if (!missingNodes1.
empty ())
657 if (
auto stream = j.
info())
659 stream << missingNodes1.
size () <<
" missing account node(s)";
660 stream <<
"First: " << missingNodes1[0].what();
664 if (
txMap_->getHash().isZero() &&
672 txMap_->walkMap (missingNodes2, 32);
675 if (!missingNodes2.
empty ())
677 if (
auto stream = j.
info())
679 stream << missingNodes2.
size () <<
" missing transaction node(s)";
680 stream <<
"First: " << missingNodes2[0].what();
683 return missingNodes1.
empty () && missingNodes2.
empty ();
703 JLOG (ledgerJ.
fatal()) <<
"ledger is not sane" << j;
720 if ((prevIndex & 0xff) == 0)
729 sle = std::make_shared<SLE>(k);
734 hashes =
static_cast<decltype(hashes)
>(
739 assert (hashes.
size () <= 256);
756 sle = std::make_shared<SLE>(k);
761 hashes =
static_cast<decltype(hashes)
>(
765 assert (hashes.
size () <= 256);
766 if (hashes.
size () == 256)
782 auto j = app.
journal (
"Ledger");
787 JLOG (j.debug()) <<
"Save aborted";
793 <<
"saveValidatedLedger "
794 << (
current ?
"" :
"fromAcquire ") << seq;
795 static boost::format deleteLedger (
796 "DELETE FROM Ledgers WHERE LedgerSeq = %u;");
797 static boost::format deleteTrans1 (
798 "DELETE FROM Transactions WHERE LedgerSeq = %u;");
799 static boost::format deleteTrans2 (
800 "DELETE FROM AccountTransactions WHERE LedgerSeq = %u;");
801 static boost::format deleteAcctTrans (
802 "DELETE FROM AccountTransactions WHERE TransID = '%s';");
806 JLOG (j.fatal()) <<
"AH is zero: "
815 JLOG (j.fatal()) <<
"saveAcceptedLedger: seq="
816 << seq <<
", current=" <<
current;
843 JLOG (j.warn()) <<
"An accepted ledger was missing nodes";
853 *db << boost::str (deleteLedger % seq);
859 soci::transaction tr(*db);
861 *db << boost::str (deleteTrans1 % seq);
862 *db << boost::str (deleteTrans2 % seq);
866 for (
auto const& [_, acceptedLedgerTx] : aLedger->getMap ())
879 auto const& accts = acceptedLedgerTx->getAffected ();
884 "INSERT INTO AccountTransactions "
885 "(TransID, Account, LedgerSeq, TxnSeq) VALUES ");
893 for (
auto const& account : accts)
913 JLOG (j.trace()) <<
"ActTx: " << sql;
919 <<
"Transaction in ledger " << seq
920 <<
" affects no accounts";
927 acceptedLedgerTx->getTxn ()->getMetaSQL (
928 seq, acceptedLedgerTx->getEscMeta ()) +
";");
936 R
"sql(INSERT OR REPLACE INTO Ledgers
937 (LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,
938 CloseTimeRes,CloseFlags,AccountSetHash,TransSetHash)
940 (:ledgerHash,:ledgerSeq,:prevHash,:totalCoins,:closingTime,:prevClosingTime,
941 :closeTimeRes,:closeFlags,:accountSetHash,:transSetHash);)sql");
945 soci::transaction tr(*db);
950 auto const closeTime =
952 auto const parentCloseTime =
954 auto const closeTimeResolution =
963 soci::use(parentHash),
965 soci::use(closeTime),
966 soci::use(parentCloseTime),
967 soci::use(closeTimeResolution),
968 soci::use(closeFlags),
969 soci::use(accountHash),
990 if (! app.getHashRouter ().setFlags (ledger->
info().
hash, SF_SAVED))
993 auto stream = app.journal (
"Ledger").debug();
994 JLOG (stream) <<
"Double pend save for "
997 if (! isSynchronous ||
998 ! app.pendingSaves().pending (ledger->
info().
seq))
1008 if (! app.pendingSaves().shouldWork (ledger->
info().
seq, isSynchronous))
1010 auto stream = app.journal (
"Ledger").debug();
1012 <<
"Pend save with seq in pending saves "
1019 char const*
const jobName {
1020 isCurrent ?
"Ledger::pendSave" :
"Ledger::pendOldSave"};
1023 if (!isSynchronous &&
1024 app.getJobQueue().addJob (jobType, jobName,
1026 saveValidatedLedger(app, ledger, isCurrent);
1069 boost::optional<std::string> sLedgerHash, sPrevHash, sAccountHash,
1071 boost::optional<std::uint64_t> totDrops, closingTime, prevClosingTime,
1072 closeResolution, closeFlags, ledgerSeq64;
1076 "LedgerHash, PrevHash, AccountSetHash, TransSetHash, "
1078 "ClosingTime, PrevClosingTime, CloseTimeRes, CloseFlags,"
1079 "LedgerSeq from Ledgers " +
1083 soci::into(sLedgerHash),
1084 soci::into(sPrevHash),
1085 soci::into(sAccountHash),
1086 soci::into(sTransHash),
1087 soci::into(totDrops),
1088 soci::into(closingTime),
1089 soci::into(prevClosingTime),
1090 soci::into(closeResolution),
1091 soci::into(closeFlags),
1092 soci::into(ledgerSeq64);
1094 if (!db->got_data ())
1097 JLOG (stream) <<
"Ledger not found: " << sqlSuffix;
1105 rangeCheckedCast<std::uint32_t>(ledgerSeq64.value_or (0));
1107 uint256 prevHash{}, accountHash{}, transHash{};
1111 prevHash.SetHexExact (*sPrevHash);
1113 accountHash.SetHexExact (*sAccountHash);
1115 transHash.SetHexExact (*sTransHash);
1124 info.
drops = totDrops.value_or(0);
1125 info.
closeTime = time_point{duration{closingTime.value_or(0)}};
1126 info.
parentCloseTime = time_point{duration{prevClosingTime.value_or(0)}};
1129 info.
seq = ledgerSeq;
1132 auto ledger = std::make_shared<Ledger>(
1149 Config
const& config,
1165 Application& app,
bool acquire)
1170 s <<
"WHERE LedgerSeq = " << ledgerIndex;
1171 std::tie (ledger, std::ignore, std::ignore) =
1176 app.journal (
"Ledger"));
1182 Application& app,
bool acquire)
1187 s <<
"WHERE LedgerHash = '" << ledgerHash <<
"'";
1188 std::tie (ledger, std::ignore, std::ignore) =
1193 app.journal (
"Ledger"));
1195 assert (!ledger || ledger->
info().
hash == ledgerHash);
1206 "SELECT LedgerHash FROM Ledgers INDEXED BY SeqLedger WHERE LedgerSeq='";
1207 sql.
append (beast::lexicalCastThrow <std::string> (ledgerIndex));
1212 auto db = app.getLedgerDB ().checkoutDb ();
1214 boost::optional<std::string> lh;
1218 if (!db->got_data () || !lh)
1226 ret.SetHexExact (hash);
1235 auto db = app.getLedgerDB ().checkoutDb ();
1237 boost::optional <std::string> lhO, phO;
1239 *db <<
"SELECT LedgerHash,PrevHash FROM Ledgers "
1240 "INDEXED BY SeqLedger Where LedgerSeq = :ls;",
1243 soci::use (ledgerIndex);
1247 auto stream = app.journal (
"Ledger").trace();
1249 <<
"Don't have ledger " << ledgerIndex;
1253 ledgerHash.SetHexExact (*lhO);
1254 parentHash.SetHexExact (*phO);
1266 "SELECT LedgerSeq,LedgerHash,PrevHash FROM Ledgers WHERE LedgerSeq >= ";
1267 sql.
append (beast::lexicalCastThrow <std::string> (minSeq));
1268 sql.
append (
" AND LedgerSeq <= ");
1269 sql.
append (beast::lexicalCastThrow <std::string> (maxSeq));
1272 auto db = app.getLedgerDB ().checkoutDb ();
1276 boost::optional<std::string> ph;
1277 soci::statement st =
1278 (db->prepare << sql,
1287 ret[rangeCheckedCast<std::uint32_t>(ls)];
1288 hashes.
first.SetHexExact (lh);
1290 hashes.
second.SetHexExact (*ph);
1295 auto stream = app.journal (
"Ledger").warn();
1297 <<
"Null prev hash for ledger seq: " << ls;
std::unique_ptr< sles_type::iter_base > slesUpperBound(uint256 const &key) const override
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > loadLedgerHelper(std::string const &sqlSuffix, Application &app, bool acquire)
sles_iter_impl(SHAMap::const_iterator iter)
std::unique_ptr< sles_type::iter_base > slesBegin() const override
virtual void missing_node(std::uint32_t refNum)=0
bool addSLE(SLE const &sle)
void rawReplace(std::shared_ptr< SLE > const &sle) override
Unconditionally replace a state item.
@ ledgerMaster
ledger master data for signing
std::shared_ptr< SHAMap > txMap_
A pair of SHAMap key and LedgerEntryType.
virtual TaggedCache< uint256, AcceptedLedger > & getAcceptedLedgerCache()=0
tx_type txRead(key_type const &key) const override
Read a transaction from the tx map.
SHAMapHash getHash() const
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Application &app, bool acquire)
Stream trace() const
Severity stream access functions.
void stream(Json::Value const &jv, Write const &write)
Stream compact JSON to the specified function.
std::unique_ptr< sles_type::iter_base > slesEnd() const override
constexpr value_type drops() const
Returns the number of drops.
const SField sfMetadata(access, STI_METADATA, 257, "Metadata")
const SF_U32 sfSequence(access, STI_UINT32, 4, "Sequence")
sles_type::value_type dereference() const override
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Serializer getSerializer() const
bool exists(Keylet const &k) const override
Determine if a state item exists.
bool equal(base_type const &impl) const override
std::shared_ptr< SLE > peek(Keylet const &k) const
std::chrono::time_point< Clock, Duration > roundCloseTime(std::chrono::time_point< Clock, Duration > closeTime, std::chrono::duration< Rep, Period > closeResolution)
Calculates the close time for a ledger, given a close time resolution.
void addRaw(LedgerInfo const &info, Serializer &s)
txs_iter_impl & operator=(txs_iter_impl const &)=delete
bool walkLedger(beast::Journal j) const
static std::string const & getMetaSQLInsertReplaceHeader()
std::string to_string(ListDisposition disposition)
void rawTxInsert(uint256 const &key, std::shared_ptr< Serializer const > const &txn, std::shared_ptr< Serializer const > const &metaData) override
Add a transaction to the tx map.
bool startWork(LedgerIndex seq)
Start working on a ledger.
txs_iter_impl(bool metadata, SHAMap::const_iterator iter)
void rawErase(std::shared_ptr< SLE > const &sle) override
Delete an existing state item.
const SF_U32 sfReserveBase(access, STI_UINT32, 31, "ReserveBase")
static void finishLoadByIndexOrHash(std::shared_ptr< Ledger > const &ledger, Config const &config, beast::Journal j)
std::shared_ptr< STTx const > deserializeTx(SHAMapItem const &item)
Deserialize a SHAMapItem containing a single STTx.
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
virtual AccountIDCache const & accountIDCache() const =0
void setImmutable(Config const &config)
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
uint256 getHashByIndex(std::uint32_t ledgerIndex, Application &app)
std::shared_ptr< SLE const > value_type
std::unique_ptr< txs_type::iter_base > txsEnd() const override
static Hasher::result_type digest(void const *data, std::size_t size) noexcept
NetClock::time_point closeTime
uint256 const & key() const
Returns the 'key' (or 'index') of this item.
const SF_U32 sfLastLedgerSequence(access, STI_UINT32, 27, "LastLedgerSequence")
LedgerInfo const & info() const override
Returns information about the ledger.
T time_since_epoch(T... args)
virtual void store(NodeObjectType type, Blob &&data, uint256 const &hash, std::uint32_t seq)=0
Store the object.
bool txExists(uint256 const &key) const override
Returns true if a tx exists in the tx map.
bool assertSane(beast::Journal ledgerJ) const
static bool saveValidatedLedger(Application &app, std::shared_ptr< Ledger const > const &ledger, bool current)
std::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Application &app, bool acquire)
LockedSociSession checkoutDb()
virtual Family & family()=0
void setAccepted(NetClock::time_point closeTime, NetClock::duration closeResolution, bool correctCloseTime, Config const &config)
void failedSave(std::uint32_t seq, uint256 const &hash)
virtual LedgerMaster & getLedgerMaster()=0
virtual PendingSaves & pendingSaves()=0
std::pair< std::shared_ptr< STTx const >, std::shared_ptr< STObject const > > deserializeTxPlusMeta(SHAMapItem const &item)
Deserialize a SHAMapItem containing STTx + STObject metadata.
static constexpr FeeUnit32 TRANSACTION_FEE_BASE
static const account_t account
std::unique_ptr< base_type > copy() const override
void Rethrow()
Rethrow the exception currently being handled.
virtual Config & config()=0
bool isCurrent(ValidationParms const &p, NetClock::time_point now, NetClock::time_point signTime, NetClock::time_point seenTime)
Whether a validation is still current.
SHAMap::const_iterator iter_
SHAMap const & stateMap() const
XRPAmount FEE_OWNER_RESERVE
AccountID calcAccountID(PublicKey const &pk)
A SHAMap is both a radix tree with a fan-out of 16 and a Merkle tree.
SHAMap::const_iterator iter_
bool addGiveItem(std::shared_ptr< SHAMapItem const > const &, bool isTransaction, bool hasMeta)
bool equal(base_type const &impl) const override
sles_iter_impl & operator=(sles_iter_impl const &)=delete
XRPAmount FEE_ACCOUNT_RESERVE
void rawInsert(std::shared_ptr< SLE > const &sle) override
Unconditionally insert a state item.
const SF_U32 sfReferenceFeeUnits(access, STI_UINT32, 30, "ReferenceFeeUnits")
@ current
This was a new validation and was added.
void finishWork(LedgerIndex seq)
Finish working on a ledger.
@ transactionID
transaction plus signature to give transaction ID
A generic endpoint for log messages.
virtual DatabaseCon & getLedgerDB()=0
bool SetHexExact(const char *psz)
Parse a hex string into a base_uint The string must contain exactly bytes * 2 hex characters and must...
static const amendments_t amendments
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
std::shared_ptr< SLE const > read(Keylet const &k) const override
Return the state item associated with a key.
SHAMap const & txMap() const
bool getCloseAgree(LedgerInfo const &info)
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
const SF_Vec256 sfHashes(access, STI_VECTOR256, 2, "Hashes")
std::unique_ptr< txs_type::iter_base > txsBegin() const override
bool inLedger(uint256 const &hash, std::uint32_t ledger)
T emplace_back(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::unordered_set< uint256, beast::uhash<> > features
virtual NodeStore::Database & getNodeStore()=0
virtual beast::Journal journal(std::string const &name)=0
const SF_Amount sfBalance(access, STI_AMOUNT, 2, "Balance")
static uint256 calculateLedgerHash(LedgerInfo const &info)
bool setup(Config const &config)
const SF_U32 sfReserveIncrement(access, STI_UINT32, 32, "ReserveIncrement")
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
NetClock::duration closeTimeResolution
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
const create_genesis_t create_genesis
std::shared_ptr< SHAMap > stateMap_
bool open() const override
Returns true if this reflects an open ledger.
boost::optional< uint256 > succ(uint256 const &key, boost::optional< uint256 > const &last=boost::none) const override
Return the key of the next state item.
int addVL(Blob const &vector)
Rules controlling protocol behavior.
bool getHashesByIndex(std::uint32_t ledgerIndex, uint256 &ledgerHash, uint256 &parentHash, Application &app)
bool check(STLedgerEntry const &) const
Returns true if the SLE matches the type.
Information about the notional ledger backing the view.
std::chrono::duration< rep, period > duration
uint256 const & as_uint256() const
const SF_Vec256 sfAmendments(access, STI_VECTOR256, 3, "Amendments")
std::chrono::duration< Rep, Period > getNextLedgerTimeResolution(std::chrono::duration< Rep, Period > previousResolution, bool previousAgree, Seq ledgerSeq)
Calculates the close time resolution for the specified ledger.
const SF_U64 sfBaseFee(access, STI_UINT64, 5, "BaseFee")
constexpr auto ledgerDefaultTimeResolution
Initial resolution of ledger close time.
txs_type::value_type dereference() const override
bool pendSaveValidated(Application &app, std::shared_ptr< Ledger const > const &ledger, bool isSynchronous, bool isCurrent)
Save, or arrange to save, a fully-validated ledger Returns false on error.
Ledger(Ledger const &)=delete
boost::optional< digest_type > digest(key_type const &key) const override
Return the digest associated with the key.
void increment() override
std::chrono::time_point< NetClock > time_point
std::unique_ptr< base_type > copy() const override
void increment() override
Slice getSlice(std::size_t bytes)
static const std::uint32_t sLCF_NoConsensusTime
virtual DatabaseCon & getTxnDB()=0
void open(soci::session &s, BasicConfig const &config, std::string const &dbName)
Open a soci session.
std::string toBase58(AccountID const &) const
Return ripple::toBase58 for the AccountID.
NetClock::time_point parentCloseTime
virtual TransactionMaster & getMasterTransaction()=0