Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In-Wallet Masternode management #7

Merged
merged 5 commits into from
Nov 11, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,4 @@ qa/pull-tester/test.*/*
.cproject
.project
/doc/doxygen/
/nbproject/
40 changes: 34 additions & 6 deletions contrib/gitian-descriptors/gitian-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@ remotes:
files: []
script: |

#unlock sudo
echo "ubuntu" | sudo -S true

sudo mkdir -p /usr/include/i386-linux-gnu/
sudo ln -s /usr/include/x86_64-linux-gnu/asm /usr/include/i386-linux-gnu/asm

WRAP_DIR=$HOME/wrapped
HOSTS="i686-pc-linux-gnu x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu"
CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests"
Expand Down Expand Up @@ -91,11 +85,45 @@ script: |
create_per-host_faketime_wrappers "2000-01-01 12:00:00"
export PATH=${WRAP_DIR}:${PATH}

EXTRA_INCLUDES_BASE=$WRAP_DIR/extra_includes
mkdir -p $EXTRA_INCLUDES_BASE

# x86 needs /usr/include/i386-linux-gnu/asm pointed to /usr/include/x86_64-linux-gnu/asm,
# but we can't write there. Instead, create a link here and force it to be included in the
# search paths by wrapping gcc/g++.

mkdir -p $EXTRA_INCLUDES_BASE/i686-pc-linux-gnu
rm -f $WRAP_DIR/extra_includes/i686-pc-linux-gnu/asm
ln -s /usr/include/x86_64-linux-gnu/asm $EXTRA_INCLUDES_BASE/i686-pc-linux-gnu/asm

for prog in gcc g++; do
rm -f ${WRAP_DIR}/${prog}
cat << EOF > ${WRAP_DIR}/${prog}
#!/bin/bash
REAL="`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1`"
for var in "\$@"
do
if [ "\$var" = "-m32" ]; then
export C_INCLUDE_PATH="$EXTRA_INCLUDES_BASE/i686-pc-linux-gnu"
export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES_BASE/i686-pc-linux-gnu"
break
fi
done
\$REAL \$@
EOF
chmod +x ${WRAP_DIR}/${prog}
done

cd darknet
BASEPREFIX=`pwd`/depends
# Build dependencies for each host
for i in $HOSTS; do
EXTRA_INCLUDES="$EXTRA_INCLUDES_BASE/$i"
if [ -d "$EXTRA_INCLUDES" ]; then
export HOST_ID_SALT="$EXTRA_INCLUDES"
fi
make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}"
unset HOST_ID_SALT
done

# Faketime for binaries
Expand Down
7 changes: 7 additions & 0 deletions src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ QT_FORMS_UI = \
qt/forms/editaddressdialog.ui \
qt/forms/helpmessagedialog.ui \
qt/forms/intro.ui \
qt/forms/masternodelist.ui \
qt/forms/openuridialog.ui \
qt/forms/optionsdialog.ui \
qt/forms/overviewpage.ui \
Expand Down Expand Up @@ -57,6 +58,7 @@ QT_MOC_CPP = \
qt/moc_intro.cpp \
qt/moc_macdockiconhandler.cpp \
qt/moc_macnotificationhandler.cpp \
qt/moc_masternodelist.cpp \
qt/moc_notificator.cpp \
qt/moc_openuridialog.cpp \
qt/moc_optionsdialog.cpp \
Expand Down Expand Up @@ -124,6 +126,7 @@ BITCOIN_QT_H = \
qt/intro.h \
qt/macdockiconhandler.h \
qt/macnotificationhandler.h \
qt/masternodelist.h \
qt/networkstyle.h \
qt/notificator.h \
qt/openuridialog.h \
Expand All @@ -133,6 +136,7 @@ BITCOIN_QT_H = \
qt/paymentrequestplus.h \
qt/paymentserver.h \
qt/peertablemodel.h \
qt/platformstyle.h \
qt/qvalidatedlineedit.h \
qt/qvaluecombobox.h \
qt/receivecoinsdialog.h \
Expand Down Expand Up @@ -201,6 +205,7 @@ RES_ICONS = \
qt/res/icons/key.png \
qt/res/icons/lock_closed.png \
qt/res/icons/lock_open.png \
qt/res/icons/masternodes.png \
qt/res/icons/overview.png \
qt/res/icons/qrcode.png \
qt/res/icons/quit.png \
Expand Down Expand Up @@ -236,6 +241,7 @@ BITCOIN_QT_CPP = \
qt/optionsdialog.cpp \
qt/optionsmodel.cpp \
qt/peertablemodel.cpp \
qt/platformstyle.cpp \
qt/qvalidatedlineedit.cpp \
qt/qvaluecombobox.cpp \
qt/rpcconsole.cpp \
Expand All @@ -253,6 +259,7 @@ BITCOIN_QT_CPP += \
qt/coincontroltreewidget.cpp \
qt/obfuscationconfig.cpp \
qt/editaddressdialog.cpp \
qt/masternodelist.cpp \
qt/openuridialog.cpp \
qt/overviewpage.cpp \
qt/paymentrequestplus.cpp \
Expand Down
1 change: 1 addition & 0 deletions src/chainparamsbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
class CBaseChainParams
{
public:

enum Network {
MAIN,
TESTNET,
Expand Down
10 changes: 10 additions & 0 deletions src/coincontrol.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef BITCOIN_COINCONTROL_H
#define BITCOIN_COINCONTROL_H

#include "script/standard.h"
#include "primitives/transaction.h"

/** Coin Control Features. */
Expand All @@ -14,6 +15,12 @@ class CCoinControl
CTxDestination destChange;
bool useObfuScation;
bool useSwiftTX;
//! If false, allows unselected inputs, but requires all selected inputs be used
bool fAllowOtherInputs;
//! Includes watch only addresses which match the ISMINE_WATCH_SOLVABLE criteria
bool fAllowWatchOnly;
//! Minimum absolute fee (not per kilobyte)
CAmount nMinimumTotalFee;

