CWalletTx& AddTx(CRecipient recipient) { CTransactionRef tx; CReserveKey reservekey(wallet.get()); CAmount fee; int changePos = -1; std::string error; CCoinControl dummy; BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, reservekey, fee, changePos, error, dummy)); CValidationState state; BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, reservekey, nullptr, state)); CMutableTransaction blocktx; { LOCK(wallet->cs_wallet); blocktx = CMutableTransaction(*wallet->mapWallet.at(tx->GetHash()).tx); } CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); LOCK(wallet->cs_wallet); auto it = wallet->mapWallet.find(tx->GetHash()); BOOST_CHECK(it != wallet->mapWallet.end()); it->second.SetMerkleBranch(chainActive.Tip(), 1); return it->second; }
void CMasternode::Check(bool forceCheck) { if(ShutdownRequested()) return; if(!forceCheck && (GetTime() - lastTimeChecked < MASTERNODE_CHECK_SECONDS)) return; lastTimeChecked = GetTime(); //once spent, stop doing the checks if(activeState == MASTERNODE_VIN_SPENT) return; if(lastPing.sigTime - sigTime < MASTERNODE_MIN_MNP_SECONDS){ activeState = MASTERNODE_PRE_ENABLED; return; } if(!IsPingedWithin(MASTERNODE_REMOVAL_SECONDS)){ activeState = MASTERNODE_REMOVE; return; } if(!IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS)){ activeState = MASTERNODE_EXPIRED; return; } if(!unitTest){ CValidationState state; CMutableTransaction tx = CMutableTransaction(); CTxOut vout = CTxOut(999.99*COIN, darkSendPool.collateralPubKey); tx.vin.push_back(vin); tx.vout.push_back(vout); { TRY_LOCK(cs_main, lockMain); if(!lockMain) return; if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL)){ activeState = MASTERNODE_VIN_SPENT; return; } } } activeState = MASTERNODE_ENABLED; // OK }
MultisigDialog::MultisigDialog(QWidget* parent) : QDialog(parent), ui(new Ui::MultisigDialog), model(0) { ui->setupUi(this); multisigTx = CMutableTransaction(); //flag to show keyScrollArea on first priv key added isFirstPrivKey = true; isFirstRawTx = true; ui->keyScrollArea->hide(); ui->txInputsScrollArea->hide(); connect(ui->commitButton, SIGNAL(clicked()), this, SLOT(commitMultisigTx())); //populate lists with initial objects on_addAddressButton_clicked(); on_addAddressButton_clicked(); on_addDestinationButton_clicked(); this->setStyleSheet(GUIUtil::loadStyleSheet()); }
bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS) { // we are a masternode with the same vin (i.e. already activated) and this mnb is ours (matches our Masternode privkey) // so nothing to do here for us if(fMasterNode && vin.prevout == activeMasternode.vin.prevout && pubkey2 == activeMasternode.pubKeyMasternode) return true; // search existing Masternode list CMasternode* pmn = mnodeman.Find(vin); if(pmn != NULL) { // nothing to do here if we already know about this masternode and it's enabled if(pmn->IsEnabled()) return true; // if it's not enabled, remove old MN first and continue else mnodeman.Remove(pmn->vin); } CValidationState state; CMutableTransaction tx = CMutableTransaction(); CTxOut vout = CTxOut(999.99*COIN, darkSendPool.collateralPubKey); tx.vin.push_back(vin); tx.vout.push_back(vout); { TRY_LOCK(cs_main, lockMain); if(!lockMain) { // not mnb fault, let it to be checked again later mnodeman.mapSeenMasternodeBroadcast.erase(GetHash()); masternodeSync.mapSeenSyncMNB.erase(GetHash()); return false; } if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL)) { //set nDos state.IsInvalid(nDoS); return false; } } LogPrint("masternode", "mnb - Accepted Masternode entry\n"); if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){ LogPrintf("mnb - Input must have at least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS); // maybe we miss few blocks, let this mnb to be checked again later mnodeman.mapSeenMasternodeBroadcast.erase(GetHash()); masternodeSync.mapSeenSyncMNB.erase(GetHash()); return false; } // verify that sig time is legit in past // should be at least not earlier than block when 1000 DASH tx got MASTERNODE_MIN_CONFIRMATIONS uint256 hashBlock = 0; CTransaction tx2; GetTransaction(vin.prevout.hash, tx2, hashBlock, true); BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi != mapBlockIndex.end() && (*mi).second) { CBlockIndex* pMNIndex = (*mi).second; // block for 1000 DASH tx -> 1 confirmation CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + MASTERNODE_MIN_CONFIRMATIONS - 1]; // block where tx got MASTERNODE_MIN_CONFIRMATIONS if(pConfIndex->GetBlockTime() > sigTime) { LogPrintf("mnb - Bad sigTime %d for Masternode %20s %105s (%i conf block is at %d)\n", sigTime, addr.ToString(), vin.ToString(), MASTERNODE_MIN_CONFIRMATIONS, pConfIndex->GetBlockTime()); return false; } } LogPrintf("mnb - Got NEW Masternode entry - %s - %s - %s - %lli \n", GetHash().ToString(), addr.ToString(), vin.ToString(), sigTime); CMasternode mn(*this); mnodeman.Add(mn); // if it matches our Masternode privkey, then we've been remotely activated if(pubkey2 == activeMasternode.pubKeyMasternode && protocolVersion == PROTOCOL_VERSION){ activeMasternode.EnableHotColdMasterNode(vin, addr); } bool isLocal = addr.IsRFC1918() || addr.IsLocal(); if(Params().NetworkID() == CBaseChainParams::REGTEST) isLocal = false; if(!isLocal) Relay(); return true; }
// Right now this is only testing eviction performance in an extremely small // mempool. Code needs to be written to generate a much wider variety of // unique transactions for a more meaningful performance measurement. static void MempoolEviction(benchmark::State& state) { CMutableTransaction tx1 = CMutableTransaction(); tx1.vin.resize(1); tx1.vin[0].scriptSig = CScript() << OP_1; tx1.vout.resize(1); tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL; tx1.vout[0].nValue = 10 * COIN; CMutableTransaction tx2 = CMutableTransaction(); tx2.vin.resize(1); tx2.vin[0].scriptSig = CScript() << OP_2; tx2.vout.resize(1); tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL; tx2.vout[0].nValue = 10 * COIN; CMutableTransaction tx3 = CMutableTransaction(); tx3.vin.resize(1); tx3.vin[0].prevout = COutPoint(tx2.GetHash(), 0); tx3.vin[0].scriptSig = CScript() << OP_2; tx3.vout.resize(1); tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL; tx3.vout[0].nValue = 10 * COIN; CMutableTransaction tx4 = CMutableTransaction(); tx4.vin.resize(2); tx4.vin[0].prevout.SetNull(); tx4.vin[0].scriptSig = CScript() << OP_4; tx4.vin[1].prevout.SetNull(); tx4.vin[1].scriptSig = CScript() << OP_4; tx4.vout.resize(2); tx4.vout[0].scriptPubKey = CScript() << OP_4 << OP_EQUAL; tx4.vout[0].nValue = 10 * COIN; tx4.vout[1].scriptPubKey = CScript() << OP_4 << OP_EQUAL; tx4.vout[1].nValue = 10 * COIN; CMutableTransaction tx5 = CMutableTransaction(); tx5.vin.resize(2); tx5.vin[0].prevout = COutPoint(tx4.GetHash(), 0); tx5.vin[0].scriptSig = CScript() << OP_4; tx5.vin[1].prevout.SetNull(); tx5.vin[1].scriptSig = CScript() << OP_5; tx5.vout.resize(2); tx5.vout[0].scriptPubKey = CScript() << OP_5 << OP_EQUAL; tx5.vout[0].nValue = 10 * COIN; tx5.vout[1].scriptPubKey = CScript() << OP_5 << OP_EQUAL; tx5.vout[1].nValue = 10 * COIN; CMutableTransaction tx6 = CMutableTransaction(); tx6.vin.resize(2); tx6.vin[0].prevout = COutPoint(tx4.GetHash(), 1); tx6.vin[0].scriptSig = CScript() << OP_4; tx6.vin[1].prevout.SetNull(); tx6.vin[1].scriptSig = CScript() << OP_6; tx6.vout.resize(2); tx6.vout[0].scriptPubKey = CScript() << OP_6 << OP_EQUAL; tx6.vout[0].nValue = 10 * COIN; tx6.vout[1].scriptPubKey = CScript() << OP_6 << OP_EQUAL; tx6.vout[1].nValue = 10 * COIN; CMutableTransaction tx7 = CMutableTransaction(); tx7.vin.resize(2); tx7.vin[0].prevout = COutPoint(tx5.GetHash(), 0); tx7.vin[0].scriptSig = CScript() << OP_5; tx7.vin[1].prevout = COutPoint(tx6.GetHash(), 0); tx7.vin[1].scriptSig = CScript() << OP_6; tx7.vout.resize(2); tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL; tx7.vout[0].nValue = 10 * COIN; tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL; tx7.vout[1].nValue = 10 * COIN; CTxMemPool pool(CFeeRate(1000)); while (state.KeepRunning()) { AddTx(tx1, 10000LL, pool); AddTx(tx2, 5000LL, pool); AddTx(tx3, 20000LL, pool); AddTx(tx4, 7000LL, pool); AddTx(tx5, 1000LL, pool); AddTx(tx6, 1100LL, pool); AddTx(tx7, 9000LL, pool); pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); pool.TrimToSize(GetVirtualTransactionSize(tx1)); } }
//spend void MultisigDialog::on_createButton_clicked() { if(!model) return; vector<CTxIn> vUserIn; vector<CTxOut> vUserOut; try{ //Add inputs from Coin Control if any are selected if (CoinControlDialog::coinControl->HasSelected()) { vector<COutPoint> vSelected; CoinControlDialog::coinControl->ListSelected(vSelected); for (auto outpoint : vSelected) vUserIn.emplace_back(CTxIn(outpoint)); }else{//check for raw inputs for(int i = 0; i < ui->inputsList->count(); i++){ QWidget* input = qobject_cast<QWidget*>(ui->inputsList->itemAt(i)->widget()); QLineEdit* txIdLine = input->findChild<QLineEdit*>("txInputId"); if(txIdLine->text().isEmpty()){ ui->createButtonStatus->setStyleSheet("QLabel { color: red; }"); ui->createButtonStatus->setText(tr("Invalid Tx Hash.")); return; } QSpinBox* txVoutLine = input->findChild<QSpinBox*>("txInputVout"); int nOutput = txVoutLine->value(); if(nOutput < 0){ ui->createButtonStatus->setStyleSheet("QLabel { color: red; }"); ui->createButtonStatus->setText(tr("Vout position must be positive.")); return; } uint256 txid = uint256S(txIdLine->text().toStdString()); CTxIn in(COutPoint(txid, nOutput)); vUserIn.emplace_back(in); } } //validate destinations bool validInput = true; for(int i = 0; i < ui->destinationsList->count(); i++){ QWidget* dest = qobject_cast<QWidget*>(ui->destinationsList->itemAt(i)->widget()); QValidatedLineEdit* addr = dest->findChild<QValidatedLineEdit*>("destinationAddress"); BitcoinAmountField* amt = dest->findChild<BitcoinAmountField*>("destinationAmount"); CBitcoinAddress address; bool validDest = true; if(!model->validateAddress(addr->text())){ addr->setValid(false); validDest = false; }else{ address = CBitcoinAddress(addr->text().toStdString()); } if(!amt->validate()){ amt->setValid(false); validDest = false; } if(!validDest){ validInput = false; continue; } CScript scriptPubKey = GetScriptForDestination(address.Get()); CTxOut out(amt->value(), scriptPubKey); vUserOut.push_back(out); } //if all user data valid create a multisig tx if(validInput){ //clear member variable multisigTx = CMutableTransaction(); string error; string fee; if(!createMultisigTransaction(vUserIn, vUserOut, fee, error)){ throw runtime_error(error); } //display status string ui->createButtonStatus->setStyleSheet("QTextEdit{ color: black }"); QString status(strprintf("Transaction has successfully created with a fee of %s.\n" "The transaction has been automatically imported to the sign tab.\n" "Please continue on to sign the tx from this wallet, to access the hex to send to other owners.", fee).c_str()); ui->createButtonStatus->setText(status); ui->transactionHex->setText(QString::fromStdString(EncodeHexTx(multisigTx))); } }catch(const runtime_error& e){ ui->createButtonStatus->setStyleSheet("QTextEdit{ color: red }"); ui->createButtonStatus->setText(tr(e.what())); } }