1#include <test/jtx/Env.h>
2#include <test/unit_test/utils.h>
4#include <xrpld/app/misc/ValidatorList.h>
6#include <xrpl/basics/Slice.h>
7#include <xrpl/basics/base64.h>
8#include <xrpl/basics/contract.h>
9#include <xrpl/basics/strHex.h>
10#include <xrpl/beast/unit_test/suite.h>
11#include <xrpl/config/Constants.h>
12#include <xrpl/protocol/HashPrefix.h>
13#include <xrpl/protocol/KeyType.h>
14#include <xrpl/protocol/PublicKey.h>
15#include <xrpl/protocol/SField.h>
16#include <xrpl/protocol/STObject.h>
17#include <xrpl/protocol/SecretKey.h>
18#include <xrpl/protocol/Seed.h>
19#include <xrpl/protocol/Serializer.h>
20#include <xrpl/protocol/Sign.h>
21#include <xrpl/protocol/tokens.h>
22#include <xrpl/server/Manifest.h>
23#include <xrpl/server/Wallet.h>
118 st[sfSequence] = seq;
119 st[sfPublicKey] = pk;
120 st[sfSigningPubKey] = spk;
141 st[sfPublicKey] = pk;
160 st[sfPublicKey] = pk;
171 return std::move(*r);
183 bool invalidSig =
false)
189 st[sfSequence] = seq;
190 st[sfPublicKey] = pk;
191 st[sfSigningPubKey] = spk;
205 return std::move(*r);
231 auto getPopulatedManifests =
235 cache.forEachManifest([&result](
Manifest const& man) { result.
push_back(&man); });
246 auto& app = env.
app();
253 m.
save(*dbCon,
"ValidatorManifests", [&unl](
PublicKey const& pubKey) {
254 return unl->listed(pubKey);
259 loaded.
load(*dbCon,
"ValidatorManifests");
263 sort(getPopulatedManifests(loaded)));
265 for (
auto const& man : loadedManifests)
266 BEAST_EXPECT(man->revoked());
274 for (
auto const& man : inManifests)
276 unl->load({}, s1, keys);
278 m.
save(*dbCon,
"ValidatorManifests", [&unl](
PublicKey const& pubKey) {
279 return unl->listed(pubKey);
282 loaded.
load(*dbCon,
"ValidatorManifests");
286 sort(getPopulatedManifests(loaded)));
288 if (inManifests.size() == loadedManifests.
size())
308 !loaded.
load(*dbCon,
"ValidatorManifests", badManifest, emptyRevocation));
317 loaded.
load(*dbCon,
"ValidatorManifests", cfgManifest, emptyRevocation));
326 !loaded.
load(*dbCon,
"ValidatorManifests", emptyManifest, badRevocation));
336 !loaded.
load(*dbCon,
"ValidatorManifests", emptyManifest, nonRevocation));
337 BEAST_EXPECT(!loaded.
revoked(pk));
342 !loaded.
load(*dbCon,
"ValidatorManifests", emptyManifest, badSigRevocation));
343 BEAST_EXPECT(!loaded.
revoked(pk));
347 loaded.
load(*dbCon,
"ValidatorManifests", emptyManifest, cfgRevocation));
349 BEAST_EXPECT(loaded.
revoked(pk));
366 st[sfPublicKey] = pk;
367 st[sfSigningPubKey] = kp.first;
374 strHex(*m.getSignature()));
377 BEAST_EXPECT(
strHex(masterSig) ==
strHex(m.getMasterSignature()));
417 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
428 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
437 BEAST_EXPECT(cache.
revoked(pk));
439 BEAST_EXPECT(cache.
getMasterKey(kp0.first) == kp0.first);
440 BEAST_EXPECT(cache.
getMasterKey(kp1.first) == kp1.first);
454 " eyJ2YWxpZGF0aW9uX3NlY3JldF9rZXkiOiI5ZWQ0NWY4NjYyNDFjYzE4YTI3NDdiNT\n",
455 " \tQzODdjMDYyNTkwNzk3MmY0ZTcxOTAyMzFmYWE5Mzc0NTdmYTlkYWY2IiwibWFuaWZl \n",
456 "\tc3QiOiJKQUFBQUFGeEllMUZ0d21pbXZHdEgyaUNjTUpxQzlnVkZLaWxHZncxL3ZDeE\n",
457 "\t hYWExwbGMyR25NaEFrRTFhZ3FYeEJ3RHdEYklENk9NU1l1TTBGREFscEFnTms4U0tG\t \t\n",
458 "bjdNTzJmZGtjd1JRSWhBT25ndTlzQUtxWFlvdUorbDJWMFcrc0FPa1ZCK1pSUzZQU2\n",
459 "hsSkFmVXNYZkFpQnNWSkdlc2FhZE9KYy9hQVpva1MxdnltR21WcmxIUEtXWDNZeXd1\n",
460 "NmluOEhBU1FLUHVnQkQ2N2tNYVJGR3ZtcEFUSGxHS0pkdkRGbFdQWXk1QXFEZWRGdj\n",
461 "VUSmEydzBpMjFlcTNNWXl3TFZKWm5GT3I3QzBrdzJBaVR6U0NqSXpkaXRROD0ifQ==\n",
464 auto const manifest =
465 "JAAAAAFxIe1FtwmimvGtH2iCcMJqC9gVFKilGfw1/"
466 "vCxHXXLplc2GnMhAkE1agqXxBwD"
467 "wDbID6OMSYuM0FDAlpAgNk8SKFn7MO2fdkcwRQIhAOngu9sAKqXYouJ+l2V0W+"
469 "+ZRS6PShlJAfUsXfAiBsVJGesaadOJc/"
470 "aAZokS1vymGmVrlHPKWX3Yywu6in8HASQKPu"
471 "gBD67kMaRFGvmpATHlGKJdvDFlWPYy5AqDedFv5TJa2w0i21eq3MYywLVJZnFO"
480 BEAST_EXPECT(
token->manifest == manifest);
502 st[sfPublicKey] = pk;
503 st[sfSigningPubKey] = spk;
506 st[sfVersion] = version;
534 0x99, 0x30, 0xE7, 0xFC, 0x9D, 0x56, 0xBB, 0x25, 0xD6, 0x89, 0x3B,
535 0xA3, 0xF3, 0x17, 0xAE, 0x5B, 0xCF, 0x33, 0xB3, 0x29, 0x1B, 0xD6,
536 0x3D, 0xB3, 0x26, 0x54, 0xA3, 0x13, 0x22, 0x2F, 0x7F, 0xD0, 0x20};
557 auto toString = [](
STObject const& st) {
564 for (
auto const keyType : keyTypes)
569 for (
auto const sKeyType : keyTypes)
576 bool noSigningPublic =
false,
577 bool noSignature =
false) {
579 st[sfSequence] = seq;
580 st[sfPublicKey] = pk;
585 if (!noSigningPublic)
586 st[sfSigningPubKey] = spk;
601 auto const st = buildManifestObject(++sequence, std::nullopt);
603 auto const m = toString(st);
606 BEAST_EXPECT(manifest);
608 BEAST_EXPECT(manifest->masterKey == pk);
609 BEAST_EXPECT(manifest->signingKey == spk);
610 BEAST_EXPECT(manifest->sequence == sequence);
611 BEAST_EXPECT(manifest->serialized == m);
612 BEAST_EXPECT(manifest->domain.empty());
613 BEAST_EXPECT(manifest->verify());
618 auto const st = buildManifestObject(++sequence,
std::string{});
624 auto const st = buildManifestObject(++sequence,
std::string{
"a.b"});
629 auto const st = buildManifestObject(++sequence, s +
".example.com");
634 auto const st = buildManifestObject(++sequence, s +
".example.com");
638 auto const st = buildManifestObject(++sequence,
std::string{
"example.com"});
642 auto const m = toString(st);
645 BEAST_EXPECT(manifest);
647 BEAST_EXPECT(manifest->masterKey == pk);
648 BEAST_EXPECT(manifest->signingKey == spk);
649 BEAST_EXPECT(manifest->sequence == sequence);
650 BEAST_EXPECT(manifest->serialized == m);
651 BEAST_EXPECT(manifest->domain ==
"example.com");
652 BEAST_EXPECT(manifest->verify());
658 badSigSt[sfSequence] = sequence + 1;
660 auto const m = toString(badSigSt);
663 BEAST_EXPECT(manifest);
665 BEAST_EXPECT(manifest->masterKey == pk);
666 BEAST_EXPECT(manifest->signingKey == spk);
667 BEAST_EXPECT(manifest->sequence == sequence + 1);
668 BEAST_EXPECT(manifest->serialized == m);
669 BEAST_EXPECT(manifest->domain ==
"example.com");
670 BEAST_EXPECT(!manifest->verify());
676 BEAST_EXPECT(badSt.delField(sfSequence));
682 BEAST_EXPECT(badSt.delField(sfPublicKey));
694 badSt[sfPublicKey] =
makeSlice(shortKey);
700 BEAST_EXPECT(badSt.delField(sfSigningPubKey));
706 badSt[sfSigningPubKey] =
makeSlice(badKey);
712 badSt[sfSigningPubKey] =
makeSlice(shortKey);
718 BEAST_EXPECT(badSt.delField(sfMasterSignature));
724 BEAST_EXPECT(badSt.delField(sfSignature));
730 st[sfSequence] = 314159;
731 st[sfPublicKey] = pk;
732 st[sfSigningPubKey] = pk;
748 auto const st = buildManifestObject(
751 auto const m = toString(st);
754 BEAST_EXPECT(manifest);
756 BEAST_EXPECT(manifest->masterKey == pk);
759 BEAST_EXPECT(!manifest->signingKey);
760 BEAST_EXPECT(manifest->revoked());
761 BEAST_EXPECT(manifest->domain.empty());
762 BEAST_EXPECT(manifest->serialized == m);
763 BEAST_EXPECT(manifest->verify());
768 auto const st = buildManifestObject(
774 auto const st = buildManifestObject(
780 auto const st = buildManifestObject(
804 st[sfPublicKey] = pk1;
806 st[sfSigningPubKey] = pk2;
817 BEAST_EXPECT(
test(
"example.com"));
818 BEAST_EXPECT(
test(
"test.example.com"));
819 BEAST_EXPECT(
test(
"example-domain.com"));
820 BEAST_EXPECT(
test(
"xn--mxavchb.gr"));
821 BEAST_EXPECT(
test(
"test.xn--mxavchb.gr"));
822 BEAST_EXPECT(
test(
"123.gr"));
823 BEAST_EXPECT(
test(
"x.yz"));
828 BEAST_EXPECT(!
test(
"example"));
831 BEAST_EXPECT(!
test(
".com"));
832 BEAST_EXPECT(!
test(
".example.com"));
835 BEAST_EXPECT(!
test(
"example.com."));
838 BEAST_EXPECT(!
test(
"-example.com"));
839 BEAST_EXPECT(!
test(
"example-.com"));
842 BEAST_EXPECT(!
test(
"double..periods.example.com"));
845 BEAST_EXPECT(!
test(
"example.x"));
849 BEAST_EXPECT(!
test(
"example.com-org"));
850 BEAST_EXPECT(!
test(
"bang!.com"));
851 BEAST_EXPECT(!
test(
"bang!.example.com"));
854 BEAST_EXPECT(!
test(
"a.b"));
902 auto const fake = sB2.serialized +
'\0';
910 BEAST_EXPECT(cache.
sequence() > seq0);
916 BEAST_EXPECT(cache.
sequence() == seq1);
934 BEAST_EXPECT(!cache.
revoked(pkA));
935 BEAST_EXPECT(sAMax.revoked());
948 BEAST_EXPECT(cache.
revoked(pkA));
void fail(String const &reason, char const *file, int line)
Record a failure.
TestcaseT testcase
Memberspace for declaring test cases.
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, ManifestRateLimitCapPolicy cap)
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()
static void cleanupDatabaseDir(std::filesystem::path const &dbPath)
~Manifest_test() override
void testManifestDomainNames()
std::string makeRevocationString(SecretKey const &sk, KeyType type, bool invalidSig=false)
Manifest makeManifest(SecretKey const &sk, KeyType type, SecretKey const &ssk, KeyType stype, int seq, bool invalidSig=false)
static PublicKey randomNode()
static std::filesystem::path getDatabasePath()
static void setupDatabaseDir(std::filesystem::path const &dbPath)
void testManifestVersioning()
Manifest makeRevocation(SecretKey const &sk, KeyType type, bool invalidSig=false)
A transaction testing environment.
ManualTimeKeeper & timeKeeper()
beast::Journal const journal
T create_directory(T... args)
T current_path(T... args)
T is_directory(T... args)
void sign(json::Value &jv, Account const &account, json::Value &sigObject)
Sign automatically into a specific Json field of the jv object.
bool equal(STAmount const &sa1, STAmount const &sa2)
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
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.
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
Seed randomSeed()
Create a seed using secure random numbers.
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 to_string(BaseUInt< Bits, Tag > const &a)
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.
@ Capped
Subject to the untrusted cap (unlisted peer gossip).
Slice makeSlice(std::array< T, N > const &a)
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
std::string base64Encode(std::uint8_t const *data, std::size_t len)
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.
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
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.
@ Accepted
Manifest is valid.
@ Invalid
Timely, but invalid signature.
@ BadEphemeralKey
The ephemeral key is not acceptable to us.
@ Stale
Sequence is too old.
std::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.
static constexpr auto kDatabasePath