CCoinControl()
{
Expand All @@ -26,6 +33,9 @@ class CCoinControl
setSelected.clear();
useSwiftTX = false;
useObfuScation = true;
fAllowOtherInputs = false;
fAllowWatchOnly = false;
nMinimumTotalFee = 0;
}

bool HasSelected() const
Expand Down
15 changes: 14 additions & 1 deletion src/coins.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "serialize.h"
#include "uint256.h"
#include "undo.h"
#include "script/standard.h"

#include <assert.h>
#include <stdint.h>
Expand Down Expand Up @@ -358,9 +359,21 @@ class CCoinsViewBacked : public CCoinsView
bool GetStats(CCoinsStats &stats) const;
};


class CCoinsViewCache;

/** Flags for nSequence and nLockTime locks */
enum {
/* Interpret sequence numbers as relative lock-time constraints. */
LOCKTIME_VERIFY_SEQUENCE = (1 << 0),

/* Use GetMedianTimePast() instead of nTime for end point timestamp. */
LOCKTIME_MEDIAN_TIME_PAST = (1 << 1),
};

/** Used as the flags parameter to sequence and nLocktime checks in non-consensus code. */
static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE |
LOCKTIME_MEDIAN_TIME_PAST;

/**
* A reference to a mutable cache entry. Encapsulating it allows us to run
* cleanup code after the modification is finished, and keeping track of
Expand Down
32 changes: 32 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,38 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
return true;
}

bool CheckFinalTx(const CTransaction &tx, int flags)
{
AssertLockHeld(cs_main);

// By convention a negative value for flags indicates that the
// current network-enforced consensus rules should be used. In
// a future soft-fork scenario that would mean checking which
// rules would be enforced for the next block and setting the
// appropriate flags. At the present time no soft-forks are
// scheduled, so no flags are set.
flags = std::max(flags, 0);

// CheckFinalTx() uses chainActive.Height()+1 to evaluate
// nLockTime because when IsFinalTx() is called within
// CBlock::AcceptBlock(), the height of the block *being*
// evaluated is what is used. Thus if we want to know if a
// transaction can be part of the *next* block, we need to call
// IsFinalTx() with one more than chainActive.Height().
const int nBlockHeight = chainActive.Height() + 1;

// BIP113 will require that time-locked transactions have nLockTime set to
// less than the median time of the previous block they're contained in.
// When the next block is created its previous block will be the current
// chain tip, so we use that to calculate the median time passed to
// IsFinalTx() if LOCKTIME_MEDIAN_TIME_PAST is set.
const int64_t nBlockTime = (flags & LOCKTIME_MEDIAN_TIME_PAST)
? chainActive.Tip()->GetMedianTimePast()
: GetAdjustedTime();

return IsFinalTx(tx, nBlockHeight, nBlockTime);
}

CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree)
{
{
Expand Down
9 changes: 9 additions & 0 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,15 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
/** Context-independent validity checks */
bool CheckTransaction(const CTransaction& tx, CValidationState& state);

