20 #include <ripple/app/main/DBInit.h>
21 #include <ripple/app/misc/Manifest.h>
22 #include <ripple/app/misc/ValidatorList.h>
23 #include <ripple/app/rdb/Wallet.h>
24 #include <ripple/basics/StringUtilities.h>
25 #include <ripple/basics/base64.h>
26 #include <ripple/basics/contract.h>
27 #include <ripple/protocol/STExchange.h>
28 #include <ripple/protocol/SecretKey.h>
29 #include <ripple/protocol/Sign.h>
30 #include <boost/algorithm/string.hpp>
31 #include <boost/filesystem.hpp>
32 #include <boost/utility/in_place_factory.hpp>
56 using namespace boost::filesystem;
57 if (!exists(dbPath) || !is_directory(dbPath) || !is_empty(dbPath))
65 using namespace boost::filesystem;
68 create_directory(dbPath);
72 if (!is_directory(dbPath))
75 Throw<std::runtime_error>(
76 "Cannot create directory: " + dbPath.string());
79 static boost::filesystem::path
82 return boost::filesystem::current_path() /
"manifest_test_databases";
139 bool invalidSig =
false)
189 return std::move(*r);
190 Throw<std::runtime_error>(
"Could not create a revocation manifest");
202 bool invalidSig =
false)
229 static_cast<char const*
>(s.
data()),
232 return std::move(*r);
233 Throw<std::runtime_error>(
"Could not create a manifest");
253 testcase(
"load/store");
264 auto getPopulatedManifests =
268 cache.for_each_manifest(
278 return lhs->serialized < rhs->serialized;
283 sort(getPopulatedManifests(m)));
285 auto& app = env.
app();
286 auto unl = std::make_unique<ValidatorList>(
290 app.config().legacy(
"database_path"),
298 "ValidatorManifests",
300 return unl->listed(pubKey);
305 loaded.
load(*dbCon,
"ValidatorManifests");
309 sort(getPopulatedManifests(loaded)));
311 for (
auto const& man : loadedManifests)
312 BEAST_EXPECT(man->revoked());
320 for (
auto const& man : inManifests)
323 unl->load(emptyLocalKey, s1, keys);
327 "ValidatorManifests",
329 return unl->listed(pubKey);
332 loaded.
load(*dbCon,
"ValidatorManifests");
336 sort(getPopulatedManifests(loaded)));
338 if (inManifests.size() == loadedManifests.
size())
343 loadedManifests.
begin(),
359 BEAST_EXPECT(!loaded.
load(
361 "ValidatorManifests",
372 BEAST_EXPECT(loaded.
load(
374 "ValidatorManifests",
385 BEAST_EXPECT(!loaded.
load(
387 "ValidatorManifests",
398 BEAST_EXPECT(!loaded.
load(
400 "ValidatorManifests",
403 BEAST_EXPECT(!loaded.
revoked(pk));
407 BEAST_EXPECT(!loaded.
load(
409 "ValidatorManifests",
412 BEAST_EXPECT(!loaded.
revoked(pk));
416 BEAST_EXPECT(loaded.
load(
418 "ValidatorManifests",
422 BEAST_EXPECT(loaded.
revoked(pk));
425 boost::filesystem::remove(
432 testcase(
"getSignature");
450 BEAST_EXPECT(
strHex(masterSig) ==
strHex(m.getMasterSignature()));
488 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
498 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
506 BEAST_EXPECT(cache.
revoked(pk));
508 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
509 BEAST_EXPECT(cache.
getMasterKey(kp1.first) == kp1.first);
515 testcase(
"validator token");
518 auto const valSecret = parseBase58<SecretKey>(
520 "paQmjZ37pKKPMrgadBLsuf9ab7Y7EUNzh27LQrZqoexpAs31nJi");
525 "eyJ2YWxpZGF0aW9uX3NlY3JldF9rZXkiOiI5ZWQ0NWY4NjYyNDFjYzE4YTI3ND"
527 " \tQzODdjMDYyNTkwNzk3MmY0ZTcxOTAyMzFmYWE5Mzc0NTdmYTlkYWY2Iiwib"
529 "\tc3QiOiJKQUFBQUFGeEllMUZ0d21pbXZHdEgyaUNjTUpxQzlnVkZLaWxHZncx"
532 "hYWExwbGMyR25NaEFrRTFhZ3FYeEJ3RHdEYklENk9NU1l1TTBGREFscEFnTms4"
534 "bjdNTzJmZGtjd1JRSWhBT25ndTlzQUtxWFlvdUorbDJWMFcrc0FPa1ZCK1pSUz"
536 "hsSkFmVXNYZkFpQnNWSkdlc2FhZE9KYy9hQVpva1MxdnltR21WcmxIUEtXWDNZ"
538 "NmluOEhBU1FLUHVnQkQ2N2tNYVJGR3ZtcEFUSGxHS0pkdkRGbFdQWXk1QXFEZW"
540 "VUSmEydzBpMjFlcTNNWXl3TFZKWm5GT3I3QzBrdzJBaVR6U0NqSXpkaXRROD0i"
544 "JAAAAAFxIe1FtwmimvGtH2iCcMJqC9gVFKilGfw1/"
545 "vCxHXXLplc2GnMhAkE1agqXxBwD"
546 "wDbID6OMSYuM0FDAlpAgNk8SKFn7MO2fdkcwRQIhAOngu9sAKqXYouJ+l2V0W+"
548 "+ZRS6PShlJAfUsXfAiBsVJGesaadOJc/"
549 "aAZokS1vymGmVrlHPKWX3Yywu6in8HASQKPu"
550 "gBD67kMaRFGvmpATHlGKJdvDFlWPYy5AqDedFv5TJa2w0i21eq3MYywLVJZnFO"
556 BEAST_EXPECT(token->validationSecret == *valSecret);
557 BEAST_EXPECT(token->manifest ==
manifest);
568 testcase(
"Versioning");
617 0x99, 0x30, 0xE7, 0xFC, 0x9D, 0x56, 0xBB, 0x25, 0xD6, 0x89, 0x3B,
618 0xA3, 0xF3, 0x17, 0xAE, 0x5B, 0xCF, 0x33, 0xB3, 0x29, 0x1B, 0xD6,
619 0x3D, 0xB3, 0x26, 0x54, 0xA3, 0x13, 0x22, 0x2F, 0x7F, 0xD0, 0x20};
640 auto toString = [](
STObject const& st) {
647 for (
auto const keyType : keyTypes)
652 for (
auto const sKeyType : keyTypes)
657 auto buildManifestObject =
660 bool noSigningPublic =
false,
661 bool noSignature =
false) {
669 if (!noSigningPublic)
686 testcase <<
"deserializeManifest: normal manifest ("
692 buildManifestObject(++sequence, std::nullopt);
694 auto const m = toString(st);
698 BEAST_EXPECT(
manifest->masterKey == pk);
699 BEAST_EXPECT(
manifest->signingKey == spk);
700 BEAST_EXPECT(
manifest->sequence == sequence);
701 BEAST_EXPECT(
manifest->serialized == m);
702 BEAST_EXPECT(
manifest->domain.empty());
715 buildManifestObject(++sequence,
std::string{
"a.b"});
721 buildManifestObject(++sequence, s +
".example.com");
727 buildManifestObject(++sequence, s +
".example.com");
731 auto const st = buildManifestObject(
736 auto const m = toString(st);
740 BEAST_EXPECT(
manifest->masterKey == pk);
741 BEAST_EXPECT(
manifest->signingKey == spk);
742 BEAST_EXPECT(
manifest->sequence == sequence);
743 BEAST_EXPECT(
manifest->serialized == m);
744 BEAST_EXPECT(
manifest->domain ==
"example.com");
752 auto const m = toString(badSigSt);
756 BEAST_EXPECT(
manifest->masterKey == pk);
757 BEAST_EXPECT(
manifest->signingKey == spk);
758 BEAST_EXPECT(
manifest->sequence == sequence + 1);
759 BEAST_EXPECT(
manifest->serialized == m);
760 BEAST_EXPECT(
manifest->domain ==
"example.com");
838 testcase <<
"deserializeManifest: revocation manifest ("
844 auto const st = buildManifestObject(
850 auto const m = toString(st);
854 BEAST_EXPECT(
manifest->masterKey == pk);
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(
897 testcase(
"Manifest Domain Names");
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));
std::string domain
The domain, if one was specified in the manifest; empty otherwise.
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)
static boost::filesystem::path getDatabasePath()
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
const SField sfGeneric(access, 0)
std::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob, beast::Journal journal)
const SF_UINT32 sfSequence
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical) noexcept
Verify a signature on a message.
PublicKey signingKey
The ephemeral key associated with this manifest.
std::string serialized
The manifest in serialized form.
std::string base64_encode(std::uint8_t const *data, std::size_t len)
PublicKey masterKey
The master key associated with this manifest.
const SF_VL sfSigningPubKey
std::string makeManifestString(PublicKey const &pk, SecretKey const &sk, PublicKey const &spk, SecretKey const &ssk, int seq)
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
const beast::Journal journal
ManualTimeKeeper & timeKeeper()
@ badEphemeralKey
The ephemeral key is not acceptable to us.
boost::filesystem::path dataDir
std::unique_ptr< DatabaseCon > makeTestWalletDB(DatabaseCon::Setup const &setup, std::string const &dbname)
makeTestWalletDB Opens a test wallet database with an arbitrary name.
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> const &isTrusted)
Save cached manifests to database.
void const * data() const noexcept
std::string makeRevocationString(SecretKey const &sk, KeyType type, bool invalidSig=false)
const SF_UINT16 sfVersion
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Manifest clone(Manifest const &m)
static PublicKey randomNode()
@ badMasterKey
The master key is not acceptable to us.
Manifest makeRevocation(SecretKey const &sk, KeyType type, bool invalidSig=false)
void testManifestDeserialization()
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
const SF_VL sfMasterSignature
bool revoked(PublicKey const &pk) const
Returns true if master key has been revoked in a manifest.
void testLoadStore(ManifestCache &m)
Seed randomSeed()
Create a seed using secure random numbers.
Slice slice() const noexcept
SecretKey generateSecretKey(KeyType type, Seed const &seed)
Generate a new secret key deterministically.
PublicKey getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
Set the regular signature on a JTx.
void addWithoutSigningFields(Serializer &s) const
static PublicKey randomMasterKey()
static void cleanupDatabaseDir(boost::filesystem::path const &dbPath)
@ invalid
Timely, but invalid signature.
void testManifestVersioning()
@ accepted
Manifest is valid.
std::uint32_t sequence
The sequence number of this manifest.
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
Set the sequence number on a JTx.
Remembers manifests with the highest sequence number.
void add(Serializer &s) const override
@ stale
Sequence is too old.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::size_t size() const noexcept
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &m)
Generate a signature for a message.
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)
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
int add32(std::uint32_t i)
std::string strHex(FwdIt begin, FwdIt end)
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
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.
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
void testValidatorToken()
A transaction testing environment.
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
BEAST_DEFINE_TESTSUITE(DeliverMin, app, ripple)