std::shared_ptr<LedgerEntry const> LedgerStateRoot::Impl::loadOffer(LedgerKey const& key) const { uint64_t offerID = key.offer().offerID; std::string actIDStrKey = KeyUtils::toStrKey(key.offer().sellerID); std::string sql = "SELECT sellerid, offerid, " "sellingassettype, sellingassetcode, sellingissuer, " "buyingassettype, buyingassetcode, buyingissuer, " "amount, pricen, priced, flags, lastmodified " "FROM offers " "WHERE sellerid= :id AND offerid= :offerid"; auto prep = mDatabase.getPreparedStatement(sql); auto& st = prep.statement(); st.exchange(soci::use(actIDStrKey)); st.exchange(soci::use(offerID)); std::vector<LedgerEntry> offers; { auto timer = mDatabase.getSelectTimer("offer"); offers = loadOffers(prep); } return offers.size() == 0 ? nullptr : std::make_shared<LedgerEntry const>(offers.front()); }
LedgerKey LedgerEntryKey(LedgerEntry const& e) { auto& d = e.data; LedgerKey k; switch (d.type()) { case ACCOUNT: k.type(ACCOUNT); k.account().accountID = d.account().accountID; break; case TRUSTLINE: k.type(TRUSTLINE); k.trustLine().accountID = d.trustLine().accountID; k.trustLine().asset = d.trustLine().asset; break; case OFFER: k.type(OFFER); k.offer().sellerID = d.offer().sellerID; k.offer().offerID = d.offer().offerID; break; case DATA: k.type(DATA); k.data().accountID = d.data().accountID; k.data().dataName = d.data().dataName; break; } return k; }
bool OfferFrame::exists(Database& db, LedgerKey const& key) { std::string actIDStrKey = PubKeyUtils::toStrKey(key.offer().sellerID); int exists = 0; auto timer = db.getSelectTimer("offer-exists"); db.getSession() << "SELECT EXISTS (SELECT NULL FROM offers " "WHERE sellerid=:id AND offerid=:s)", use(actIDStrKey), use(key.offer().offerID), into(exists); return exists != 0; }
void AccountFrame::storeDelete(LedgerDelta& delta, Database& db, LedgerKey const& key) { flushCachedEntry(key, db); std::string actIDStrKey = PubKeyUtils::toStrKey(key.account().accountID); { auto timer = db.getDeleteTimer("account"); auto prep = db.getPreparedStatement( "DELETE from accounts where accountid= :v1"); auto& st = prep.statement(); st.exchange(soci::use(actIDStrKey)); st.define_and_bind(); st.execute(true); } { auto timer = db.getDeleteTimer("signer"); auto prep = db.getPreparedStatement("DELETE from signers where accountid= :v1"); auto& st = prep.statement(); st.exchange(soci::use(actIDStrKey)); st.define_and_bind(); st.execute(true); } delta.deleteEntry(key); }
bool OfferFrame::exists(Database& db, LedgerKey const& key) { std::string actIDStrKey = PubKeyUtils::toStrKey(key.offer().sellerID); int exists = 0; auto timer = db.getSelectTimer("offer-exists"); auto prep = db.getPreparedStatement("SELECT EXISTS (SELECT NULL FROM offers " "WHERE sellerid=:id AND offerid=:s)"); auto& st = prep.statement(); st.exchange(use(actIDStrKey)); st.exchange(use(key.offer().offerID)); st.exchange(into(exists)); st.define_and_bind(); st.execute(true); return exists != 0; }
void OfferFrame::storeDelete(LedgerDelta& delta, Database& db, LedgerKey const& key) { auto timer = db.getDeleteTimer("offer"); db.getSession() << "DELETE FROM offers WHERE offerid=:s", use(key.offer().offerID); delta.deleteEntry(key); }
void OfferFrame::storeDelete(LedgerDelta& delta, Database& db, LedgerKey const& key) { auto timer = db.getDeleteTimer("offer"); auto prep = db.getPreparedStatement("DELETE FROM offers WHERE offerid=:s"); auto& st = prep.statement(); st.exchange(use(key.offer().offerID)); st.define_and_bind(); st.execute(true); delta.deleteEntry(key); }
std::shared_ptr<LedgerEntry const> LedgerStateRoot::Impl::loadData(LedgerKey const& key) const { std::string actIDStrKey = KeyUtils::toStrKey(key.data().accountID); std::string const& dataName = key.data().dataName; std::string dataValue; soci::indicator dataValueIndicator; LedgerEntry le; le.data.type(DATA); DataEntry& de = le.data.data(); std::string sql = "SELECT datavalue, lastmodified " "FROM accountdata " "WHERE accountid= :id AND dataname= :dataname"; auto prep = mDatabase.getPreparedStatement(sql); auto& st = prep.statement(); st.exchange(soci::into(dataValue, dataValueIndicator)); st.exchange(soci::into(le.lastModifiedLedgerSeq)); st.exchange(soci::use(actIDStrKey)); st.exchange(soci::use(dataName)); st.define_and_bind(); st.execute(true); if (!st.got_data()) { return nullptr; } de.accountID = key.data().accountID; de.dataName = dataName; if (dataValueIndicator != soci::i_ok) { throw std::runtime_error("bad database state"); } decoder::decode_b64(dataValue, de.dataValue); return std::make_shared<LedgerEntry const>(std::move(le)); }
bool AccountFrame::exists(Database& db, LedgerKey const& key) { if (cachedEntryExists(key, db) && getCachedEntry(key, db) != nullptr) { return true; } std::string actIDStrKey = PubKeyUtils::toStrKey(key.account().accountID); int exists = 0; { auto timer = db.getSelectTimer("account-exists"); db.getSession() << "SELECT EXISTS (SELECT NULL FROM accounts " "WHERE accountid=:v1)", use(actIDStrKey), into(exists); } return exists != 0; }
void LedgerStateRoot::Impl::deleteOffer(LedgerKey const& key) { auto const& offer = key.offer(); auto prep = mDatabase.getPreparedStatement("DELETE FROM offers WHERE offerid=:s"); auto& st = prep.statement(); st.exchange(soci::use(offer.offerID)); st.define_and_bind(); { auto timer = mDatabase.getDeleteTimer("offer"); st.execute(true); } if (st.get_affected_rows() != 1) { throw std::runtime_error("Could not update data in SQL"); } }
void AccountFrame::storeDelete(LedgerDelta& delta, Database& db, LedgerKey const& key) { flushCachedEntry(key, db); std::string actIDStrKey = PubKeyUtils::toStrKey(key.account().accountID); soci::session& session = db.getSession(); { auto timer = db.getDeleteTimer("account"); session << "DELETE from accounts where accountid= :v1", soci::use(actIDStrKey); } { auto timer = db.getDeleteTimer("signer"); session << "DELETE from signers where accountid= :v1", soci::use(actIDStrKey); } delta.deleteEntry(key); }
void LedgerStateRoot::Impl::deleteData(LedgerKey const& key) { auto const& data = key.data(); std::string actIDStrKey = KeyUtils::toStrKey(data.accountID); std::string const& dataName = data.dataName; auto prep = mDatabase.getPreparedStatement( "DELETE FROM accountdata WHERE accountid=:id AND dataname=:s"); auto& st = prep.statement(); st.exchange(soci::use(actIDStrKey)); st.exchange(soci::use(dataName)); st.define_and_bind(); { auto timer = mDatabase.getDeleteTimer("data"); st.execute(true); } if (st.get_affected_rows() != 1) { throw std::runtime_error("Could not update data in SQL"); } }
bool AccountFrame::exists(Database& db, LedgerKey const& key) { if (cachedEntryExists(key, db) && getCachedEntry(key, db) != nullptr) { return true; } std::string actIDStrKey = PubKeyUtils::toStrKey(key.account().accountID); int exists = 0; { auto timer = db.getSelectTimer("account-exists"); auto prep = db.getPreparedStatement("SELECT EXISTS (SELECT NULL FROM accounts " "WHERE accountid=:v1)"); auto& st = prep.statement(); st.exchange(use(actIDStrKey)); st.exchange(into(exists)); st.define_and_bind(); st.execute(true); } return exists != 0; }
void TrustFrame::getKeyFields(LedgerKey const& key, std::string& actIDStrKey, std::string& issuerStrKey, std::string& assetCode) { actIDStrKey = PubKeyUtils::toStrKey(key.trustLine().accountID); if (key.trustLine().asset.type() == ASSET_TYPE_CREDIT_ALPHANUM4) { issuerStrKey = PubKeyUtils::toStrKey(key.trustLine().asset.alphaNum4().issuer); assetCodeToStr(key.trustLine().asset.alphaNum4().assetCode, assetCode); } else if (key.trustLine().asset.type() == ASSET_TYPE_CREDIT_ALPHANUM12) { issuerStrKey = PubKeyUtils::toStrKey(key.trustLine().asset.alphaNum12().issuer); assetCodeToStr(key.trustLine().asset.alphaNum12().assetCode, assetCode); } if (actIDStrKey == issuerStrKey) throw std::runtime_error("Issuer's own trustline should not be used " "outside of OperationFrame"); }
AccountFrame::pointer AccountFrame::loadAccount(AccountID const& accountID, Database& db) { LedgerKey key; key.type(ACCOUNT); key.account().accountID = accountID; if (cachedEntryExists(key, db)) { auto p = getCachedEntry(key, db); return p ? std::make_shared<AccountFrame>(*p) : nullptr; } std::string actIDStrKey = PubKeyUtils::toStrKey(accountID); std::string publicKey, inflationDest, creditAuthKey; std::string homeDomain, thresholds; soci::indicator inflationDestInd; AccountFrame::pointer res = make_shared<AccountFrame>(accountID); AccountEntry& account = res->getAccount(); auto prep = db.getPreparedStatement("SELECT balance, seqnum, numsubentries, " "inflationdest, homedomain, thresholds, " "flags, lastmodified " "FROM accounts WHERE accountid=:v1"); auto& st = prep.statement(); st.exchange(into(account.balance)); st.exchange(into(account.seqNum)); st.exchange(into(account.numSubEntries)); st.exchange(into(inflationDest, inflationDestInd)); st.exchange(into(homeDomain)); st.exchange(into(thresholds)); st.exchange(into(account.flags)); st.exchange(into(res->getLastModified())); st.exchange(use(actIDStrKey)); st.define_and_bind(); { auto timer = db.getSelectTimer("account"); st.execute(true); } if (!st.got_data()) { putCachedEntry(key, nullptr, db); return nullptr; } account.homeDomain = homeDomain; bn::decode_b64(thresholds.begin(), thresholds.end(), res->mAccountEntry.thresholds.begin()); if (inflationDestInd == soci::i_ok) { account.inflationDest.activate() = PubKeyUtils::fromStrKey(inflationDest); } account.signers.clear(); if (account.numSubEntries != 0) { auto signers = loadSigners(db, actIDStrKey); account.signers.insert(account.signers.begin(), signers.begin(), signers.end()); } res->normalize(); res->mUpdateSigners = false; assert(res->isValid()); res->mKeyCalculated = false; res->putCachedEntry(db); return res; }
AccountFrame::pointer AccountFrame::loadAccount(AccountID const& accountID, Database& db) { LedgerKey key; key.type(ACCOUNT); key.account().accountID = accountID; if (cachedEntryExists(key, db)) { auto p = getCachedEntry(key, db); return p ? std::make_shared<AccountFrame>(*p) : nullptr; } std::string actIDStrKey = PubKeyUtils::toStrKey(accountID); std::string publicKey, inflationDest, creditAuthKey; std::string homeDomain, thresholds; soci::indicator inflationDestInd, homeDomainInd, thresholdsInd; soci::session& session = db.getSession(); AccountFrame::pointer res = make_shared<AccountFrame>(accountID); AccountEntry& account = res->getAccount(); { auto timer = db.getSelectTimer("account"); session << "SELECT balance, seqnum, numsubentries, " "inflationdest, homedomain, thresholds, flags " "FROM accounts WHERE accountid=:v1", into(account.balance), into(account.seqNum), into(account.numSubEntries), into(inflationDest, inflationDestInd), into(homeDomain, homeDomainInd), into(thresholds, thresholdsInd), into(account.flags), use(actIDStrKey); } if (!session.got_data()) { putCachedEntry(key, nullptr, db); return nullptr; } if (homeDomainInd == soci::i_ok) { account.homeDomain = homeDomain; } if (thresholdsInd == soci::i_ok) { bn::decode_b64(thresholds.begin(), thresholds.end(), res->mAccountEntry.thresholds.begin()); } if (inflationDestInd == soci::i_ok) { account.inflationDest.activate() = PubKeyUtils::fromStrKey(inflationDest); } account.signers.clear(); if (account.numSubEntries != 0) { string pubKey; Signer signer; auto prep = db.getPreparedStatement("SELECT publickey, weight from " "signers where accountid =:id"); auto& st = prep.statement(); st.exchange(use(actIDStrKey)); st.exchange(into(pubKey)); st.exchange(into(signer.weight)); st.define_and_bind(); { auto timer = db.getSelectTimer("signer"); st.execute(true); } while (st.got_data()) { signer.pubKey = PubKeyUtils::fromStrKey(pubKey); account.signers.push_back(signer); st.fetch(); } } res->normalize(); res->mUpdateSigners = false; res->mKeyCalculated = false; res->putCachedEntry(db); return res; }
TrustFrame::pointer TrustFrame::loadTrustLine(AccountID const& accountID, Asset const& asset, Database& db) { if (asset.type() == ASSET_TYPE_NATIVE) { throw std::runtime_error("XLM TrustLine?"); } else { if (accountID == getIssuer(asset)) { return createIssuerFrame(asset); } } LedgerKey key; key.type(TRUSTLINE); key.trustLine().accountID = accountID; key.trustLine().asset = asset; if (cachedEntryExists(key, db)) { auto p = getCachedEntry(key, db); return p ? std::make_shared<TrustFrame>(*p) : nullptr; } std::string accStr, issuerStr, assetStr; accStr = PubKeyUtils::toStrKey(accountID); if (asset.type() == ASSET_TYPE_CREDIT_ALPHANUM4) { assetCodeToStr(asset.alphaNum4().assetCode, assetStr); issuerStr = PubKeyUtils::toStrKey(asset.alphaNum4().issuer); } else if (asset.type() == ASSET_TYPE_CREDIT_ALPHANUM12) { assetCodeToStr(asset.alphaNum12().assetCode, assetStr); issuerStr = PubKeyUtils::toStrKey(asset.alphaNum12().issuer); } auto query = std::string(trustLineColumnSelector); query += (" WHERE accountid = :id " " AND issuer = :issuer " " AND assetcode = :asset"); auto prep = db.getPreparedStatement(query); auto& st = prep.statement(); st.exchange(use(accStr)); st.exchange(use(issuerStr)); st.exchange(use(assetStr)); pointer retLine; auto timer = db.getSelectTimer("trust"); loadLines(prep, [&retLine](LedgerEntry const& trust) { retLine = make_shared<TrustFrame>(trust); }); if (retLine) { retLine->putCachedEntry(db); } else { putCachedEntry(key, nullptr, db); } return retLine; }