2#include <test/unit_test/utils.h>
4#include <xrpld/app/misc/ValidatorList.h>
6#include <xrpl/basics/base64.h>
7#include <xrpl/basics/contract.h>
8#include <xrpl/protocol/STExchange.h>
9#include <xrpl/protocol/SecretKey.h>
10#include <xrpl/protocol/Sign.h>
11#include <xrpl/rdb/DBInit.h>
12#include <xrpl/server/Manifest.h>
13#include <xrpl/server/Wallet.h>
15#include <boost/algorithm/string.hpp>
16#include <boost/filesystem.hpp>
17#include <boost/utility/in_place_factory.hpp>
40 using namespace boost::filesystem;
41 if (!exists(dbPath) || !is_directory(dbPath) || !is_empty(dbPath))
49 using namespace boost::filesystem;
52 create_directory(dbPath);
56 if (!is_directory(dbPath))
59 Throw<std::runtime_error>(
"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 st[sfPublicKey] = pk;
141 st[sfPublicKey] = pk;
152 return std::move(*r);
153 Throw<std::runtime_error>(
"Could not create a revocation manifest");
164 bool invalidSig =
false)
170 st[sfSequence] =
seq;
171 st[sfPublicKey] = pk;
172 st[sfSigningPubKey] = spk;
186 return std::move(*r);
187 Throw<std::runtime_error>(
"Could not create a manifest");
212 auto getPopulatedManifests =
216 cache.for_each_manifest([&result](
Manifest const& man) { result.
push_back(&man); });
221 return lhs->serialized < rhs->serialized;
227 auto& app = env.
app();
234 m.
save(*dbCon,
"ValidatorManifests", [&unl](
PublicKey const& pubKey) {
235 return unl->listed(pubKey);
240 loaded.
load(*dbCon,
"ValidatorManifests");
244 sort(getPopulatedManifests(loaded)));
246 for (
auto const& man : loadedManifests)
247 BEAST_EXPECT(man->revoked());
255 for (
auto const& man : inManifests)
257 unl->load({}, s1, keys);
259 m.
save(*dbCon,
"ValidatorManifests", [&unl](
PublicKey const& pubKey) {
260 return unl->listed(pubKey);
263 loaded.
load(*dbCon,
"ValidatorManifests");
267 sort(getPopulatedManifests(loaded)));
269 if (inManifests.
size() == loadedManifests.
size())
275 loadedManifests.
begin(),
290 !loaded.
load(*dbCon,
"ValidatorManifests", badManifest, emptyRevocation));
299 loaded.
load(*dbCon,
"ValidatorManifests", cfgManifest, emptyRevocation));
308 !loaded.
load(*dbCon,
"ValidatorManifests", emptyManifest, badRevocation));
318 !loaded.
load(*dbCon,
"ValidatorManifests", emptyManifest, nonRevocation));
319 BEAST_EXPECT(!loaded.
revoked(pk));
324 !loaded.
load(*dbCon,
"ValidatorManifests", emptyManifest, badSigRevocation));
325 BEAST_EXPECT(!loaded.
revoked(pk));
329 loaded.
load(*dbCon,
"ValidatorManifests", emptyManifest, cfgRevocation));
331 BEAST_EXPECT(loaded.
revoked(pk));
334 boost::filesystem::remove(
getDatabasePath() / boost::filesystem::path(dbName));
348 st[sfPublicKey] = pk;
349 st[sfSigningPubKey] = kp.first;
356 strHex(*m.getSignature()));
359 BEAST_EXPECT(
strHex(masterSig) ==
strHex(m.getMasterSignature()));
397 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
407 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
415 BEAST_EXPECT(cache.
revoked(pk));
417 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
418 BEAST_EXPECT(cache.
getMasterKey(kp1.first) == kp1.first);
427 auto const valSecret = parseBase58<SecretKey>(
432 " eyJ2YWxpZGF0aW9uX3NlY3JldF9rZXkiOiI5ZWQ0NWY4NjYyNDFjYzE4YTI3NDdiNT\n",
433 " \tQzODdjMDYyNTkwNzk3MmY0ZTcxOTAyMzFmYWE5Mzc0NTdmYTlkYWY2IiwibWFuaWZl \n",
434 "\tc3QiOiJKQUFBQUFGeEllMUZ0d21pbXZHdEgyaUNjTUpxQzlnVkZLaWxHZncxL3ZDeE\n",
435 "\t hYWExwbGMyR25NaEFrRTFhZ3FYeEJ3RHdEYklENk9NU1l1TTBGREFscEFnTms4U0tG\t \t\n",
436 "bjdNTzJmZGtjd1JRSWhBT25ndTlzQUtxWFlvdUorbDJWMFcrc0FPa1ZCK1pSUzZQU2\n",
437 "hsSkFmVXNYZkFpQnNWSkdlc2FhZE9KYy9hQVpva1MxdnltR21WcmxIUEtXWDNZeXd1\n",
438 "NmluOEhBU1FLUHVnQkQ2N2tNYVJGR3ZtcEFUSGxHS0pkdkRGbFdQWXk1QXFEZWRGdj\n",
439 "VUSmEydzBpMjFlcTNNWXl3TFZKWm5GT3I3QzBrdzJBaVR6U0NqSXpkaXRROD0ifQ==\n",
443 "JAAAAAFxIe1FtwmimvGtH2iCcMJqC9gVFKilGfw1/"
444 "vCxHXXLplc2GnMhAkE1agqXxBwD"
445 "wDbID6OMSYuM0FDAlpAgNk8SKFn7MO2fdkcwRQIhAOngu9sAKqXYouJ+l2V0W+"
447 "+ZRS6PShlJAfUsXfAiBsVJGesaadOJc/"
448 "aAZokS1vymGmVrlHPKWX3Yywu6in8HASQKPu"
449 "gBD67kMaRFGvmpATHlGKJdvDFlWPYy5AqDedFv5TJa2w0i21eq3MYywLVJZnFO"
456 BEAST_EXPECT(
test::equal(token->validationSecret, *valSecret));
458 BEAST_EXPECT(token->manifest ==
manifest);
480 st[sfPublicKey] = pk;
481 st[sfSigningPubKey] = spk;
484 st[sfVersion] = version;
512 0x99, 0x30, 0xE7, 0xFC, 0x9D, 0x56, 0xBB, 0x25, 0xD6, 0x89, 0x3B,
513 0xA3, 0xF3, 0x17, 0xAE, 0x5B, 0xCF, 0x33, 0xB3, 0x29, 0x1B, 0xD6,
514 0x3D, 0xB3, 0x26, 0x54, 0xA3, 0x13, 0x22, 0x2F, 0x7F, 0xD0, 0x20};
535 auto toString = [](
STObject const& st) {
542 for (
auto const keyType : keyTypes)
547 for (
auto const sKeyType : keyTypes)
554 bool noSigningPublic =
false,
555 bool noSignature =
false) {
557 st[sfSequence] =
seq;
558 st[sfPublicKey] = pk;
563 if (!noSigningPublic)
564 st[sfSigningPubKey] = spk;
579 auto const st = buildManifestObject(++sequence,
std::nullopt);
581 auto const m = toString(st);
586 BEAST_EXPECT(
manifest->masterKey == pk);
587 BEAST_EXPECT(
manifest->signingKey == spk);
588 BEAST_EXPECT(
manifest->sequence == sequence);
589 BEAST_EXPECT(
manifest->serialized == m);
590 BEAST_EXPECT(
manifest->domain.empty());
596 auto const st = buildManifestObject(++sequence,
std::string{});
602 auto const st = buildManifestObject(++sequence,
std::string{
"a.b"});
607 auto const st = buildManifestObject(++sequence, s +
".example.com");
612 auto const st = buildManifestObject(++sequence, s +
".example.com");
616 auto const st = buildManifestObject(++sequence,
std::string{
"example.com"});
620 auto const m = toString(st);
625 BEAST_EXPECT(
manifest->masterKey == pk);
626 BEAST_EXPECT(
manifest->signingKey == spk);
627 BEAST_EXPECT(
manifest->sequence == sequence);
628 BEAST_EXPECT(
manifest->serialized == m);
629 BEAST_EXPECT(
manifest->domain ==
"example.com");
636 badSigSt[sfSequence] = sequence + 1;
638 auto const m = toString(badSigSt);
643 BEAST_EXPECT(
manifest->masterKey == pk);
644 BEAST_EXPECT(
manifest->signingKey == spk);
645 BEAST_EXPECT(
manifest->sequence == sequence + 1);
646 BEAST_EXPECT(
manifest->serialized == m);
647 BEAST_EXPECT(
manifest->domain ==
"example.com");
654 BEAST_EXPECT(badSt.delField(sfSequence));
660 BEAST_EXPECT(badSt.delField(sfPublicKey));
672 badSt[sfPublicKey] =
makeSlice(shortKey);
678 BEAST_EXPECT(badSt.delField(sfSigningPubKey));
684 badSt[sfSigningPubKey] =
makeSlice(badKey);
690 badSt[sfSigningPubKey] =
makeSlice(shortKey);
696 BEAST_EXPECT(badSt.delField(sfMasterSignature));
702 BEAST_EXPECT(badSt.delField(sfSignature));
708 st[sfSequence] = 314159;
709 st[sfPublicKey] = pk;
710 st[sfSigningPubKey] = pk;
726 auto const st = buildManifestObject(
729 auto const m = toString(st);
734 BEAST_EXPECT(
manifest->masterKey == pk);
737 BEAST_EXPECT(!
manifest->signingKey);
739 BEAST_EXPECT(
manifest->domain.empty());
740 BEAST_EXPECT(
manifest->serialized == m);
746 auto const st = buildManifestObject(
752 auto const st = buildManifestObject(
758 auto const st = buildManifestObject(
782 st[sfPublicKey] = pk1;
784 st[sfSigningPubKey] = pk2;
795 BEAST_EXPECT(test(
"example.com"));
796 BEAST_EXPECT(test(
"test.example.com"));
797 BEAST_EXPECT(test(
"example-domain.com"));
798 BEAST_EXPECT(test(
"xn--mxavchb.gr"));
799 BEAST_EXPECT(test(
"test.xn--mxavchb.gr"));
800 BEAST_EXPECT(test(
"123.gr"));
801 BEAST_EXPECT(test(
"x.yz"));
802 BEAST_EXPECT(test(
std::string(63,
'a') +
".example.com"));
806 BEAST_EXPECT(!test(
"example"));
809 BEAST_EXPECT(!test(
".com"));
810 BEAST_EXPECT(!test(
".example.com"));
813 BEAST_EXPECT(!test(
"example.com."));
816 BEAST_EXPECT(!test(
"-example.com"));
817 BEAST_EXPECT(!test(
"example-.com"));
820 BEAST_EXPECT(!test(
"double..periods.example.com"));
823 BEAST_EXPECT(!test(
"example.x"));
824 BEAST_EXPECT(!test(
"example." +
std::string(64,
'a')));
827 BEAST_EXPECT(!test(
"example.com-org"));
828 BEAST_EXPECT(!test(
"bang!.com"));
829 BEAST_EXPECT(!test(
"bang!.example.com"));
832 BEAST_EXPECT(!test(
"a.b"));
835 BEAST_EXPECT(!test(
std::string(64,
'a') +
".com"));
836 BEAST_EXPECT(!test(
std::string(64,
'a') +
".example.com"));
881 auto const fake = s_b2.serialized +
'\0';
887 BEAST_EXPECT(cache.
sequence() > seq0);
891 BEAST_EXPECT(cache.
sequence() == seq1);
901 BEAST_EXPECT(!cache.
revoked(pk_a));
902 BEAST_EXPECT(s_aMax.revoked());
907 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.
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.
std::optional< PublicKey > getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
std::uint32_t sequence() const
A monotonically increasing number used to detect new manifests.
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> const &isTrusted)
Save cached manifests to database.
bool revoked(PublicKey const &pk) const
Returns true if master key has been revoked in a manifest.
void addWithoutSigningFields(Serializer &s) const
void add(Serializer &s) const override
Slice slice() const noexcept
std::size_t size() const noexcept
void const * data() const noexcept
static Manifest clone(Manifest const &m)
void testManifestDeserialization()
void testLoadStore(ManifestCache &m)
static PublicKey randomMasterKey()
void run() override
Runs the suite.
static std::string makeManifestString(PublicKey const &pk, SecretKey const &sk, PublicKey const &spk, SecretKey const &ssk, int seq)
void testValidatorToken()
void testManifestDomainNames()
std::string makeRevocationString(SecretKey const &sk, KeyType type, bool invalidSig=false)
static void setupDatabaseDir(boost::filesystem::path const &dbPath)
static void cleanupDatabaseDir(boost::filesystem::path const &dbPath)
Manifest makeManifest(SecretKey const &sk, KeyType type, SecretKey const &ssk, KeyType stype, int seq, bool invalidSig=false)
static PublicKey randomNode()
static boost::filesystem::path getDatabasePath()
void testManifestVersioning()
Manifest makeRevocation(SecretKey const &sk, KeyType type, bool invalidSig=false)
A transaction testing environment.
ManualTimeKeeper & timeKeeper()
beast::Journal const journal
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.
bool equal(std::unique_ptr< Step > const &s1, DirectStepInfo const &dsi)
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.
Seed randomSeed()
Create a seed using secure random numbers.
std::string to_string(base_uint< Bits, Tag > const &a)
std::string strHex(FwdIt begin, FwdIt end)
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig) noexcept
Verify a signature on a message.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
SecretKey generateSecretKey(KeyType type, Seed const &seed)
Generate a new secret key deterministically.
std::string base64_encode(std::uint8_t const *data, std::size_t len)
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
SecretKey randomSecretKey()
Create a secret key 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.
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)
std::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob, beast::Journal journal=beast::Journal(beast::Journal::getNullSink()))
@ 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.
boost::filesystem::path dataDir
PublicKey masterKey
The master key associated with this manifest.
std::string serialized
The manifest in serialized form.
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.
std::uint32_t sequence
The sequence number of this manifest.
Set the sequence number on a JTx.