BIP144: Handshake and relay (receiver side)
Service bit logic by Nicolas Dorier. Only download blocks from witness peers after fork.
This commit is contained in:
parent
8b49040854
commit
b8a97498df
6 changed files with 60 additions and 9 deletions
12
src/init.cpp
12
src/init.cpp
|
@ -1377,6 +1377,18 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Params().GetConsensus().vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout != 0) {
|
||||||
|
// Only advertize witness capabilities if they have a reasonable start time.
|
||||||
|
// This allows us to have the code merged without a defined softfork, by setting its
|
||||||
|
// end time to 0.
|
||||||
|
// Note that setting NODE_WITNESS is never required: the only downside from not
|
||||||
|
// doing so is that after activation, no upgraded nodes will fetch from you.
|
||||||
|
nLocalServices = ServiceFlags(nLocalServices | NODE_WITNESS);
|
||||||
|
// Only care about others providing witness capabilities if there is a softfork
|
||||||
|
// defined.
|
||||||
|
nRelevantServices = ServiceFlags(nRelevantServices | NODE_WITNESS);
|
||||||
|
}
|
||||||
|
|
||||||
// ********************************************************* Step 10: import blocks
|
// ********************************************************* Step 10: import blocks
|
||||||
|
|
||||||
if (mapArgs.count("-blocknotify"))
|
if (mapArgs.count("-blocknotify"))
|
||||||
|
|
44
src/main.cpp
44
src/main.cpp
|
@ -313,6 +313,7 @@ struct CNodeState {
|
||||||
fPreferHeaders = false;
|
fPreferHeaders = false;
|
||||||
fPreferHeaderAndIDs = false;
|
fPreferHeaderAndIDs = false;
|
||||||
fProvidesHeaderAndIDs = false;
|
fProvidesHeaderAndIDs = false;
|
||||||
|
fHaveWitness = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4812,6 +4813,14 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t GetFetchFlags(CNode* pfrom, CBlockIndex* pprev, const Consensus::Params& chainparams) {
|
||||||
|
uint32_t nFetchFlags = 0;
|
||||||
|
if (IsWitnessEnabled(pprev, chainparams) && State(pfrom->GetId())->fHaveWitness) {
|
||||||
|
nFetchFlags |= MSG_WITNESS_FLAG;
|
||||||
|
}
|
||||||
|
return nFetchFlags;
|
||||||
|
}
|
||||||
|
|
||||||
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams)
|
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams)
|
||||||
{
|
{
|
||||||
LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
|
LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
|
||||||
|
@ -4918,6 +4927,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||||
|
|
||||||
pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);
|
pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);
|
||||||
|
|
||||||
|
if((pfrom->nServices & NODE_WITNESS))
|
||||||
|
{
|
||||||
|
LOCK(cs_main);
|
||||||
|
State(pfrom->GetId())->fHaveWitness = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Potentially mark this peer as a preferred download peer.
|
// Potentially mark this peer as a preferred download peer.
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
@ -5119,17 +5134,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
|
uint32_t nFetchFlags = GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus());
|
||||||
|
|
||||||
std::vector<CInv> vToFetch;
|
std::vector<CInv> vToFetch;
|
||||||
|
|
||||||
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
|
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
|
||||||
{
|
{
|
||||||
const CInv &inv = vInv[nInv];
|
CInv &inv = vInv[nInv];
|
||||||
|
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
|
|
||||||
bool fAlreadyHave = AlreadyHave(inv);
|
bool fAlreadyHave = AlreadyHave(inv);
|
||||||
LogPrint("net", "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id);
|
LogPrint("net", "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id);
|
||||||
|
|
||||||
|
if (inv.type == MSG_TX) {
|
||||||
|
inv.type |= nFetchFlags;
|
||||||
|
}
|
||||||
|
|
||||||
if (inv.type == MSG_BLOCK) {
|
if (inv.type == MSG_BLOCK) {
|
||||||
UpdateBlockAvailability(pfrom->GetId(), inv.hash);
|
UpdateBlockAvailability(pfrom->GetId(), inv.hash);
|
||||||
if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) {
|
if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) {
|
||||||
|
@ -5144,7 +5165,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||||
pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash);
|
pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash);
|
||||||
CNodeState *nodestate = State(pfrom->GetId());
|
CNodeState *nodestate = State(pfrom->GetId());
|
||||||
if (CanDirectFetch(chainparams.GetConsensus()) &&
|
if (CanDirectFetch(chainparams.GetConsensus()) &&
|
||||||
nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER &&
|
||||||
|
(!IsWitnessEnabled(chainActive.Tip(), chainparams.GetConsensus()) || State(pfrom->GetId())->fHaveWitness)) {
|
||||||
|
inv.type |= nFetchFlags;
|
||||||
if (nodestate->fProvidesHeaderAndIDs)
|
if (nodestate->fProvidesHeaderAndIDs)
|
||||||
vToFetch.push_back(CInv(MSG_CMPCT_BLOCK, inv.hash));
|
vToFetch.push_back(CInv(MSG_CMPCT_BLOCK, inv.hash));
|
||||||
else
|
else
|
||||||
|
@ -5730,7 +5753,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||||
// Calculate all the blocks we'd need to switch to pindexLast, up to a limit.
|
// Calculate all the blocks we'd need to switch to pindexLast, up to a limit.
|
||||||
while (pindexWalk && !chainActive.Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
while (pindexWalk && !chainActive.Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
||||||
if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
|
if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
|
||||||
!mapBlocksInFlight.count(pindexWalk->GetBlockHash())) {
|
!mapBlocksInFlight.count(pindexWalk->GetBlockHash()) &&
|
||||||
|
(!IsWitnessEnabled(pindexWalk->pprev, chainparams.GetConsensus()) || State(pfrom->GetId())->fHaveWitness)) {
|
||||||
// We don't have this block, and it's not yet in flight.
|
// We don't have this block, and it's not yet in flight.
|
||||||
vToFetch.push_back(pindexWalk);
|
vToFetch.push_back(pindexWalk);
|
||||||
}
|
}
|
||||||
|
@ -5752,7 +5776,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||||
// Can't download any more from this peer
|
// Can't download any more from this peer
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash()));
|
uint32_t nFetchFlags = GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus());
|
||||||
|
vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
|
||||||
MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), chainparams.GetConsensus(), pindex);
|
MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), chainparams.GetConsensus(), pindex);
|
||||||
LogPrint("net", "Requesting block %s from peer=%d\n",
|
LogPrint("net", "Requesting block %s from peer=%d\n",
|
||||||
pindex->GetBlockHash().ToString(), pfrom->id);
|
pindex->GetBlockHash().ToString(), pfrom->id);
|
||||||
|
@ -6598,10 +6623,13 @@ bool SendMessages(CNode* pto)
|
||||||
NodeId staller = -1;
|
NodeId staller = -1;
|
||||||
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
|
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
|
||||||
BOOST_FOREACH(CBlockIndex *pindex, vToDownload) {
|
BOOST_FOREACH(CBlockIndex *pindex, vToDownload) {
|
||||||
vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash()));
|
if (State(pto->GetId())->fHaveWitness || !IsWitnessEnabled(pindex->pprev, consensusParams)) {
|
||||||
MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex);
|
uint32_t nFetchFlags = GetFetchFlags(pto, pindex->pprev, consensusParams);
|
||||||
LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
|
vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
|
||||||
pindex->nHeight, pto->id);
|
MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex);
|
||||||
|
LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
|
||||||
|
pindex->nHeight, pto->id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (state.nBlocksInFlight == 0 && staller != -1) {
|
if (state.nBlocksInFlight == 0 && staller != -1) {
|
||||||
if (State(staller)->nStallingSince == 0) {
|
if (State(staller)->nStallingSince == 0) {
|
||||||
|
|
|
@ -72,7 +72,7 @@ namespace {
|
||||||
const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*";
|
const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*";
|
||||||
|
|
||||||
/** Services this node implementation cares about */
|
/** Services this node implementation cares about */
|
||||||
static const ServiceFlags nRelevantServices = NODE_NETWORK;
|
ServiceFlags nRelevantServices = NODE_NETWORK;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Global state variables
|
// Global state variables
|
||||||
|
@ -1676,6 +1676,10 @@ void ThreadOpenConnections()
|
||||||
if (nANow - addr.nLastTry < 600 && nTries < 30)
|
if (nANow - addr.nLastTry < 600 && nTries < 30)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// only consider nodes missing relevant services after 40 failed attemps
|
||||||
|
if ((addr.nServices & nRelevantServices) != nRelevantServices && nTries < 40)
|
||||||
|
continue;
|
||||||
|
|
||||||
// do not allow non-default ports, unless after 50 invalid addresses selected already
|
// do not allow non-default ports, unless after 50 invalid addresses selected already
|
||||||
if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
|
if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -156,6 +156,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
|
||||||
extern bool fDiscover;
|
extern bool fDiscover;
|
||||||
extern bool fListen;
|
extern bool fListen;
|
||||||
extern ServiceFlags nLocalServices;
|
extern ServiceFlags nLocalServices;
|
||||||
|
extern ServiceFlags nRelevantServices;
|
||||||
extern bool fRelayTxes;
|
extern bool fRelayTxes;
|
||||||
extern uint64_t nLocalHostNonce;
|
extern uint64_t nLocalHostNonce;
|
||||||
extern CAddrMan addrman;
|
extern CAddrMan addrman;
|
||||||
|
|
|
@ -264,6 +264,9 @@ enum ServiceFlags : uint64_t {
|
||||||
// Bitcoin Core nodes used to support this by default, without advertising this bit,
|
// Bitcoin Core nodes used to support this by default, without advertising this bit,
|
||||||
// but no longer do as of protocol version 70011 (= NO_BLOOM_VERSION)
|
// but no longer do as of protocol version 70011 (= NO_BLOOM_VERSION)
|
||||||
NODE_BLOOM = (1 << 2),
|
NODE_BLOOM = (1 << 2),
|
||||||
|
// Indicates that a node can be asked for blocks and transactions including
|
||||||
|
// witness data.
|
||||||
|
NODE_WITNESS = (1 << 3),
|
||||||
|
|
||||||
// Bits 24-31 are reserved for temporary experiments. Just pick a bit that
|
// Bits 24-31 are reserved for temporary experiments. Just pick a bit that
|
||||||
// isn't getting used, or one not being used much, and notify the
|
// isn't getting used, or one not being used much, and notify the
|
||||||
|
|
|
@ -909,6 +909,9 @@ QString formatServicesStr(quint64 mask)
|
||||||
case NODE_BLOOM:
|
case NODE_BLOOM:
|
||||||
strList.append("BLOOM");
|
strList.append("BLOOM");
|
||||||
break;
|
break;
|
||||||
|
case NODE_WITNESS:
|
||||||
|
strList.append("WITNESS");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
strList.append(QString("%1[%2]").arg("UNKNOWN").arg(check));
|
strList.append(QString("%1[%2]").arg("UNKNOWN").arg(check));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue