3#include <xrpld/app/main/DBInit.h>
4#include <xrpld/app/misc/Manifest.h>
5#include <xrpld/app/misc/ValidatorList.h>
6#include <xrpld/app/rdb/Wallet.h>
8#include <xrpl/basics/base64.h>
9#include <xrpl/basics/contract.h>
10#include <xrpl/protocol/STExchange.h>
11#include <xrpl/protocol/SecretKey.h>
12#include <xrpl/protocol/Sign.h>
14#include <boost/algorithm/string.hpp>
15#include <boost/filesystem.hpp>
16#include <boost/utility/in_place_factory.hpp>
39 using namespace boost::filesystem;
40 if (!exists(dbPath) || !is_directory(dbPath) || !is_empty(dbPath))
48 using namespace boost::filesystem;
51 create_directory(dbPath);
55 if (!is_directory(dbPath))
58 Throw<std::runtime_error>(
59 "Cannot create directory: " + dbPath.string());
62 static boost::filesystem::path
65 return boost::filesystem::current_path() /
"manifest_test_databases";
100 st[sfPublicKey] = pk;
101 st[sfSigningPubKey] = spk;
122 bool invalidSig =
false)
128 st[sfPublicKey] = pk;
154 st[sfPublicKey] = pk;
172 return std::move(*r);
173 Throw<std::runtime_error>(
"Could not create a revocation manifest");
185 bool invalidSig =
false)
191 st[sfSequence] =
seq;
192 st[sfPublicKey] = pk;
193 st[sfSigningPubKey] = spk;
212 static_cast<char const*
>(s.
data()),
215 return std::move(*r);
216 Throw<std::runtime_error>(
"Could not create a manifest");
243 auto getPopulatedManifests =
247 cache.for_each_manifest(
257 return lhs->serialized < rhs->serialized;
262 sort(getPopulatedManifests(m)));
264 auto& app = env.
app();
269 app.config().legacy(
"database_path"),
277 "ValidatorManifests",
279 return unl->listed(pubKey);
284 loaded.
load(*dbCon,
"ValidatorManifests");
288 sort(getPopulatedManifests(loaded)));
290 for (
auto const& man : loadedManifests)
291 BEAST_EXPECT(man->revoked());
298 for (
auto const& man : inManifests)
301 unl->load({}, s1, keys);
305 "ValidatorManifests",
307 return unl->listed(pubKey);
310 loaded.
load(*dbCon,
"ValidatorManifests");
314 sort(getPopulatedManifests(loaded)));
316 if (inManifests.
size() == loadedManifests.
size())
321 loadedManifests.
begin(),
337 BEAST_EXPECT(!loaded.
load(
339 "ValidatorManifests",
350 BEAST_EXPECT(loaded.
load(
352 "ValidatorManifests",
363 BEAST_EXPECT(!loaded.
load(
365 "ValidatorManifests",
376 BEAST_EXPECT(!loaded.
load(
378 "ValidatorManifests",
381 BEAST_EXPECT(!loaded.
revoked(pk));
385 BEAST_EXPECT(!loaded.
load(
387 "ValidatorManifests",
390 BEAST_EXPECT(!loaded.
revoked(pk));
394 BEAST_EXPECT(loaded.
load(
396 "ValidatorManifests",
400 BEAST_EXPECT(loaded.
revoked(pk));
403 boost::filesystem::remove(
419 st[sfPublicKey] = pk;
420 st[sfSigningPubKey] = kp.first;
428 BEAST_EXPECT(
strHex(masterSig) ==
strHex(m.getMasterSignature()));
466 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
476 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
484 BEAST_EXPECT(cache.
revoked(pk));
486 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
487 BEAST_EXPECT(cache.
getMasterKey(kp1.first) == kp1.first);
496 auto const valSecret = parseBase58<SecretKey>(
498 "paQmjZ37pKKPMrgadBLsuf9ab7Y7EUNzh27LQrZqoexpAs31nJi");
503 "eyJ2YWxpZGF0aW9uX3NlY3JldF9rZXkiOiI5ZWQ0NWY4NjYyNDFjYzE4YTI3ND"
505 " \tQzODdjMDYyNTkwNzk3MmY0ZTcxOTAyMzFmYWE5Mzc0NTdmYTlkYWY2Iiwib"
507 "\tc3QiOiJKQUFBQUFGeEllMUZ0d21pbXZHdEgyaUNjTUpxQzlnVkZLaWxHZncx"
510 "hYWExwbGMyR25NaEFrRTFhZ3FYeEJ3RHdEYklENk9NU1l1TTBGREFscEFnTms4"
512 "bjdNTzJmZGtjd1JRSWhBT25ndTlzQUtxWFlvdUorbDJWMFcrc0FPa1ZCK1pSUz"
514 "hsSkFmVXNYZkFpQnNWSkdlc2FhZE9KYy9hQVpva1MxdnltR21WcmxIUEtXWDNZ"
516 "NmluOEhBU1FLUHVnQkQ2N2tNYVJGR3ZtcEFUSGxHS0pkdkRGbFdQWXk1QXFEZW"
518 "VUSmEydzBpMjFlcTNNWXl3TFZKWm5GT3I3QzBrdzJBaVR6U0NqSXpkaXRROD0i"
522 "JAAAAAFxIe1FtwmimvGtH2iCcMJqC9gVFKilGfw1/"
523 "vCxHXXLplc2GnMhAkE1agqXxBwD"
524 "wDbID6OMSYuM0FDAlpAgNk8SKFn7MO2fdkcwRQIhAOngu9sAKqXYouJ+l2V0W+"
526 "+ZRS6PShlJAfUsXfAiBsVJGesaadOJc/"
527 "aAZokS1vymGmVrlHPKWX3Yywu6in8HASQKPu"
528 "gBD67kMaRFGvmpATHlGKJdvDFlWPYy5AqDedFv5TJa2w0i21eq3MYywLVJZnFO"
534 BEAST_EXPECT(token->validationSecret == *valSecret);
535 BEAST_EXPECT(token->manifest ==
manifest);
557 st[sfPublicKey] = pk;
558 st[sfSigningPubKey] = spk;
561 st[sfVersion] = version;
595 0x99, 0x30, 0xE7, 0xFC, 0x9D, 0x56, 0xBB, 0x25, 0xD6, 0x89, 0x3B,
596 0xA3, 0xF3, 0x17, 0xAE, 0x5B, 0xCF, 0x33, 0xB3, 0x29, 0x1B, 0xD6,
597 0x3D, 0xB3, 0x26, 0x54, 0xA3, 0x13, 0x22, 0x2F, 0x7F, 0xD0, 0x20};
618 auto toString = [](
STObject const& st) {
625 for (
auto const keyType : keyTypes)
630 for (
auto const sKeyType : keyTypes)
635 auto buildManifestObject =
638 bool noSigningPublic =
false,
639 bool noSignature =
false) {
641 st[sfSequence] =
seq;
642 st[sfPublicKey] = pk;
647 if (!noSigningPublic)
648 st[sfSigningPubKey] = spk;
664 testcase <<
"deserializeManifest: normal manifest ("
672 auto const m = toString(st);
676 BEAST_EXPECT(
manifest->masterKey == pk);
677 BEAST_EXPECT(
manifest->signingKey == spk);
678 BEAST_EXPECT(
manifest->sequence == sequence);
679 BEAST_EXPECT(
manifest->serialized == m);
680 BEAST_EXPECT(
manifest->domain.empty());
693 buildManifestObject(++sequence,
std::string{
"a.b"});
699 buildManifestObject(++sequence, s +
".example.com");
705 buildManifestObject(++sequence, s +
".example.com");
709 auto const st = buildManifestObject(
714 auto const m = toString(st);
718 BEAST_EXPECT(
manifest->masterKey == pk);
719 BEAST_EXPECT(
manifest->signingKey == spk);
720 BEAST_EXPECT(
manifest->sequence == sequence);
721 BEAST_EXPECT(
manifest->serialized == m);
722 BEAST_EXPECT(
manifest->domain ==
"example.com");
728 badSigSt[sfSequence] = sequence + 1;
730 auto const m = toString(badSigSt);
734 BEAST_EXPECT(
manifest->masterKey == pk);
735 BEAST_EXPECT(
manifest->signingKey == spk);
736 BEAST_EXPECT(
manifest->sequence == sequence + 1);
737 BEAST_EXPECT(
manifest->serialized == m);
738 BEAST_EXPECT(
manifest->domain ==
"example.com");
744 BEAST_EXPECT(badSt.delField(sfSequence));
750 BEAST_EXPECT(badSt.delField(sfPublicKey));
762 badSt[sfPublicKey] =
makeSlice(shortKey);
768 BEAST_EXPECT(badSt.delField(sfSigningPubKey));
774 badSt[sfSigningPubKey] =
makeSlice(badKey);
780 badSt[sfSigningPubKey] =
makeSlice(shortKey);
786 BEAST_EXPECT(badSt.delField(sfMasterSignature));
792 BEAST_EXPECT(badSt.delField(sfSignature));
798 st[sfSequence] = 314159;
799 st[sfPublicKey] = pk;
800 st[sfSigningPubKey] = pk;
816 testcase <<
"deserializeManifest: revocation manifest ("
822 auto const st = buildManifestObject(
828 auto const m = toString(st);
832 BEAST_EXPECT(
manifest->masterKey == pk);
836 BEAST_EXPECT(!
manifest->signingKey);
838 BEAST_EXPECT(
manifest->domain.empty());
839 BEAST_EXPECT(
manifest->serialized == m);
844 auto const st = buildManifestObject(
853 auto const st = buildManifestObject(
862 auto const st = buildManifestObject(
889 st[sfPublicKey] = pk1;
891 st[sfSigningPubKey] = pk2;
908 BEAST_EXPECT(test(
"example.com"));
909 BEAST_EXPECT(test(
"test.example.com"));
910 BEAST_EXPECT(test(
"example-domain.com"));
911 BEAST_EXPECT(test(
"xn--mxavchb.gr"));
912 BEAST_EXPECT(test(
"test.xn--mxavchb.gr"));
913 BEAST_EXPECT(test(
"123.gr"));
914 BEAST_EXPECT(test(
"x.yz"));
915 BEAST_EXPECT(test(
std::string(63,
'a') +
".example.com"));
919 BEAST_EXPECT(!test(
"example"));
922 BEAST_EXPECT(!test(
".com"));
923 BEAST_EXPECT(!test(
".example.com"));
926 BEAST_EXPECT(!test(
"example.com."));
929 BEAST_EXPECT(!test(
"-example.com"));
930 BEAST_EXPECT(!test(
"example-.com"));
933 BEAST_EXPECT(!test(
"double..periods.example.com"));
936 BEAST_EXPECT(!test(
"example.x"));
937 BEAST_EXPECT(!test(
"example." +
std::string(64,
'a')));
940 BEAST_EXPECT(!test(
"example.com-org"));
941 BEAST_EXPECT(!test(
"bang!.com"));
942 BEAST_EXPECT(!test(
"bang!.example.com"));
945 BEAST_EXPECT(!test(
"a.b"));
948 BEAST_EXPECT(!test(
std::string(64,
'a') +
".com"));
949 BEAST_EXPECT(!test(
std::string(64,
'a') +
".example.com"));
996 auto const fake = s_b2.serialized +
'\0';
1020 BEAST_EXPECT(!cache.
revoked(pk_a));
1021 BEAST_EXPECT(s_aMax.revoked());
1032 BEAST_EXPECT(cache.
revoked(pk_a));
testcase_t testcase
Memberspace for declaring test cases.
void fail(String const &reason, char const *file, int line)
Record a failure.
Remembers manifests with the highest sequence number.
std::optional< PublicKey > getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
bool revoked(PublicKey const &pk) const
Returns true if master key has been revoked in a manifest.
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
bool load(DatabaseCon &dbCon, std::string const &dbTable, std::string const &configManifest, std::vector< std::string > const &configRevocation)
Populate manifest cache with manifests in database and config.
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> const &isTrusted)
Save cached manifests to database.
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
void add(Serializer &s) const override
void addWithoutSigningFields(Serializer &s) const
std::size_t size() const noexcept
void const * data() const noexcept
Slice slice() const noexcept
void testManifestVersioning()
void testValidatorToken()
static PublicKey randomNode()
std::string makeRevocationString(SecretKey const &sk, KeyType type, bool invalidSig=false)
void run() override
Runs the suite.
void testManifestDomainNames()
Manifest makeManifest(SecretKey const &sk, KeyType type, SecretKey const &ssk, KeyType stype, int seq, bool invalidSig=false)
static void setupDatabaseDir(boost::filesystem::path const &dbPath)
static PublicKey randomMasterKey()
static boost::filesystem::path getDatabasePath()
static void cleanupDatabaseDir(boost::filesystem::path const &dbPath)
Manifest makeRevocation(SecretKey const &sk, KeyType type, bool invalidSig=false)
std::string makeManifestString(PublicKey const &pk, SecretKey const &sk, PublicKey const &spk, SecretKey const &ssk, int seq)
Manifest clone(Manifest const &m)
void testLoadStore(ManifestCache &m)
void testManifestDeserialization()
A transaction testing environment.
beast::Journal const journal
ManualTimeKeeper & timeKeeper()
Set the regular signature on a JTx.
void sign(Json::Value &jv, Account const &account, Json::Value &sigObject)
Sign automatically into a specific Json field of the jv object.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical=true) noexcept
Verify a signature on a message.
Seed randomSeed()
Create a seed using secure random numbers.
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.
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
SecretKey generateSecretKey(KeyType type, Seed const &seed)
Generate a new secret key deterministically.
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
std::string strHex(FwdIt begin, FwdIt end)
@ badMasterKey
The master key is not acceptable to us.
@ stale
Sequence is too old.
@ accepted
Manifest is valid.
@ badEphemeralKey
The ephemeral key is not acceptable to us.
@ invalid
Timely, but invalid signature.
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
std::string base64_encode(std::uint8_t const *data, std::size_t len)
std::string to_string(base_uint< Bits, Tag > const &a)
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
std::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob, beast::Journal journal)
boost::filesystem::path dataDir
std::string serialized
The manifest in serialized form.
std::uint32_t sequence
The sequence number of this manifest.
std::string domain
The domain, if one was specified in the manifest; empty otherwise.
std::optional< PublicKey > signingKey
The ephemeral key associated with this manifest.
PublicKey masterKey
The master key associated with this manifest.
Set the sequence number on a JTx.