14 changes: 8 additions & 6 deletions src/chainparams.cpp
Expand Up @@ -91,10 +91,11 @@ class CMainParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1462060800; // May 1st, 2016
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017

// Deployment of SegWit (BIP141, BIP143, and BIP147)
// BIP149 deployment of SegWit (BIP141, BIP143, and BIP147)
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1479168000; // November 15th, 2016.
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1510704000; // November 15th, 2017.
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1510790400; // November 16th, 2017.
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1530662400; // July 4th, 2018.
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].fLockInOnTimeout = true; // BIP8 flag

// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000003f94d1ad391682fe038bf5");
Expand Down Expand Up @@ -283,6 +284,7 @@ class CRegTestParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 999999999999ULL;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].fLockInOnTimeout = true;

// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x00");
Expand Down Expand Up @@ -327,7 +329,7 @@ class CRegTestParams : public CChainParams {
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container<std::vector<unsigned char> >();
}

void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
{
consensus.vDeployments[d].nStartTime = nStartTime;
consensus.vDeployments[d].nTimeout = nTimeout;
Expand Down Expand Up @@ -360,8 +362,8 @@ void SelectParams(const std::string& network)
pCurrentParams = &Params(network);
}

void UpdateRegtestBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
void UpdateRegtestVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
{
regTestParams.UpdateBIP9Parameters(d, nStartTime, nTimeout);
regTestParams.UpdateVersionBitsParameters(d, nStartTime, nTimeout);
}

4 changes: 2 additions & 2 deletions src/chainparams.h
Expand Up @@ -112,8 +112,8 @@ CChainParams& Params(const std::string& chain);
void SelectParams(const std::string& chain);

/**
* Allows modifying the BIP9 regtest parameters.
* Allows modifying the Version Bits regtest parameters.
*/
void UpdateRegtestBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
void UpdateRegtestVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);

#endif // BITCOIN_CHAINPARAMS_H
2 changes: 2 additions & 0 deletions src/consensus/params.h
Expand Up @@ -31,6 +31,8 @@ struct BIP9Deployment {
int64_t nStartTime;
/** Timeout/expiry MedianTime for the deployment attempt. */
int64_t nTimeout;
/** If true STARTED->FAILED will become STARTED->LOCKED_IN */
bool fLockInOnTimeout = false;
};

