Skip to content

Commit

Permalink
Merge pull request #4 from cakedefi/feature_masternodes
Browse files Browse the repository at this point in the history
Basic masternodes functionality
  • Loading branch information
uzyn authored Oct 7, 2019
2 parents 337add2 + 6c14705 commit 2f38ef8
Show file tree
Hide file tree
Showing 32 changed files with 2,294 additions and 84 deletions.
7 changes: 7 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ BITCOIN_CORE_H = \
dbwrapper.h \
limitedmap.h \
logging.h \
masternodes/masternodes.h \
masternodes/mn_checks.h \
masternodes/mn_txdb.h \
memusage.h \
merkleblock.h \
miner.h \
Expand Down Expand Up @@ -276,6 +279,10 @@ libbitcoin_server_a_SOURCES = \
interfaces/node.cpp \
init.cpp \
dbwrapper.cpp \
masternodes/masternodes.cpp \
masternodes/mn_checks.cpp \
masternodes/mn_txdb.cpp \
masternodes/mn_rpc.cpp \
miner.cpp \
net.cpp \
net_processing.cpp \
Expand Down
1 change: 1 addition & 0 deletions src/Makefile.bench.include
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES)
bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
bench_bench_bitcoin_LDADD = \
$(LIBBITCOIN_MN) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_WALLET) \
$(LIBBITCOIN_SERVER) \
Expand Down
137 changes: 103 additions & 34 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include <chainparamsseeds.h>
#include <consensus/merkle.h>
#include <key_io.h>
#include <masternodes/masternodes.h>
#include <tinyformat.h>
#include <util/system.h>
#include <util/strencodings.h>
Expand All @@ -17,7 +19,43 @@
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>

static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward)

std::vector<CTransactionRef> CChainParams::CreateGenesisMasternodes() const
{
// CChainParamsDummy dummy(*this);


std::vector<CTransactionRef> mnTxs;
for (auto const & addrs : vMasternodes)
{
CMutableTransaction txNew;
txNew.nVersion = 1;
txNew.vin.resize(1);
txNew.vout.resize(2);
txNew.vin[0].scriptSig = CScript(); // << 486604799 << CScriptNum(4) << std::vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));

CTxDestination operatorDest = DecodeDestination(addrs.operatorAddress, *this);
assert(operatorDest.which() == 1 || operatorDest.which() == 4);
CTxDestination ownerDest = DecodeDestination(addrs.ownerAddress, *this);
assert(ownerDest.which() == 1 || ownerDest.which() == 4);

CKeyID operatorAuthKey = operatorDest.which() == 1 ? CKeyID(*boost::get<PKHash>(&operatorDest)) : CKeyID(*boost::get<WitnessV0KeyHash>(&operatorDest)) ;
CDataStream metadata(MnTxMarker, SER_NETWORK, PROTOCOL_VERSION);
metadata << static_cast<unsigned char>(MasternodesTxType::CreateMasternode)
<< static_cast<char>(operatorDest.which()) << operatorAuthKey;

CScript scriptMeta;
scriptMeta << OP_RETURN << ToByteVector(metadata);

txNew.vout[0] = CTxOut(consensus.mn.creationFee, scriptMeta);
txNew.vout[1] = CTxOut(consensus.mn.collateralAmount, GetScriptForDestination(ownerDest));

mnTxs.push_back(MakeTransactionRef(std::move(txNew)));
}
return mnTxs;
}

static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward, std::vector<CTransactionRef> const & extraTxs)
{
CMutableTransaction txNew;
txNew.nVersion = 1;
Expand All @@ -35,6 +73,12 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi
genesis.stakeModifier = uint256S("0");
genesis.mintedBlocks = 0;
genesis.vtx.push_back(MakeTransactionRef(std::move(txNew)));

for (auto tx : extraTxs)
{
genesis.vtx.push_back(tx);
}

genesis.hashPrevBlock.SetNull();
genesis.hashMerkleRoot = BlockMerkleRoot(genesis);
return genesis;
Expand All @@ -51,11 +95,11 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi
* CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
* vMerkleTree: 4a5e1e
*/
static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward)
static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward, std::vector<CTransactionRef> const & extraTxs)
{
const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
const CScript genesisOutputScript = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nBits, nVersion, genesisReward);
return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nBits, nVersion, genesisReward, extraTxs);
}

