aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2015-11-17 00:20:49 +0100
committerPieter Wuille <pieter.wuille@gmail.com>2016-06-22 15:42:59 +0200
commitb8a97498df1e83f8dcc49bc3fa4344f9e9799242 (patch)
treed14eb0cb55048583a5233b1ef25f25fb8d7651ab
parent8b49040854be2e26b66366aeae1cba4716f93d93 (diff)
BIP144: Handshake and relay (receiver side)
Service bit logic by Nicolas Dorier. Only download blocks from witness peers after fork.
-rw-r--r--src/init.cpp12
-rw-r--r--src/main.cpp44
-rw-r--r--src/net.cpp6
-rw-r--r--src/net.h1
-rw-r--r--src/protocol.h3
-rw-r--r--src/qt/guiutil.cpp3
6 files changed, 60 insertions, 9 deletions
diff --git a/src/init.cpp b/src/init.cpp
index b572bfc327..6bce0a9b49 100644
--- a/src/init.cpp
+++ b/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
if (mapArgs.count("-blocknotify"))
diff --git a/src/main.cpp b/src/main.cpp
index 8d91d6d625..73e4c8f51c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -313,6 +313,7 @@ struct CNodeState {
fPreferHeaders = false;
fPreferHeaderAndIDs = 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)
{
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);
+ if((pfrom->nServices & NODE_WITNESS))
+ {
+ LOCK(cs_main);
+ State(pfrom->GetId())->fHaveWitness = true;
+ }
+
// Potentially mark this peer as a preferred download peer.
{
LOCK(cs_main);
@@ -5119,17 +5134,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
LOCK(cs_main);
+ uint32_t nFetchFlags = GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus());
+
std::vector<CInv> vToFetch;
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
{
- const CInv &inv = vInv[nInv];
+ CInv &inv = vInv[nInv];
boost::this_thread::interruption_point();
bool fAlreadyHave = AlreadyHave(inv);
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) {
UpdateBlockAvailability(pfrom->GetId(), 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);
CNodeState *nodestate = State(pfrom->GetId());
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)
vToFetch.push_back(CInv(MSG_CMPCT_BLOCK, inv.hash));
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.
while (pindexWalk && !chainActive.Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
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.
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
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);
LogPrint("net", "Requesting block %s from peer=%d\n",
pindex->GetBlockHash().ToString(), pfrom->id);
@@ -6598,10 +6623,13 @@ bool SendMessages(CNode* pto)
NodeId staller = -1;
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
BOOST_FOREACH(CBlockIndex *pindex, vToDownload) {
- vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash()));
- 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(pto->GetId())->fHaveWitness || !IsWitnessEnabled(pindex->pprev, consensusParams)) {
+ uint32_t nFetchFlags = GetFetchFlags(pto, pindex->pprev, consensusParams);
+ vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
+ 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(staller)->nStallingSince == 0) {
diff --git a/src/net.cpp b/src/net.cpp
index 336163a896..dc83f19be4 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -72,7 +72,7 @@ namespace {
const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*";
/** Services this node implementation cares about */
-static const ServiceFlags nRelevantServices = NODE_NETWORK;
+ServiceFlags nRelevantServices = NODE_NETWORK;
//
// Global state variables
@@ -1676,6 +1676,10 @@ void ThreadOpenConnections()
if (nANow - addr.nLastTry < 600 && nTries < 30)
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
if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
continue;
diff --git a/src/net.h b/src/net.h
index cb35d8c4f2..7ed18b2050 100644
--- a/src/net.h
+++ b/src/net.h
@@ -156,6 +156,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
extern bool fDiscover;
extern bool fListen;
extern ServiceFlags nLocalServices;
+extern ServiceFlags nRelevantServices;
extern bool fRelayTxes;
extern uint64_t nLocalHostNonce;
extern CAddrMan addrman;
diff --git a/src/protocol.h b/src/protocol.h
index dd07092f5f..15f27e2d2f 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -264,6 +264,9 @@ enum ServiceFlags : uint64_t {
// 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)
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
// isn't getting used, or one not being used much, and notify the
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index ff4320b36a..4327de9b0c 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -909,6 +909,9 @@ QString formatServicesStr(quint64 mask)
case NODE_BLOOM:
strList.append("BLOOM");
break;
+ case NODE_WITNESS:
+ strList.append("WITNESS");
+ break;
default:
strList.append(QString("%1[%2]").arg("UNKNOWN").arg(check));
}