CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,const int nHeightIn) { // Create new block auto_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate()); if(!pblocktemplate.get()) return NULL; CBlock *pblock = &pblocktemplate->block; // pointer for convenience CBlockIndex* pindexPrev; if(nHeightIn<=0) { pindexPrev = chainActive.Tip(); } else pindexPrev = chainActive[nHeightIn-1]; int nHeight = pindexPrev->nBlockHeight + 1; pblock->nBlockHeight=nHeight; UpdateTime(pblock, pindexPrev); // -regtest only: allow overriding block.nVersion with // -blockversion=N to test forking scenarios if (Params().MineBlocksOnDemand()) pblock->nVersion = GetArg("-blockversion", pblock->nVersion); // Create coinbase tx CMutableTransaction txNew; txNew.vin.resize(1); txNew.vin[0].prevout.SetNull(); txNew.vin[0].prevout.n=nHeight; txNew.vin[0].scriptSig=CScript()<<0; txNew.vout.resize(1); txNew.vout[0].scriptPubKey = scriptPubKeyIn; txNew.vout[0].nLockTime=nHeight +COINBASE_MATURITY; // Add dummy coinbase tx as first transaction pblock->vtx.push_back(CTransaction()); pblocktemplate->vTxFees.push_back(-1); // updated at end pblocktemplate->vTxSigOps.push_back(-1); // updated at end // Largest block you're willing to create: unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity: nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize)); // How much of the block should be dedicated to high-priority transactions, // included regardless of the fees they pay unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE); nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize); // Minimum block size you want to create; block will be filled with free transactions // until there are no more or the block reaches this size: unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE); nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize); //min tx size to judge finish of block.set this a little bit higher so as to make mining faster unsigned int nMinTxSize=200; // Collect memory pool transactions into the block CAmount nFees = 0; uint64_t nBlockSize = 1000; uint64_t nBlockTx = 0; int nBlockSigOps = 100; { LOCK2(cs_main, mempool.cs); if(nHeightIn<=0) { CCoinsViewCache view(pcoinsTip); // Priority order to process transactions list<COrphan> vOrphan; // list memory doesn't move map<uint256, vector<COrphan*> > mapDependers; // Collect transactions into block for (int i=0;i<(int)mempool.queue.size();i++) { const CTransaction& tx = mempool.mapTx[mempool.queue[i]].GetTx(); if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight)) continue; COrphan* porphan = NULL; CAmount nTotalIn = 0; bool fMissingInputs = false; BOOST_FOREACH(const CTxIn& txin, tx.vin) { // Read prev transaction if (!view.HaveCoins(txin.prevout.hash)) { //don't take in transactions with prevout in mempool,because txs are queued by fee, not sequence, we can't guarantee it's //previous tx can be included in this block fMissingInputs = true; break; // This should never happen; all transactions in the memory // pool should connect to either transactions in the chain // or other transactions in the memory pool. if (!mempool.mapTx.count(txin.prevout.hash)) { LogPrintf("ERROR: mempool transaction missing input\n"); if (fDebug) assert("mempool transaction missing input" == 0); fMissingInputs = true; if (porphan) vOrphan.pop_back(); break; } // Has to wait for dependencies if (!porphan) { // Use list for automatic deletion vOrphan.push_back(COrphan(&tx)); porphan = &vOrphan.back(); } mapDependers[txin.prevout.hash].push_back(porphan); porphan->setDependsOn.insert(txin.prevout.hash); nTotalIn += mempool.mapTx[txin.prevout.hash].GetTx().vout[txin.prevout.n].nValue; continue; } const CCoins* coins = view.AccessCoins(txin.prevout.hash); assert(coins); if ((int64_t)coins->vout[txin.prevout.n].nLockTime >= ((int64_t)coins->vout[txin.prevout.n].nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nHeight : std::min((int64_t)pindexPrev->nTime,std::max((int64_t)pindexPrev->GetMedianTimePast()+1, (int64_t)GetAdjustedTime())))) fMissingInputs = true; CAmount nValueIn = coins->vout[txin.prevout.n].nValue; nTotalIn += nValueIn; } if (fMissingInputs) continue; // Size limits unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); if (nBlockSize + nTxSize >= nBlockMaxSize) continue; // Legacy limits on sigOps: unsigned int nTxSigOps = GetLegacySigOpCount(tx); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) continue; if (!view.HaveInputs(tx)) continue; CAmount nTxFees = tx.GetFee(); nTxSigOps += GetP2SHSigOpCount(tx, view); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) continue; // Note that flags: we don't want to set mempool/IsStandard() // policy here, but we still have to ensure that the block we // create only contains transactions that are valid in new blocks. CValidationState state; if (!CheckInputs(tx, tx,state, view, pblock,true, MANDATORY_SCRIPT_VERIFY_FLAGS, true)) continue; CTxUndo txundo; UpdateCoins(tx, state, view, txundo, nHeight); // Added pblock->vtx.push_back(tx); pblocktemplate->vTxFees.push_back(nTxFees); pblocktemplate->vTxSigOps.push_back(nTxSigOps); nBlockSize += nTxSize; ++nBlockTx; nBlockSigOps += nTxSigOps; nFees += nTxFees; if (nBlockSize+nMinTxSize>nBlockMaxSize) break; } } CBlock prevBlock; ReadBlockFromDisk(prevBlock, pindexPrev); CAmount prevCoinbaseFee=prevBlock.vtx[0].GetFee(); nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; // Compute final coinbase transaction. CAmount coinbaseInput=GetBlockValue(nHeight, nFees)+prevCoinbaseFee; txNew.vin[0].prevout.nValue = coinbaseInput; txNew.vout[0].nValue = 0; CAmount coinbaseFee=CFeeRate(DEFAULT_TRANSACTION_FEE).GetFee(txNew.GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)+10); CAmount coinbaseOutput=coinbaseInput-coinbaseFee; if(nHeightIn<=0&&coinbaseOutput<=minRelayTxFee.GetFee(DUST_THRESHOLD)) return NULL; txNew.vout[0].nValue =coinbaseOutput; pblock->vtx[0] = txNew; pblocktemplate->vTxFees[0] = -nFees; // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock); pblock->nNonce = 0; pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); CValidationState state; if (nHeightIn<=0&&!TestBlockValidity(state, *pblock, pindexPrev, false, false)) { LogPrintf("CreateNewBlock() : TestBlockValidity failed \n" ); return NULL; } }
bool MultisigDialog::createMultisigTransaction(vector<CTxIn> vUserIn, vector<CTxOut> vUserOut, string& feeStringRet, string& errorRet) { try{ //attempt to access the given inputs CCoinsViewCache view = getInputsCoinsViewCache(vUserIn); //retrieve total input val and change dest CAmount totalIn = 0; vector<CAmount> vInputVals; CScript changePubKey; bool fFirst = true; for(CTxIn in : vUserIn){ const CCoins* coins = view.AccessCoins(in.prevout.hash); if(!coins->IsAvailable(in.prevout.n) || coins == NULL){ continue; } CTxOut prevout = coins->vout[in.prevout.n]; CScript privKey = prevout.scriptPubKey; vInputVals.push_back(prevout.nValue); totalIn += prevout.nValue; if(!fFirst){ if(privKey != changePubKey){ throw runtime_error("Address mismatch! Inputs must originate from the same multisignature address."); } }else{ fFirst = false; changePubKey = privKey; } } CAmount totalOut = 0; //retrieve total output val for(CTxOut out : vUserOut){ totalOut += out.nValue; } if(totalIn < totalOut){ throw runtime_error("Not enough PIV provided as input to complete transaction (including fee)."); } //calculate change amount CAmount changeAmount = totalIn - totalOut; CTxOut change(changeAmount, changePubKey); //generate random position for change unsigned int changeIndex = rand() % (vUserOut.size() + 1); //insert change into random position if(changeIndex < vUserOut.size()){ vUserOut.insert(vUserOut.begin() + changeIndex, change); }else{ vUserOut.emplace_back(change); } //populate tx CMutableTransaction tx; tx.vin = vUserIn; tx.vout = vUserOut; const CCoins* coins = view.AccessCoins(tx.vin[0].prevout.hash); if(coins == NULL || !coins->IsAvailable(tx.vin[0].prevout.n)){ throw runtime_error("Coins unavailable (unconfirmed/spent)"); } CScript prevPubKey = coins->vout[tx.vin[0].prevout.n].scriptPubKey; //get payment destination CTxDestination address; if(!ExtractDestination(prevPubKey, address)){ throw runtime_error("Could not find address for destination."); } CScriptID hash = boost::get<CScriptID>(address); CScript redeemScript; if (!pwalletMain->GetCScript(hash, redeemScript)){ throw runtime_error("could not redeem"); } txnouttype type; vector<CTxDestination> addresses; int nReq; if(!ExtractDestinations(redeemScript, type, addresses, nReq)){ throw runtime_error("Could not extract destinations from redeem script."); } for(CTxIn& in : tx.vin){ in.scriptSig.clear(); //scale estimate to account for multisig scriptSig for(unsigned int i = 0; i < 50*(nReq+addresses.size()); i++){ in.scriptSig << INT64_MAX; } } //calculate fee unsigned int nBytes = tx.GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION); CAmount fee = ::minRelayTxFee.GetFee(nBytes); if(tx.vout.at(changeIndex).nValue > fee){ tx.vout.at(changeIndex).nValue -= fee; feeStringRet = strprintf("%d",((double)fee)/COIN).c_str(); }else{ throw runtime_error("Not enough PIV provided to cover fee"); } //clear junk from script sigs for(CTxIn& in : tx.vin){ in.scriptSig.clear(); } multisigTx = tx; }catch(const runtime_error& e){ errorRet = e.what(); return false; } return true; }