22#include <xrpld/app/main/DBInit.h>
23#include <xrpld/app/misc/Manifest.h>
24#include <xrpld/app/misc/ValidatorList.h>
25#include <xrpld/app/rdb/Wallet.h>
27#include <xrpl/basics/base64.h>
28#include <xrpl/basics/contract.h>
29#include <xrpl/protocol/STExchange.h>
30#include <xrpl/protocol/SecretKey.h>
31#include <xrpl/protocol/Sign.h>
33#include <boost/algorithm/string.hpp>
34#include <boost/filesystem.hpp>
35#include <boost/utility/in_place_factory.hpp>
58 using namespace boost::filesystem;
59 if (!exists(dbPath) || !is_directory(dbPath) || !is_empty(dbPath))
67 using namespace boost::filesystem;
70 create_directory(dbPath);
74 if (!is_directory(dbPath))
77 Throw<std::runtime_error>(
78 "Cannot create directory: " + dbPath.string());
81 static boost::filesystem::path
84 return boost::filesystem::current_path() /
"manifest_test_databases";
118 st[sfSequence] =
seq;
119 st[sfPublicKey] = pk;
120 st[sfSigningPubKey] = spk;
141 bool invalidSig =
false)
147 st[sfPublicKey] = pk;
173 st[sfPublicKey] = pk;
191 return std::move(*r);
192 Throw<std::runtime_error>(
"Could not create a revocation manifest");
204 bool invalidSig =
false)
210 st[sfSequence] =
seq;
211 st[sfPublicKey] = pk;
212 st[sfSigningPubKey] = spk;
231 static_cast<char const*
>(s.
data()),
234 return std::move(*r);
235 Throw<std::runtime_error>(
"Could not create a manifest");
262 auto getPopulatedManifests =
266 cache.for_each_manifest(
276 return lhs->serialized < rhs->serialized;
281 sort(getPopulatedManifests(m)));
283 auto& app = env.
app();
288 app.config().legacy(
"database_path"),
296 "ValidatorManifests",
298 return unl->listed(pubKey);
303 loaded.
load(*dbCon,
"ValidatorManifests");
307 sort(getPopulatedManifests(loaded)));
309 for (
auto const& man : loadedManifests)
310 BEAST_EXPECT(man->revoked());
317 for (
auto const& man : inManifests)
320 unl->load({}, s1, keys);
324 "ValidatorManifests",
326 return unl->listed(pubKey);
329 loaded.
load(*dbCon,
"ValidatorManifests");
333 sort(getPopulatedManifests(loaded)));
335 if (inManifests.
size() == loadedManifests.
size())
340 loadedManifests.
begin(),
356 BEAST_EXPECT(!loaded.
load(
358 "ValidatorManifests",
369 BEAST_EXPECT(loaded.
load(
371 "ValidatorManifests",
382 BEAST_EXPECT(!loaded.
load(
384 "ValidatorManifests",
395 BEAST_EXPECT(!loaded.
load(
397 "ValidatorManifests",
400 BEAST_EXPECT(!loaded.
revoked(pk));
404 BEAST_EXPECT(!loaded.
load(
406 "ValidatorManifests",
409 BEAST_EXPECT(!loaded.
revoked(pk));
413 BEAST_EXPECT(loaded.
load(
415 "ValidatorManifests",
419 BEAST_EXPECT(loaded.
revoked(pk));
422 boost::filesystem::remove(
438 st[sfPublicKey] = pk;
439 st[sfSigningPubKey] = kp.first;
447 BEAST_EXPECT(
strHex(masterSig) ==
strHex(m.getMasterSignature()));
485 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
495 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
503 BEAST_EXPECT(cache.
revoked(pk));
505 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
506 BEAST_EXPECT(cache.
getMasterKey(kp1.first) == kp1.first);
515 auto const valSecret = parseBase58<SecretKey>(
517 "paQmjZ37pKKPMrgadBLsuf9ab7Y7EUNzh27LQrZqoexpAs31nJi");
522 "eyJ2YWxpZGF0aW9uX3NlY3JldF9rZXkiOiI5ZWQ0NWY4NjYyNDFjYzE4YTI3ND"
524 " \tQzODdjMDYyNTkwNzk3MmY0ZTcxOTAyMzFmYWE5Mzc0NTdmYTlkYWY2Iiwib"
526 "\tc3QiOiJKQUFBQUFGeEllMUZ0d21pbXZHdEgyaUNjTUpxQzlnVkZLaWxHZncx"
529 "hYWExwbGMyR25NaEFrRTFhZ3FYeEJ3RHdEYklENk9NU1l1TTBGREFscEFnTms4"
531 "bjdNTzJmZGtjd1JRSWhBT25ndTlzQUtxWFlvdUorbDJWMFcrc0FPa1ZCK1pSUz"
533 "hsSkFmVXNYZkFpQnNWSkdlc2FhZE9KYy9hQVpva1MxdnltR21WcmxIUEtXWDNZ"
535 "NmluOEhBU1FLUHVnQkQ2N2tNYVJGR3ZtcEFUSGxHS0pkdkRGbFdQWXk1QXFEZW"
537 "VUSmEydzBpMjFlcTNNWXl3TFZKWm5GT3I3QzBrdzJBaVR6U0NqSXpkaXRROD0i"
541 "JAAAAAFxIe1FtwmimvGtH2iCcMJqC9gVFKilGfw1/"
542 "vCxHXXLplc2GnMhAkE1agqXxBwD"
543 "wDbID6OMSYuM0FDAlpAgNk8SKFn7MO2fdkcwRQIhAOngu9sAKqXYouJ+l2V0W+"
545 "+ZRS6PShlJAfUsXfAiBsVJGesaadOJc/"
546 "aAZokS1vymGmVrlHPKWX3Yywu6in8HASQKPu"
547 "gBD67kMaRFGvmpATHlGKJdvDFlWPYy5AqDedFv5TJa2w0i21eq3MYywLVJZnFO"
553 BEAST_EXPECT(token->validationSecret == *valSecret);
554 BEAST_EXPECT(token->manifest ==
manifest);
576 st[sfPublicKey] = pk;
577 st[sfSigningPubKey] = spk;
580 st[sfVersion] = version;
614 0x99, 0x30, 0xE7, 0xFC, 0x9D, 0x56, 0xBB, 0x25, 0xD6, 0x89, 0x3B,
615 0xA3, 0xF3, 0x17, 0xAE, 0x5B, 0xCF, 0x33, 0xB3, 0x29, 0x1B, 0xD6,
616 0x3D, 0xB3, 0x26, 0x54, 0xA3, 0x13, 0x22, 0x2F, 0x7F, 0xD0, 0x20};
637 auto toString = [](
STObject const& st) {
644 for (
auto const keyType : keyTypes)
649 for (
auto const sKeyType : keyTypes)
654 auto buildManifestObject =
657 bool noSigningPublic =
false,
658 bool noSignature =
false) {
660 st[sfSequence] =
seq;
661 st[sfPublicKey] = pk;
666 if (!noSigningPublic)
667 st[sfSigningPubKey] = spk;
683 testcase <<
"deserializeManifest: normal manifest ("
691 auto const m = toString(st);
695 BEAST_EXPECT(
manifest->masterKey == pk);
696 BEAST_EXPECT(
manifest->signingKey == spk);
697 BEAST_EXPECT(
manifest->sequence == sequence);
698 BEAST_EXPECT(
manifest->serialized == m);
699 BEAST_EXPECT(
manifest->domain.empty());
712 buildManifestObject(++sequence,
std::string{
"a.b"});
718 buildManifestObject(++sequence, s +
".example.com");
724 buildManifestObject(++sequence, s +
".example.com");
728 auto const st = buildManifestObject(
733 auto const m = toString(st);
737 BEAST_EXPECT(
manifest->masterKey == pk);
738 BEAST_EXPECT(
manifest->signingKey == spk);
739 BEAST_EXPECT(
manifest->sequence == sequence);
740 BEAST_EXPECT(
manifest->serialized == m);
741 BEAST_EXPECT(
manifest->domain ==
"example.com");
747 badSigSt[sfSequence] = sequence + 1;
749 auto const m = toString(badSigSt);
753 BEAST_EXPECT(
manifest->masterKey == pk);
754 BEAST_EXPECT(
manifest->signingKey == spk);
755 BEAST_EXPECT(
manifest->sequence == sequence + 1);
756 BEAST_EXPECT(
manifest->serialized == m);
757 BEAST_EXPECT(
manifest->domain ==
"example.com");
763 BEAST_EXPECT(badSt.delField(sfSequence));
769 BEAST_EXPECT(badSt.delField(sfPublicKey));
781 badSt[sfPublicKey] =
makeSlice(shortKey);
787 BEAST_EXPECT(badSt.delField(sfSigningPubKey));
793 badSt[sfSigningPubKey] =
makeSlice(badKey);
799 badSt[sfSigningPubKey] =
makeSlice(shortKey);
805 BEAST_EXPECT(badSt.delField(sfMasterSignature));
811 BEAST_EXPECT(badSt.delField(sfSignature));
817 st[sfSequence] = 314159;
818 st[sfPublicKey] = pk;
819 st[sfSigningPubKey] = pk;
835 testcase <<
"deserializeManifest: revocation manifest ("
841 auto const st = buildManifestObject(
847 auto const m = toString(st);
851 BEAST_EXPECT(
manifest->masterKey == pk);
855 BEAST_EXPECT(!
manifest->signingKey);
857 BEAST_EXPECT(
manifest->domain.empty());
858 BEAST_EXPECT(
manifest->serialized == m);
863 auto const st = buildManifestObject(
872 auto const st = buildManifestObject(
881 auto const st = buildManifestObject(
908 st[sfPublicKey] = pk1;
910 st[sfSigningPubKey] = pk2;
927 BEAST_EXPECT(test(
"example.com"));
928 BEAST_EXPECT(test(
"test.example.com"));
929 BEAST_EXPECT(test(
"example-domain.com"));
930 BEAST_EXPECT(test(
"xn--mxavchb.gr"));
931 BEAST_EXPECT(test(
"test.xn--mxavchb.gr"));
932 BEAST_EXPECT(test(
"123.gr"));
933 BEAST_EXPECT(test(
"x.yz"));
934 BEAST_EXPECT(test(
std::string(63,
'a') +
".example.com"));
938 BEAST_EXPECT(!test(
"example"));
941 BEAST_EXPECT(!test(
".com"));
942 BEAST_EXPECT(!test(
".example.com"));
945 BEAST_EXPECT(!test(
"example.com."));
948 BEAST_EXPECT(!test(
"-example.com"));
949 BEAST_EXPECT(!test(
"example-.com"));
952 BEAST_EXPECT(!test(
"double..periods.example.com"));
955 BEAST_EXPECT(!test(
"example.x"));
956 BEAST_EXPECT(!test(
"example." +
std::string(64,
'a')));
959 BEAST_EXPECT(!test(
"example.com-org"));
960 BEAST_EXPECT(!test(
"bang!.com"));
961 BEAST_EXPECT(!test(
"bang!.example.com"));
964 BEAST_EXPECT(!test(
"a.b"));
967 BEAST_EXPECT(!test(
std::string(64,
'a') +
".com"));
968 BEAST_EXPECT(!test(
std::string(64,
'a') +
".example.com"));
1015 auto const fake = s_b2.serialized +
'\0';
1039 BEAST_EXPECT(!cache.
revoked(pk_a));
1040 BEAST_EXPECT(s_aMax.revoked());
1051 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)
Sign automatically.
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.