Выяснил следующее - CoinStake транзация пытается сгенерироваться в методе
wallet.cpp/CreateCoinStake как и положено.
bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64_t nSearchInterval, int64_t nFees, CTransaction& txNew, CKey& key)
{
CBlockIndex* pindexPrev = pindexBest;
CBigNum bnTargetPerCoinDay;
bnTargetPerCoinDay.SetCompact(nBits);
txNew.vin.clear();
txNew.vout.clear();
// Mark coin stake transaction
CScript scriptEmpty;
scriptEmpty.clear();
txNew.vout.push_back(CTxOut(0, scriptEmpty));
// Choose coins to use
int64_t nBalance = GetBalance();
if (nBalance <= nReserveBalance)
return false;
vector vwtxPrev;
set > setCoins;
int64_t nValueIn = 0;
// Select coins with suitable depth
if (!SelectCoinsForStaking(nBalance - nReserveBalance, setCoins, nValueIn))
return false;
if (setCoins.empty())
return false;
int64_t nCredit = 0;
CScript scriptPubKeyKernel;
CTxDB txdb("r");
BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
{
static int nMaxStakeSearchInterval = 60;
bool fKernelFound = false;
for (unsigned int n=0; n {
boost::this_thread::interruption_point();
// Search backward in time from the given txNew timestamp
// Search nSearchInterval seconds back up to nMaxStakeSearchInterval
COutPoint prevoutStake = COutPoint(pcoin.first->GetHash(), pcoin.second);
int64_t nBlockTime;
if (CheckKernel(pindexPrev, nBits, txNew.nTime - n, prevoutStake, &nBlockTime))
{
// Found a kernel
LogPrint("coinstake", "CreateCoinStake : kernel found\n");
vector vSolutions;
txnouttype whichType;
CScript scriptPubKeyOut;
scriptPubKeyKernel = pcoin.first->vout[pcoin.second].scriptPubKey;
if (!Solver(scriptPubKeyKernel, whichType, vSolutions))
{
LogPrint("coinstake", "CreateCoinStake : failed to parse kernel\n");
break;
}
LogPrint("coinstake", "CreateCoinStake : parsed kernel type=%d\n", whichType);
if (whichType != TX_PUBKEY && whichType != TX_PUBKEYHASH)
{
LogPrint("coinstake", "CreateCoinStake : no support for kernel type=%d\n", whichType);
break; // only support pay to public key and pay to address
}
if (whichType == TX_PUBKEYHASH) // pay to address type
{
// convert to pay to public key type
if (!keystore.GetKey(uint160(vSolutions[0]), key))
{
LogPrint("coinstake", "CreateCoinStake : failed to get key for kernel type=%d\n", whichType);
break; // unable to find corresponding public key
}
scriptPubKeyOut << key.GetPubKey() << OP_CHECKSIG;
}
if (whichType == TX_PUBKEY)
{
valtype& vchPubKey = vSolutions[0];
if (!keystore.GetKey(Hash160(vchPubKey), key))
{
LogPrint("coinstake", "CreateCoinStake : failed to get key for kernel type=%d\n", whichType);
break; // unable to find corresponding public key
}
if (key.GetPubKey() != vchPubKey)
{
LogPrint("coinstake", "CreateCoinStake : invalid key for kernel type=%d\n", whichType);
break; // keys mismatch
}
scriptPubKeyOut = scriptPubKeyKernel;
}
txNew.nTime -= n;
txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
nCredit += pcoin.first->vout[pcoin.second].nValue;
vwtxPrev.push_back(pcoin.first);
txNew.vout.push_back(CTxOut(0, scriptPubKeyOut));
LogPrint("coinstake", "CreateCoinStake : added kernel type=%d\n", whichType);
fKernelFound = true;
break;
}
}
if (fKernelFound)
break; // if kernel is found stop searching
}
if (nCredit == 0 || nCredit > nBalance - nReserveBalance)
return false;
BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
{
// Attempt to add more inputs
// Only add coins of the same key/address as kernel
if (txNew.vout.size() == 2 && ((pcoin.first->vout[pcoin.second].scriptPubKey == scriptPubKeyKernel || pcoin.first->vout[pcoin.second].scriptPubKey == txNew.vout[1].scriptPubKey))
&& pcoin.first->GetHash() != txNew.vin[0].prevout.hash)
{
// Stop adding more inputs if already too many inputs
if (txNew.vin.size() >= 10)
break;
// Stop adding inputs if reached reserve limit
if (nCredit + pcoin.first->vout[pcoin.second].nValue > nBalance - nReserveBalance)
break;
// Do not add additional significant input
if (pcoin.first->vout[pcoin.second].nValue >= GetStakeCombineThreshold())
continue;
txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
nCredit += pcoin.first->vout[pcoin.second].nValue;
vwtxPrev.push_back(pcoin.first);
}
}
// Calculate reward
{
int64_t nReward = GetProofOfStakeReward(pindexPrev, 0, nFees);
if (nReward <= 0)
return false;
LogPrintf("nReward <= 0\n");
nCredit += nReward;
}
if (nCredit >= GetStakeSplitThreshold())
txNew.vout.push_back(CTxOut(0, txNew.vout[1].scriptPubKey)); //split stake
// Set output amount
if (txNew.vout.size() == 3)
{
txNew.vout[1].nValue = (nCredit / 2 / CENT) * CENT;
txNew.vout[2].nValue = nCredit - txNew.vout[1].nValue;
}
else
txNew.vout[1].nValue = nCredit;
// Sign
int nIn = 0;
BOOST_FOREACH(const CWalletTx* pcoin, vwtxPrev)
{
if (!SignSignature(*this, *pcoin, txNew, nIn++))
return error("CreateCoinStake : failed to sign coinstake");
}
// Limit size
unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
return error("CreateCoinStake : exceeded coinstake size limit");
// Successfully generated coinstake
return true;
}
Но она не проходит проверку
if (nCredit == 0 || nCredit > nBalance - nReserveBalance).
А именно потому, что
nCredit равен нулю.
Что это вообще за переменная? За что она отвечает?
Она должна суммировать какие-то значения здесь
nCredit += pcoin.first->vout[pcoin.second].nValue;Но этого не просходит.