/**
Expand Down Expand Up @@ -96,6 +140,13 @@ class CMainParams : public CChainParams {
// By default assume that the signatures in ancestors of this block are valid.
consensus.defaultAssumeValid = uint256S("0x0000000000000000000f1c54590ee18d15ec70e68c8cd4cfbadb1b4f11697eee"); //563378

// Masternodes' params
consensus.mn.activationDelay = 1500;
consensus.mn.collateralUnlockDelay = 300;
consensus.mn.creationFee = 1 * COIN;
consensus.mn.collateralAmount = 100 * COIN;
consensus.mn.historyFrame = 300;

/**
* The message start string is designed to be unlikely to occur in normal data.
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
Expand All @@ -110,8 +161,15 @@ class CMainParams : public CChainParams {
m_assumed_blockchain_size = 240;
m_assumed_chain_state_size = 3;

genesis = CreateGenesisBlock(1569396815, 0x1e0fffff, 1, 50 * COIN);
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,18); // '8' (0('1') for bitcoin)
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,90); // 'd' (5('3') for bitcoin)
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,128); // (128 ('5', 'K' or 'L') for bitcoin)
base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E};
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4};

bech32_hrp = "df";

genesis = CreateGenesisBlock(1569396815, 0x1e0fffff, 1, 50 * COIN, CreateGenesisMasternodes());
consensus.hashGenesisBlock = genesis.GetHash();
assert(consensus.hashGenesisBlock == uint256S("0xc0f410a59e9aa22afd67ee4671d41c2e3135c0efc589446e4b393cc534d178ac"));
assert(genesis.hashMerkleRoot == uint256S("0x800c7581a09c96d98bdad848db8fc027e8869d28d890ca21f6c25124baf53afe"));
Expand All @@ -130,14 +188,6 @@ class CMainParams : public CChainParams {
// vSeeds.emplace_back("seed.bitcoin.sprovoost.nl"); // Sjors Provoost
// vSeeds.emplace_back("dnsseed.emzy.de"); // Stephan Oeste

base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,18); // '8' (0('1') for bitcoin)
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,90); // 'd' (5('3') for bitcoin)
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,128); // (128 ('5', 'K' or 'L') for bitcoin)
base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E};
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4};

bech32_hrp = "df";

vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));

fDefaultConsistencyChecks = false;
Expand Down Expand Up @@ -209,6 +259,13 @@ class CTestNetParams : public CChainParams {
// By default assume that the signatures in ancestors of this block are valid.
consensus.defaultAssumeValid = uint256S("0x0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75"); //1354312

// Masternodes' params
consensus.mn.activationDelay = 10;
consensus.mn.collateralUnlockDelay = 10;
consensus.mn.creationFee = 1 * COIN;
consensus.mn.collateralAmount = 10 * COIN;
consensus.mn.historyFrame = 300;

pchMessageStart[0] = 0x0b;
pchMessageStart[1] = 0x11;
pchMessageStart[2] = 0x09;
Expand All @@ -218,7 +275,15 @@ class CTestNetParams : public CChainParams {
m_assumed_blockchain_size = 30;
m_assumed_chain_state_size = 2;

genesis = CreateGenesisBlock(1569396815, 0x1e0fffff, 1, 50 * COIN);
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,15); // '7' (111 ('m' or 'n') for bitcoin)
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,128); // 't' (196 ('2') for bitcoin)
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239); // (239 ('9' or 'c') for bitcoin)
base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF};
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94};

bech32_hrp = "tf";

genesis = CreateGenesisBlock(1569396815, 0x1e0fffff, 1, 50 * COIN, CreateGenesisMasternodes());
consensus.hashGenesisBlock = genesis.GetHash();

assert(consensus.hashGenesisBlock == uint256S("0xc0f410a59e9aa22afd67ee4671d41c2e3135c0efc589446e4b393cc534d178ac"));
Expand All @@ -232,14 +297,6 @@ class CTestNetParams : public CChainParams {
// vSeeds.emplace_back("seed.testnet.bitcoin.sprovoost.nl");
// vSeeds.emplace_back("testnet-seed.bluematt.me"); // Just a static list of stable node(s), only supports x9

base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,15); // '7' (111 ('m' or 'n') for bitcoin)
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,128); // 't' (196 ('2') for bitcoin)
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239); // (239 ('9' or 'c') for bitcoin)
base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF};
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94};

bech32_hrp = "tf";

vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test));

fDefaultConsistencyChecks = false;
Expand Down Expand Up @@ -299,6 +356,13 @@ class CRegTestParams : public CChainParams {
// By default assume that the signatures in ancestors of this block are valid.
consensus.defaultAssumeValid = uint256S("0x00");

// Masternodes' params
consensus.mn.activationDelay = 10;
consensus.mn.collateralUnlockDelay = 10;
consensus.mn.creationFee = 1 * COIN;
consensus.mn.collateralAmount = 10 * COIN;
consensus.mn.historyFrame = 300;

pchMessageStart[0] = 0xfa;
pchMessageStart[1] = 0xbf;
pchMessageStart[2] = 0xb5;
Expand All @@ -310,11 +374,24 @@ class CRegTestParams : public CChainParams {

UpdateActivationParametersFromArgs(args);

genesis = CreateGenesisBlock(1569396815, 0x1e0fffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111);
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196);
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239);
base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF};
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94};

assert(consensus.hashGenesisBlock == uint256S("0xc0f410a59e9aa22afd67ee4671d41c2e3135c0efc589446e4b393cc534d178ac"));
assert(genesis.hashMerkleRoot == uint256S("0x800c7581a09c96d98bdad848db8fc027e8869d28d890ca21f6c25124baf53afe"));
bech32_hrp = "bcrt";

// owner base58, operator base58
vMasternodes.push_back({"mwsZw8nF7pKxWH8eoKL9tPxTpaFkz7QeLU", "mswsMVsyGMj1FzDMbbxw2QW3KvQAv2FKiy"});
vMasternodes.push_back({"msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7", "mps7BdmwEF2vQ9DREDyNPibqsuSRZ8LuwQ"});
vMasternodes.push_back({"bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", "bcrt1qmfvw3dp3u6fdvqkdc0y3lr0e596le9cf22vtsv"});
vMasternodes.push_back({"bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu", "bcrt1qurwyhta75n2g75u2u5nds9p6w9v62y8wr40d2r"});

genesis = CreateGenesisBlock(1296688602, 0x207fffff, 1, 50 * COIN, CreateGenesisMasternodes());
consensus.hashGenesisBlock = genesis.GetHash();
assert(consensus.hashGenesisBlock == uint256S("0x000006772a3244d0a5a4911a5cb1d7e910e175f4e4b77c755018459122fa7a89"));
assert(genesis.hashMerkleRoot == uint256S("0x2faeba8cd467cb0df14c48d30b57736f1ed3275790401d127a03d55037df7b5c"));

vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds.
vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds.
Expand All @@ -325,7 +402,7 @@ class CRegTestParams : public CChainParams {

checkpointData = {
{
{0, uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")},
{0, uint256S("0x000006772a3244d0a5a4911a5cb1d7e910e175f4e4b77c755018459122fa7a89")},
}
};

Expand All @@ -334,14 +411,6 @@ class CRegTestParams : public CChainParams {
0,
0
};

base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111);
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196);
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239);
base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF};
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94};

bech32_hrp = "bcrt";
}

/**
Expand Down
8 changes: 8 additions & 0 deletions src/chainparams.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ class CChainParams
bool m_is_test_chain;
CCheckpointData checkpointData;
ChainTxData chainTxData;

struct MasternodeKeys
{
std::string ownerAddress;
std::string operatorAddress;
};
std::vector<MasternodeKeys> vMasternodes;
std::vector<CTransactionRef> CreateGenesisMasternodes() const;
};

/**
Expand Down
10 changes: 10 additions & 0 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef BITCOIN_CONSENSUS_PARAMS_H
#define BITCOIN_CONSENSUS_PARAMS_H

#include <amount.h>
#include <uint256.h>
#include <limits>
#include <map>
Expand Down Expand Up @@ -91,6 +92,15 @@ struct Params {

uint256 nMinimumChainWork;
uint256 defaultAssumeValid;

struct MnParams {
CAmount creationFee;
CAmount collateralAmount;
int activationDelay;
int collateralUnlockDelay;
int historyFrame;
};
MnParams mn;
};
} // namespace Consensus

Expand Down
9 changes: 8 additions & 1 deletion src/consensus/tx_verify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <consensus/tx_verify.h>

#include <consensus/consensus.h>
#include <masternodes/masternodes.h>
#include <primitives/transaction.h>
#include <script/interpreter.h>
#include <consensus/validation.h>
Expand Down Expand Up @@ -156,7 +157,7 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i
return nSigOps;
}

bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee)
bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, const CMasternodesView * mnview, int nSpendHeight, CAmount& txfee)
{
// are the actual inputs available?
if (!inputs.HaveInputs(tx)) {
Expand All @@ -181,6 +182,12 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange");
}

if (prevout.n == 1 && !mnview->CanSpend(prevout.hash, nSpendHeight))
{
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "mn-collateral-locked",
strprintf("tried to spend locked collateral for %s", prevout.hash.ToString())); /// @todo @max may be somehow place the height of unlocking?
}
}

const CAmount value_out = tx.GetValueOut();
Expand Down
3 changes: 2 additions & 1 deletion src/consensus/tx_verify.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

class CBlockIndex;
class CCoinsViewCache;
class CMasternodesView;
class CTransaction;
class CValidationState;

Expand All @@ -24,7 +25,7 @@ namespace Consensus {
* @param[out] txfee Set to the transaction fee if successful.
* Preconditions: tx.IsCoinBase() is false.
*/
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee);
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, const CMasternodesView * mnview, int nSpendHeight, CAmount& txfee);
} // namespace Consensus

/** Auxiliary functions for transaction validation (ideally should not be exposed) */
Expand Down
Loading

0 comments on commit 2f38ef8

Please sign in to comment.