20 #include <ripple/app/misc/Manifest.h>
21 #include <ripple/app/misc/ValidatorList.h>
22 #include <ripple/basics/base64.h>
23 #include <ripple/basics/contract.h>
24 #include <ripple/basics/StringUtilities.h>
26 #include <ripple/core/DatabaseCon.h>
27 #include <ripple/app/main/DBInit.h>
28 #include <ripple/protocol/SecretKey.h>
29 #include <ripple/protocol/Sign.h>
30 #include <ripple/protocol/STExchange.h>
31 #include <boost/filesystem.hpp>
32 #include <boost/algorithm/string.hpp>
33 #include <boost/utility/in_place_factory.hpp>
57 using namespace boost::filesystem;
58 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> (
"Cannot create directory: " +
81 return boost::filesystem::current_path () /
"manifest_test_databases";
127 static_cast<char const*
> (s.
data()), s.
size()));
134 bool invalidSig =
false)
144 BEAST_EXPECT(invalidSig ^
verify(
151 static_cast<char const*
> (s.
data()), s.
size()));
166 BEAST_EXPECT(invalidSig ^
verify(
174 return std::move(*r);
175 Throw<std::runtime_error> (
"Could not create a revocation manifest");
182 int seq,
bool invalidSig =
false)
197 BEAST_EXPECT(invalidSig ^
verify(
205 return std::move (*r);
206 Throw<std::runtime_error> (
"Could not create a manifest");
224 testcase (
"load/store");
236 auto getPopulatedManifests =
241 cache.for_each_manifest (
250 { return lhs->serialized < rhs->serialized; });
254 sort (getPopulatedManifests (m)));
257 auto& app = env.
app();
258 auto unl = std::make_unique<ValidatorList> (
260 app.config().legacy(
"database_path"),
266 m.
save (dbCon,
"ValidatorManifests",
269 return unl->listed (pubKey);
274 loaded.
load (dbCon,
"ValidatorManifests");
278 sort (getPopulatedManifests (loaded)));
280 for (
auto const& man : loadedManifests)
281 BEAST_EXPECT(man->revoked());
289 for (
auto const& man : inManifests)
292 unl->load (emptyLocalKey, s1, keys);
294 m.
save (dbCon,
"ValidatorManifests",
297 return unl->listed (pubKey);
300 loaded.
load (dbCon,
"ValidatorManifests");
304 sort (getPopulatedManifests (loaded)));
306 if (inManifests.size () == loadedManifests.
size ())
309 (inManifests.begin (), inManifests.end (),
310 loadedManifests.
begin (),
312 {return *lhs == *rhs;}));
325 BEAST_EXPECT(! loaded.
load (
326 dbCon,
"ValidatorManifests", badManifest, emptyRevocation));
335 BEAST_EXPECT(loaded.
load (
336 dbCon,
"ValidatorManifests", cfgManifest, emptyRevocation));
344 BEAST_EXPECT(! loaded.
load (
345 dbCon,
"ValidatorManifests", emptyManifest, badRevocation));
354 BEAST_EXPECT(! loaded.
load (
355 dbCon,
"ValidatorManifests", emptyManifest, nonRevocation));
356 BEAST_EXPECT(! loaded.
revoked(pk));
360 BEAST_EXPECT(! loaded.
load (
361 dbCon,
"ValidatorManifests", emptyManifest, badSigRevocation));
362 BEAST_EXPECT(! loaded.
revoked(pk));
366 BEAST_EXPECT(loaded.
load (
367 dbCon,
"ValidatorManifests", emptyManifest, cfgRevocation));
369 BEAST_EXPECT(loaded.
revoked(pk));
373 boost::filesystem::path (dbName));
378 testcase (
"getSignature");
396 BEAST_EXPECT(
strHex(masterSig) ==
strHex(m.getMasterSignature()));
401 testcase (
"getKeys");
431 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
441 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
449 BEAST_EXPECT(cache.
revoked(pk));
451 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
452 BEAST_EXPECT(cache.
getMasterKey(kp1.first) == kp1.first);
457 testcase (
"validator token");
460 auto const valSecret = parseBase58<SecretKey>(
462 "paQmjZ37pKKPMrgadBLsuf9ab7Y7EUNzh27LQrZqoexpAs31nJi");
466 " eyJ2YWxpZGF0aW9uX3NlY3JldF9rZXkiOiI5ZWQ0NWY4NjYyNDFjYzE4YTI3NDdiNT\n",
467 " \tQzODdjMDYyNTkwNzk3MmY0ZTcxOTAyMzFmYWE5Mzc0NTdmYTlkYWY2IiwibWFuaWZl \n",
468 "\tc3QiOiJKQUFBQUFGeEllMUZ0d21pbXZHdEgyaUNjTUpxQzlnVkZLaWxHZncxL3ZDeE\n",
469 "\t hYWExwbGMyR25NaEFrRTFhZ3FYeEJ3RHdEYklENk9NU1l1TTBGREFscEFnTms4U0tG\t \t\n",
470 "bjdNTzJmZGtjd1JRSWhBT25ndTlzQUtxWFlvdUorbDJWMFcrc0FPa1ZCK1pSUzZQU2\n",
471 "hsSkFmVXNYZkFpQnNWSkdlc2FhZE9KYy9hQVpva1MxdnltR21WcmxIUEtXWDNZeXd1\n",
472 "NmluOEhBU1FLUHVnQkQ2N2tNYVJGR3ZtcEFUSGxHS0pkdkRGbFdQWXk1QXFEZWRGdj\n",
473 "VUSmEydzBpMjFlcTNNWXl3TFZKWm5GT3I3QzBrdzJBaVR6U0NqSXpkaXRROD0ifQ==\n"
477 "JAAAAAFxIe1FtwmimvGtH2iCcMJqC9gVFKilGfw1/vCxHXXLplc2GnMhAkE1agqXxBwD"
478 "wDbID6OMSYuM0FDAlpAgNk8SKFn7MO2fdkcwRQIhAOngu9sAKqXYouJ+l2V0W+sAOkVB"
479 "+ZRS6PShlJAfUsXfAiBsVJGesaadOJc/aAZokS1vymGmVrlHPKWX3Yywu6in8HASQKPu"
480 "gBD67kMaRFGvmpATHlGKJdvDFlWPYy5AqDedFv5TJa2w0i21eq3MYywLVJZnFOr7C0kw"
485 BEAST_EXPECT(token->validationSecret == *valSecret);
486 BEAST_EXPECT(token->manifest ==
manifest);
496 testcase (
"Versioning");
540 auto const ret =
strUnHex(
"9930E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020");
541 auto const badKey =
Slice{ret->
data(), ret->size()};
544 auto const retShort =
strUnHex(
"0330");
545 auto const shortKey =
Slice{retShort->
data(), retShort->size()};
547 auto toString = [](
STObject const& st)
555 for (
auto const keyType : keyTypes)
560 for (
auto const sKeyType : keyTypes)
565 auto buildManifestObject = [&](
567 boost::optional<std::string> domain,
568 bool noSigningPublic =
false,
569 bool noSignature =
false)
578 if (! noSigningPublic)
590 testcase <<
"deserializeManifest: normal manifest (" <<
595 auto const st = buildManifestObject(
596 ++sequence, boost::none);
598 auto const m = toString(st);
602 BEAST_EXPECT(
manifest->masterKey == pk);
603 BEAST_EXPECT(
manifest->signingKey == spk);
604 BEAST_EXPECT(
manifest->sequence == sequence);
605 BEAST_EXPECT(
manifest->serialized == m);
606 BEAST_EXPECT(
manifest->domain.empty());
611 auto const st = buildManifestObject(
618 auto const st = buildManifestObject(
624 auto const st = buildManifestObject(
625 ++sequence, s +
".example.com");
630 auto const st = buildManifestObject(
631 ++sequence, s +
".example.com");
635 auto const st = buildManifestObject(
640 auto const m = toString(st);
644 BEAST_EXPECT(
manifest->masterKey == pk);
645 BEAST_EXPECT(
manifest->signingKey == spk);
646 BEAST_EXPECT(
manifest->sequence == sequence);
647 BEAST_EXPECT(
manifest->serialized == m);
648 BEAST_EXPECT(
manifest->domain ==
"example.com");
656 auto const m = toString(badSigSt);
660 BEAST_EXPECT(
manifest->masterKey == spk);
661 BEAST_EXPECT(
manifest->signingKey == spk);
662 BEAST_EXPECT(
manifest->sequence == sequence);
663 BEAST_EXPECT(
manifest->serialized == m);
664 BEAST_EXPECT(
manifest->domain ==
"example.com");
724 testcase <<
"deserializeManifest: revocation manifest (" <<
730 auto const st = buildManifestObject(
732 boost::none,
true,
true);
734 auto const m = toString(st);
738 BEAST_EXPECT(
manifest->masterKey == pk);
741 BEAST_EXPECT(
manifest->domain.empty());
742 BEAST_EXPECT(
manifest->serialized == m);
747 auto const st = buildManifestObject(
749 boost::none,
true,
false);
754 auto const st = buildManifestObject(
756 boost::none,
false,
true);
761 auto const st = buildManifestObject(
763 boost::none,
false,
false);
774 testcase (
"Manifest Domain Names");
800 BEAST_EXPECT(test(
"example.com"));
801 BEAST_EXPECT(test(
"test.example.com"));
802 BEAST_EXPECT(test(
"example-domain.com"));
803 BEAST_EXPECT(test(
"xn--mxavchb.gr"));
804 BEAST_EXPECT(test(
"test.xn--mxavchb.gr"));
805 BEAST_EXPECT(test(
"123.gr"));
806 BEAST_EXPECT(test(
"x.yz"));
807 BEAST_EXPECT(test(
std::string(63,
'a') +
".example.com"));
812 BEAST_EXPECT(!test(
"example"));
815 BEAST_EXPECT(!test(
".com"));
816 BEAST_EXPECT(!test(
".example.com"));
819 BEAST_EXPECT(!test(
"example.com."));
822 BEAST_EXPECT(!test(
"-example.com"));
823 BEAST_EXPECT(!test(
"example-.com"));
826 BEAST_EXPECT(!test(
"double..periods.example.com"));
829 BEAST_EXPECT(!test(
"example.x"));
830 BEAST_EXPECT(!test(
"example." +
std::string(64,
'a')));
833 BEAST_EXPECT(!test(
"example.com-org"));
834 BEAST_EXPECT(!test(
"bang!.com"));
835 BEAST_EXPECT(!test(
"bang!.example.com"));
838 BEAST_EXPECT(!test(
"a.b"));
841 BEAST_EXPECT(!test(
std::string(64,
'a') +
".com"));
842 BEAST_EXPECT(!test(
std::string(64,
'a') +
".example.com"));
877 auto const fake = s_b1.serialized +
'\0';
890 BEAST_EXPECT(!cache.
revoked (pk_a));
891 BEAST_EXPECT(s_aMax.revoked ());
896 BEAST_EXPECT(cache.
revoked (pk_a));
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> isTrusted)
Save cached manifests to database.
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)
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
static boost::filesystem::path getDatabasePath()
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
const SField sfGeneric(access, 0)
boost::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
An immutable linear range of bytes.
const SF_Blob sfSigningPubKey(access, STI_VL, 3, "SigningPubKey")
PublicKey signingKey
The ephemeral key associated with this manifest.
std::string serialized
The manifest in serialized form.
const SF_U32 sfSequence(access, STI_UINT32, 4, "Sequence")
std::string base64_encode(std::uint8_t const *data, std::size_t len)
PublicKey masterKey
The master key associated with this manifest.
std::string makeManifestString(PublicKey const &pk, SecretKey const &sk, PublicKey const &spk, SecretKey const &ssk, int seq)
const SF_Blob sfMasterSignature(access, STI_VL, 18, "MasterSignature", SField::sMD_Default, SField::notSigning)
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
const beast::Journal journal
ManualTimeKeeper & timeKeeper()
static boost::optional< ValidatorToken > make_ValidatorToken(std::vector< std::string > const &tokenBlob)
boost::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
boost::filesystem::path dataDir
std::string to_string(ListDisposition disposition)
const SF_Blob sfSignature(access, STI_VL, 6, "Signature", SField::sMD_Default, SField::notSigning)
void const * data() const noexcept
std::string makeRevocationString(SecretKey const &sk, KeyType type, bool invalidSig=false)
Manifest clone(Manifest const &m)
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical)
Verify a signature on a message.
static PublicKey randomNode()
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.
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.
const SF_U16 sfVersion(access, STI_UINT16, 16, "Version")
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.
const SF_Blob sfPublicKey(access, STI_VL, 1, "PublicKey")
@ stale
Sequence is too old.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
boost::optional< Manifest > deserializeManifest(Slice s)
Constructs Manifest from serialized string.
std::size_t size() const noexcept
virtual void add(Serializer &s) const override
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 strHex(FwdIt begin, FwdIt end)
constexpr std::array< char const *, 6 > WalletDBInit
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.
const SF_Blob sfDomain(access, STI_VL, 7, "Domain")