Skip to content

Commit

Permalink
[FOLD] Switch to adaptor design from CRTP:
Browse files Browse the repository at this point in the history
Since the implementing CRTP base class (e.g. RCLConsensus) no longer needs to
call into any generic Consensus public/protected members, it makes more sense
for it to provide the callback functions as an Adaptor class.

Additionally, ConsensusMode, ConsensusPhase where promoted from inner types
of Consensus to ripple namespace level types.
  • Loading branch information
bachase committed May 18, 2017
1 parent 3862a35 commit cc309bd
Show file tree
Hide file tree
Showing 9 changed files with 900 additions and 701 deletions.
2 changes: 2 additions & 0 deletions Builds/VisualStudio2015/RippleD.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1831,6 +1831,8 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\consensus\ConsensusProposal.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\consensus\ConsensusTypes.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\consensus\DisputedTx.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\consensus\LedgerTiming.cpp">
Expand Down
3 changes: 3 additions & 0 deletions Builds/VisualStudio2015/RippleD.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -2460,6 +2460,9 @@
<ClInclude Include="..\..\src\ripple\consensus\ConsensusProposal.h">
<Filter>ripple\consensus</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\consensus\ConsensusTypes.h">
<Filter>ripple\consensus</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\consensus\DisputedTx.h">
<Filter>ripple\consensus</Filter>
</ClInclude>
Expand Down
150 changes: 81 additions & 69 deletions docs/consensus.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -480,69 +480,87 @@ struct Ledger
//... implementation specific
};
```
[heading Generic Consensus Interface]

Following the
[@https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern CRTP]
idiom, generic =Consensus= relies on a deriving class implementing a set of
helpers and callbacks that encapsulate implementation specific details of the
algorithm. Below are excerpts of the generic consensus implementation and of
helper types that will interact with the concrete implementing class.

[heading PeerProposal] The =PeerProposal= type represents the signed position taken
by a peer during consensus. The only type requirement is owning an instance of a
generic =ConsensusProposal=.
```

// Represents our proposed position or a peer's proposed position
// and is provided with the generic code
template <class NodeID_t, class LedgerID_t, class Position_t> class ConsensusProposal;

struct PeerPosition
{
ConsensusProposal<
NodeID_t,
typename Ledger::ID,
typename TxSet::ID> const &
proposal() const;

// ... implementation specific
};
```
[heading Generic Consensus Interface]

The generic =Consensus= relies on =Adaptor= template class to implement a set
of helper functions that plug the consensus algorithm into a specific application.
The =Adaptor= class also defines the types above needed by the algorithm. Below
are excerpts of the generic consensus implementation and of helper types that will
interact with the concrete implementing class.

```
// Represents a transction under dispute this round
template <class Tx_t, class NodeID_t> class DisputedTx;

template <class Derived, class Traits> class Consensus
// Represents how the node participates in Consensus this round
enum class ConsensusMode { proposing, observing, wrongLedger, switchedLedger};

// Measure duration of phases of consensus
class ConsensusTimer
{
public:
std::chrono::milliseconds read() const;
// details omitted ...
};

// Initial ledger close times, not rounded by closeTimeResolution
// Used to gauge degree of synchronization between a node and its peers
struct ConsensusCloseTimes
{
std::map<NetClock::time_point, int> peers;
NetClock::time_point self;
};

