20 #include <ripple/app/main/DBInit.h>
21 #include <ripple/app/misc/Manifest.h>
22 #include <ripple/app/misc/ValidatorList.h>
23 #include <ripple/basics/StringUtilities.h>
24 #include <ripple/basics/base64.h>
25 #include <ripple/basics/contract.h>
26 #include <ripple/core/DatabaseCon.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");
266 auto getPopulatedManifests =
270 cache.for_each_manifest(
280 return lhs->serialized < rhs->serialized;
285 sort(getPopulatedManifests(m)));
288 auto& app = env.
app();
289 auto unl = std::make_unique<ValidatorList>(
293 app.config().legacy(
"database_path"),
301 "ValidatorManifests",
303 return unl->listed(pubKey);
308 loaded.
load(dbCon,
"ValidatorManifests");
312 sort(getPopulatedManifests(loaded)));
314 for (
auto const& man : loadedManifests)
315 BEAST_EXPECT(man->revoked());
323 for (
auto const& man : inManifests)
326 unl->load(emptyLocalKey, s1, keys);
330 "ValidatorManifests",
332 return unl->listed(pubKey);
335 loaded.
load(dbCon,
"ValidatorManifests");
339 sort(getPopulatedManifests(loaded)));
341 if (inManifests.size() == loadedManifests.
size())
346 loadedManifests.
begin(),
362 BEAST_EXPECT(!loaded.
load(
363 dbCon,
"ValidatorManifests", badManifest, emptyRevocation));
372 BEAST_EXPECT(loaded.
load(
373 dbCon,
"ValidatorManifests", cfgManifest, emptyRevocation));
382 BEAST_EXPECT(!loaded.
load(
383 dbCon,
"ValidatorManifests", emptyManifest, badRevocation));
392 BEAST_EXPECT(!loaded.
load(
393 dbCon,
"ValidatorManifests", emptyManifest, nonRevocation));
394 BEAST_EXPECT(!loaded.
revoked(pk));
398 BEAST_EXPECT(!loaded.
load(
400 "ValidatorManifests",
403 BEAST_EXPECT(!loaded.
revoked(pk));
407 BEAST_EXPECT(loaded.
load(
408 dbCon,
"ValidatorManifests", emptyManifest, cfgRevocation));
410 BEAST_EXPECT(loaded.
revoked(pk));
413 boost::filesystem::remove(
420 testcase(
"getSignature");
438 BEAST_EXPECT(
strHex(masterSig) ==
strHex(m.getMasterSignature()));
476 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
487 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
495 BEAST_EXPECT(cache.
revoked(pk));
497 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
498 BEAST_EXPECT(cache.
getMasterKey(kp1.first) == kp1.first);
504 testcase(
"validator token");
507 auto const valSecret = parseBase58<SecretKey>(
509 "paQmjZ37pKKPMrgadBLsuf9ab7Y7EUNzh27LQrZqoexpAs31nJi");
514 "eyJ2YWxpZGF0aW9uX3NlY3JldF9rZXkiOiI5ZWQ0NWY4NjYyNDFjYzE4YTI3ND"
516 " \tQzODdjMDYyNTkwNzk3MmY0ZTcxOTAyMzFmYWE5Mzc0NTdmYTlkYWY2Iiwib"
518 "\tc3QiOiJKQUFBQUFGeEllMUZ0d21pbXZHdEgyaUNjTUpxQzlnVkZLaWxHZncx"
521 "hYWExwbGMyR25NaEFrRTFhZ3FYeEJ3RHdEYklENk9NU1l1TTBGREFscEFnTms4"
523 "bjdNTzJmZGtjd1JRSWhBT25ndTlzQUtxWFlvdUorbDJWMFcrc0FPa1ZCK1pSUz"
525 "hsSkFmVXNYZkFpQnNWSkdlc2FhZE9KYy9hQVpva1MxdnltR21WcmxIUEtXWDNZ"
527 "NmluOEhBU1FLUHVnQkQ2N2tNYVJGR3ZtcEFUSGxHS0pkdkRGbFdQWXk1QXFEZW"
529 "VUSmEydzBpMjFlcTNNWXl3TFZKWm5GT3I3QzBrdzJBaVR6U0NqSXpkaXRROD0i"
533 "JAAAAAFxIe1FtwmimvGtH2iCcMJqC9gVFKilGfw1/"
534 "vCxHXXLplc2GnMhAkE1agqXxBwD"
535 "wDbID6OMSYuM0FDAlpAgNk8SKFn7MO2fdkcwRQIhAOngu9sAKqXYouJ+l2V0W+"
537 "+ZRS6PShlJAfUsXfAiBsVJGesaadOJc/"
538 "aAZokS1vymGmVrlHPKWX3Yywu6in8HASQKPu"
539 "gBD67kMaRFGvmpATHlGKJdvDFlWPYy5AqDedFv5TJa2w0i21eq3MYywLVJZnFO"
545 BEAST_EXPECT(token->validationSecret == *valSecret);
546 BEAST_EXPECT(token->manifest ==
manifest);
557 testcase(
"Versioning");
606 "9930E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02"
608 auto const badKey =
Slice{ret->
data(), ret->size()};
611 auto const retShort =
strUnHex(
"0330");
612 auto const shortKey =
Slice{retShort->
data(), retShort->size()};
614 auto toString = [](
STObject const& st) {
621 for (
auto const keyType : keyTypes)
626 for (
auto const sKeyType : keyTypes)
631 auto buildManifestObject =
633 boost::optional<std::string> domain,
634 bool noSigningPublic =
false,
635 bool noSignature =
false) {
643 if (!noSigningPublic)
660 testcase <<
"deserializeManifest: normal manifest ("
666 buildManifestObject(++sequence, boost::none);
668 auto const m = toString(st);
672 BEAST_EXPECT(
manifest->masterKey == pk);
673 BEAST_EXPECT(
manifest->signingKey == spk);
674 BEAST_EXPECT(
manifest->sequence == sequence);
675 BEAST_EXPECT(
manifest->serialized == m);
676 BEAST_EXPECT(
manifest->domain.empty());
689 buildManifestObject(++sequence,
std::string{
"a.b"});
695 buildManifestObject(++sequence, s +
".example.com");
701 buildManifestObject(++sequence, s +
".example.com");
705 auto const st = buildManifestObject(
710 auto const m = toString(st);
714 BEAST_EXPECT(
manifest->masterKey == pk);
715 BEAST_EXPECT(
manifest->signingKey == spk);
716 BEAST_EXPECT(
manifest->sequence == sequence);
717 BEAST_EXPECT(
manifest->serialized == m);
718 BEAST_EXPECT(
manifest->domain ==
"example.com");
726 auto const m = toString(badSigSt);
730 BEAST_EXPECT(
manifest->masterKey == spk);
731 BEAST_EXPECT(
manifest->signingKey == spk);
732 BEAST_EXPECT(
manifest->sequence == sequence);
733 BEAST_EXPECT(
manifest->serialized == m);
734 BEAST_EXPECT(
manifest->domain ==
"example.com");
794 testcase <<
"deserializeManifest: revocation manifest ("
800 auto const st = buildManifestObject(
806 auto const m = toString(st);
810 BEAST_EXPECT(
manifest->masterKey == pk);
813 BEAST_EXPECT(
manifest->domain.empty());
814 BEAST_EXPECT(
manifest->serialized == m);
819 auto const st = buildManifestObject(
828 auto const st = buildManifestObject(
837 auto const st = buildManifestObject(
853 testcase(
"Manifest Domain Names");
883 BEAST_EXPECT(test(
"example.com"));
884 BEAST_EXPECT(test(
"test.example.com"));
885 BEAST_EXPECT(test(
"example-domain.com"));
886 BEAST_EXPECT(test(
"xn--mxavchb.gr"));
887 BEAST_EXPECT(test(
"test.xn--mxavchb.gr"));
888 BEAST_EXPECT(test(
"123.gr"));
889 BEAST_EXPECT(test(
"x.yz"));
890 BEAST_EXPECT(test(
std::string(63,
'a') +
".example.com"));
894 BEAST_EXPECT(!test(
"example"));
897 BEAST_EXPECT(!test(
".com"));
898 BEAST_EXPECT(!test(
".example.com"));
901 BEAST_EXPECT(!test(
"example.com."));
904 BEAST_EXPECT(!test(
"-example.com"));
905 BEAST_EXPECT(!test(
"example-.com"));
908 BEAST_EXPECT(!test(
"double..periods.example.com"));
911 BEAST_EXPECT(!test(
"example.x"));
912 BEAST_EXPECT(!test(
"example." +
std::string(64,
'a')));
915 BEAST_EXPECT(!test(
"example.com-org"));
916 BEAST_EXPECT(!test(
"bang!.com"));
917 BEAST_EXPECT(!test(
"bang!.example.com"));
920 BEAST_EXPECT(!test(
"a.b"));
923 BEAST_EXPECT(!test(
std::string(64,
'a') +
".com"));
924 BEAST_EXPECT(!test(
std::string(64,
'a') +
".example.com"));
965 auto const fake = s_b1.serialized +
'\0';
985 BEAST_EXPECT(!cache.
revoked(pk_a));
986 BEAST_EXPECT(s_aMax.revoked());
997 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()
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
boost::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob)
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)
int add32(std::uint32_t i)
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")