比特币源码解析-交易确认

图1 交易确认

主要描述bool CTransaction::ConnectInputs(CTxDB& txdb, map& mapTestPool, CDiskTxPos posThisTx, int nHeight, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee)函数的功能。

当前交易不是创币交易

if (!IsCoinBase())

{

}

遍历输入交易并获取输入交易的COutPoint信息

for (int i = 0; i < vin.size(); i++)

{

    COutPoint prevout = vin[i].prevout;

}

判断交易信息

如果当前矿工标志位为1,从mapTestPool中获取交易索引信息,否则从从交易数据库中判断前一个输出是否存在.

CTxIndex txindex;

bool fFound = true;

if (fMiner && mapTestPool.count(prevout.hash))

{

    // Get txindex from current proposed changes

    txindex = mapTestPool[prevout.hash];

}

else

{

    // Read txindex from txdb

    fFound = txdb.ReadTxIndex(prevout.hash, txindex);

}

if (!fFound && (fBlock || fMiner))

    return fMiner ? false : error("ConnectInputs() : %s prev tx %s index entry not found", GetHash().ToString().substr(0,6).c_str(),  prevout.hash.ToString().substr(0,6).c_str());

获取前一个交易信息

// Read txPrev

CTransaction txPrev;

if (!fFound || txindex.pos == CDiskTxPos(1,1,1))

{

    // Get prev tx from single transactions in memory

    CRITICAL_BLOCK(cs_mapTransactions)

    {

        if (!mapTransactions.count(prevout.hash))

            return error("ConnectInputs() : %s mapTransactions prev not found %s", GetHash().ToString().substr(0,6).c_str(),  prevout.hash.ToString().substr(0,6).c_str());

        txPrev = mapTransactions[prevout.hash];

    }

    if (!fFound)

        txindex.vSpent.resize(txPrev.vout.size());

}

else

{

    // Get prev tx from disk

    if (!txPrev.ReadFromDisk(txindex.pos))

        return error("ConnectInputs() : %s ReadFromDisk prev tx %s failed", GetHash().ToString().substr(0,6).c_str(),  prevout.hash.ToString().substr(0,6).c_str());

}

校验前一交易信息

如果前一交易是创币交易,则是否被足够多的区块确认

if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size())

    return error("ConnectInputs() : %s prevout.n out of range %d %d %d", GetHash().ToString().substr(0,6).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size());



// If prev is coinbase, check that it's matured

if (txPrev.IsCoinBase())

    for (CBlockIndex* pindex = pindexBest; pindex && nBestHeight - pindex->nHeight < COINBASE_MATURITY-1; pindex = pindex->pprev)

        if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile)

            return error("ConnectInputs() : tried to spend coinbase at depth %d", nBestHeight - pindex->nHeight);

校验签名信息并确认交易未被花费

// Verify signature

if (!VerifySignature(txPrev, *this, i))

    return error("ConnectInputs() : %s VerifySignature failed", GetHash().ToString().substr(0,6).c_str());



// Check for conflicts

if (!txindex.vSpent[prevout.n].IsNull())

    return fMiner ? false : error("ConnectInputs() : %s prev tx already used at %s", GetHash().ToString().substr(0,6).c_str(), txindex.vSpent[prevout.n].ToString().c_str());



// Mark outpoints as spent

txindex.vSpent[prevout.n] = posThisTx;

更新交易信息

if (fBlock)

    txdb.UpdateTxIndex(prevout.hash, txindex);

else if (fMiner)

    mapTestPool[prevout.hash] = txindex;



nValueIn += txPrev.vout[prevout.n].nValue;

轮询交易结束,计算交易手续费,且不小于最低手续费

int64 nTxFee = nValueIn - GetValueOut();

if (nTxFee < 0)

    return error("ConnectInputs() : %s nTxFee < 0", GetHash().ToString().substr(0,6).c_str());

if (nTxFee < nMinFee)

    return false;

nFees += nTxFee;

当前交易是创币交易

如果是创币交易并且当前是区块标志位fBlock为1则保存到交易数据库中,如果当前是矿工标志位fMiner为1则保存到mapTestPool中

if (fBlock)

{

    // Add transaction to disk index

    if (!txdb.AddTxIndex(*this, posThisTx, nHeight))

        return error("ConnectInputs() : AddTxPos failed");

}

else if (fMiner)

{

    // Add transaction to test pool

    mapTestPool[GetHash()] = CTxIndex(CDiskTxPos(1,1,1), vout.size());

}

 

没有更多推荐了,返回首页