// Encapsulates the result of consensus.
template <class Adaptor>
struct ConsensusResult
{
protected:
enum class Mode { proposing, observing, wrongLedger, switchedLedger};

// Measure duration of phases of consensus
class Stopwatch
{
public:
std::chrono::milliseconds read() const;
// details omitted ...
};

// Initial ledger close times, not rounded by closeTimeResolution
// Used to gauge degree of synchronization between a node and its peers
struct CloseTimes
{
std::map<NetClock::time_point, int> peers;
NetClock::time_point self;
};

// Encapsulates the result of consensus.
struct Result
{
//! The set of transactions consensus agrees go in the ledger
TxSet_t set;

//! Our proposed position on transactions/close time
Proposal_t position;

//! Transactions which are under dispute with our peers
using Dispute_t = DisputedTx<Tx_t, NodeID_t>;
hash_map<typename Tx_t::ID, Dispute_t> disputes;

// Set of TxSet ids we have already compared/created disputes
hash_set<typename TxSet_t::ID> compares;

// Measures the duration of the establish phase for this consensus round
Stopwatch roundTime;

// Indicates state in which consensus ended. Once in the accept phase
// will be either Yes or MovedOn
ConsensusState state = ConsensusState::No;
};
//! The set of transactions consensus agrees go in the ledger
Adaptor::TxSet_t set;

//! Our proposed position on transactions/close time
ConsensusProposal<...> position;

//! Transactions which are under dispute with our peers
hash_map<Adaptor::Tx_t::ID, DisputedTx<...>> disputes;

// Set of TxSet ids we have already compared/created disputes
hash_set<typename Adaptor::TxSet_t::ID> compares;

// Measures the duration of the establish phase for this consensus round
ConsensusTimer roundTime;

// Indicates state in which consensus ended. Once in the accept phase
// will be either Yes or MovedOn
ConsensusState state = ConsensusState::No;
};

template <class Adaptor>
class Consensus
{
public:
Consensus(clock_type, Adaptor &, beast::journal);

// Kick-off the next round of consensus.
void startRound(
NetClock::time_point const& now,
Expand All @@ -568,26 +586,20 @@ public:
The stub below shows the set of callback/helper functions required in the implementing class.

```
struct Traits
struct Adaptor
{
using Ledger_t = Ledger;
using TxSet_t = TxSet;
using NodeID_t = ...; // Integer-like std::uint32_t to uniquely identify a node
using Ledger_t = Ledger;
using TxSet_t = TxSet;
using PeerProposal_t = PeerProposal;
using NodeID_t = ...; // Integer-like std::uint32_t to uniquely identify a node

};

class ConsensusImp : public Consensus<ConsensusImp, Traits>
{
// Attempt to acquire a specific ledger from the network.
boost::optional<Ledger> acquireLedger(Ledger::ID const & ledgerID);

// Acquire the transaction set associated with a proposed position.
boost::optional<TxSet> acquireTxSet(TxSet::ID const & setID);

// Get peers' proposed positions. Returns an iterable
// with value_type convertable to ConsensusPosition<...>
auto const & proposals(Ledger::ID const & ledgerID);

// Whether any transactions are in the open ledger
bool hasOpenTransactions() const;

Expand All @@ -602,24 +614,24 @@ class ConsensusImp : public Consensus<ConsensusImp, Traits>
// application thinks consensus should use as the prior ledger.
Ledger::ID getPrevLedger(Ledger::ID const & prevLedgerID,
Ledger const & prevLedger,
Mode mode);
ConsensusMode mode);

// Called when ledger closes. Implementation should generate an initial Result
// with position based on the current open ledger's transactions.
Result onClose(Ledger const &, Ledger const & prev, Mode mode);
ConsensusResult onClose(Ledger const &, Ledger const & prev, ConsensusMode mode);

// Called when ledger is accepted by consensus
void onAccept(Result const & result,
void onAccept(ConsensusResult const & result,
RCLCxLedger const & prevLedger,
NetClock::duration closeResolution,
CloseTimes const & rawCloseTimes,
Mode const & mode);
ConsensusCloseTimes const & rawCloseTimes,
ConsensusMode const & mode);

// Propose the position to peers.
void propose(ConsensusProposal<...> const & pos);

// Relay a received peer proposal on to other peer's.
void relay(ConsensusProposal<...> const & pos);
void relay(PeerPosition_t const & pos);

// Relay a disputed transaction to peers
void relay(TxSet::Tx const & tx);
Expand Down
1 change: 1 addition & 0 deletions docs/source.dox
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ INPUT = \
../src/test/jtx/WSClient.h \
../src/ripple/consensus/Consensus.h \
../src/ripple/consensus/ConsensusProposal.h \
../src/ripple/consensus/ConsensusTypes.h \
../src/ripple/consensus/DisputedTx.h \
../src/ripple/consensus/LedgerTiming.h \
../src/ripple/app/consensus/RCLCxTx.h \
Expand Down
Loading

0 comments on commit cc309bd

Please sign in to comment.