/**
* Check if transaction will be final in the next block to be created.
*
* Calls IsFinalTx() with current block height and appropriate block time.
*
* See consensus/consensus.h for flag definitions.
*/
bool CheckFinalTx(const CTransaction &tx, int flags = -1);

/** Check for standard transaction types
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
*/
Expand Down
1 change: 1 addition & 0 deletions src/masternode-sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class CMasternodeSync
void Process();
bool IsSynced();
bool IsBlockchainSynced();
bool IsMasternodeListSynced() { return RequestedMasternodeAssets > MASTERNODE_SYNC_LIST; }
void ClearFulfilledRequest();
};

Expand Down
107 changes: 107 additions & 0 deletions src/masternode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ CMasternode::CMasternode()
cacheInputAgeBlock = 0;
unitTest = false;
allowFreeTx = true;
nActiveState = MASTERNODE_ENABLED,
protocolVersion = PROTOCOL_VERSION;
nLastDsq = 0;
nScanningErrorCount = 0;
Expand All @@ -93,6 +94,7 @@ CMasternode::CMasternode(const CMasternode& other)
cacheInputAgeBlock = other.cacheInputAgeBlock;
unitTest = other.unitTest;
allowFreeTx = other.allowFreeTx;
nActiveState = MASTERNODE_ENABLED,
protocolVersion = other.protocolVersion;
nLastDsq = other.nLastDsq;
nScanningErrorCount = other.nScanningErrorCount;
Expand All @@ -117,6 +119,7 @@ CMasternode::CMasternode(const CMasternodeBroadcast& mnb)
cacheInputAgeBlock = 0;
unitTest = false;
allowFreeTx = true;
nActiveState = MASTERNODE_ENABLED,
protocolVersion = mnb.protocolVersion;
nLastDsq = mnb.nLastDsq;
nScanningErrorCount = 0;
Expand Down Expand Up @@ -284,6 +287,28 @@ int64_t CMasternode::GetLastPaid() {
return 0;
}

std::string CMasternode::GetStatus()
{
switch(nActiveState) {
case CMasternode::MASTERNODE_PRE_ENABLED: return "PRE_ENABLED";
case CMasternode::MASTERNODE_ENABLED: return "ENABLED";
case CMasternode::MASTERNODE_EXPIRED: return "EXPIRED";
case CMasternode::MASTERNODE_OUTPOINT_SPENT: return "OUTPOINT_SPENT";
case CMasternode::MASTERNODE_REMOVE: return "REMOVE";
case CMasternode::MASTERNODE_WATCHDOG_EXPIRED: return "WATCHDOG_EXPIRED";
case CMasternode::MASTERNODE_POSE_BAN: return "POSE_BAN";
default: return "UNKNOWN";
}
}

bool CMasternode::IsValidNetAddr()
{
// TODO: regtest is fine with any addresses for now,
// should probably be a bit smarter if one day we start to implement tests for this
return Params().NetworkID() == CBaseChainParams::REGTEST ||
(IsReachable(addr) && addr.IsRoutable());
}

