|
|
|
@ -7,7 +7,6 @@
@@ -7,7 +7,6 @@
|
|
|
|
|
|
|
|
|
|
#include "uint256.h" |
|
|
|
|
#include "serialize.h" |
|
|
|
|
#include "util.h" |
|
|
|
|
#include "script.h" |
|
|
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
@ -42,15 +41,8 @@ public:
@@ -42,15 +41,8 @@ public:
|
|
|
|
|
return !(a == b); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string ToString() const |
|
|
|
|
{ |
|
|
|
|
return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10).c_str(), n); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void print() const |
|
|
|
|
{ |
|
|
|
|
printf("%s\n", ToString().c_str()); |
|
|
|
|
} |
|
|
|
|
std::string ToString() const; |
|
|
|
|
void print() const; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** An inpoint - a combination of a transaction and an index n into its vin */ |
|
|
|
@ -82,19 +74,8 @@ public:
@@ -82,19 +74,8 @@ public:
|
|
|
|
|
nSequence = std::numeric_limits<unsigned int>::max(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max()) |
|
|
|
|
{ |
|
|
|
|
prevout = prevoutIn; |
|
|
|
|
scriptSig = scriptSigIn; |
|
|
|
|
nSequence = nSequenceIn; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max()) |
|
|
|
|
{ |
|
|
|
|
prevout = COutPoint(hashPrevTx, nOut); |
|
|
|
|
scriptSig = scriptSigIn; |
|
|
|
|
nSequence = nSequenceIn; |
|
|
|
|
} |
|
|
|
|
explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max()); |
|
|
|
|
CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max()); |
|
|
|
|
|
|
|
|
|
IMPLEMENT_SERIALIZE |
|
|
|
|
( |
|
|
|
@ -120,25 +101,8 @@ public:
@@ -120,25 +101,8 @@ public:
|
|
|
|
|
return !(a == b); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string ToString() const |
|
|
|
|
{ |
|
|
|
|
std::string str; |
|
|
|
|
str += "CTxIn("; |
|
|
|
|
str += prevout.ToString(); |
|
|
|
|
if (prevout.IsNull()) |
|
|
|
|
str += strprintf(", coinbase %s", HexStr(scriptSig).c_str()); |
|
|
|
|
else |
|
|
|
|
str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str()); |
|
|
|
|
if (nSequence != std::numeric_limits<unsigned int>::max()) |
|
|
|
|
str += strprintf(", nSequence=%u", nSequence); |
|
|
|
|
str += ")"; |
|
|
|
|
return str; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void print() const |
|
|
|
|
{ |
|
|
|
|
printf("%s\n", ToString().c_str()); |
|
|
|
|
} |
|
|
|
|
std::string ToString() const; |
|
|
|
|
void print() const; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -158,11 +122,7 @@ public:
@@ -158,11 +122,7 @@ public:
|
|
|
|
|
SetNull(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CTxOut(int64 nValueIn, CScript scriptPubKeyIn) |
|
|
|
|
{ |
|
|
|
|
nValue = nValueIn; |
|
|
|
|
scriptPubKey = scriptPubKeyIn; |
|
|
|
|
} |
|
|
|
|
CTxOut(int64 nValueIn, CScript scriptPubKeyIn); |
|
|
|
|
|
|
|
|
|
IMPLEMENT_SERIALIZE |
|
|
|
|
( |
|
|
|
@ -181,10 +141,7 @@ public:
@@ -181,10 +141,7 @@ public:
|
|
|
|
|
return (nValue == -1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint256 GetHash() const |
|
|
|
|
{ |
|
|
|
|
return SerializeHash(*this); |
|
|
|
|
} |
|
|
|
|
uint256 GetHash() const; |
|
|
|
|
|
|
|
|
|
bool IsDust(int64 nMinRelayTxFee) const |
|
|
|
|
{ |
|
|
|
@ -210,17 +167,8 @@ public:
@@ -210,17 +167,8 @@ public:
|
|
|
|
|
return !(a == b); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string ToString() const |
|
|
|
|
{ |
|
|
|
|
if (scriptPubKey.size() < 6) |
|
|
|
|
return "CTxOut(error)"; |
|
|
|
|
return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30).c_str()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void print() const |
|
|
|
|
{ |
|
|
|
|
printf("%s\n", ToString().c_str()); |
|
|
|
|
} |
|
|
|
|
std::string ToString() const; |
|
|
|
|
void print() const; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -265,39 +213,8 @@ public:
@@ -265,39 +213,8 @@ public:
|
|
|
|
|
return (vin.empty() && vout.empty()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint256 GetHash() const |
|
|
|
|
{ |
|
|
|
|
return SerializeHash(*this); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsNewerThan(const CTransaction& old) const |
|
|
|
|
{ |
|
|
|
|
if (vin.size() != old.vin.size()) |
|
|
|
|
return false; |
|
|
|
|
for (unsigned int i = 0; i < vin.size(); i++) |
|
|
|
|
if (vin[i].prevout != old.vin[i].prevout) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
bool fNewer = false; |
|
|
|
|
unsigned int nLowest = std::numeric_limits<unsigned int>::max(); |
|
|
|
|
for (unsigned int i = 0; i < vin.size(); i++) |
|
|
|
|
{ |
|
|
|
|
if (vin[i].nSequence != old.vin[i].nSequence) |
|
|
|
|
{ |
|
|
|
|
if (vin[i].nSequence <= nLowest) |
|
|
|
|
{ |
|
|
|
|
fNewer = false; |
|
|
|
|
nLowest = vin[i].nSequence; |
|
|
|
|
} |
|
|
|
|
if (old.vin[i].nSequence < nLowest) |
|
|
|
|
{ |
|
|
|
|
fNewer = true; |
|
|
|
|
nLowest = old.vin[i].nSequence; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return fNewer; |
|
|
|
|
} |
|
|
|
|
uint256 GetHash() const; |
|
|
|
|
bool IsNewerThan(const CTransaction& old) const; |
|
|
|
|
|
|
|
|
|
bool IsCoinBase() const |
|
|
|
|
{ |
|
|
|
@ -318,26 +235,8 @@ public:
@@ -318,26 +235,8 @@ public:
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string ToString() const |
|
|
|
|
{ |
|
|
|
|
std::string str; |
|
|
|
|
str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%"PRIszu", vout.size=%"PRIszu", nLockTime=%u)\n", |
|
|
|
|
GetHash().ToString().substr(0,10).c_str(), |
|
|
|
|
nVersion, |
|
|
|
|
vin.size(), |
|
|
|
|
vout.size(), |
|
|
|
|
nLockTime); |
|
|
|
|
for (unsigned int i = 0; i < vin.size(); i++) |
|
|
|
|
str += " " + vin[i].ToString() + "\n"; |
|
|
|
|
for (unsigned int i = 0; i < vout.size(); i++) |
|
|
|
|
str += " " + vout[i].ToString() + "\n"; |
|
|
|
|
return str; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void print() const |
|
|
|
|
{ |
|
|
|
|
printf("%s", ToString().c_str()); |
|
|
|
|
} |
|
|
|
|
std::string ToString() const; |
|
|
|
|
void print() const; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** wrapper for CTxOut that provides a more compact serialization */ |
|
|
|
@ -521,26 +420,7 @@ public:
@@ -521,26 +420,7 @@ public:
|
|
|
|
|
return !(a == b); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// calculate number of bytes for the bitmask, and its number of non-zero bytes
|
|
|
|
|
// each bit in the bitmask represents the availability of one output, but the
|
|
|
|
|
// availabilities of the first two outputs are encoded separately
|
|
|
|
|
void CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const { |
|
|
|
|
unsigned int nLastUsedByte = 0; |
|
|
|
|
for (unsigned int b = 0; 2+b*8 < vout.size(); b++) { |
|
|
|
|
bool fZero = true; |
|
|
|
|
for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) { |
|
|
|
|
if (!vout[2+b*8+i].IsNull()) { |
|
|
|
|
fZero = false; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!fZero) { |
|
|
|
|
nLastUsedByte = b + 1; |
|
|
|
|
nNonzeroBytes++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
nBytes += nLastUsedByte; |
|
|
|
|
} |
|
|
|
|
void CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const; |
|
|
|
|
|
|
|
|
|
bool IsCoinBase() const { |
|
|
|
|
return fCoinBase; |
|
|
|
@ -633,28 +513,10 @@ public:
@@ -633,28 +513,10 @@ public:
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// mark an outpoint spent, and construct undo information
|
|
|
|
|
bool Spend(const COutPoint &out, CTxInUndo &undo) { |
|
|
|
|
if (out.n >= vout.size()) |
|
|
|
|
return false; |
|
|
|
|
if (vout[out.n].IsNull()) |
|
|
|
|
return false; |
|
|
|
|
undo = CTxInUndo(vout[out.n]); |
|
|
|
|
vout[out.n].SetNull(); |
|
|
|
|
Cleanup(); |
|
|
|
|
if (vout.size() == 0) { |
|
|
|
|
undo.nHeight = nHeight; |
|
|
|
|
undo.fCoinBase = fCoinBase; |
|
|
|
|
undo.nVersion = this->nVersion; |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
bool Spend(const COutPoint &out, CTxInUndo &undo); |
|
|
|
|
|
|
|
|
|
// mark a vout spent
|
|
|
|
|
bool Spend(int nPos) { |
|
|
|
|
CTxInUndo undo; |
|
|
|
|
COutPoint out(0, nPos); |
|
|
|
|
return Spend(out, undo); |
|
|
|
|
} |
|
|
|
|
bool Spend(int nPos); |
|
|
|
|
|
|
|
|
|
// check whether a particular output is still available
|
|
|
|
|
bool IsAvailable(unsigned int nPos) const { |
|
|
|
@ -722,10 +584,7 @@ public:
@@ -722,10 +584,7 @@ public:
|
|
|
|
|
return (nBits == 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint256 GetHash() const |
|
|
|
|
{ |
|
|
|
|
return Hash(BEGIN(nVersion), END(nNonce)); |
|
|
|
|
} |
|
|
|
|
uint256 GetHash() const; |
|
|
|
|
|
|
|
|
|
int64 GetBlockTime() const |
|
|
|
|
{ |
|
|
|
@ -779,24 +638,7 @@ public:
@@ -779,24 +638,7 @@ public:
|
|
|
|
|
return block; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint256 BuildMerkleTree() const |
|
|
|
|
{ |
|
|
|
|
vMerkleTree.clear(); |
|
|
|
|
BOOST_FOREACH(const CTransaction& tx, vtx) |
|
|
|
|
vMerkleTree.push_back(tx.GetHash()); |
|
|
|
|
int j = 0; |
|
|
|
|
for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) |
|
|
|
|
{ |
|
|
|
|
for (int i = 0; i < nSize; i += 2) |
|
|
|
|
{ |
|
|
|
|
int i2 = std::min(i+1, nSize-1); |
|
|
|
|
vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]), |
|
|
|
|
BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2]))); |
|
|
|
|
} |
|
|
|
|
j += nSize; |
|
|
|
|
} |
|
|
|
|
return (vMerkleTree.empty() ? 0 : vMerkleTree.back()); |
|
|
|
|
} |
|
|
|
|
uint256 BuildMerkleTree() const; |
|
|
|
|
|
|
|
|
|
const uint256 &GetTxHash(unsigned int nIndex) const { |
|
|
|
|
assert(vMerkleTree.size() > 0); // BuildMerkleTree must have been called first
|
|
|
|
@ -804,56 +646,9 @@ public:
@@ -804,56 +646,9 @@ public:
|
|
|
|
|
return vMerkleTree[nIndex]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::vector<uint256> GetMerkleBranch(int nIndex) const |
|
|
|
|
{ |
|
|
|
|
if (vMerkleTree.empty()) |
|
|
|
|
BuildMerkleTree(); |
|
|
|
|
std::vector<uint256> vMerkleBranch; |
|
|
|
|
int j = 0; |
|
|
|
|
for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) |
|
|
|
|
{ |
|
|
|
|
int i = std::min(nIndex^1, nSize-1); |
|
|
|
|
vMerkleBranch.push_back(vMerkleTree[j+i]); |
|
|
|
|
nIndex >>= 1; |
|
|
|
|
j += nSize; |
|
|
|
|
} |
|
|
|
|
return vMerkleBranch; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex) |
|
|
|
|
{ |
|
|
|
|
if (nIndex == -1) |
|
|
|
|
return 0; |
|
|
|
|
BOOST_FOREACH(const uint256& otherside, vMerkleBranch) |
|
|
|
|
{ |
|
|
|
|
if (nIndex & 1) |
|
|
|
|
hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash)); |
|
|
|
|
else |
|
|
|
|
hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside)); |
|
|
|
|
nIndex >>= 1; |
|
|
|
|
} |
|
|
|
|
return hash; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void print() const |
|
|
|
|
{ |
|
|
|
|
printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n", |
|
|
|
|
GetHash().ToString().c_str(), |
|
|
|
|
nVersion, |
|
|
|
|
hashPrevBlock.ToString().c_str(), |
|
|
|
|
hashMerkleRoot.ToString().c_str(), |
|
|
|
|
nTime, nBits, nNonce, |
|
|
|
|
vtx.size()); |
|
|
|
|
for (unsigned int i = 0; i < vtx.size(); i++) |
|
|
|
|
{ |
|
|
|
|
printf(" "); |
|
|
|
|
vtx[i].print(); |
|
|
|
|
} |
|
|
|
|
printf(" vMerkleTree: "); |
|
|
|
|
for (unsigned int i = 0; i < vMerkleTree.size(); i++) |
|
|
|
|
printf("%s ", vMerkleTree[i].ToString().c_str()); |
|
|
|
|
printf("\n"); |
|
|
|
|
} |
|
|
|
|
std::vector<uint256> GetMerkleBranch(int nIndex) const; |
|
|
|
|
static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex); |
|
|
|
|
void print() const; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|