mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Migrate thread safety to RCLConsensus (RIPD-1389):
Moves thread safety from generic Consensus to RCLConsensus and switch generic Consensus to adaptor design.
This commit is contained in:
150
src/test/app/ValidatorKeys_test.cpp
Normal file
150
src/test/app/ValidatorKeys_test.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright 2017 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/app/misc/ValidatorKeys.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/core/ConfigSections.h>
|
||||
#include <string>
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
|
||||
class ValidatorKeys_test : public beast::unit_test::suite
|
||||
{
|
||||
// Used with [validation_seed]
|
||||
const std::string seed = "shUwVw52ofnCUX5m7kPTKzJdr4HEH";
|
||||
|
||||
// Used with [validation_token]
|
||||
const std::string tokenSecretStr =
|
||||
"paQmjZ37pKKPMrgadBLsuf9ab7Y7EUNzh27LQrZqoexpAs31nJi";
|
||||
|
||||
const std::vector<std::string> tokenBlob = {
|
||||
" "
|
||||
"eyJ2YWxpZGF0aW9uX3NlY3JldF9rZXkiOiI5ZWQ0NWY4NjYyNDFjYzE4YTI3NDdiNT\n",
|
||||
" \tQzODdjMDYyNTkwNzk3MmY0ZTcxOTAyMzFmYWE5Mzc0NTdmYTlkYWY2IiwibWFuaWZl "
|
||||
" \n",
|
||||
"\tc3QiOiJKQUFBQUFGeEllMUZ0d21pbXZHdEgyaUNjTUpxQzlnVkZLaWxHZncxL3ZDeE"
|
||||
"\n",
|
||||
"\t "
|
||||
"hYWExwbGMyR25NaEFrRTFhZ3FYeEJ3RHdEYklENk9NU1l1TTBGREFscEFnTms4U0tG\t "
|
||||
"\t\n",
|
||||
"bjdNTzJmZGtjd1JRSWhBT25ndTlzQUtxWFlvdUorbDJWMFcrc0FPa1ZCK1pSUzZQU2\n",
|
||||
"hsSkFmVXNYZkFpQnNWSkdlc2FhZE9KYy9hQVpva1MxdnltR21WcmxIUEtXWDNZeXd1\n",
|
||||
"NmluOEhBU1FLUHVnQkQ2N2tNYVJGR3ZtcEFUSGxHS0pkdkRGbFdQWXk1QXFEZWRGdj\n",
|
||||
"VUSmEydzBpMjFlcTNNWXl3TFZKWm5GT3I3QzBrdzJBaVR6U0NqSXpkaXRROD0ifQ==\n"};
|
||||
|
||||
const std::string tokenManifest =
|
||||
"JAAAAAFxIe1FtwmimvGtH2iCcMJqC9gVFKilGfw1/vCxHXXLplc2GnMhAkE1agqXxBwD"
|
||||
"wDbID6OMSYuM0FDAlpAgNk8SKFn7MO2fdkcwRQIhAOngu9sAKqXYouJ+l2V0W+sAOkVB"
|
||||
"+ZRS6PShlJAfUsXfAiBsVJGesaadOJc/aAZokS1vymGmVrlHPKWX3Yywu6in8HASQKPu"
|
||||
"gBD67kMaRFGvmpATHlGKJdvDFlWPYy5AqDedFv5TJa2w0i21eq3MYywLVJZnFOr7C0kw"
|
||||
"2AiTzSCjIzditQ8=";
|
||||
|
||||
public:
|
||||
void
|
||||
run() override
|
||||
{
|
||||
beast::Journal j;
|
||||
|
||||
// Keys when using [validation_seed]
|
||||
auto const seedSecretKey =
|
||||
generateSecretKey(KeyType::secp256k1, *parseBase58<Seed>(seed));
|
||||
auto const seedPublicKey =
|
||||
derivePublicKey(KeyType::secp256k1, seedSecretKey);
|
||||
|
||||
// Keys when using [validation_token]
|
||||
auto const tokenSecretKey = *parseBase58<SecretKey>(
|
||||
TokenType::TOKEN_NODE_PRIVATE, tokenSecretStr);
|
||||
|
||||
auto const tokenPublicKey =
|
||||
derivePublicKey(KeyType::secp256k1, tokenSecretKey);
|
||||
|
||||
{
|
||||
// No config -> no key but valid
|
||||
Config c;
|
||||
ValidatorKeys k{c, j};
|
||||
BEAST_EXPECT(k.publicKey.size() == 0);
|
||||
BEAST_EXPECT(k.manifest.empty());
|
||||
BEAST_EXPECT(!k.configInvalid());
|
||||
|
||||
}
|
||||
{
|
||||
// validation seed section -> empty manifest and valid seeds
|
||||
Config c;
|
||||
c.section(SECTION_VALIDATION_SEED).append(seed);
|
||||
|
||||
ValidatorKeys k{c, j};
|
||||
BEAST_EXPECT(k.publicKey == seedPublicKey);
|
||||
BEAST_EXPECT(k.secretKey == seedSecretKey);
|
||||
BEAST_EXPECT(k.manifest.empty());
|
||||
BEAST_EXPECT(!k.configInvalid());
|
||||
}
|
||||
|
||||
{
|
||||
// validation seed bad seed -> invalid
|
||||
Config c;
|
||||
c.section(SECTION_VALIDATION_SEED).append("badseed");
|
||||
|
||||
ValidatorKeys k{c, j};
|
||||
BEAST_EXPECT(k.configInvalid());
|
||||
BEAST_EXPECT(k.publicKey.size() == 0);
|
||||
BEAST_EXPECT(k.manifest.empty());
|
||||
}
|
||||
|
||||
{
|
||||
// validator token
|
||||
Config c;
|
||||
c.section(SECTION_VALIDATOR_TOKEN).append(tokenBlob);
|
||||
ValidatorKeys k{c, j};
|
||||
|
||||
BEAST_EXPECT(k.publicKey == tokenPublicKey);
|
||||
BEAST_EXPECT(k.secretKey == tokenSecretKey);
|
||||
BEAST_EXPECT(k.manifest == tokenManifest);
|
||||
BEAST_EXPECT(!k.configInvalid());
|
||||
}
|
||||
{
|
||||
// invalid validator token
|
||||
Config c;
|
||||
c.section(SECTION_VALIDATOR_TOKEN).append("badtoken");
|
||||
ValidatorKeys k{c, j};
|
||||
BEAST_EXPECT(k.configInvalid());
|
||||
BEAST_EXPECT(k.publicKey.size() == 0);
|
||||
BEAST_EXPECT(k.manifest.empty());
|
||||
}
|
||||
|
||||
{
|
||||
// Cannot specify both
|
||||
Config c;
|
||||
c.section(SECTION_VALIDATION_SEED).append(seed);
|
||||
c.section(SECTION_VALIDATOR_TOKEN).append(tokenBlob);
|
||||
ValidatorKeys k{c, j};
|
||||
|
||||
BEAST_EXPECT(k.configInvalid());
|
||||
BEAST_EXPECT(k.publicKey.size() == 0);
|
||||
BEAST_EXPECT(k.manifest.empty());
|
||||
}
|
||||
|
||||
}
|
||||
}; // namespace test
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(ValidatorKeys, app, ripple);
|
||||
|
||||
} // namespace test
|
||||
} // namespace ripple
|
||||
@@ -21,7 +21,8 @@
|
||||
|
||||
#include <boost/container/flat_map.hpp>
|
||||
#include <boost/container/flat_set.hpp>
|
||||
|
||||
#include <ripple/consensus/Consensus.h>
|
||||
#include <ripple/consensus/ConsensusProposal.h>
|
||||
#include <test/csf/Ledger.h>
|
||||
#include <test/csf/Tx.h>
|
||||
#include <test/csf/UNL.h>
|
||||
@@ -115,20 +116,43 @@ public:
|
||||
directly from the generic types.
|
||||
*/
|
||||
using Proposal = ConsensusProposal<PeerID, Ledger::ID, TxSetType>;
|
||||
class PeerPosition
|
||||
{
|
||||
public:
|
||||
PeerPosition(Proposal const & p)
|
||||
: proposal_(p)
|
||||
{
|
||||
}
|
||||
|
||||
struct Traits
|
||||
Proposal const&
|
||||
proposal() const
|
||||
{
|
||||
return proposal_;
|
||||
}
|
||||
|
||||
Json::Value
|
||||
getJson() const
|
||||
{
|
||||
return proposal_.getJson();
|
||||
}
|
||||
|
||||
private:
|
||||
Proposal proposal_;
|
||||
};
|
||||
|
||||
|
||||
/** Represents a single node participating in the consensus process.
|
||||
It implements the Adaptor requirements of generic Consensus.
|
||||
*/
|
||||
struct Peer
|
||||
{
|
||||
using Ledger_t = Ledger;
|
||||
using NodeID_t = PeerID;
|
||||
using TxSet_t = TxSet;
|
||||
};
|
||||
using PeerPosition_t = PeerPosition;
|
||||
using Result = ConsensusResult<Peer>;
|
||||
|
||||
/** Represents a single node participating in the consensus process.
|
||||
It implements the Callbacks required by Consensus.
|
||||
*/
|
||||
struct Peer : public Consensus<Peer, Traits>
|
||||
{
|
||||
using Base = Consensus<Peer, Traits>;
|
||||
Consensus<Peer> consensus;
|
||||
|
||||
//! Our unique ID
|
||||
PeerID id;
|
||||
@@ -172,12 +196,17 @@ struct Peer : public Consensus<Peer, Traits>
|
||||
bool validating_ = true;
|
||||
bool proposing_ = true;
|
||||
|
||||
ConsensusParms parms_;
|
||||
std::size_t prevProposers_ = 0;
|
||||
std::chrono::milliseconds prevRoundTime_;
|
||||
|
||||
//! All peers start from the default constructed ledger
|
||||
Peer(PeerID i, BasicNetwork<Peer*>& n, UNL const& u, ConsensusParms p)
|
||||
: Consensus<Peer, Traits>(n.clock(), p, beast::Journal{})
|
||||
: consensus(n.clock(), *this, beast::Journal{})
|
||||
, id{i}
|
||||
, net{n}
|
||||
, unl(u)
|
||||
, parms_(p)
|
||||
{
|
||||
ledgers[lastClosedLedger.id()] = lastClosedLedger;
|
||||
}
|
||||
@@ -210,12 +239,6 @@ struct Peer : public Consensus<Peer, Traits>
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto const&
|
||||
proposals(Ledger::ID const& ledgerHash)
|
||||
{
|
||||
return peerPositions_[ledgerHash];
|
||||
}
|
||||
|
||||
TxSet const*
|
||||
acquireTxSet(TxSet::ID const& setId)
|
||||
{
|
||||
@@ -245,17 +268,17 @@ struct Peer : public Consensus<Peer, Traits>
|
||||
}
|
||||
|
||||
Result
|
||||
onClose(Ledger const& prevLedger, NetClock::time_point closeTime, Mode mode)
|
||||
onClose(Ledger const& prevLedger, NetClock::time_point closeTime, ConsensusMode mode)
|
||||
{
|
||||
TxSet res{openTxs};
|
||||
|
||||
return Result{TxSet{openTxs},
|
||||
Proposal{prevLedger.id(),
|
||||
return Result(TxSet{openTxs},
|
||||
Proposal(prevLedger.id(),
|
||||
Proposal::seqJoin,
|
||||
res.id(),
|
||||
closeTime,
|
||||
now(),
|
||||
id}};
|
||||
id));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -263,10 +286,17 @@ struct Peer : public Consensus<Peer, Traits>
|
||||
Result const& result,
|
||||
Ledger const& prevLedger,
|
||||
NetClock::duration const& closeResolution,
|
||||
CloseTimes const& rawCloseTimes,
|
||||
Mode const& mode)
|
||||
ConsensusCloseTimes const& rawCloseTimes,
|
||||
ConsensusMode const& mode,
|
||||
Json::Value && consensusJson)
|
||||
{
|
||||
onAccept(result, prevLedger, closeResolution, rawCloseTimes, mode);
|
||||
onAccept(
|
||||
result,
|
||||
prevLedger,
|
||||
closeResolution,
|
||||
rawCloseTimes,
|
||||
mode,
|
||||
std::move(consensusJson));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -274,8 +304,9 @@ struct Peer : public Consensus<Peer, Traits>
|
||||
Result const& result,
|
||||
Ledger const& prevLedger,
|
||||
NetClock::duration const& closeResolution,
|
||||
CloseTimes const& rawCloseTimes,
|
||||
Mode const& mode)
|
||||
ConsensusCloseTimes const& rawCloseTimes,
|
||||
ConsensusMode const& mode,
|
||||
Json::Value && consensusJson)
|
||||
{
|
||||
auto newLedger = prevLedger.close(
|
||||
result.set.txs_,
|
||||
@@ -283,7 +314,8 @@ struct Peer : public Consensus<Peer, Traits>
|
||||
rawCloseTimes.self,
|
||||
result.position.closeTime() != NetClock::time_point{});
|
||||
ledgers[newLedger.id()] = newLedger;
|
||||
|
||||
prevProposers_ = result.proposers;
|
||||
prevRoundTime_ = result.roundTime.read();
|
||||
lastClosedLedger = newLedger;
|
||||
|
||||
auto it =
|
||||
@@ -304,16 +336,16 @@ struct Peer : public Consensus<Peer, Traits>
|
||||
// TODO: reconsider this and instead just save LCL generated here?
|
||||
if (completedLedgers <= targetLedgers)
|
||||
{
|
||||
startRound(
|
||||
consensus.startRound(
|
||||
now(), lastClosedLedger.id(), lastClosedLedger, proposing_);
|
||||
}
|
||||
}
|
||||
|
||||
Ledger::ID
|
||||
getPrevLedger(Ledger::ID const& ledgerID, Ledger const& ledger, Mode mode)
|
||||
getPrevLedger(Ledger::ID const& ledgerID, Ledger const& ledger, ConsensusMode mode)
|
||||
{
|
||||
// TODO: Use generic validation code
|
||||
if (mode != Mode::wrongLedger && ledgerID.seq > 0 &&
|
||||
if (mode != ConsensusMode::wrongLedger && ledgerID.seq > 0 &&
|
||||
ledger.id().seq > 0)
|
||||
return peerValidations.getBestLCL(ledgerID, ledger.parentID());
|
||||
return ledgerID;
|
||||
@@ -323,24 +355,31 @@ struct Peer : public Consensus<Peer, Traits>
|
||||
propose(Proposal const& pos)
|
||||
{
|
||||
if (proposing_)
|
||||
relay(pos);
|
||||
relay(PeerPosition(pos));
|
||||
}
|
||||
|
||||
ConsensusParms const &
|
||||
parms() const
|
||||
{
|
||||
return parms_;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// non-callback helpers
|
||||
void
|
||||
receive(Proposal const& p)
|
||||
receive(PeerPosition const& peerPos)
|
||||
{
|
||||
Proposal const & p = peerPos.proposal();
|
||||
if (unl.find(p.nodeID()) == unl.end())
|
||||
return;
|
||||
|
||||
// TODO: Be sure this is a new proposal!!!!!
|
||||
// TODO: Supress repeats more efficiently
|
||||
auto& dest = peerPositions_[p.prevLedger()];
|
||||
if (std::find(dest.begin(), dest.end(), p) != dest.end())
|
||||
return;
|
||||
|
||||
dest.push_back(p);
|
||||
peerProposal(now(), p);
|
||||
consensus.peerProposal(now(), peerPos);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -349,7 +388,7 @@ struct Peer : public Consensus<Peer, Traits>
|
||||
// save and map complete?
|
||||
auto it = txSets.insert(std::make_pair(txs.id(), txs));
|
||||
if (it.second)
|
||||
gotTxSet(now(), txs);
|
||||
consensus.gotTxSet(now(), txs);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -392,7 +431,7 @@ struct Peer : public Consensus<Peer, Traits>
|
||||
void
|
||||
timerEntry()
|
||||
{
|
||||
Base::timerEntry(now());
|
||||
consensus.timerEntry(now());
|
||||
// only reschedule if not completed
|
||||
if (completedLedgers < targetLedgers)
|
||||
net.timer(parms().ledgerGRANULARITY, [&]() { timerEntry(); });
|
||||
@@ -406,7 +445,7 @@ struct Peer : public Consensus<Peer, Traits>
|
||||
// so there is no gaurantee that bestLCL == lastClosedLedger.id()
|
||||
auto bestLCL = peerValidations.getBestLCL(
|
||||
lastClosedLedger.id(), lastClosedLedger.parentID());
|
||||
startRound(now(), bestLCL, lastClosedLedger, proposing_);
|
||||
consensus.startRound(now(), bestLCL, lastClosedLedger, proposing_);
|
||||
}
|
||||
|
||||
NetClock::time_point
|
||||
@@ -435,6 +474,28 @@ struct Peer : public Consensus<Peer, Traits>
|
||||
else
|
||||
net.timer(when, std::forward<T>(what));
|
||||
}
|
||||
|
||||
Ledger::ID
|
||||
prevLedgerID()
|
||||
{
|
||||
return consensus.prevLedgerID();
|
||||
}
|
||||
|
||||
std::size_t
|
||||
prevProposers()
|
||||
{
|
||||
return prevProposers_;
|
||||
}
|
||||
|
||||
std::chrono::milliseconds
|
||||
prevRoundTime()
|
||||
{
|
||||
return prevRoundTime_;
|
||||
}
|
||||
|
||||
// Not interested in tracking consensus mode
|
||||
void
|
||||
onModeChange(ConsensusMode, ConsensusMode) {}
|
||||
};
|
||||
|
||||
} // csf
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <test/app/Transaction_ordering_test.cpp>
|
||||
#include <test/app/TrustAndBalance_test.cpp>
|
||||
#include <test/app/TxQ_test.cpp>
|
||||
#include <test/app/ValidatorKeys_test.cpp>
|
||||
#include <test/app/ValidatorList_test.cpp>
|
||||
#include <test/app/ValidatorSite_test.cpp>
|
||||
#include <test/app/SetTrust_test.cpp>
|
||||
|
||||
Reference in New Issue
Block a user