CMasternodeBroadcast::CMasternodeBroadcast()
{
vin = CTxIn();
Expand Down Expand Up @@ -344,6 +369,88 @@ CMasternodeBroadcast::CMasternodeBroadcast(const CMasternode& mn)
nLastScanningErrorBlockHeight = mn.nLastScanningErrorBlockHeight;
}

bool CMasternodeBroadcast::Create(std::string strService, std::string strKeyMasternode, std::string strTxHash, std::string strOutputIndex, std::string& strErrorRet, CMasternodeBroadcast &mnbRet, bool fOffline)
{
CTxIn txin;
CPubKey pubKeyCollateralAddressNew;
CKey keyCollateralAddressNew;
CPubKey pubKeyMasternodeNew;
CKey keyMasternodeNew;

//need correct blocks to send ping
if(!fOffline && !masternodeSync.IsBlockchainSynced()) {
strErrorRet = "Sync in progress. Must wait until sync is complete to start Masternode";
LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
return false;
}

if(!obfuScationSigner.GetKeysFromSecret(strKeyMasternode, keyMasternodeNew, pubKeyMasternodeNew)) {
strErrorRet = strprintf("Invalid masternode key %s", strKeyMasternode);
LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
return false;
}

if(!pwalletMain->GetMasternodeVinAndKeys(txin, pubKeyCollateralAddressNew, keyCollateralAddressNew, strTxHash, strOutputIndex)) {
strErrorRet = strprintf("Could not allocate txin %s:%s for masternode %s", strTxHash, strOutputIndex, strService);
LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
return false;
}

CService service = CService(strService);
int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort();
if(Params().NetworkID() == CBaseChainParams::MAIN) {
if(service.GetPort() != mainnetDefaultPort) {
strErrorRet = strprintf("Invalid port %u for masternode %s, only %d is supported on mainnet.", service.GetPort(), strService, mainnetDefaultPort);
LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
return false;
}
} else if (service.GetPort() == mainnetDefaultPort) {
strErrorRet = strprintf("Invalid port %u for masternode %s, %d is the only supported on mainnet.", service.GetPort(), strService, mainnetDefaultPort);
LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
return false;
}

return Create(txin, CService(strService), keyCollateralAddressNew, pubKeyCollateralAddressNew, keyMasternodeNew, pubKeyMasternodeNew, strErrorRet, mnbRet);
}

bool CMasternodeBroadcast::Create(CTxIn txin, CService service, CKey keyCollateralAddressNew, CPubKey pubKeyCollateralAddressNew, CKey keyMasternodeNew, CPubKey pubKeyMasternodeNew, std::string &strErrorRet, CMasternodeBroadcast &mnbRet)
{
// wait for reindex and/or import to finish
if (fImporting || fReindex) return false;

LogPrint("masternode", "CMasternodeBroadcast::Create -- pubKeyCollateralAddressNew = %s, pubKeyMasternodeNew.GetID() = %s\n",
CBitcoinAddress(pubKeyCollateralAddressNew.GetID()).ToString(),
pubKeyMasternodeNew.GetID().ToString());


CMasternodePing mnp(txin);
if(!mnp.Sign(keyMasternodeNew, pubKeyMasternodeNew)) {
strErrorRet = strprintf("Failed to sign ping, masternode=%s", txin.prevout.ToStringShort());
LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
mnbRet = CMasternodeBroadcast();
return false;
}

mnbRet = CMasternodeBroadcast(service, txin, pubKeyCollateralAddressNew, pubKeyMasternodeNew, PROTOCOL_VERSION);

if(!mnbRet.IsValidNetAddr()) {
strErrorRet = strprintf("Invalid IP address, masternode=%s", txin.prevout.ToStringShort());
LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
mnbRet = CMasternodeBroadcast();
return false;
}

mnbRet.lastPing = mnp;
if(!mnbRet.Sign(keyCollateralAddressNew)) {
strErrorRet = strprintf("Failed to sign broadcast, masternode=%s", txin.prevout.ToStringShort());
LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
mnbRet = CMasternodeBroadcast();
return false;
}

return true;
}

bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
{
// make sure signature isn't in the future (past is OK)
Expand Down
Loading