0x00 摘要
交易(transaction)是比特币甚至所有区块链中最核心的数据结构之一,可以说其他所有的模块都是为交易服务的,包括交易的产生、广播、共识、存储等等,所以我们首先从交易出发,然后逐步延伸到其他的部分。
0x01 COutPoint
class COutPoint
{
public:
uint256 hash;
uint32_t n;
COutPoint() { SetNull(); }
COutPoint(uint256 hashIn, uint32_t nIn) { hash = hashIn; n = nIn; }
ADD_SERIALIZE_METHODS;
template <
typename Stream,
typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(hash);
READWRITE(n);
}
void SetNull() { hash.SetNull(); n = (uint32_t) -
1; }
bool IsNull()
const {
return (hash.IsNull() && n == (uint32_t) -
1); }
friend bool operator<(
const COutPoint& a,
const COutPoint& b)
{
int cmp = a.hash.Compare(b.hash);
return cmp <
0 || (cmp ==
0 && a.n < b.n);
}
friend bool operator==(
const COutPoint& a,
const COutPoint& b)
{
return (a.hash == b.hash && a.n == b.n);
}
friend bool operator!=(
const COutPoint& a,
const COutPoint& b)
{
return !(a == b);
}
std::
string ToString()
const;
};
0x02 CTxIn
class CTxIn
{
public:
COutPoint prevout;
CScript scriptSig;
uint32_t nSequence;
CScriptWitness scriptWitness;
static const uint32_t SEQUENCE_FINAL =
0xffffffff;
static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (
1 <<
31);
static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (
1 <<
22);
static const uint32_t SEQUENCE_LOCKTIME_MASK =
0x0000ffff;
static const int SEQUENCE_LOCKTIME_GRANULARITY =
9;
CTxIn()
{
nSequence = SEQUENCE_FINAL;
}
explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL);
CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL);
ADD_SERIALIZE_METHODS;
template <
typename Stream,
typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(prevout);
READWRITE(*(CScriptBase*)(&scriptSig));
READWRITE(nSequence);
}
friend bool operator==(
const CTxIn& a,
const CTxIn& b)
{
return (a.prevout == b.prevout &&
a.scriptSig == b.scriptSig &&
a.nSequence == b.nSequence);
}
friend bool operator!=(
const CTxIn& a,
const CTxIn& b)
{
return !(a == b);
}
std::
string ToString()
const;
};
0x03 CTxOut
class CTxOut
{
public:
CAmount nValue;
CScript scriptPubKey;
CTxOut()
{
SetNull();
}
CTxOut(
const CAmount& nValueIn, CScript scriptPubKeyIn);
ADD_SERIALIZE_METHODS;
template <
typename Stream,
typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(nValue);
READWRITE(*(CScriptBase*)(&scriptPubKey));
}
void SetNull()
{
nValue = -
1;
scriptPubKey.clear();
}
bool IsNull()
const
{
return (nValue == -
1);
}
CAmount GetDustThreshold(
const CFeeRate &minRelayTxFee)
const
{
if (scriptPubKey.IsUnspendable())
return 0;
size_t nSize = GetSerializeSize(*
this, SER_DISK,
0);
int witnessversion =
0;
std::
vector<unsigned char> witnessprogram;
if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
nSize += (
32 +
4 +
1 + (
107 / WITNESS_SCALE_FACTOR) +
4);
}
else {
nSize += (
32 +
4 +
1 +
107 +
4);
}
return 3 * minRelayTxFee.GetFee(nSize);
}
bool IsDust(
const CFeeRate &minRelayTxFee)
const
{
return (nValue < GetDustThreshold(minRelayTxFee));
}
friend bool operator==(
const CTxOut& a,
const CTxOut& b)
{
return (a.nValue == b.nValue &&
a.scriptPubKey == b.scriptPubKey);
}
friend bool operator!=(
const CTxOut& a,
const CTxOut& b)
{
return !(a == b);
}
std::
string ToString()
const;
};
0x04 CTransaction
/** The basic transaction that is broadcasted on the network and contained in blocks.
* A transaction can contain multiple inputs and outputs.
* 下面就是在网络中广播然后被打包进区块的最基本的交易的结构,一个交易可能包含多个交易输入和输出。
*/
class CTransaction
{
public:
// Default transaction version. 默认交易版本
static const int32_t CURRENT_VERSION=
2;
static const int32_t MAX_STANDARD_VERSION=
2;
/** 下面这些变量都被定义为常量类型,从而避免无意识的修改了交易而没有更新缓存的hash值;
* 但还是可以通过重新构造一个交易然后赋值给当前交易来进行修改,这样就更新了交易的所有内容
*/
const int32_t nVersion;
const std::vector<CTxIn> vin;
const std::vector<CTxOut> vout;
const uint32_t nLockTime;
private:
/** Memory only. */
const uint256 hash;
uint256 ComputeHash()
const;
public:
/** Construct a CTransaction that qualifies as
IsNull() */
CTransaction();
/** Convert a CMutableTransaction into a CTransaction. */
CTransaction(
const CMutableTransaction &tx);
CTransaction(CMutableTransaction &&tx);
template <typename Stream>
inline
void Serialize(Stream& s)
const {
SerializeTransaction(*
this, s);
}
/** This deserializing constructor is provided instead of an Unserialize method.
* Unserialize is not possible, since it would require overwriting const fields. */
template <typename Stream>
CTransaction(deserialize_type, Stream& s) : CTransaction(CMutableTransaction(deserialize, s)) {}
bool IsNull()
const {
return vin.empty() && vout.empty();
}
const uint256& GetHash()
const {
return hash;
}
uint256 GetWitnessHash()
const;
CAmount GetValueOut()
const;
/**
* Get the total transaction size in bytes, including witness data.
* "Total Size" defined in BIP141 and BIP144.
* @return Total transaction size in bytes
*/
unsigned
int GetTotalSize()
const;
bool IsCoinBase()
const
{
return (vin.size() ==
1 && vin[
0].prevout.IsNull());
}
friend bool operator==(
const CTransaction& a,
const CTransaction& b)
{
return a.hash == b.hash;
}
friend bool operator!=(
const CTransaction& a,
const CTransaction& b)
{
return a.hash != b.hash;
}
std::string ToString()
const;
bool HasWitness()
const
{
for (size_t i =
0; i < vin.size(); i++) {
if (!vin[i].scriptWitness.IsNull()) {
return true;
}
}
return false;
}
};
除了这个结构以外,还定义了一个CMutableTransaction其中的变量内容和CTransaction相同,但是都是可以直接修改的,但是最后广播和网络中传输的类型都是CTransaction。