Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche.h
// Copyright (c) 2018 The Bitcoin developers | // Copyright (c) 2018 The Bitcoin developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#ifndef BITCOIN_AVALANCHE_H | #ifndef BITCOIN_AVALANCHE_H | ||||
#define BITCOIN_AVALANCHE_H | #define BITCOIN_AVALANCHE_H | ||||
#include "blockindexworkcomparator.h" | #include "blockindexworkcomparator.h" | ||||
#include "net.h" | #include "net.h" | ||||
#include "protocol.h" // for CInv | #include "protocol.h" // for CInv | ||||
#include "rwcollection.h" | #include "rwcollection.h" | ||||
#include "serialize.h" | #include "serialize.h" | ||||
#include "uint256.h" | #include "uint256.h" | ||||
#include <boost/multi_index/composite_key.hpp> | |||||
#include <boost/multi_index/hashed_index.hpp> | |||||
#include <boost/multi_index/member.hpp> | |||||
#include <boost/multi_index/ordered_index.hpp> | |||||
#include <boost/multi_index_container.hpp> | |||||
#include <atomic> | #include <atomic> | ||||
#include <chrono> | #include <chrono> | ||||
#include <condition_variable> | #include <condition_variable> | ||||
#include <cstdint> | #include <cstdint> | ||||
#include <vector> | #include <vector> | ||||
class Config; | class Config; | ||||
class CBlockIndex; | class CBlockIndex; | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | public: | ||||
template <typename Stream, typename Operation> | template <typename Stream, typename Operation> | ||||
inline void SerializationOp(Stream &s, Operation ser_action) { | inline void SerializationOp(Stream &s, Operation ser_action) { | ||||
READWRITE(error); | READWRITE(error); | ||||
READWRITE(hash); | READWRITE(hash); | ||||
} | } | ||||
}; | }; | ||||
class AvalancheResponse { | class AvalancheResponse { | ||||
uint64_t round; | |||||
uint32_t cooldown; | uint32_t cooldown; | ||||
std::vector<AvalancheVote> votes; | std::vector<AvalancheVote> votes; | ||||
public: | public: | ||||
AvalancheResponse(uint32_t cooldownIn, std::vector<AvalancheVote> votesIn) | AvalancheResponse(uint64_t roundIn, uint32_t cooldownIn, | ||||
: cooldown(cooldownIn), votes(votesIn) {} | std::vector<AvalancheVote> votesIn) | ||||
: round(roundIn), cooldown(cooldownIn), votes(votesIn) {} | |||||
uint64_t getRound() const { return round; } | |||||
uint32_t getCooldown() const { return cooldown; } | uint32_t getCooldown() const { return cooldown; } | ||||
const std::vector<AvalancheVote> &GetVotes() const { return votes; } | const std::vector<AvalancheVote> &GetVotes() const { return votes; } | ||||
// serialization support | // serialization support | ||||
ADD_SERIALIZE_METHODS; | ADD_SERIALIZE_METHODS; | ||||
template <typename Stream, typename Operation> | template <typename Stream, typename Operation> | ||||
inline void SerializationOp(Stream &s, Operation ser_action) { | inline void SerializationOp(Stream &s, Operation ser_action) { | ||||
READWRITE(round); | |||||
READWRITE(cooldown); | READWRITE(cooldown); | ||||
READWRITE(votes); | READWRITE(votes); | ||||
} | } | ||||
}; | }; | ||||
class AvalanchePoll { | class AvalanchePoll { | ||||
uint32_t round; | uint64_t round; | ||||
std::vector<CInv> invs; | std::vector<CInv> invs; | ||||
public: | public: | ||||
AvalanchePoll(uint32_t roundIn, std::vector<CInv> invsIn) | AvalanchePoll(uint32_t roundIn, std::vector<CInv> invsIn) | ||||
: round(roundIn), invs(invsIn) {} | : round(roundIn), invs(invsIn) {} | ||||
const std::vector<CInv> &GetInvs() const { return invs; } | const std::vector<CInv> &GetInvs() const { return invs; } | ||||
Show All 37 Lines | public: | ||||
} | } | ||||
}; | }; | ||||
typedef std::map<const CBlockIndex *, VoteRecord, CBlockIndexWorkComparator> | typedef std::map<const CBlockIndex *, VoteRecord, CBlockIndexWorkComparator> | ||||
BlockVoteMap; | BlockVoteMap; | ||||
typedef std::map<std::chrono::time_point<std::chrono::steady_clock>, NodeId> | typedef std::map<std::chrono::time_point<std::chrono::steady_clock>, NodeId> | ||||
NodeCooldownMap; | NodeCooldownMap; | ||||
struct query_timeout {}; | |||||
class AvalancheProcessor { | class AvalancheProcessor { | ||||
private: | private: | ||||
CConnman *connman; | CConnman *connman; | ||||
/** | /** | ||||
* Blocks to run avalanche on. | * Blocks to run avalanche on. | ||||
*/ | */ | ||||
RWCollection<BlockVoteMap> vote_records; | RWCollection<BlockVoteMap> vote_records; | ||||
/** | /** | ||||
* Keep track of peers and queries sent. | * Keep track of peers and queries sent. | ||||
*/ | */ | ||||
struct RequestRecord { | typedef std::chrono::time_point<std::chrono::steady_clock> TimePoint; | ||||
private: | |||||
int64_t timestamp; | |||||
std::vector<CInv> invs; | |||||
public: | std::atomic<uint64_t> round; | ||||
RequestRecord() : timestamp(0), invs() {} | RWCollection<std::set<NodeId>> nodeids; | ||||
RequestRecord(int64_t timestampIn, std::vector<CInv> invIn) | RWCollection<NodeCooldownMap> nodecooldown; | ||||
: timestamp(timestampIn), invs(std::move(invIn)) {} | |||||
int64_t GetTimestamp() const { return timestamp; } | struct Query { | ||||
const std::vector<CInv> &GetInvs() const { return invs; } | NodeId nodeid; | ||||
uint64_t round; | |||||
TimePoint timeout; | |||||
/** | |||||
* We declare this as mutable so it can be modified in the multi_index. | |||||
* This is ok because we do not use this field to index in anyway. | |||||
* | |||||
* /!\ Do not use any mutable field as index. | |||||
*/ | |||||
mutable std::vector<CInv> invs; | |||||
}; | }; | ||||
std::atomic<uint32_t> round; | typedef boost::multi_index_container< | ||||
RWCollection<std::set<NodeId>> nodeids; | Query, | ||||
RWCollection<std::map<NodeId, RequestRecord>> queries; | boost::multi_index::indexed_by< | ||||
RWCollection<NodeCooldownMap> nodecooldown; | // index by nodeid/round | ||||
boost::multi_index::ordered_unique< | |||||
boost::multi_index::composite_key< | |||||
Query, | |||||
boost::multi_index::member<Query, NodeId, &Query::nodeid>, | |||||
boost::multi_index::member<Query, uint64_t, | |||||
&Query::round>>>, | |||||
// sorted by timeout | |||||
boost::multi_index::ordered_non_unique< | |||||
boost::multi_index::tag<query_timeout>, | |||||
boost::multi_index::member<Query, TimePoint, &Query::timeout>>>> | |||||
QuerySet; | |||||
RWCollection<QuerySet> queries; | |||||
/** | /** | ||||
* Start stop machinery. | * Start stop machinery. | ||||
*/ | */ | ||||
std::atomic<bool> stopRequest; | std::atomic<bool> stopRequest; | ||||
bool running GUARDED_BY(cs_running); | bool running GUARDED_BY(cs_running); | ||||
CWaitableCriticalSection cs_running; | CWaitableCriticalSection cs_running; | ||||
Show All 25 Lines |