本文整理汇总了C++中CMutableTransaction类的典型用法代码示例。如果您正苦于以下问题:C++ CMutableTransaction类的具体用法?C++ CMutableTransaction怎么用?C++ CMutableTransaction使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了CMutableTransaction类的13个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: Verify
static bool
Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, ScriptError& err)
{
// Create dummy to/from transactions:
CMutableTransaction txFrom;
txFrom.vout.resize(1);
txFrom.vout[0].scriptPubKey = scriptPubKey;
CMutableTransaction txTo;
txTo.vin.resize(1);
txTo.vout.resize(1);
txTo.vin[0].prevout.n = 0;
txTo.vin[0].prevout.hash = txFrom.GetHash();
txTo.vin[0].scriptSig = scriptSig;
txTo.vout[0].nValue = 1;
return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0), &err);
}
示例2: BuildTxs
/**
* Builds a creationTx from scriptPubKey and a spendingTx from scriptSig
* and witness such that spendingTx spends output zero of creationTx.
* Also inserts creationTx's output into the coins view.
*/
void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableTransaction& creationTx, const CScript& scriptPubKey, const CScript& scriptSig, const CTxInWitness& witness)
{
creationTx.nVersion = 1;
creationTx.vin.resize(1);
creationTx.vin[0].prevout.SetNull();
creationTx.vin[0].scriptSig = CScript();
creationTx.wit.vtxinwit.resize(1);
creationTx.vout.resize(1);
creationTx.vout[0].nValue = 1;
creationTx.vout[0].scriptPubKey = scriptPubKey;
spendingTx.nVersion = 1;
spendingTx.vin.resize(1);
spendingTx.vin[0].prevout.hash = creationTx.GetHash();
spendingTx.vin[0].prevout.n = 0;
spendingTx.vin[0].scriptSig = scriptSig;
spendingTx.wit.vtxinwit.resize(1);
spendingTx.wit.vtxinwit[0] = witness;
spendingTx.vout.resize(1);
spendingTx.vout[0].nValue = 1;
spendingTx.vout[0].scriptPubKey = CScript();
coins.ModifyCoins(creationTx.GetHash())->FromTx(creationTx, 0);
}
示例3: BuildSpendingTransaction
// FIXME: Dedup with BuildSpendingTransaction in test/script_tests.cpp.
static CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMutableTransaction& txCredit)
{
CMutableTransaction txSpend;
txSpend.nVersion = 1;
txSpend.nLockTime = 0;
txSpend.vin.resize(1);
txSpend.vout.resize(1);
txSpend.vin[0].prevout.hash = txCredit.GetHash();
txSpend.vin[0].prevout.n = 0;
txSpend.vin[0].scriptSig = scriptSig;
txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
txSpend.vout[0].scriptPubKey = CScript();
txSpend.vout[0].nValue = txCredit.vout[0].nValue;
return txSpend;
}
示例4: BuildSpendingTransaction
CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMutableTransaction& txCredit)
{
CMutableTransaction txSpend;
txSpend.nVersion = 1;
txSpend.nLockTime = 0;
txSpend.vin.resize(1);
txSpend.vout.resize(1);
txSpend.vin[0].prevout.hash = txCredit.GetHash();
txSpend.vin[0].prevout.n = 0;
txSpend.vin[0].scriptSig = scriptSig;
txSpend.vin[0].nSequence = std::numeric_limits<unsigned int>::max();
txSpend.vout[0].scriptPubKey = CScript();
txSpend.vout[0].nValue = 0;
return txSpend;
}
示例5: AddRawTxNameOperation
/**
* Implement the rawtx name operation feature. This routine interprets
* the given JSON object describing the desired name operation and then
* modifies the transaction accordingly.
* @param tx The transaction to extend.
* @param obj The name operation "description" as given to the call.
*/
void
AddRawTxNameOperation (CMutableTransaction& tx, const UniValue& obj)
{
UniValue val = find_value (obj, "op");
if (!val.isStr ())
throw JSONRPCError (RPC_INVALID_PARAMETER, "missing op key");
const std::string op = val.get_str ();
if (op != "name_update")
throw JSONRPCError (RPC_INVALID_PARAMETER,
"only name_update is implemented for the rawtx API");
val = find_value (obj, "name");
if (!val.isStr ())
throw JSONRPCError (RPC_INVALID_PARAMETER, "missing name key");
const valtype name = ValtypeFromString (val.get_str ());
val = find_value (obj, "value");
if (!val.isStr ())
throw JSONRPCError (RPC_INVALID_PARAMETER, "missing value key");
const valtype value = ValtypeFromString (val.get_str ());
val = find_value (obj, "address");
if (!val.isStr ())
throw JSONRPCError (RPC_INVALID_PARAMETER, "missing address key");
const CBitcoinAddress toAddress(val.get_str ());
if (!toAddress.IsValid ())
throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, "invalid address");
const CScript addr = GetScriptForDestination (toAddress.Get ());
tx.SetNamecoin ();
/* We do not add the name input. This has to be done explicitly,
but is easy from the name_show output. That way, createrawtransaction
doesn't depend on the chainstate at all. */
const CScript outScript = CNameScript::buildNameUpdate (addr, name, value);
tx.vout.push_back (CTxOut (NAME_LOCKED_AMOUNT, outScript));
}
示例6: buildMultisigTxStatusString
/***
*private helper functions
*/
QString MultisigDialog::buildMultisigTxStatusString(bool fComplete, const CMutableTransaction& tx)
{
string sTxHex = EncodeHexTx(tx);
if(fComplete){
ui->commitButton->setEnabled(true);
string sTxId = tx.GetHash().GetHex();
string sTxComplete = "Complete: true!\n"
"The commit button has now been enabled for you to finalize the transaction.\n"
"Once the commit button is clicked, the transaction will be published and coins transferred "
"to their destinations.\nWARNING: THE ACTIONS OF THE COMMIT BUTTON ARE FINAL AND CANNOT BE REVERSED.";
return QString(strprintf("%s\nTx Id:\n%s\nTx Hex:\n%s",sTxComplete, sTxId, sTxHex).c_str());
} else {
string sTxIncomplete = "Complete: false.\n"
"You may now send the hex below to another owner to sign.\n"
"Keep in mind the transaction must be passed from one owner to the next for signing.\n"
"Ensure all owners have imported the redeem before trying to sign. (besides creator)";
return QString(strprintf("%s\nTx Hex: %s", sTxIncomplete, sTxHex).c_str());
}
}
示例7: BuildTxs
/**
* Builds a creationTx from scriptPubKey and a spendingTx from scriptSig
* and witness such that spendingTx spends output zero of creationTx.
* Also inserts creationTx's output into the coins view.
*/
static void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableTransaction& creationTx, const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& witness)
{
creationTx.nVersion = 1;
creationTx.vin.resize(1);
creationTx.vin[0].prevout.SetNull();
creationTx.vin[0].scriptSig = CScript();
creationTx.vout.resize(1);
creationTx.vout[0].nValue = 1;
creationTx.vout[0].scriptPubKey = scriptPubKey;
spendingTx.nVersion = 1;
spendingTx.vin.resize(1);
spendingTx.vin[0].prevout.hash = creationTx.GetHash();
spendingTx.vin[0].prevout.n = 0;
spendingTx.vin[0].scriptSig = scriptSig;
spendingTx.vin[0].scriptWitness = witness;
spendingTx.vout.resize(1);
spendingTx.vout[0].nValue = 1;
spendingTx.vout[0].scriptPubKey = CScript();
AddCoins(coins, creationTx, 0);
}
示例8: TestPackageSelection
// Test suite for ancestor feerate transaction selection.
// Implemented as an additional function, rather than a separate test case,
// to allow reusing the blockchain created in CreateNewBlock_validity.
// Note that this test assumes blockprioritysize is 0.
void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, std::vector<CTransaction *>& txFirst)
{
// Test the ancestor feerate transaction selection.
TestMemPoolEntryHelper entry;
// Test that a medium fee transaction will be selected after a higher fee
// rate package with a low fee rate parent.
CMutableTransaction tx;
tx.vin.resize(1);
tx.vin[0].scriptSig = CScript() << OP_1;
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
tx.vin[0].prevout.n = 0;
tx.vout.resize(1);
tx.vout[0].nValue = 5000000000LL - 1000;
// This tx has a low fee: 1000 satoshis
uint256 hashParentTx = tx.GetHash(); // save this txid for later use
mempool.addUnchecked(hashParentTx, entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
// This tx has a medium fee: 10000 satoshis
tx.vin[0].prevout.hash = txFirst[1]->GetHash();
tx.vout[0].nValue = 5000000000LL - 10000;
uint256 hashMediumFeeTx = tx.GetHash();
mempool.addUnchecked(hashMediumFeeTx, entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
// This tx has a high fee, but depends on the first transaction
tx.vin[0].prevout.hash = hashParentTx;
tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee
uint256 hashHighFeeTx = tx.GetHash();
mempool.addUnchecked(hashHighFeeTx, entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
CBlockTemplate *pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
BOOST_CHECK(pblocktemplate->block.vtx[1].GetHash() == hashParentTx);
BOOST_CHECK(pblocktemplate->block.vtx[2].GetHash() == hashHighFeeTx);
BOOST_CHECK(pblocktemplate->block.vtx[3].GetHash() == hashMediumFeeTx);
// Test that a package below the min relay fee doesn't get included
tx.vin[0].prevout.hash = hashHighFeeTx;
tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee
uint256 hashFreeTx = tx.GetHash();
mempool.addUnchecked(hashFreeTx, entry.Fee(0).FromTx(tx));
size_t freeTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
// Calculate a fee on child transaction that will put the package just
// below the min relay fee (assuming 1 child tx of the same size).
CAmount feeToUse = minRelayTxFee.GetFee(2*freeTxSize) - 1;
tx.vin[0].prevout.hash = hashFreeTx;
tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
uint256 hashLowFeeTx = tx.GetHash();
mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse).FromTx(tx));
pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
// Verify that the free tx and the low fee tx didn't get selected
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashFreeTx);
BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashLowFeeTx);
}
// Test that packages above the min relay fee do get included, even if one
// of the transactions is below the min relay fee
// Remove the low fee transaction and replace with a higher fee transaction
std::list<CTransaction> dummy;
mempool.removeRecursive(tx, dummy);
tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee
hashLowFeeTx = tx.GetHash();
mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse+2).FromTx(tx));
pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
BOOST_CHECK(pblocktemplate->block.vtx[4].GetHash() == hashFreeTx);
BOOST_CHECK(pblocktemplate->block.vtx[5].GetHash() == hashLowFeeTx);
// Test that transaction selection properly updates ancestor fee
// calculations as ancestor transactions get included in a block.
// Add a 0-fee transaction that has 2 outputs.
tx.vin[0].prevout.hash = txFirst[2]->GetHash();
tx.vout.resize(2);
tx.vout[0].nValue = 5000000000LL - 100000000;
tx.vout[1].nValue = 100000000; // 1BTC output
uint256 hashFreeTx2 = tx.GetHash();
mempool.addUnchecked(hashFreeTx2, entry.Fee(0).SpendsCoinbase(true).FromTx(tx));
// This tx can't be mined by itself
tx.vin[0].prevout.hash = hashFreeTx2;
tx.vout.resize(1);
feeToUse = minRelayTxFee.GetFee(freeTxSize);
tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse;
uint256 hashLowFeeTx2 = tx.GetHash();
mempool.addUnchecked(hashLowFeeTx2, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));
pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
// Verify that this tx isn't selected.
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashFreeTx2);
BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashLowFeeTx2);
}
// This tx will be mineable, and should cause hashLowFeeTx2 to be selected
// as well.
//.........这里部分代码省略.........
示例9: CreateNewBlock
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;
//.........这里部分代码省略.........
示例10: FillBlockPayments
void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet, std::vector<CTxOut>& voutSuperblockRet)
{
// only create superblocks if spork is enabled AND if superblock is actually triggered
// (height should be validated inside)
if(sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED) &&
CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
LogPrint("gobject", "FillBlockPayments -- triggered superblock creation at height %d\n", nBlockHeight);
CSuperblockManager::CreateSuperblock(txNew, nBlockHeight, voutSuperblockRet);
return;
}
// FILL BLOCK PAYEE WITH MASTERNODE PAYMENT OTHERWISE
mnpayments.FillBlockPayee(txNew, nBlockHeight, blockReward, txoutMasternodeRet);
LogPrint("mnpayments", "FillBlockPayments -- nBlockHeight %d blockReward %lld txoutMasternodeRet %s txNew %s",
nBlockHeight, blockReward, txoutMasternodeRet.ToString(), txNew.ToString());
}
示例11: getInputsCoinsViewCache
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);
//.........这里部分代码省略.........
示例12: LOCK
{
LOCK(mempool.cs);
return CheckSequenceLocks(tx, flags);
}
// Test suite for ancestor feerate transaction selection.
// Implemented as an additional function, rather than a separate test case,
// to allow reusing the blockchain created in CreateNewBlock_validity.
static void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::mempool.cs)
{
// Test the ancestor feerate transaction selection.
TestMemPoolEntryHelper entry;
// Test that a medium fee transaction will be selected after a higher fee
// rate package with a low fee rate parent.
CMutableTransaction tx;
tx.vin.resize(1);
tx.vin[0].scriptSig = CScript() << OP_1;
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
tx.vin[0].prevout.n = 0;
tx.vout.resize(1);
tx.vout[0].nValue = 5000000000LL - 1000;
// This tx has a low fee: 1000 satoshis
uint256 hashParentTx = tx.GetHash(); // save this txid for later use
mempool.addUnchecked(entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
// This tx has a medium fee: 10000 satoshis
tx.vin[0].prevout.hash = txFirst[1]->GetHash();
tx.vout[0].nValue = 5000000000LL - 10000;
uint256 hashMediumFeeTx = tx.GetHash();
mempool.addUnchecked(entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
示例13: CreateGameTransactions
bool
CreateGameTransactions (const CCoinsView& view, unsigned nHeight,
const StepResult& stepResult,
std::vector<CTransaction>& vGameTx)
{
vGameTx.clear ();
/* Destroy name-coins of killed players. */
bool haveTxKills = false;
CMutableTransaction txKills;
txKills.SetGameTx ();
const PlayerSet& killedPlayers = stepResult.GetKilledPlayers ();
const KilledByMap& killedBy = stepResult.GetKilledBy ();
txKills.vin.reserve (killedPlayers.size ());
BOOST_FOREACH(const PlayerID &victim, killedPlayers)
{
const valtype vchName = ValtypeFromString (victim);
CNameData data;
if (!view.GetName (vchName, data))
return error ("Game engine killed a non-existing player %s",
victim.c_str ());
CTxIn txin(data.getUpdateOutpoint ());
/* List all killers, if player was simultaneously killed by several
other players. If the reason was not KILLED_DESTRUCT, handle
it also. If multiple reasons apply, the game tx is constructed
for the first reason according to the ordering inside of KilledByMap.
(Which in turn is determined by the enum values for KILLED_*.) */
typedef KilledByMap::const_iterator Iter;
const std::pair<Iter, Iter> iters = killedBy.equal_range (victim);
if (iters.first == iters.second)
return error ("No reason for killed player %s", victim.c_str ());
const KilledByInfo::Reason reason = iters.first->second.reason;
/* Unless we have destruct, there should be exactly one entry with
the "first" reason. There may be multiple entries for different
reasons, for instance, killed by poison and staying in spawn
area at the same time. */
{
Iter it = iters.first;
++it;
if (reason != KilledByInfo::KILLED_DESTRUCT && it != iters.second
&& reason == it->second.reason)
return error ("Multiple same-reason, non-destruct killed-by"
" entries for %s", victim.c_str ());
}
switch (reason)
{
case KilledByInfo::KILLED_DESTRUCT:
txin.scriptSig << vchName << GAMEOP_KILLED_BY;
for (Iter it = iters.first; it != iters.second; ++it)
{
if (it->second.reason != KilledByInfo::KILLED_DESTRUCT)
{
assert (it != iters.first);
break;
}
txin.scriptSig
<< ValtypeFromString (it->second.killer.ToString ());
}
break;
case KilledByInfo::KILLED_SPAWN:
txin.scriptSig << vchName << GAMEOP_KILLED_BY;
break;
case KilledByInfo::KILLED_POISON:
txin.scriptSig << vchName << GAMEOP_KILLED_POISON;
break;
default:
assert (false);
}
txKills.vin.push_back (txin);
haveTxKills = true;
}
if (haveTxKills)
{
const CTransaction tx(txKills);
assert (tx.IsGameTx () && !tx.IsBountyTx ());
vGameTx.push_back (tx);
}
/* Pay bounties to the players who collected them. The transaction
inputs are just "dummy" containing informational messages. */
bool haveTxBounties = false;
CMutableTransaction txBounties;
txBounties.SetGameTx ();
txBounties.vin.reserve (stepResult.bounties.size ());
txBounties.vout.reserve (stepResult.bounties.size ());
BOOST_FOREACH(const CollectedBounty& bounty, stepResult.bounties)
//.........这里部分代码省略.........