Collateral is now checked for age

This commit is contained in:
Evan Duffield 2015-07-12 16:37:55 -07:00
parent 8e7c4e7491
commit acf09d1bc1
5 changed files with 57 additions and 102 deletions

View File

@ -849,30 +849,6 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
return nSigOps;
}
/*
int GetInputAge(CTxIn& vin)
{
// Fetch previous transactions (inputs):
CCoinsView viewDummy;
CCoinsViewCache view(viewDummy);
{
LOCK(mempool.cs);
CCoinsViewCache &viewChain = *pcoinsTip;
CCoinsViewMemPool viewMempool(viewChain, mempool);
view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
const uint256& prevHash = vin.prevout.hash;
CCoins coins;
view.GetCoins(prevHash, coins); // this is certainly allowed to fail
view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
}
if(!view.HaveCoins(vin.prevout.hash)) return -1;
const CCoins &coins = view.GetCoins(vin.prevout.hash);
return (chainActive.Tip()->nHeight+1) - coins.nHeight;
}*/
int GetInputAge(CTxIn& vin)
{
CCoinsView viewDummy;
@ -883,13 +859,34 @@ int GetInputAge(CTxIn& vin)
view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
const CCoins* coins = view.AccessCoins(vin.prevout.hash);
if (coins)
if (coins){
if(coins->nHeight < 0) return 0;
return (chainActive.Tip()->nHeight+1) - coins->nHeight;
}
else
return -1;
}
}
int GetInputAgeIX(uint256 nTXHash, CTxIn& vin)
{
int sigs = 0;
int nResult = GetInputAge(vin);
if(nResult < 0) nResult = 0;
if (nResult < 6){
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(nTXHash);
if (i != mapTxLocks.end()){
sigs = (*i).second.CountSignatures();
}
if(sigs >= INSTANTX_SIGNATURES_REQUIRED){
return nInstantXDepth+nResult;
}
}
return -1;
}
bool CheckTransaction(const CTransaction& tx, CValidationState &state)
{

View File

@ -234,7 +234,8 @@ bool AcceptableInputs(CTxMemPool& pool, CValidationState &state, const CTransact
bool* pfMissingInputs, bool fRejectInsaneFee=false, bool ignoreFees=false);
int GetInputAge(CTxIn& vin);
// get age + lock confirmations
int GetInputAgeIX(uint256 nTXHash, CTxIn& vin);
struct CNodeStateStats {
int nMisbehavior;

View File

@ -37,6 +37,7 @@ bool IsBudgetCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, s
CTransaction txCollateral;
uint256 hash;
if(!GetTransaction(nTxCollateralHash, txCollateral, hash, true)){
strError = "Can't find collateral tx %s\n", txCollateral.ToString().c_str();
LogPrintf ("CBudgetProposalBroadcast::FeeTXValid - Can't find collateral tx %s\n", txCollateral.ToString().c_str());
return false;
}
@ -50,14 +51,24 @@ bool IsBudgetCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, s
bool foundOpReturn = false;
BOOST_FOREACH(const CTxOut o, txCollateral.vout){
if(!o.scriptPubKey.IsNormalPaymentScript() && !o.scriptPubKey.IsUnspendable()){
LogPrintf ("CBudgetProposalBroadcast::FeeTXValid - Invalid Script %s\n", txCollateral.ToString().c_str());
strError = "Invalid Script";
LogPrintf ("CBudgetProposalBroadcast::FeeTXValid - Invalid Script %s\n", txCollateral.ToString());
return false;
}
if(o.scriptPubKey == findScript && o.nValue >= BUDGET_FEE_TX) foundOpReturn = true;
}
if(!foundOpReturn){
LogPrintf ("CBudgetProposalBroadcast::IsBudgetCollateralValid - Couldn't find opReturn %s\n", txCollateral.ToString().c_str());
strError = "Couldn't find opReturn";
LogPrintf ("CBudgetProposalBroadcast::IsBudgetCollateralValid - Couldn't find opReturn %s\n", txCollateral.ToString());
return false;
}
CTxIn in(COutPoint(txCollateral.GetHash(), 0));
int conf = GetInputAgeIX(txCollateral.GetHash(), in);
if(conf < BUDGET_FEE_CONFIRMATIONS){
strError = "Collateral requires at least 6 confirmations - " + boost::lexical_cast<std::string>(conf) + " confirmations ";
LogPrintf ("CBudgetProposalBroadcast::IsBudgetCollateralValid - Collateral requires at least 6 confirmations - %s - %d confirmations\n", txCollateral.GetHash().ToString(), conf);
return false;
}
@ -91,13 +102,11 @@ void CBudgetManager::SubmitFinalBudget()
CBlockIndex* pindexPrev = chainActive.Tip();
if(!pindexPrev) return;
int nBlockStart = pindexPrev->nHeight-(pindexPrev->nHeight % GetBudgetPaymentCycleBlocks())+GetBudgetPaymentCycleBlocks();
if(nSubmittedFinalBudget >= nBlockStart) return;
if(nBlockStart - pindexPrev->nHeight > 100) return;
std::vector<CBudgetProposal*> vBudgetProposals = budget.GetBudget();
std::string strBudgetName = "main";
std::vector<CTxBudgetPayment> vecTxBudgetPayments;
@ -113,7 +122,6 @@ void CBudgetManager::SubmitFinalBudget()
LogPrintf("SubmitFinalBudget - Found No Proposals For Period\n");
return;
}
nSubmittedFinalBudget = nBlockStart;
CPubKey pubKeyMasternode;
CKey keyMasternode;
@ -128,11 +136,25 @@ void CBudgetManager::SubmitFinalBudget()
//create fee tx
CTransaction tx;
if(!pwalletMain->GetBudgetSystemCollateralTX(tx, tempBudget.GetHash(), true)){
LogPrintf("SubmitFinalBudget - Can't make collateral transaction\n");
if(!mapCollateral.count(tempBudget.GetHash())){
if(!pwalletMain->GetBudgetSystemCollateralTX(tx, tempBudget.GetHash(), true)){
LogPrintf("SubmitFinalBudget - Can't make collateral transaction\n");
return;
}
mapCollateral.insert(make_pair(tempBudget.GetHash(), tx));
} else {
tx = mapCollateral[tempBudget.GetHash()];
}
CTxIn in(COutPoint(tx.GetHash(), 0));
int conf = GetInputAgeIX(tx.GetHash(), in);
if(conf < BUDGET_FEE_CONFIRMATIONS+1){
LogPrintf ("CBudgetProposalBroadcast::IsBudgetCollateralValid - Collateral requires at least 6 confirmations - %s - %d confirmations\n", tx.GetHash().ToString(), conf);
return;
}
nSubmittedFinalBudget = nBlockStart;
//create the proposal incase we're the first to make it
CFinalizedBudgetBroadcast finalizedBudgetBroadcast(strBudgetName, nBlockStart, vecTxBudgetPayments, tx.GetHash());

View File

@ -31,6 +31,7 @@ class CTxBudgetPayment;
#define VOTE_NO 2
static const int64_t BUDGET_FEE_TX = (0.5*COIN);
static const int64_t BUDGET_FEE_CONFIRMATIONS = 6;
extern std::map<uint256, CBudgetProposalBroadcast> mapSeenMasternodeBudgetProposals;
extern std::map<uint256, CBudgetVote> mapSeenMasternodeBudgetVotes;
@ -79,6 +80,9 @@ private:
// critical section to protect the inner data structures
mutable CCriticalSection cs;
//hold txes until they mature enough to use
map<uint256, CTransaction> mapCollateral;
public:
// keep track of the scanning errors I've seen
map<uint256, CBudgetProposal> mapProposals;

View File

@ -439,80 +439,11 @@ Value mnfinalbudget(const Array& params, bool fHelp)
"mnbudget \"command\"... ( \"passphrase\" )\n"
"Vote or show current budgets\n"
"\nAvailable commands:\n"
" suggest - Suggest a budget to be paid\n"
" vote-many - Vote on a finalized budget\n"
" vote - Vote on a finalized budget\n"
" show - Show existing finalized budgets\n"
);
if(strCommand == "suggest")
{
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
mnEntries = masternodeConfig.getEntries();
CBlockIndex* pindexPrev = chainActive.Tip();
if(!pindexPrev)
return "Must be synced to suggest";
if (params.size() < 3)
throw runtime_error("Correct usage of suggest is 'mnfinalbudget suggest BUDGET_NAME PROPNAME [PROP2 PROP3 PROP4]'");
std::string strBudgetName = params[1].get_str();
if(strBudgetName.size() > 20)
return "Invalid budget name, limit of 20 characters.";
int nBlockStart = pindexPrev->nHeight-(pindexPrev->nHeight % GetBudgetPaymentCycleBlocks())+GetBudgetPaymentCycleBlocks();
std::vector<CTxBudgetPayment> vecPayments;
for(int i = 2; i < (int)params.size(); i++)
{
std::string strHash = params[i].get_str();
uint256 hash(strHash);
CBudgetProposal* pbudgetProposal = budget.FindProposal(hash);
if(!pbudgetProposal){
return "Invalid proposal " + strHash + ". Please check the proposal hash";
} else {
CTxBudgetPayment out;
out.nProposalHash = hash;
out.payee = pbudgetProposal->GetPayee();
out.nAmount = pbudgetProposal->GetAmount();
vecPayments.push_back(out);
}
}
CPubKey pubKeyMasternode;
CKey keyMasternode;
std::string errorMessage;
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
return("Masternode signing error, could not set key correctly");
//create transaction
uint256 hash = 0;
//create the proposal incase we're the first to make it
CFinalizedBudgetBroadcast finalizedBudgetBroadcast(strBudgetName, nBlockStart, vecPayments, hash);
if(!finalizedBudgetBroadcast.IsValid())
return "Invalid finalized budget broadcast (are all the hashes correct?)";
mapSeenFinalizedBudgets.insert(make_pair(finalizedBudgetBroadcast.GetHash(), finalizedBudgetBroadcast));
finalizedBudgetBroadcast.Relay();
budget.AddFinalizedBudget(finalizedBudgetBroadcast);
CFinalizedBudgetVote vote(activeMasternode.vin, finalizedBudgetBroadcast.GetHash());
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
return "Failure to sign.";
}
mapSeenFinalizedBudgetVotes.insert(make_pair(vote.GetHash(), vote));
vote.Relay();
budget.UpdateFinalizedBudget(vote, NULL);
return "success";
}
if(strCommand == "vote-many")
{
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;