/**
Expand Down
30 changes: 19 additions & 11 deletions src/init.cpp
Expand Up @@ -48,6 +48,7 @@
#include <stdint.h>
#include <stdio.h>
#include <memory>
#include <ctime>

#ifndef WIN32
#include <signal.h>
Expand Down Expand Up @@ -444,7 +445,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT));
strUsage += HelpMessageOpt("-limitdescendantcount=<n>", strprintf("Do not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT));
strUsage += HelpMessageOpt("-limitdescendantsize=<n>", strprintf("Do not accept transactions if any ancestor would have more than <n> kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT));
strUsage += HelpMessageOpt("-bip9params=deployment:start:end", "Use given start/end times for specified BIP9 deployment (regtest-only)");
strUsage += HelpMessageOpt("-vbparams=deployment:start:end", "Use given start/end times for specified version bits deployment (regtest-only)");
}
strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
_("If <category> is not supplied or if <category> = 1, output all debugging information.") + " " + _("<category> can be:") + " " + ListLogCategories() + ".");
Expand Down Expand Up @@ -1100,17 +1101,17 @@ bool AppInitParameterInteraction()
fEnableReplacement = (std::find(vstrReplacementModes.begin(), vstrReplacementModes.end(), "fee") != vstrReplacementModes.end());
}

if (mapMultiArgs.count("-bip9params")) {
// Allow overriding BIP9 parameters for testing
if (mapMultiArgs.count("-vbparams")) {
// Allow overriding version bits parameters for testing
if (!chainparams.MineBlocksOnDemand()) {
return InitError("BIP9 parameters may only be overridden on regtest.");
return InitError("Version bits parameters may only be overridden on regtest.");
}
const std::vector<std::string>& deployments = mapMultiArgs.at("-bip9params");
const std::vector<std::string>& deployments = mapMultiArgs.at("-vbparams");
for (auto i : deployments) {
std::vector<std::string> vDeploymentParams;
boost::split(vDeploymentParams, i, boost::is_any_of(":"));
if (vDeploymentParams.size() != 3) {
return InitError("BIP9 parameters malformed, expecting deployment:start:end");
return InitError("Version bits parameters malformed, expecting deployment:start:end");
}
int64_t nStartTime, nTimeout;
if (!ParseInt64(vDeploymentParams[1], &nStartTime)) {
Expand All @@ -1123,9 +1124,9 @@ bool AppInitParameterInteraction()
for (int j=0; j<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j)
{
if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[j].name) == 0) {
UpdateRegtestBIP9Parameters(Consensus::DeploymentPos(j), nStartTime, nTimeout);
UpdateRegtestVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout);
found = true;
LogPrintf("Setting BIP9 activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout);
LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout);
break;
}
}
Expand Down Expand Up @@ -1179,6 +1180,13 @@ bool AppInitSanityChecks()
bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
{
const CChainParams& chainparams = Params();
std::time_t result = std::time(nullptr);

// Don't allow this to run on mainnet before before Nov 7th 2017
if (!Params().GetConsensus().fPowAllowMinDifficultyBlocks && result < 1510012800) {
InitError("This BIP149 SegWit-UASF implementation is not safe to run on mainnet until after November 7th 2017 providing BIP9 segwit has failed to activate or lock-in.\n\nFeel free to run a standard node until then with uacomment=UASF-SegWit-BIP149 in the bitcoin.conf file.\n\nYou can run this version using -testnet or -regtest modes.");
return false;
}
// ********************************************************* Step 4a: application initialization
// After daemonization get the data directory lock again and hold on to it until exit
// This creates a slight window for a race condition to happen, however this condition is harmless: it
Expand Down Expand Up @@ -1585,12 +1593,12 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
// Only advertise 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
// Note that setting NODE_UAWITNESS 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);
nLocalServices = ServiceFlags(nLocalServices | NODE_UAWITNESS);
// Only care about others providing witness capabilities if there is a softfork
// defined.
nRelevantServices = ServiceFlags(nRelevantServices | NODE_WITNESS);
nRelevantServices = ServiceFlags(nRelevantServices | NODE_UAWITNESS);
}

// ********************************************************* Step 10: import blocks
Expand Down
24 changes: 12 additions & 12 deletions src/net_processing.cpp
Expand Up @@ -192,7 +192,7 @@ struct CNodeState {
//! Whether this peer wants witnesses in cmpctblocks/blocktxns
bool fWantsCmpctWitness;
/**
* If we've announced NODE_WITNESS to this peer: whether the peer sends witnesses in cmpctblocks/blocktxns,
* If we've announced NODE_UAWITNESS to this peer: whether the peer sends witnesses in cmpctblocks/blocktxns,
* otherwise: whether this peer sends non-witnesses in cmpctblocks/blocktxns.
*/
bool fSupportsDesiredCmpctVersion;
Expand Down Expand Up @@ -414,7 +414,7 @@ void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman& connman) {
}
connman.ForNode(nodeid, [&connman](CNode* pfrom){
bool fAnnounceUsingCMPCTBLOCK = false;
uint64_t nCMPCTBLOCKVersion = (pfrom->GetLocalServices() & NODE_WITNESS) ? 2 : 1;
uint64_t nCMPCTBLOCKVersion = (pfrom->GetLocalServices() & NODE_UAWITNESS) ? 3 : 1;
if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
// As per BIP152, we only get 3 of our peers to announce
// blocks using compact encodings.
Expand Down Expand Up @@ -1164,7 +1164,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam

uint32_t GetFetchFlags(CNode* pfrom) {
uint32_t nFetchFlags = 0;
if ((pfrom->GetLocalServices() & NODE_WITNESS) && State(pfrom->GetId())->fHaveWitness) {
if ((pfrom->GetLocalServices() & NODE_UAWITNESS) && State(pfrom->GetId())->fHaveWitness) {
nFetchFlags |= MSG_WITNESS_FLAG;
}
return nFetchFlags;
Expand Down Expand Up @@ -1335,7 +1335,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
pfrom->SetSendVersion(nSendVersion);
pfrom->nVersion = nVersion;

if((nServices & NODE_WITNESS))
if((nServices & NODE_UAWITNESS))
{
LOCK(cs_main);
State(pfrom->GetId())->fHaveWitness = true;
Expand Down Expand Up @@ -1431,14 +1431,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDHEADERS));
}
if (pfrom->nVersion >= SHORT_IDS_BLOCKS_VERSION) {
// Tell our peer we are willing to provide version 1 or 2 cmpctblocks
// Tell our peer we are willing to provide version 1 or 3 cmpctblocks
// However, we do not request new block announcements using
// cmpctblock messages.
// We send this to non-NODE NETWORK peers as well, because
// they may wish to request compact blocks from us
bool fAnnounceUsingCMPCTBLOCK = false;
uint64_t nCMPCTBLOCKVersion = 2;
if (pfrom->GetLocalServices() & NODE_WITNESS)
uint64_t nCMPCTBLOCKVersion = 3;
if (pfrom->GetLocalServices() & NODE_UAWITNESS)
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
nCMPCTBLOCKVersion = 1;
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
Expand Down Expand Up @@ -1512,18 +1512,18 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
bool fAnnounceUsingCMPCTBLOCK = false;
uint64_t nCMPCTBLOCKVersion = 0;
vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
if (nCMPCTBLOCKVersion == 1 || ((pfrom->GetLocalServices() & NODE_WITNESS) && nCMPCTBLOCKVersion == 2)) {
if (nCMPCTBLOCKVersion == 1 || ((pfrom->GetLocalServices() & NODE_UAWITNESS) && nCMPCTBLOCKVersion == 3)) {
LOCK(cs_main);
// fProvidesHeaderAndIDs is used to "lock in" version of compact blocks we send (fWantsCmpctWitness)
if (!State(pfrom->GetId())->fProvidesHeaderAndIDs) {
State(pfrom->GetId())->fProvidesHeaderAndIDs = true;
State(pfrom->GetId())->fWantsCmpctWitness = nCMPCTBLOCKVersion == 2;
State(pfrom->GetId())->fWantsCmpctWitness = nCMPCTBLOCKVersion == 3;
}
if (State(pfrom->GetId())->fWantsCmpctWitness == (nCMPCTBLOCKVersion == 2)) // ignore later version announces
if (State(pfrom->GetId())->fWantsCmpctWitness == (nCMPCTBLOCKVersion == 3)) // ignore later version announces
State(pfrom->GetId())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK;
if (!State(pfrom->GetId())->fSupportsDesiredCmpctVersion) {
if (pfrom->GetLocalServices() & NODE_WITNESS)
State(pfrom->GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 2);
if (pfrom->GetLocalServices() & NODE_UAWITNESS)
State(pfrom->GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 3);
else
State(pfrom->GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 1);
}
Expand Down
3 changes: 3 additions & 0 deletions src/protocol.h
Expand Up @@ -267,6 +267,9 @@ enum ServiceFlags : uint64_t {
// NODE_XTHIN means the node supports Xtreme Thinblocks
// If this is turned off then the node will not service nor make xthin requests
NODE_XTHIN = (1 << 4),
// NODE_UAWITNESS indicates that a node can be asked for blocks and transactions including
// witness data.
NODE_UAWITNESS = (1 << 5),

// 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
Expand Down
2 changes: 1 addition & 1 deletion src/qt/guiutil.cpp
Expand Up @@ -924,7 +924,7 @@ QString formatServicesStr(quint64 mask)
case NODE_BLOOM:
strList.append("BLOOM");
break;
case NODE_WITNESS:
case NODE_UAWITNESS:
strList.append("WITNESS");
break;
case NODE_XTHIN:
Expand Down
21 changes: 16 additions & 5 deletions src/rpc/blockchain.cpp
Expand Up @@ -1041,7 +1041,7 @@ static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex*
return rv;
}

static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
static UniValue VBSoftForkDesc(const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
{
UniValue rv(UniValue::VOBJ);
const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id);
Expand All @@ -1062,13 +1062,13 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse
return rv;
}

void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
void VBSoftForkDescPushBack(UniValue& vb_softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
{
// Deployments with timeout value of 0 are hidden.
// A timeout value of 0 guarantees a softfork will never be activated.
// This is used when softfork codes are merged without specifying the deployment schedule.
if (consensusParams.vDeployments[id].nTimeout > 0)
bip9_softforks.push_back(Pair(name, BIP9SoftForkDesc(consensusParams, id)));
vb_softforks.push_back(Pair(name, VBSoftForkDesc(consensusParams, id)));
}

UniValue getblockchaininfo(const JSONRPCRequest& request)
Expand Down Expand Up @@ -1098,6 +1098,15 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
" },\n"
" }, ...\n"
" ],\n"
" \"bip8_softforks\": { (object) status of BIP9 softforks in progress\n"
" \"xxxx\" : { (string) name of the softfork\n"
" \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n"
" \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n"
" \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n"
" \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n"
" \"since\": xx (numeric) height of the first block to which the status applies\n"
" }\n"
" },\n"
" \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n"
" \"xxxx\" : { (string) name of the softfork\n"
" \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n"
Expand Down Expand Up @@ -1129,13 +1138,15 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
const Consensus::Params& consensusParams = Params().GetConsensus();
CBlockIndex* tip = chainActive.Tip();
UniValue softforks(UniValue::VARR);
UniValue bip8_softforks(UniValue::VOBJ);
UniValue bip9_softforks(UniValue::VOBJ);
softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
BIP9SoftForkDescPushBack(bip9_softforks, "csv", consensusParams, Consensus::DEPLOYMENT_CSV);
BIP9SoftForkDescPushBack(bip9_softforks, "segwit", consensusParams, Consensus::DEPLOYMENT_SEGWIT);
VBSoftForkDescPushBack(bip9_softforks, "csv", consensusParams, Consensus::DEPLOYMENT_CSV);
VBSoftForkDescPushBack(bip8_softforks, "segwit", consensusParams, Consensus::DEPLOYMENT_SEGWIT);
obj.push_back(Pair("softforks", softforks));
obj.push_back(Pair("bip8_softforks", bip8_softforks));
obj.push_back(Pair("bip9_softforks", bip9_softforks));

if (fPruneMode)
Expand Down