1#include <xrpl/server/Wallet.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/UnorderedContainers.h>
5#include <xrpl/basics/base_uint.h>
6#include <xrpl/basics/safe_cast.h>
7#include <xrpl/beast/hash/uhash.h>
8#include <xrpl/beast/utility/Journal.h>
9#include <xrpl/core/PeerReservationTable.h>
10#include <xrpl/protocol/KeyType.h>
11#include <xrpl/protocol/PublicKey.h>
12#include <xrpl/protocol/SecretKey.h>
13#include <xrpl/protocol/tokens.h>
14#include <xrpl/rdb/DBInit.h>
15#include <xrpl/rdb/DatabaseCon.h>
16#include <xrpl/rdb/SociDB.h>
17#include <xrpl/server/Manifest.h>
19#include <boost/optional/optional.hpp>
21#include <soci/blob-exchange.h>
23#include <soci/boost-optional.h>
25#include <soci/session.h>
26#include <soci/statement.h>
27#include <soci/transaction.h>
41std::unique_ptr<DatabaseCon>
59 soci::session& session,
65 std::string const sql =
"SELECT RawData FROM " + dbTable +
";";
66 soci::blob sociRawData(session);
67 soci::statement st = (session.prepare << sql, soci::into(sociRawData));
72 convert(sociRawData, serialized);
77 JLOG(j.
warn()) <<
"Unverifiable manifest in db";
87 JLOG(j.
warn()) <<
"Malformed manifest in database";
98 soci::blob rawData(session);
100 session <<
"INSERT INTO " << dbTable <<
" (RawData) VALUES (:rawData);", soci::use(rawData);
105 soci::session& session,
111 soci::transaction tr(session);
112 session <<
"DELETE FROM " << dbTable;
116 for (
auto const& v : map)
120 if (!isTrusted(v.second.masterKey))
132 JLOG(j.
info()) << skipped <<
" untrusted manifest(s) in cache not saved to db";
139 soci::transaction tr(session);
140 saveManifest(session,
"ValidatorManifests", serialized);
147 session <<
"DELETE FROM NodeIdentity;";
155 boost::optional<std::string> pubKO, priKO;
157 (session.prepare <<
"SELECT PublicKey, PrivateKey FROM NodeIdentity;",
176 "INSERT INTO NodeIdentity (PublicKey,PrivateKey) "
177 "VALUES ('{}','{}');",
181 return {newpublicKey, newsecretKey};
190 boost::optional<std::string> valPubKey, valDesc;
195 (session.prepare <<
"SELECT PublicKey, Description FROM PeerReservations;",
196 soci::into(valPubKey),
197 soci::into(valDesc));
201 if (!valPubKey || !valDesc)
210 JLOG(j.
warn()) <<
"load: not a public key: " << valPubKey;
221 soci::session& session,
226 session <<
"INSERT INTO PeerReservations (PublicKey, Description) "
227 "VALUES (:nodeId, :desc) "
228 "ON CONFLICT (PublicKey) DO UPDATE SET "
229 "Description=excluded.Description",
230 soci::use(sNodeId), soci::use(description);
237 session <<
"DELETE FROM PeerReservations WHERE PublicKey = :nodeId", soci::use(sNodeId);
243 soci::transaction tr(session);
245 "SELECT count(*) FROM sqlite_master "
246 "WHERE type='table' AND name='FeatureVotes'";
248 boost::optional<int> featureVotesCount;
249 session << sql, soci::into(featureVotesCount);
250 bool const exists =
static_cast<bool>(*featureVotesCount);
255 session <<
"CREATE TABLE FeatureVotes ( "
256 "AmendmentHash CHARACTER(64) NOT NULL, "
257 "AmendmentName TEXT, "
258 "Veto INTEGER NOT NULL );";
266 soci::session& session,
268 boost::optional<std::string> amendmentHash,
269 boost::optional<std::string> amendmentName,
270 boost::optional<AmendmentVote> vote)>
const& callback)
273 auto intToVote = [](boost::optional<int>
const& dbVote) -> boost::optional<AmendmentVote> {
277 soci::transaction
const tr(session);
279 "SELECT AmendmentHash, AmendmentName, Veto FROM "
280 "( SELECT AmendmentHash, AmendmentName, Veto, RANK() OVER "
281 "( PARTITION BY AmendmentHash ORDER BY ROWID DESC ) "
282 "as rnk FROM FeatureVotes ) WHERE rnk = 1";
284 boost::optional<std::string> amendmentHash;
285 boost::optional<std::string> amendmentName;
286 boost::optional<int> voteToVeto;
288 (session.prepare << sql,
289 soci::into(amendmentHash),
290 soci::into(amendmentName),
291 soci::into(voteToVeto));
295 callback(amendmentHash, amendmentName, intToVote(voteToVeto));
301 soci::session& session,
306 soci::transaction tr(session);
308 "INSERT INTO FeatureVotes (AmendmentHash, AmendmentName, Veto) VALUES "
311 sql +=
"', '" + name;
A generic endpoint for log messages.
Remembers manifests with the highest sequence number.
ManifestDisposition applyManifest(Manifest m, ManifestRateLimitCapPolicy cap)
Add manifest to cache.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
void saveManifests(soci::session &session, std::string const &dbTable, std::function< bool(PublicKey const &)> const &isTrusted, hash_map< PublicKey, Manifest > const &map, beast::Journal j)
saveManifests Saves all given manifests to the database.
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
static void saveManifest(soci::session &session, std::string const &dbTable, std::string const &serialized)
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
void deletePeerReservation(soci::session &session, PublicKey const &nodeId)
deletePeerReservation Deletes an entry from the peer reservation table.
std::pair< PublicKey, SecretKey > getNodeIdentity(soci::session &session)
Returns a stable public and private key for this node.
void insertPeerReservation(soci::session &session, PublicKey const &nodeId, std::string const &description)
insertPeerReservation Adds an entry to the peer reservation table.
void readAmendments(soci::session &session, std::function< void(boost::optional< std::string > amendmentHash, boost::optional< std::string > amendmentName, boost::optional< AmendmentVote > vote)> const &callback)
readAmendments Reads all amendments from the FeatureVotes table.
constexpr auto kWalletDbName
std::unordered_set< PeerReservation, beast::Uhash<>, KeyEqual > getPeerReservationTable(soci::session &session, beast::Journal j)
getPeerReservationTable Returns the peer reservation table.
constexpr Dest safeCast(Src s) noexcept
std::string to_string(BaseUInt< Bits, Tag > const &a)
void addValidatorManifest(soci::session &session, std::string const &serialized)
addValidatorManifest Saves the manifest of a validator to the database.
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
constexpr std::array< char const *, 6 > kWalletDbInit
@ Uncapped
Bypasses the cap (listed/trusted or config manifests).
std::unique_ptr< DatabaseCon > makeWalletDB(DatabaseCon::Setup const &setup, beast::Journal j)
makeWalletDB Opens the wallet database and returns it.
bool createFeatureVotes(soci::session &session)
createFeatureVotes Creates the FeatureVote table if it does not exist.
std::unordered_map< Key, Value, Hash, Pred, Allocator > hash_map
void clearNodeIdentity(soci::session &session)
Delete any saved public/private key associated with this node.
void getManifests(soci::session &session, std::string const &dbTable, ManifestCache &cache, beast::Journal j)
getManifests Loads a manifest from the wallet database and stores it in the cache.
std::unique_ptr< DatabaseCon > makeTestWalletDB(DatabaseCon::Setup const &setup, std::string const &dbname, beast::Journal j)
makeTestWalletDB Opens a test wallet database with an arbitrary name.
void voteAmendment(soci::session &session, uint256 const &amendment, std::string const &name, AmendmentVote vote)
voteAmendment Set the veto value for a particular amendment.
void convert(soci::blob &from, std::vector< std::uint8_t > &to)