mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-04 11:15:56 +00:00
Begin consensus refactor (RIPD-1011):
* New RCLCx* classes * Refactor consensus positions * Refactor proposed transaction sets * Refactor disputed transactions * Refactor position broadcast/replay
This commit is contained in:
committed by
Edward Hennis
parent
97806b42c4
commit
f456355da2
@@ -783,6 +783,12 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\protobuf\vsprojects\config.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\consensus\RCLCxPos.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\consensus\RCLCxTraits.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\consensus\RCLCxTx.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\ledger\AcceptedLedger.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -821,10 +827,6 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\impl\ConsensusImp.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\ledger\impl\DisputedTx.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\impl\DisputedTx.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\ledger\impl\InboundLedger.cpp">
|
||||
|
||||
@@ -94,6 +94,9 @@
|
||||
<Filter Include="ripple\app">
|
||||
<UniqueIdentifier>{83B96C00-A786-6597-826D-E12FA6187AA8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\app\consensus">
|
||||
<UniqueIdentifier>{0E8BC18A-9853-B13E-1A9D-C55FA29DA60F}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\app\ledger">
|
||||
<UniqueIdentifier>{CE126498-A44D-30A2-345B-0F672BCDF947}</UniqueIdentifier>
|
||||
</Filter>
|
||||
@@ -1299,6 +1302,15 @@
|
||||
<ClInclude Include="..\..\src\protobuf\vsprojects\config.h">
|
||||
<Filter>protobuf\vsprojects</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\consensus\RCLCxPos.h">
|
||||
<Filter>ripple\app\consensus</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\consensus\RCLCxTraits.h">
|
||||
<Filter>ripple\app\consensus</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\consensus\RCLCxTx.h">
|
||||
<Filter>ripple\app\consensus</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\ledger\AcceptedLedger.cpp">
|
||||
<Filter>ripple\app\ledger</Filter>
|
||||
</ClCompile>
|
||||
@@ -1338,9 +1350,6 @@
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\impl\ConsensusImp.h">
|
||||
<Filter>ripple\app\ledger\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\ledger\impl\DisputedTx.cpp">
|
||||
<Filter>ripple\app\ledger\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\impl\DisputedTx.h">
|
||||
<Filter>ripple\app\ledger\impl</Filter>
|
||||
</ClInclude>
|
||||
|
||||
143
src/ripple/app/consensus/RCLCxPos.h
Normal file
143
src/ripple/app/consensus/RCLCxPos.h
Normal file
@@ -0,0 +1,143 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012-2016 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_APP_CONSENSUS_RCLCXPOSITION_H_INCLUDED
|
||||
#define RIPPLE_APP_CONSENSUS_RCLCXPOSITION_H_INCLUDED
|
||||
|
||||
#include <ripple/app/ledger/LedgerProposal.h>
|
||||
#include <ripple/json/json_value.h>
|
||||
#include <ripple/basics/chrono.h>
|
||||
#include <ripple/protocol/UintTypes.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// A position taken during a consensus round
|
||||
// As seen by the RCL consensus process
|
||||
class RCLCxPos
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
static std::uint32_t constexpr seqInitial = 0;
|
||||
static std::uint32_t constexpr seqLeave = 0xffffffff;
|
||||
|
||||
RCLCxPos (LedgerProposal const& prop) :
|
||||
proposal_ (prop)
|
||||
{ }
|
||||
|
||||
std::uint32_t getSequence() const
|
||||
{
|
||||
return proposal_.getProposeSeq();
|
||||
}
|
||||
|
||||
NetClock::time_point getCloseTime () const
|
||||
{
|
||||
return proposal_.getCloseTime();
|
||||
}
|
||||
|
||||
NetClock::time_point getSeenTime() const
|
||||
{
|
||||
return proposal_.getSeenTime();
|
||||
}
|
||||
|
||||
bool isStale (NetClock::time_point lastValid) const
|
||||
{
|
||||
return getSeenTime() < lastValid;
|
||||
}
|
||||
|
||||
NodeID const& getNodeID() const
|
||||
{
|
||||
return proposal_.getPeerID();
|
||||
}
|
||||
|
||||
LedgerHash const& getPosition() const
|
||||
{
|
||||
return proposal_.getCurrentHash();
|
||||
}
|
||||
|
||||
LedgerHash const& getPrevLedger() const
|
||||
{
|
||||
return proposal_.getPrevLedger();
|
||||
}
|
||||
|
||||
bool changePosition (
|
||||
LedgerHash const& position,
|
||||
NetClock::time_point closeTime,
|
||||
NetClock::time_point now)
|
||||
{
|
||||
return proposal_.changePosition (position, closeTime, now);
|
||||
}
|
||||
|
||||
bool bowOut (NetClock::time_point now)
|
||||
{
|
||||
if (isBowOut ())
|
||||
return false;
|
||||
|
||||
proposal_.bowOut (now);
|
||||
return true;
|
||||
}
|
||||
|
||||
Json::Value getJson() const
|
||||
{
|
||||
return proposal_.getJson();
|
||||
}
|
||||
|
||||
bool isInitial () const
|
||||
{
|
||||
return getSequence() == seqInitial;
|
||||
}
|
||||
|
||||
bool isBowOut() const
|
||||
{
|
||||
return getSequence() == seqLeave;
|
||||
}
|
||||
|
||||
// These three functions will be removed. New code
|
||||
// should use getPosition, getSequence and getNodeID
|
||||
LedgerHash const& getCurrentHash() const
|
||||
{
|
||||
return getPosition();
|
||||
}
|
||||
NodeID const& getPeerID() const
|
||||
{
|
||||
return getNodeID();
|
||||
}
|
||||
std::uint32_t getProposeSeq() const
|
||||
{
|
||||
return getSequence();
|
||||
}
|
||||
|
||||
LedgerProposal const& peek() const
|
||||
{
|
||||
return proposal_;
|
||||
}
|
||||
|
||||
LedgerProposal& peek()
|
||||
{
|
||||
return proposal_;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
LedgerProposal proposal_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
55
src/ripple/app/consensus/RCLCxTraits.h
Normal file
55
src/ripple/app/consensus/RCLCxTraits.h
Normal file
@@ -0,0 +1,55 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012-2016 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_APP_CONSENSUS_RCLCXTRAITS_H_INCLUDED
|
||||
#define RIPPLE_APP_CONSENSUS_RCLCXTRAITS_H_INCLUDED
|
||||
|
||||
#include <ripple/basics/chrono.h>
|
||||
#include <ripple/basics/base_uint.h>
|
||||
|
||||
#include <ripple/protocol/UintTypes.h>
|
||||
#include <ripple/protocol/RippleLedgerHash.h>
|
||||
|
||||
#include <ripple/app/consensus/RCLCxPos.h>
|
||||
#include <ripple/app/consensus/RCLCxTx.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// Consensus traits class
|
||||
// For adapting consensus to RCL
|
||||
|
||||
class RCLCxTraits
|
||||
{
|
||||
public:
|
||||
|
||||
using Time_t = NetClock::time_point;
|
||||
|
||||
using Pos_t = RCLCxPos;
|
||||
using TxSet_t = RCLTxSet;
|
||||
using Tx_t = RCLCxTx;
|
||||
|
||||
using LgrID_t = LedgerHash;
|
||||
using TxID_t = uint256;
|
||||
using TxSetID_t = uint256;
|
||||
using NodeID_t = NodeID;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
156
src/ripple/app/consensus/RCLCxTx.h
Normal file
156
src/ripple/app/consensus/RCLCxTx.h
Normal file
@@ -0,0 +1,156 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012-2016 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_APP_CONSENSUS_RCLCXTX_H_INCLUDED
|
||||
#define RIPPLE_APP_CONSENSUS_RCLCXTX_H_INCLUDED
|
||||
|
||||
#include <ripple/basics/chrono.h>
|
||||
#include <ripple/protocol/UintTypes.h>
|
||||
#include <ripple/shamap/SHAMap.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// Transactions, as seen by the consensus code in the rippled app
|
||||
class RCLCxTx
|
||||
{
|
||||
public:
|
||||
|
||||
RCLCxTx (SHAMapItem const& txn) : txn_ (txn)
|
||||
{ }
|
||||
|
||||
uint256 const& getID() const
|
||||
{
|
||||
return txn_.key ();
|
||||
}
|
||||
|
||||
SHAMapItem const& txn() const
|
||||
{
|
||||
return txn_;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
SHAMapItem const txn_;
|
||||
};
|
||||
|
||||
class RCLTxSet;
|
||||
|
||||
class MutableRCLTxSet
|
||||
{
|
||||
public:
|
||||
|
||||
MutableRCLTxSet (RCLTxSet const&);
|
||||
|
||||
bool
|
||||
addEntry (RCLCxTx const& p)
|
||||
{
|
||||
return map_->addItem (
|
||||
SHAMapItem {p.getID(), p.txn().peekData()},
|
||||
true, false);
|
||||
}
|
||||
|
||||
bool
|
||||
removeEntry (uint256 const& entry)
|
||||
{
|
||||
return map_->delItem (entry);
|
||||
}
|
||||
|
||||
std::shared_ptr <SHAMap> const& map() const
|
||||
{
|
||||
return map_;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::shared_ptr <SHAMap> map_;
|
||||
};
|
||||
|
||||
// Sets of transactions
|
||||
// as seen by the consensus code in the rippled app
|
||||
class RCLTxSet
|
||||
{
|
||||
public:
|
||||
|
||||
using mutable_t = MutableRCLTxSet;
|
||||
|
||||
RCLTxSet (std::shared_ptr<SHAMap> map) :
|
||||
map_ (std::move(map))
|
||||
{
|
||||
assert (map_);
|
||||
}
|
||||
|
||||
RCLTxSet (MutableRCLTxSet const& set) :
|
||||
map_ (set.map()->snapShot (false))
|
||||
{ }
|
||||
|
||||
bool hasEntry (uint256 const& entry) const
|
||||
{
|
||||
return map_->hasItem (entry);
|
||||
}
|
||||
|
||||
boost::optional <RCLCxTx const>
|
||||
getEntry (uint256 const& entry) const
|
||||
{
|
||||
auto item = map_->peekItem (entry);
|
||||
if (item)
|
||||
return RCLCxTx(*item);
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
uint256 getID() const
|
||||
{
|
||||
return map_->getHash().as_uint256();
|
||||
}
|
||||
|
||||
std::map <uint256, bool>
|
||||
getDifferences (RCLTxSet const& j) const
|
||||
{
|
||||
SHAMap::Delta delta;
|
||||
|
||||
// Bound the work we do in case of a malicious
|
||||
// map from a trusted validator
|
||||
map_->compare (*(j.map_), delta, 65536);
|
||||
|
||||
std::map <uint256, bool> ret;
|
||||
for (auto const& item : delta)
|
||||
{
|
||||
assert ( (item.second.first && ! item.second.second) ||
|
||||
(item.second.second && ! item.second.first) );
|
||||
|
||||
ret[item.first] = static_cast<bool> (item.second.first);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<SHAMap> const& map() const
|
||||
{
|
||||
return map_;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::shared_ptr <SHAMap> map_;
|
||||
};
|
||||
|
||||
inline MutableRCLTxSet::MutableRCLTxSet (RCLTxSet const& set)
|
||||
: map_ (set.map()->snapShot (true))
|
||||
{ }
|
||||
|
||||
}
|
||||
#endif
|
||||
115
src/ripple/app/consensus/README.md
Normal file
115
src/ripple/app/consensus/README.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Consensus Algorithm
|
||||
|
||||
This directory holds the types and classes needed
|
||||
to connect consensus to rippled.
|
||||
|
||||
## Types
|
||||
|
||||
All types must be copy constructible and assignable.
|
||||
|
||||
* `LgrID_t`
|
||||
Represents a ledger identifier.
|
||||
Typically a 256-bit hash of the ledger header.
|
||||
|
||||
* `TxID_t`
|
||||
Represents a transaction identifier.
|
||||
Typically a 256-bit hash of the transaction data.
|
||||
|
||||
* `TxSetID_t`
|
||||
Represents an identifier of a set of transactions.
|
||||
Typically a 256-bit hash of the set's root tree node.
|
||||
|
||||
* `NodeID_t`
|
||||
Represents an identifier for a node that can take positions during
|
||||
the consenus process.
|
||||
|
||||
* `Time_t`
|
||||
Encodes absolute times. Used for the close times of ledgers and the
|
||||
expiration times of positions.
|
||||
|
||||
* `Pos_t`
|
||||
Represents a position on a consensus taken by a participant.
|
||||
Typically it encodes the previous ledger identifier, the transaction
|
||||
set identifier, the participant, and a sequence number. It also includes
|
||||
either the time it was signed or the time it was first seen. It may also
|
||||
include additional information such as the participant's public key or
|
||||
signature
|
||||
|
||||
* `Tx_t`
|
||||
Represent a transaction. Has an identifier and also whatever information
|
||||
is needed to add it to a set.
|
||||
|
||||
* `TxSet_t`
|
||||
Represents a set of transactions. It has an identifier and can report
|
||||
which transactions it has and provide the actual transaction data.
|
||||
If non-const, it can be modified.
|
||||
|
||||
## `Pos_t`
|
||||
|
||||
Represents a position taken by a validator during a consensus round.
|
||||
Must provide:
|
||||
|
||||
static std::uint32_t seqInitial;
|
||||
|
||||
static std::uint32_t seqLeave;
|
||||
|
||||
std::uint32_t getSequence() const;
|
||||
|
||||
Time_t getCloseTime() const;
|
||||
|
||||
Time_t getSeenTime() const;
|
||||
|
||||
bool isStale (Time_t) const;
|
||||
|
||||
NodeID_t getNodeID() const;
|
||||
|
||||
TxSetID_t getPosition() const;
|
||||
|
||||
LgrID_t getPrevLedger() const;
|
||||
|
||||
bool isInitial() const;
|
||||
|
||||
bool isBowOut() const;
|
||||
|
||||
Json::Value getJson() const;
|
||||
|
||||
bool changePosition (TxSetID_t const& position, Time_t closeTime, Time_t now);
|
||||
|
||||
bool bowOut (Time_t now);
|
||||
|
||||
|
||||
### `Tx_t`
|
||||
|
||||
Represents a transaction.
|
||||
Must provide:
|
||||
|
||||
TxID_t getID() const;
|
||||
|
||||
|
||||
### TxSet_t
|
||||
|
||||
Represents a set of transactions.
|
||||
Must provide:
|
||||
|
||||
TxSet_t (TxSet_t::mutable_t const&);
|
||||
|
||||
TxSetID_t getID() const;
|
||||
|
||||
bool hasEntry (TxID_t const&) const;
|
||||
|
||||
bool hasEntry (Tx_t const&) const;
|
||||
|
||||
boost::optional <Tx_t const> const getEntry (TxID_t const&) const;
|
||||
|
||||
std::map <TxID_t, bool> getDifferences(TxSet_t const&) const;
|
||||
|
||||
## TxSet_t::mutable_t
|
||||
|
||||
Represents a set of transactions that can be modified.
|
||||
Must provide:
|
||||
|
||||
TxSet_t::mutable_t (TxSet_t const &);
|
||||
|
||||
bool addEntry (Tx_t const&);
|
||||
|
||||
bool removeEntry (TxID_t const&);
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <ripple/app/ledger/LedgerConsensus.h>
|
||||
#include <ripple/app/ledger/LedgerMaster.h>
|
||||
#include <ripple/app/ledger/InboundTransactions.h>
|
||||
#include <ripple/app/consensus/RCLCxTraits.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/core/Config.h>
|
||||
@@ -64,7 +65,7 @@ public:
|
||||
|
||||
/** Called to create a LedgerConsensus instance */
|
||||
virtual
|
||||
std::shared_ptr<LedgerConsensus>
|
||||
std::shared_ptr<LedgerConsensus<RCLCxTraits>>
|
||||
makeLedgerConsensus (
|
||||
Application& app,
|
||||
InboundTransactions& inboundTransactions,
|
||||
@@ -75,7 +76,7 @@ public:
|
||||
virtual
|
||||
void
|
||||
startRound (
|
||||
LedgerConsensus& consensus,
|
||||
LedgerConsensus<RCLCxTraits>& consensus,
|
||||
LedgerHash const &prevLCLHash,
|
||||
std::shared_ptr<Ledger const> const& previousLedger,
|
||||
NetClock::time_point closeTime) = 0;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/app/ledger/LedgerProposal.h>
|
||||
#include <ripple/app/ledger/InboundTransactions.h>
|
||||
#include <ripple/app/consensus/RCLCxTraits.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/misc/CanonicalTXSet.h>
|
||||
#include <ripple/app/misc/FeeVote.h>
|
||||
@@ -34,30 +35,37 @@
|
||||
namespace ripple {
|
||||
|
||||
/** Manager for achieving consensus on the next ledger.
|
||||
|
||||
This object is created when the consensus process starts, and
|
||||
is destroyed when the process is complete.
|
||||
*/
|
||||
class LedgerConsensus
|
||||
template <class Traits>
|
||||
class LedgerConsensus : public Traits
|
||||
{
|
||||
public:
|
||||
|
||||
using typename Traits::Time_t;
|
||||
using typename Traits::Pos_t;
|
||||
using typename Traits::TxSet_t;
|
||||
using typename Traits::Tx_t;
|
||||
using typename Traits::LgrID_t;
|
||||
using typename Traits::TxID_t;
|
||||
using typename Traits::TxSetID_t;
|
||||
using typename Traits::NodeID_t;
|
||||
|
||||
virtual ~LedgerConsensus() = default;
|
||||
|
||||
virtual Json::Value getJson (bool full) = 0;
|
||||
|
||||
virtual uint256 getLCL () = 0;
|
||||
virtual LgrID_t getLCL () = 0;
|
||||
|
||||
virtual void gotMap (
|
||||
std::shared_ptr<SHAMap> const& map) = 0;
|
||||
virtual void gotMap (TxSet_t const& map) = 0;
|
||||
|
||||
virtual void timerEntry () = 0;
|
||||
|
||||
virtual bool peerPosition (LedgerProposal::ref) = 0;
|
||||
virtual bool peerPosition (Pos_t const& position) = 0;
|
||||
|
||||
virtual void startRound (
|
||||
LedgerHash const& prevLCLHash,
|
||||
LgrID_t const& prevLCLHash,
|
||||
std::shared_ptr<Ledger const> const& prevLedger,
|
||||
NetClock::time_point closeTime,
|
||||
Time_t closeTime,
|
||||
int previousProposers,
|
||||
std::chrono::milliseconds previousConvergeTime) = 0;
|
||||
|
||||
|
||||
@@ -33,8 +33,10 @@ LedgerProposal::LedgerProposal (
|
||||
std::uint32_t seq,
|
||||
uint256 const& tx,
|
||||
NetClock::time_point closeTime,
|
||||
NetClock::time_point now,
|
||||
PublicKey const& publicKey,
|
||||
NodeID const& nodeID,
|
||||
Slice const& signature,
|
||||
uint256 const& suppression)
|
||||
: mPreviousLedger (pLgr)
|
||||
, mCurrentHash (tx)
|
||||
@@ -43,8 +45,11 @@ LedgerProposal::LedgerProposal (
|
||||
, mProposeSeq (seq)
|
||||
, publicKey_ (publicKey)
|
||||
, mPeerID (nodeID)
|
||||
, mTime (std::chrono::steady_clock::now ())
|
||||
, mTime (now)
|
||||
{
|
||||
signature_.resize (signature.size());
|
||||
std::memcpy(signature_.data(),
|
||||
signature.data(), signature.size());
|
||||
}
|
||||
|
||||
// Used to construct local proposals
|
||||
@@ -52,12 +57,13 @@ LedgerProposal::LedgerProposal (
|
||||
LedgerProposal::LedgerProposal (
|
||||
uint256 const& prevLgr,
|
||||
uint256 const& position,
|
||||
NetClock::time_point closeTime)
|
||||
NetClock::time_point closeTime,
|
||||
NetClock::time_point now)
|
||||
: mPreviousLedger (prevLgr)
|
||||
, mCurrentHash (position)
|
||||
, mCloseTime (closeTime)
|
||||
, mProposeSeq (seqJoin)
|
||||
, mTime (std::chrono::steady_clock::now ())
|
||||
, mTime (now)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -76,27 +82,28 @@ bool LedgerProposal::checkSign () const
|
||||
return verifyDigest (
|
||||
publicKey_,
|
||||
getSigningHash(),
|
||||
signature_,
|
||||
makeSlice (signature_),
|
||||
false);
|
||||
}
|
||||
|
||||
bool LedgerProposal::changePosition (
|
||||
uint256 const& newPosition,
|
||||
NetClock::time_point closeTime)
|
||||
NetClock::time_point closeTime,
|
||||
NetClock::time_point now)
|
||||
{
|
||||
if (mProposeSeq == seqLeave)
|
||||
return false;
|
||||
|
||||
mCurrentHash = newPosition;
|
||||
mCloseTime = closeTime;
|
||||
mTime = std::chrono::steady_clock::now ();
|
||||
mTime = now;
|
||||
++mProposeSeq;
|
||||
return true;
|
||||
}
|
||||
|
||||
void LedgerProposal::bowOut ()
|
||||
void LedgerProposal::bowOut (NetClock::time_point now)
|
||||
{
|
||||
mTime = std::chrono::steady_clock::now ();
|
||||
mTime = now;
|
||||
mProposeSeq = seqLeave;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,15 +55,18 @@ public:
|
||||
std::uint32_t proposeSeq,
|
||||
uint256 const& propose,
|
||||
NetClock::time_point closeTime,
|
||||
NetClock::time_point now,
|
||||
PublicKey const& publicKey,
|
||||
NodeID const& nodeID,
|
||||
Slice const& signature,
|
||||
uint256 const& suppress);
|
||||
|
||||
// Our own proposal:
|
||||
LedgerProposal (
|
||||
uint256 const& prevLedger,
|
||||
uint256 const& position,
|
||||
NetClock::time_point closeTime);
|
||||
NetClock::time_point closeTime,
|
||||
NetClock::time_point now);
|
||||
|
||||
uint256 getSigningHash () const;
|
||||
bool checkSign () const;
|
||||
@@ -96,17 +99,14 @@ public:
|
||||
{
|
||||
return mCloseTime;
|
||||
}
|
||||
|
||||
void setSignature (Buffer&& sig)
|
||||
NetClock::time_point getSeenTime () const
|
||||
{
|
||||
signature_ = std::move(sig);
|
||||
return mTime;
|
||||
}
|
||||
|
||||
Slice getSignature () const
|
||||
Blob const& getSignature () const
|
||||
{
|
||||
return signature_;
|
||||
}
|
||||
|
||||
bool isInitial () const
|
||||
{
|
||||
return mProposeSeq == seqJoin;
|
||||
@@ -116,14 +116,16 @@ public:
|
||||
return mProposeSeq == seqLeave;
|
||||
}
|
||||
|
||||
bool isStale (std::chrono::steady_clock::time_point cutoff) const
|
||||
bool isStale (NetClock::time_point cutoff) const
|
||||
{
|
||||
return mTime <= cutoff;
|
||||
}
|
||||
|
||||
bool changePosition (
|
||||
uint256 const& newPosition, NetClock::time_point newCloseTime);
|
||||
void bowOut ();
|
||||
uint256 const& newPosition,
|
||||
NetClock::time_point newCloseTime,
|
||||
NetClock::time_point now);
|
||||
void bowOut (NetClock::time_point now);
|
||||
Json::Value getJson () const;
|
||||
|
||||
private:
|
||||
@@ -145,9 +147,9 @@ private:
|
||||
|
||||
PublicKey publicKey_;
|
||||
NodeID mPeerID;
|
||||
Buffer signature_;
|
||||
Blob signature_;
|
||||
|
||||
std::chrono::steady_clock::time_point mTime;
|
||||
NetClock::time_point mTime;
|
||||
};
|
||||
|
||||
/** Calculate a unique identifier for a signed proposal.
|
||||
|
||||
@@ -63,7 +63,7 @@ ConsensusImp::getLastCloseDuration () const
|
||||
return lastCloseConvergeTook_;
|
||||
}
|
||||
|
||||
std::shared_ptr<LedgerConsensus>
|
||||
std::shared_ptr<LedgerConsensus<RCLCxTraits>>
|
||||
ConsensusImp::makeLedgerConsensus (
|
||||
Application& app,
|
||||
InboundTransactions& inboundTransactions,
|
||||
@@ -76,7 +76,7 @@ ConsensusImp::makeLedgerConsensus (
|
||||
|
||||
void
|
||||
ConsensusImp::startRound (
|
||||
LedgerConsensus& consensus,
|
||||
LedgerConsensus<RCLCxTraits>& consensus,
|
||||
LedgerHash const &prevLCLHash,
|
||||
std::shared_ptr<Ledger const> const& previousLedger,
|
||||
NetClock::time_point closeTime)
|
||||
@@ -154,11 +154,11 @@ ConsensusImp::storeProposal (
|
||||
props.push_back (proposal);
|
||||
}
|
||||
|
||||
std::vector <std::shared_ptr <LedgerProposal>>
|
||||
std::vector <RCLCxPos>
|
||||
ConsensusImp::getStoredProposals (uint256 const& prevLedger)
|
||||
{
|
||||
|
||||
std::vector <std::shared_ptr <LedgerProposal>> ret;
|
||||
std::vector <RCLCxPos> ret;
|
||||
|
||||
{
|
||||
std::lock_guard <std::mutex> _(lock_);
|
||||
@@ -166,15 +166,13 @@ ConsensusImp::getStoredProposals (uint256 const& prevLedger)
|
||||
for (auto const& it : storedProposals_)
|
||||
for (auto const& prop : it.second)
|
||||
if (prop->getPrevLedger() == prevLedger)
|
||||
ret.push_back (prop);
|
||||
ret.emplace_back (*prop);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
std::unique_ptr<Consensus>
|
||||
std::unique_ptr <Consensus>
|
||||
make_Consensus (Config const& config, Logs& logs)
|
||||
{
|
||||
return std::make_unique<ConsensusImp> (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
std::chrono::milliseconds
|
||||
getLastCloseDuration () const override;
|
||||
|
||||
std::shared_ptr<LedgerConsensus>
|
||||
std::shared_ptr<LedgerConsensus<RCLCxTraits>>
|
||||
makeLedgerConsensus (
|
||||
Application& app,
|
||||
InboundTransactions& inboundTransactions,
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
|
||||
void
|
||||
startRound (
|
||||
LedgerConsensus& ledgerConsensus,
|
||||
LedgerConsensus<RCLCxTraits>& ledgerConsensus,
|
||||
LedgerHash const& prevLCLHash,
|
||||
std::shared_ptr<Ledger const> const& previousLedger,
|
||||
NetClock::time_point closeTime) override;
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
NetClock::time_point
|
||||
getLastCloseTime () const;
|
||||
|
||||
std::vector <std::shared_ptr <LedgerProposal>>
|
||||
std::vector <RCLCxPos>
|
||||
getStoredProposals (uint256 const& previousLedger);
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 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 <BeastConfig.h>
|
||||
#include <ripple/app/ledger/impl/DisputedTx.h>
|
||||
#include <ripple/app/ledger/LedgerTiming.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// Track a peer's yes/no vote on a particular disputed transaction
|
||||
void DisputedTx::setVote (NodeID const& peer, bool votesYes)
|
||||
{
|
||||
auto res = mVotes.insert (std::make_pair (peer, votesYes));
|
||||
|
||||
// new vote
|
||||
if (res.second)
|
||||
{
|
||||
if (votesYes)
|
||||
{
|
||||
JLOG (j_.debug())
|
||||
<< "Peer " << peer << " votes YES on " << mTransactionID;
|
||||
++mYays;
|
||||
}
|
||||
else
|
||||
{
|
||||
JLOG (j_.debug())
|
||||
<< "Peer " << peer << " votes NO on " << mTransactionID;
|
||||
++mNays;
|
||||
}
|
||||
}
|
||||
// changes vote to yes
|
||||
else if (votesYes && !res.first->second)
|
||||
{
|
||||
JLOG (j_.debug())
|
||||
<< "Peer " << peer << " now votes YES on " << mTransactionID;
|
||||
--mNays;
|
||||
++mYays;
|
||||
res.first->second = true;
|
||||
}
|
||||
// changes vote to no
|
||||
else if (!votesYes && res.first->second)
|
||||
{
|
||||
JLOG (j_.debug())
|
||||
<< "Peer " << peer << " now votes NO on " << mTransactionID;
|
||||
++mNays;
|
||||
--mYays;
|
||||
res.first->second = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove a peer's vote on this disputed transasction
|
||||
void DisputedTx::unVote (NodeID const& peer)
|
||||
{
|
||||
auto it = mVotes.find (peer);
|
||||
|
||||
if (it != mVotes.end ())
|
||||
{
|
||||
if (it->second)
|
||||
--mYays;
|
||||
else
|
||||
--mNays;
|
||||
|
||||
mVotes.erase (it);
|
||||
}
|
||||
}
|
||||
|
||||
bool DisputedTx::updateVote (int percentTime, bool proposing)
|
||||
{
|
||||
// VFALCO TODO Give the return value a descriptive local variable name
|
||||
// and don't return from the middle.
|
||||
|
||||
if (mOurVote && (mNays == 0))
|
||||
return false;
|
||||
|
||||
if (!mOurVote && (mYays == 0))
|
||||
return false;
|
||||
|
||||
bool newPosition;
|
||||
int weight;
|
||||
|
||||
if (proposing) // give ourselves full weight
|
||||
{
|
||||
// This is basically the percentage of nodes voting 'yes' (including us)
|
||||
weight = (mYays * 100 + (mOurVote ? 100 : 0)) / (mNays + mYays + 1);
|
||||
|
||||
// VFALCO TODO Rename these macros and turn them into language
|
||||
// constructs. consolidate them into a class that collects
|
||||
// all these related values.
|
||||
//
|
||||
// To prevent avalanche stalls, we increase the needed weight slightly
|
||||
// over time.
|
||||
if (percentTime < AV_MID_CONSENSUS_TIME)
|
||||
newPosition = weight > AV_INIT_CONSENSUS_PCT;
|
||||
else if (percentTime < AV_LATE_CONSENSUS_TIME)
|
||||
newPosition = weight > AV_MID_CONSENSUS_PCT;
|
||||
else if (percentTime < AV_STUCK_CONSENSUS_TIME)
|
||||
newPosition = weight > AV_LATE_CONSENSUS_PCT;
|
||||
else
|
||||
newPosition = weight > AV_STUCK_CONSENSUS_PCT;
|
||||
}
|
||||
else // don't let us outweigh a proposing node, just recognize consensus
|
||||
{
|
||||
weight = -1;
|
||||
newPosition = mYays > mNays;
|
||||
}
|
||||
|
||||
if (newPosition == mOurVote)
|
||||
{
|
||||
JLOG (j_.info())
|
||||
<< "No change (" << (mOurVote ? "YES" : "NO") << ") : weight "
|
||||
<< weight << ", percent " << percentTime;
|
||||
JLOG (j_.debug()) << getJson ();
|
||||
return false;
|
||||
}
|
||||
|
||||
mOurVote = newPosition;
|
||||
JLOG (j_.debug())
|
||||
<< "We now vote " << (mOurVote ? "YES" : "NO")
|
||||
<< " on " << mTransactionID;
|
||||
JLOG (j_.debug()) << getJson ();
|
||||
return true;
|
||||
}
|
||||
|
||||
Json::Value DisputedTx::getJson ()
|
||||
{
|
||||
Json::Value ret (Json::objectValue);
|
||||
|
||||
ret["yays"] = mYays;
|
||||
ret["nays"] = mNays;
|
||||
ret["our_vote"] = mOurVote;
|
||||
|
||||
if (!mVotes.empty ())
|
||||
{
|
||||
Json::Value votesj (Json::objectValue);
|
||||
for (auto& vote : mVotes)
|
||||
votesj[to_string (vote.first)] = vote.second;
|
||||
ret["votes"] = votesj;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
@@ -36,22 +36,28 @@ namespace ripple {
|
||||
|
||||
Undisputed transactions have no corresponding @ref DisputedTx object.
|
||||
*/
|
||||
|
||||
template <class Traits>
|
||||
class DisputedTx
|
||||
{
|
||||
public:
|
||||
// VFALCO `Blob` is a poor choice of parameter
|
||||
DisputedTx (uint256 const& txID,
|
||||
Blob const& tx, bool ourVote, beast::Journal j)
|
||||
: mTransactionID (txID)
|
||||
|
||||
using Tx_t = typename Traits::Tx_t;
|
||||
using TxID_t = typename Traits::TxID_t;
|
||||
using NodeID_t = typename Traits::NodeID_t;
|
||||
|
||||
DisputedTx (Tx_t const& tx,
|
||||
bool ourVote, beast::Journal j)
|
||||
: mTransactionID (tx.getID())
|
||||
, mYays (0)
|
||||
, mNays (0)
|
||||
, mOurVote (ourVote)
|
||||
, transaction (tx.data(), tx.size())
|
||||
, transaction (tx)
|
||||
, j_ (j)
|
||||
{
|
||||
}
|
||||
|
||||
uint256 const& getTransactionID () const
|
||||
TxID_t const& getID () const
|
||||
{
|
||||
return mTransactionID;
|
||||
}
|
||||
@@ -61,9 +67,7 @@ public:
|
||||
return mOurVote;
|
||||
}
|
||||
|
||||
// VFALCO TODO make this const
|
||||
// VFALCO TODO Don't return a Serializer (doh)
|
||||
Serializer& peekTransaction ()
|
||||
Tx_t const& tx () const
|
||||
{
|
||||
return transaction;
|
||||
}
|
||||
@@ -73,26 +77,158 @@ public:
|
||||
mOurVote = o;
|
||||
}
|
||||
|
||||
// VFALCO NOTE its not really a peer, its the 160 bit hash of the
|
||||
// validator's public key.
|
||||
void setVote (NodeID const& peer, bool votesYes);
|
||||
void unVote (NodeID const& peer);
|
||||
void setVote (NodeID_t const& peer, bool votesYes);
|
||||
void unVote (NodeID_t const& peer);
|
||||
|
||||
bool updateVote (int percentTime, bool proposing);
|
||||
Json::Value getJson ();
|
||||
|
||||
private:
|
||||
uint256 mTransactionID;
|
||||
TxID_t mTransactionID;
|
||||
int mYays;
|
||||
int mNays;
|
||||
bool mOurVote;
|
||||
// VFALCO Why is this being stored as a Serializer?
|
||||
Serializer transaction;
|
||||
Tx_t transaction;
|
||||
|
||||
hash_map <NodeID, bool> mVotes;
|
||||
hash_map <NodeID_t, bool> mVotes;
|
||||
beast::Journal j_;
|
||||
};
|
||||
|
||||
// Track a peer's yes/no vote on a particular disputed transaction
|
||||
template <class Traits>
|
||||
void DisputedTx<Traits>::setVote (NodeID_t const& peer, bool votesYes)
|
||||
{
|
||||
auto res = mVotes.insert (std::make_pair (peer, votesYes));
|
||||
|
||||
// new vote
|
||||
if (res.second)
|
||||
{
|
||||
if (votesYes)
|
||||
{
|
||||
JLOG (j_.debug())
|
||||
<< "Peer " << peer << " votes YES on " << mTransactionID;
|
||||
++mYays;
|
||||
}
|
||||
else
|
||||
{
|
||||
JLOG (j_.debug())
|
||||
<< "Peer " << peer << " votes NO on " << mTransactionID;
|
||||
++mNays;
|
||||
}
|
||||
}
|
||||
// changes vote to yes
|
||||
else if (votesYes && !res.first->second)
|
||||
{
|
||||
JLOG (j_.debug())
|
||||
<< "Peer " << peer << " now votes YES on " << mTransactionID;
|
||||
--mNays;
|
||||
++mYays;
|
||||
res.first->second = true;
|
||||
}
|
||||
// changes vote to no
|
||||
else if (!votesYes && res.first->second)
|
||||
{
|
||||
JLOG (j_.debug())
|
||||
<< "Peer " << peer << " now votes NO on " << mTransactionID;
|
||||
++mNays;
|
||||
--mYays;
|
||||
res.first->second = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove a peer's vote on this disputed transasction
|
||||
template <class Traits>
|
||||
void DisputedTx<Traits>::unVote (NodeID_t const& peer)
|
||||
{
|
||||
auto it = mVotes.find (peer);
|
||||
|
||||
if (it != mVotes.end ())
|
||||
{
|
||||
if (it->second)
|
||||
--mYays;
|
||||
else
|
||||
--mNays;
|
||||
|
||||
mVotes.erase (it);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Traits>
|
||||
bool DisputedTx<Traits>::updateVote (int percentTime, bool proposing)
|
||||
{
|
||||
if (mOurVote && (mNays == 0))
|
||||
return false;
|
||||
|
||||
if (!mOurVote && (mYays == 0))
|
||||
return false;
|
||||
|
||||
bool newPosition;
|
||||
int weight;
|
||||
|
||||
if (proposing) // give ourselves full weight
|
||||
{
|
||||
// This is basically the percentage of nodes voting 'yes' (including us)
|
||||
weight = (mYays * 100 + (mOurVote ? 100 : 0)) / (mNays + mYays + 1);
|
||||
|
||||
// VFALCO TODO Rename these macros and turn them into language
|
||||
// constructs. consolidate them into a class that collects
|
||||
// all these related values.
|
||||
//
|
||||
// To prevent avalanche stalls, we increase the needed weight slightly
|
||||
// over time.
|
||||
if (percentTime < AV_MID_CONSENSUS_TIME)
|
||||
newPosition = weight > AV_INIT_CONSENSUS_PCT;
|
||||
else if (percentTime < AV_LATE_CONSENSUS_TIME)
|
||||
newPosition = weight > AV_MID_CONSENSUS_PCT;
|
||||
else if (percentTime < AV_STUCK_CONSENSUS_TIME)
|
||||
newPosition = weight > AV_LATE_CONSENSUS_PCT;
|
||||
else
|
||||
newPosition = weight > AV_STUCK_CONSENSUS_PCT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't let us outweigh a proposing node, just recognize consensus
|
||||
weight = -1;
|
||||
newPosition = mYays > mNays;
|
||||
}
|
||||
|
||||
if (newPosition == mOurVote)
|
||||
{
|
||||
JLOG (j_.info())
|
||||
<< "No change (" << (mOurVote ? "YES" : "NO") << ") : weight "
|
||||
<< weight << ", percent " << percentTime;
|
||||
JLOG (j_.debug()) << getJson ();
|
||||
return false;
|
||||
}
|
||||
|
||||
mOurVote = newPosition;
|
||||
JLOG (j_.debug())
|
||||
<< "We now vote " << (mOurVote ? "YES" : "NO")
|
||||
<< " on " << mTransactionID;
|
||||
JLOG (j_.debug()) << getJson ();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Traits>
|
||||
Json::Value DisputedTx<Traits>::getJson ()
|
||||
{
|
||||
Json::Value ret (Json::objectValue);
|
||||
|
||||
ret["yays"] = mYays;
|
||||
ret["nays"] = mNays;
|
||||
ret["our_vote"] = mOurVote;
|
||||
|
||||
if (!mVotes.empty ())
|
||||
{
|
||||
Json::Value votesj (Json::objectValue);
|
||||
for (auto& vote : mVotes)
|
||||
votesj[to_string (vote.first)] = vote.second;
|
||||
ret["votes"] = std::move (votesj);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,19 +37,16 @@ namespace ripple {
|
||||
Provides the implementation for LedgerConsensus.
|
||||
|
||||
Achieves consensus on the next ledger.
|
||||
This object is created when the consensus process starts, and
|
||||
is destroyed when the process is complete.
|
||||
|
||||
Nearly everything herein is invoked with the master lock.
|
||||
|
||||
Two things need consensus:
|
||||
1. The set of transactions.
|
||||
2. The close time for the ledger.
|
||||
*/
|
||||
template <class Traits>
|
||||
class LedgerConsensusImp
|
||||
: public LedgerConsensus
|
||||
, public std::enable_shared_from_this <LedgerConsensusImp>
|
||||
, public CountedObject <LedgerConsensusImp>
|
||||
: public LedgerConsensus<Traits>
|
||||
, public std::enable_shared_from_this <LedgerConsensusImp<Traits>>
|
||||
, public CountedObject <LedgerConsensusImp<Traits>>
|
||||
{
|
||||
private:
|
||||
enum class State
|
||||
@@ -70,6 +67,17 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
using typename Traits::Time_t;
|
||||
using typename Traits::Pos_t;
|
||||
using typename Traits::TxSet_t;
|
||||
using typename Traits::Tx_t;
|
||||
using typename Traits::LgrID_t;
|
||||
using typename Traits::TxID_t;
|
||||
using typename Traits::TxSetID_t;
|
||||
using typename Traits::NodeID_t;
|
||||
using Dispute_t = DisputedTx <Traits>;
|
||||
|
||||
/**
|
||||
* The result of applying a transaction to a ledger.
|
||||
*/
|
||||
@@ -82,6 +90,7 @@ public:
|
||||
|
||||
~LedgerConsensusImp () = default;
|
||||
|
||||
|
||||
/**
|
||||
@param localtx transactions issued by local clients
|
||||
@param inboundTransactions set of inbound transaction sets
|
||||
@@ -104,9 +113,9 @@ public:
|
||||
@param previousConvergeTime how long the last round took (ms)
|
||||
*/
|
||||
void startRound (
|
||||
LedgerHash const& prevLCLHash,
|
||||
LgrID_t const& prevLCLHash,
|
||||
std::shared_ptr<Ledger const> const& prevLedger,
|
||||
NetClock::time_point closeTime,
|
||||
Time_t closeTime,
|
||||
int previousProposers,
|
||||
std::chrono::milliseconds previousConvergeTime) override;
|
||||
|
||||
@@ -120,24 +129,20 @@ public:
|
||||
Json::Value getJson (bool full) override;
|
||||
|
||||
/* The hash of the last closed ledger */
|
||||
uint256 getLCL () override;
|
||||
LgrID_t getLCL () override;
|
||||
|
||||
/**
|
||||
We have a complete transaction set, typically acquired from the network
|
||||
|
||||
@param map the transaction set.
|
||||
@param acquired true if we have acquired the transaction set.
|
||||
*/
|
||||
void gotMap (
|
||||
std::shared_ptr<SHAMap> const& map) override;
|
||||
void gotMap (TxSet_t const& map) override;
|
||||
|
||||
/**
|
||||
On timer call the correct handler for each state.
|
||||
*/
|
||||
void timerEntry () override;
|
||||
|
||||
std::shared_ptr<SHAMap> getTransactionTree (uint256 const& hash);
|
||||
|
||||
/**
|
||||
A server has taken a new position, adjust our tracking
|
||||
Called when a peer takes a new postion.
|
||||
@@ -145,11 +150,16 @@ public:
|
||||
@param newPosition the new position
|
||||
@return true if we should do delayed relay of this position.
|
||||
*/
|
||||
bool peerPosition (LedgerProposal::ref newPosition) override;
|
||||
bool peerPosition (Pos_t const& newPosition) override;
|
||||
|
||||
void simulate(
|
||||
boost::optional<std::chrono::milliseconds> consensusDelay) override;
|
||||
|
||||
/**
|
||||
Put a transaction set where peers can find it
|
||||
*/
|
||||
void shareSet (TxSet_t const&);
|
||||
|
||||
private:
|
||||
/**
|
||||
Handle pre-close state.
|
||||
@@ -179,7 +189,7 @@ private:
|
||||
|
||||
@param lclHash Hash of the last closed ledger.
|
||||
*/
|
||||
void handleLCL (uint256 const& lclHash);
|
||||
void handleLCL (LgrID_t const& lclHash);
|
||||
|
||||
/**
|
||||
We have a complete transaction set, typically acquired from the network
|
||||
@@ -188,14 +198,14 @@ private:
|
||||
@param acquired true if we have acquired the transaction set.
|
||||
*/
|
||||
void mapCompleteInternal (
|
||||
std::shared_ptr<SHAMap> const& map,
|
||||
TxSet_t const& map,
|
||||
bool acquired);
|
||||
|
||||
/** We have a new last closed ledger, process it. Final accept logic
|
||||
|
||||
@param set Our consensus set
|
||||
*/
|
||||
void accept (std::shared_ptr<SHAMap> set);
|
||||
void accept (TxSet_t const& set);
|
||||
|
||||
/**
|
||||
Compare two proposed transaction sets and create disputed
|
||||
@@ -204,17 +214,16 @@ private:
|
||||
@param m1 One transaction set
|
||||
@param m2 The other transaction set
|
||||
*/
|
||||
void createDisputes (std::shared_ptr<SHAMap> const& m1,
|
||||
std::shared_ptr<SHAMap> const& m2);
|
||||
void createDisputes (TxSet_t const& m1,
|
||||
TxSet_t const& m2);
|
||||
|
||||
/**
|
||||
Add a disputed transaction (one that at least one node wants
|
||||
in the consensus set and at least one node does not) to our tracking
|
||||
|
||||
@param txID The ID of the disputed transaction
|
||||
@param tx The data of the disputed transaction
|
||||
@param tx The disputed transaction
|
||||
*/
|
||||
void addDisputedTransaction (uint256 const& txID, Blob const& tx);
|
||||
void addDisputedTransaction (Tx_t const& tx);
|
||||
|
||||
/**
|
||||
Adjust the votes on all disputed transactions based
|
||||
@@ -223,8 +232,8 @@ private:
|
||||
@param map A disputed position
|
||||
@param peers peers which are taking the position map
|
||||
*/
|
||||
void adjustCount (std::shared_ptr<SHAMap> const& map,
|
||||
const std::vector<NodeID>& peers);
|
||||
void adjustCount (TxSet_t const& map,
|
||||
std::vector<NodeID_t> const& peers);
|
||||
|
||||
/**
|
||||
Revoke our outstanding proposal, if any, and
|
||||
@@ -247,7 +256,7 @@ private:
|
||||
/** Determine our initial proposed transaction set based on
|
||||
our open ledger
|
||||
*/
|
||||
std::shared_ptr<SHAMap> makeInitialPosition();
|
||||
std::pair <TxSet_t, Pos_t> makeInitialPosition();
|
||||
|
||||
/** Take an initial position on what we think the consensus set should be
|
||||
*/
|
||||
@@ -296,16 +305,18 @@ private:
|
||||
FeeVote& feeVote_;
|
||||
std::recursive_mutex lock_;
|
||||
|
||||
NodeID_t ourID_;
|
||||
State state_;
|
||||
|
||||
// The wall time this ledger closed
|
||||
NetClock::time_point closeTime_;
|
||||
Time_t closeTime_;
|
||||
|
||||
uint256 prevLedgerHash_;
|
||||
uint256 acquiringLedger_;
|
||||
LgrID_t prevLedgerHash_;
|
||||
LgrID_t acquiringLedger_;
|
||||
|
||||
std::shared_ptr<Ledger const> previousLedger_;
|
||||
LedgerProposal::pointer ourPosition_;
|
||||
boost::optional<Pos_t> ourPosition_;
|
||||
boost::optional<TxSet_t> ourSet_;
|
||||
PublicKey valPublic_;
|
||||
SecretKey valSecret_;
|
||||
bool proposing_, validating_, haveCorrectLCL_, consensusFail_;
|
||||
@@ -328,26 +339,26 @@ private:
|
||||
std::chrono::milliseconds previousRoundTime_;
|
||||
|
||||
// Convergence tracking, trusted peers indexed by hash of public key
|
||||
hash_map<NodeID, LedgerProposal::pointer> peerPositions_;
|
||||
hash_map<NodeID_t, Pos_t> peerPositions_;
|
||||
|
||||
// Transaction Sets, indexed by hash of transaction tree
|
||||
hash_map<uint256, std::shared_ptr<SHAMap>> acquired_;
|
||||
hash_map<TxSetID_t, const TxSet_t> acquired_;
|
||||
|
||||
// Disputed transactions
|
||||
hash_map<uint256, std::shared_ptr <DisputedTx>> disputes_;
|
||||
hash_set<uint256> compares_;
|
||||
hash_map<TxID_t, Dispute_t> disputes_;
|
||||
hash_set<TxSetID_t> compares_;
|
||||
|
||||
// Close time estimates, keep ordered for predictable traverse
|
||||
std::map<NetClock::time_point, int> closeTimes_;
|
||||
std::map <Time_t, int> closeTimes_;
|
||||
|
||||
// nodes that have bowed out of this consensus process
|
||||
hash_set<NodeID> deadNodes_;
|
||||
hash_set<NodeID_t> deadNodes_;
|
||||
beast::Journal j_;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::shared_ptr <LedgerConsensus>
|
||||
std::shared_ptr <LedgerConsensus <RCLCxTraits>>
|
||||
make_LedgerConsensus (
|
||||
Application& app,
|
||||
ConsensusImp& consensus,
|
||||
@@ -370,10 +381,12 @@ make_LedgerConsensus (
|
||||
CanonicalTXSet
|
||||
applyTransactions (
|
||||
Application& app,
|
||||
SHAMap const& set,
|
||||
RCLTxSet const& set,
|
||||
OpenView& view,
|
||||
std::function<bool(uint256 const&)> txFilter);
|
||||
|
||||
extern template class LedgerConsensusImp <RCLCxTraits>;
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -459,8 +459,7 @@ public:
|
||||
, [this](std::shared_ptr <SHAMap> const& set,
|
||||
bool fromAcquire)
|
||||
{
|
||||
if (set)
|
||||
gotTXSet (set, fromAcquire);
|
||||
gotTXSet (set, fromAcquire);
|
||||
}))
|
||||
|
||||
, m_acceptedLedgerCache ("AcceptedLedger", 4, 60, stopwatch(),
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <ripple/protocol/Quality.h>
|
||||
#include <ripple/core/DatabaseCon.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/consensus/RCLCxTraits.h>
|
||||
#include <ripple/app/ledger/Consensus.h>
|
||||
#include <ripple/app/ledger/LedgerConsensus.h>
|
||||
#include <ripple/app/ledger/AcceptedLedger.h>
|
||||
@@ -529,7 +530,7 @@ private:
|
||||
DeadlineTimer m_clusterTimer;
|
||||
|
||||
std::unique_ptr<Consensus> mConsensus;
|
||||
std::shared_ptr<LedgerConsensus> mLedgerConsensus;
|
||||
std::shared_ptr<LedgerConsensus<RCLCxTraits>> mLedgerConsensus;
|
||||
|
||||
LedgerMaster& m_ledgerMaster;
|
||||
std::shared_ptr<InboundLedger> mAcquiringLedger;
|
||||
@@ -1503,14 +1504,12 @@ void NetworkOPsImp::processTrustedProposal (
|
||||
std::shared_ptr<protocol::TMProposeSet> set,
|
||||
NodeID const& node)
|
||||
{
|
||||
{
|
||||
mConsensus->storeProposal (proposal, node);
|
||||
mConsensus->storeProposal (proposal, node);
|
||||
|
||||
if (mLedgerConsensus->peerPosition (proposal))
|
||||
app_.overlay().relay(*set, proposal->getSuppressionID());
|
||||
else
|
||||
JLOG(m_journal.info()) << "Not relaying trusted proposal";
|
||||
}
|
||||
if (mLedgerConsensus->peerPosition (*proposal))
|
||||
app_.overlay().relay(*set, proposal->getSuppressionID());
|
||||
else
|
||||
JLOG(m_journal.info()) << "Not relaying trusted proposal";
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1531,7 +1530,7 @@ NetworkOPsImp::mapComplete (
|
||||
|
||||
// We acquired it because consensus asked us to
|
||||
if (fromAcquire)
|
||||
mLedgerConsensus->gotMap (map);
|
||||
mLedgerConsensus->gotMap (RCLTxSet{map});
|
||||
}
|
||||
|
||||
void NetworkOPsImp::endConsensus (bool correctLCL)
|
||||
|
||||
@@ -1233,7 +1233,7 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMProposeSet> const& m)
|
||||
|
||||
PublicKey const publicKey (makeSlice(set.nodepubkey()));
|
||||
NetClock::time_point const closeTime { NetClock::duration{set.closetime()} };
|
||||
Buffer signature (set.signature().data(), set.signature ().size());
|
||||
Slice signature (set.signature().data(), set.signature ().size());
|
||||
|
||||
uint256 proposeHash, prevLedger;
|
||||
memcpy (proposeHash.begin (), set.currenttxhash ().data (), 32);
|
||||
@@ -1278,8 +1278,8 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMProposeSet> const& m)
|
||||
|
||||
auto proposal = std::make_shared<LedgerProposal> (
|
||||
prevLedger, set.proposeseq (), proposeHash, closeTime,
|
||||
publicKey, calcNodeID(publicKey), suppression);
|
||||
proposal->setSignature (std::move(signature));
|
||||
app_.timeKeeper().closeTime(), publicKey, calcNodeID(publicKey),
|
||||
signature, suppression);
|
||||
|
||||
std::weak_ptr<PeerImp> weak = shared_from_this();
|
||||
app_.getJobQueue ().addJob (
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <ripple/app/ledger/TransactionStateSF.cpp>
|
||||
|
||||
#include <ripple/app/ledger/impl/ConsensusImp.cpp>
|
||||
#include <ripple/app/ledger/impl/DisputedTx.cpp>
|
||||
#include <ripple/app/ledger/impl/InboundLedger.cpp>
|
||||
#include <ripple/app/ledger/impl/InboundLedgers.cpp>
|
||||
#include <ripple/app/ledger/impl/InboundTransactions.cpp>
|
||||
|
||||
Reference in New Issue
Block a user