Merge pull request #4778
This commit is contained in:
commit
135a43df7b
5 changed files with 162 additions and 163 deletions
99
src/main.cpp
99
src/main.cpp
|
@ -732,53 +732,6 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
|
||||||
return nSigOps;
|
return nSigOps;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
|
|
||||||
{
|
|
||||||
AssertLockHeld(cs_main);
|
|
||||||
CBlock blockTmp;
|
|
||||||
|
|
||||||
if (pblock == NULL) {
|
|
||||||
CCoins coins;
|
|
||||||
if (pcoinsTip->GetCoins(GetHash(), coins)) {
|
|
||||||
CBlockIndex *pindex = chainActive[coins.nHeight];
|
|
||||||
if (pindex) {
|
|
||||||
if (!ReadBlockFromDisk(blockTmp, pindex))
|
|
||||||
return 0;
|
|
||||||
pblock = &blockTmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pblock) {
|
|
||||||
// Update the tx's hashBlock
|
|
||||||
hashBlock = pblock->GetHash();
|
|
||||||
|
|
||||||
// Locate the transaction
|
|
||||||
for (nIndex = 0; nIndex < (int)pblock->vtx.size(); nIndex++)
|
|
||||||
if (pblock->vtx[nIndex] == *(CTransaction*)this)
|
|
||||||
break;
|
|
||||||
if (nIndex == (int)pblock->vtx.size())
|
|
||||||
{
|
|
||||||
vMerkleBranch.clear();
|
|
||||||
nIndex = -1;
|
|
||||||
LogPrintf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in merkle branch
|
|
||||||
vMerkleBranch = pblock->GetMerkleBranch(nIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is the tx in a block that's in the main chain
|
|
||||||
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
|
|
||||||
if (mi == mapBlockIndex.end())
|
|
||||||
return 0;
|
|
||||||
CBlockIndex* pindex = (*mi).second;
|
|
||||||
if (!pindex || !chainActive.Contains(pindex))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return chainActive.Height() - pindex->nHeight + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1028,58 +981,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const
|
|
||||||
{
|
|
||||||
if (hashBlock == 0 || nIndex == -1)
|
|
||||||
return 0;
|
|
||||||
AssertLockHeld(cs_main);
|
|
||||||
|
|
||||||
// Find the block it claims to be in
|
|
||||||
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
|
|
||||||
if (mi == mapBlockIndex.end())
|
|
||||||
return 0;
|
|
||||||
CBlockIndex* pindex = (*mi).second;
|
|
||||||
if (!pindex || !chainActive.Contains(pindex))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Make sure the merkle branch connects to this block
|
|
||||||
if (!fMerkleVerified)
|
|
||||||
{
|
|
||||||
if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
|
|
||||||
return 0;
|
|
||||||
fMerkleVerified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pindexRet = pindex;
|
|
||||||
return chainActive.Height() - pindex->nHeight + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
|
|
||||||
{
|
|
||||||
AssertLockHeld(cs_main);
|
|
||||||
int nResult = GetDepthInMainChainINTERNAL(pindexRet);
|
|
||||||
if (nResult == 0 && !mempool.exists(GetHash()))
|
|
||||||
return -1; // Not in chain, not in mempool
|
|
||||||
|
|
||||||
return nResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CMerkleTx::GetBlocksToMaturity() const
|
|
||||||
{
|
|
||||||
if (!IsCoinBase())
|
|
||||||
return 0;
|
|
||||||
return max(0, (COINBASE_MATURITY+1) - GetDepthInMainChain());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectInsaneFee)
|
|
||||||
{
|
|
||||||
CValidationState state;
|
|
||||||
return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectInsaneFee);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock
|
// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock
|
||||||
bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
|
bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
|
||||||
{
|
{
|
||||||
|
|
60
src/main.h
60
src/main.h
|
@ -344,66 +344,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A transaction with a merkle branch linking it to the block chain. */
|
|
||||||
class CMerkleTx : public CTransaction
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
int GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
uint256 hashBlock;
|
|
||||||
std::vector<uint256> vMerkleBranch;
|
|
||||||
int nIndex;
|
|
||||||
|
|
||||||
// memory only
|
|
||||||
mutable bool fMerkleVerified;
|
|
||||||
|
|
||||||
|
|
||||||
CMerkleTx()
|
|
||||||
{
|
|
||||||
Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
|
|
||||||
{
|
|
||||||
Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Init()
|
|
||||||
{
|
|
||||||
hashBlock = 0;
|
|
||||||
nIndex = -1;
|
|
||||||
fMerkleVerified = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
IMPLEMENT_SERIALIZE
|
|
||||||
(
|
|
||||||
nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
|
|
||||||
nVersion = this->nVersion;
|
|
||||||
READWRITE(hashBlock);
|
|
||||||
READWRITE(vMerkleBranch);
|
|
||||||
READWRITE(nIndex);
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
int SetMerkleBranch(const CBlock* pblock=NULL);
|
|
||||||
|
|
||||||
// Return depth of transaction in blockchain:
|
|
||||||
// -1 : not in blockchain, and not in memory pool (conflicted transaction)
|
|
||||||
// 0 : in memory pool, waiting to be included in a block
|
|
||||||
// >=1 : this many blocks deep in the main chain
|
|
||||||
int GetDepthInMainChain(CBlockIndex* &pindexRet) const;
|
|
||||||
int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
|
|
||||||
bool IsInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; }
|
|
||||||
int GetBlocksToMaturity() const;
|
|
||||||
bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectInsaneFee=true);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Data structure that represents a partial merkle tree.
|
/** Data structure that represents a partial merkle tree.
|
||||||
*
|
*
|
||||||
* It respresents a subset of the txid's of a known block, in a way that
|
* It respresents a subset of the txid's of a known block, in a way that
|
||||||
|
|
|
@ -54,9 +54,11 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
|
||||||
{
|
{
|
||||||
Object result;
|
Object result;
|
||||||
result.push_back(Pair("hash", block.GetHash().GetHex()));
|
result.push_back(Pair("hash", block.GetHash().GetHex()));
|
||||||
CMerkleTx txGen(block.vtx[0]);
|
int confirmations = -1;
|
||||||
txGen.SetMerkleBranch(&block);
|
// Only report confirmations if the block is on the main chain
|
||||||
result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain()));
|
if (chainActive.Contains(blockindex))
|
||||||
|
confirmations = chainActive.Height() - blockindex->nHeight + 1;
|
||||||
|
result.push_back(Pair("confirmations", confirmations));
|
||||||
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
|
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
|
||||||
result.push_back(Pair("height", blockindex->nHeight));
|
result.push_back(Pair("height", blockindex->nHeight));
|
||||||
result.push_back(Pair("version", block.nVersion));
|
result.push_back(Pair("version", block.nVersion));
|
||||||
|
@ -242,7 +244,7 @@ Value getblock(const Array& params, bool fHelp)
|
||||||
"\nResult (for verbose = true):\n"
|
"\nResult (for verbose = true):\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
|
" \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
|
||||||
" \"confirmations\" : n, (numeric) The number of confirmations\n"
|
" \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
|
||||||
" \"size\" : n, (numeric) The block size\n"
|
" \"size\" : n, (numeric) The block size\n"
|
||||||
" \"height\" : n, (numeric) The block height or index\n"
|
" \"height\" : n, (numeric) The block height or index\n"
|
||||||
" \"version\" : n, (numeric) The block version\n"
|
" \"version\" : n, (numeric) The block version\n"
|
||||||
|
|
|
@ -2194,3 +2194,102 @@ CWalletKey::CWalletKey(int64_t nExpires)
|
||||||
nTimeCreated = (nExpires ? GetTime() : 0);
|
nTimeCreated = (nExpires ? GetTime() : 0);
|
||||||
nTimeExpires = nExpires;
|
nTimeExpires = nExpires;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
|
CBlock blockTmp;
|
||||||
|
|
||||||
|
if (pblock == NULL) {
|
||||||
|
CCoins coins;
|
||||||
|
if (pcoinsTip->GetCoins(GetHash(), coins)) {
|
||||||
|
CBlockIndex *pindex = chainActive[coins.nHeight];
|
||||||
|
if (pindex) {
|
||||||
|
if (!ReadBlockFromDisk(blockTmp, pindex))
|
||||||
|
return 0;
|
||||||
|
pblock = &blockTmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pblock) {
|
||||||
|
// Update the tx's hashBlock
|
||||||
|
hashBlock = pblock->GetHash();
|
||||||
|
|
||||||
|
// Locate the transaction
|
||||||
|
for (nIndex = 0; nIndex < (int)pblock->vtx.size(); nIndex++)
|
||||||
|
if (pblock->vtx[nIndex] == *(CTransaction*)this)
|
||||||
|
break;
|
||||||
|
if (nIndex == (int)pblock->vtx.size())
|
||||||
|
{
|
||||||
|
vMerkleBranch.clear();
|
||||||
|
nIndex = -1;
|
||||||
|
LogPrintf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in merkle branch
|
||||||
|
vMerkleBranch = pblock->GetMerkleBranch(nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the tx in a block that's in the main chain
|
||||||
|
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
|
||||||
|
if (mi == mapBlockIndex.end())
|
||||||
|
return 0;
|
||||||
|
CBlockIndex* pindex = (*mi).second;
|
||||||
|
if (!pindex || !chainActive.Contains(pindex))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return chainActive.Height() - pindex->nHeight + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const
|
||||||
|
{
|
||||||
|
if (hashBlock == 0 || nIndex == -1)
|
||||||
|
return 0;
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
|
|
||||||
|
// Find the block it claims to be in
|
||||||
|
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
|
||||||
|
if (mi == mapBlockIndex.end())
|
||||||
|
return 0;
|
||||||
|
CBlockIndex* pindex = (*mi).second;
|
||||||
|
if (!pindex || !chainActive.Contains(pindex))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Make sure the merkle branch connects to this block
|
||||||
|
if (!fMerkleVerified)
|
||||||
|
{
|
||||||
|
if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
|
||||||
|
return 0;
|
||||||
|
fMerkleVerified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pindexRet = pindex;
|
||||||
|
return chainActive.Height() - pindex->nHeight + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
|
int nResult = GetDepthInMainChainINTERNAL(pindexRet);
|
||||||
|
if (nResult == 0 && !mempool.exists(GetHash()))
|
||||||
|
return -1; // Not in chain, not in mempool
|
||||||
|
|
||||||
|
return nResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CMerkleTx::GetBlocksToMaturity() const
|
||||||
|
{
|
||||||
|
if (!IsCoinBase())
|
||||||
|
return 0;
|
||||||
|
return max(0, (COINBASE_MATURITY+1) - GetDepthInMainChain());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectInsaneFee)
|
||||||
|
{
|
||||||
|
CValidationState state;
|
||||||
|
return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectInsaneFee);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
57
src/wallet.h
57
src/wallet.h
|
@ -457,6 +457,63 @@ struct COutputEntry
|
||||||
int vout;
|
int vout;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** A transaction with a merkle branch linking it to the block chain. */
|
||||||
|
class CMerkleTx : public CTransaction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint256 hashBlock;
|
||||||
|
std::vector<uint256> vMerkleBranch;
|
||||||
|
int nIndex;
|
||||||
|
|
||||||
|
// memory only
|
||||||
|
mutable bool fMerkleVerified;
|
||||||
|
|
||||||
|
|
||||||
|
CMerkleTx()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init()
|
||||||
|
{
|
||||||
|
hashBlock = 0;
|
||||||
|
nIndex = -1;
|
||||||
|
fMerkleVerified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IMPLEMENT_SERIALIZE
|
||||||
|
(
|
||||||
|
nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
|
||||||
|
nVersion = this->nVersion;
|
||||||
|
READWRITE(hashBlock);
|
||||||
|
READWRITE(vMerkleBranch);
|
||||||
|
READWRITE(nIndex);
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
int SetMerkleBranch(const CBlock* pblock=NULL);
|
||||||
|
|
||||||
|
// Return depth of transaction in blockchain:
|
||||||
|
// -1 : not in blockchain, and not in memory pool (conflicted transaction)
|
||||||
|
// 0 : in memory pool, waiting to be included in a block
|
||||||
|
// >=1 : this many blocks deep in the main chain
|
||||||
|
int GetDepthInMainChain(CBlockIndex* &pindexRet) const;
|
||||||
|
int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
|
||||||
|
bool IsInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; }
|
||||||
|
int GetBlocksToMaturity() const;
|
||||||
|
bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectInsaneFee=true);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** A transaction with a bunch of additional info that only the owner cares about.
|
/** A transaction with a bunch of additional info that only the owner cares about.
|
||||||
* It includes any unrecorded transactions needed to link it back to the block chain.
|
* It includes any unrecorded transactions needed to link it back to the block chain.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue