Changeset View
Changeset View
Standalone View
Standalone View
src/primitives/transaction.h
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#ifndef BITCOIN_PRIMITIVES_TRANSACTION_H | #ifndef BITCOIN_PRIMITIVES_TRANSACTION_H | ||||
#define BITCOIN_PRIMITIVES_TRANSACTION_H | #define BITCOIN_PRIMITIVES_TRANSACTION_H | ||||
#include "amount.h" | #include "amount.h" | ||||
#include "script/script.h" | #include "script/script.h" | ||||
#include "serialize.h" | #include "serialize.h" | ||||
#include "uint256.h" | #include "uint256.h" | ||||
static const int SERIALIZE_TRANSACTION = 0x00; | static const int SERIALIZE_TRANSACTION = 0x00; | ||||
/** A TxHash is the double sha256 hash of the full transaction data */ | |||||
struct TxHash : public uint256 { | |||||
TxHash() {} | |||||
// TODO: make this explicit once the full refactoring txid->txhash is done | |||||
TxHash(const uint256 &b) : uint256(b) {} | |||||
}; | |||||
/** An outpoint - a combination of a transaction hash and an index n into its | /** An outpoint - a combination of a transaction hash and an index n into its | ||||
* vout */ | * vout */ | ||||
class COutPoint { | class COutPoint { | ||||
public: | public: | ||||
uint256 hash; | TxHash hash; | ||||
deadalnix: It is not correct to use the TxHash in the outpoint. It should be an TxId , to identify the… | |||||
tomtomtom7AuthorUnsubmitted Not Done Inline ActionsYes. But see comment: It is not going to be easy to do the full refactoring carefully. There is quite a risk of leaving txid's that should be txhashes. Hence I propose, to first fully refactor txid to txhash. (which corresponds to the current rules). Afterwards change txhash to txid for Outpoints. This is my assessment from initial investigation for the full refactor at D614. Is that acceptable? tomtomtom7: Yes. But see comment: It is not going to be easy to do the full refactoring carefully. There is… | |||||
uint32_t n; | uint32_t n; | ||||
COutPoint() { SetNull(); } | COutPoint() { SetNull(); } | ||||
COutPoint(uint256 hashIn, uint32_t nIn) { | COutPoint(TxHash hashIn, uint32_t nIn) { | ||||
hash = hashIn; | hash = hashIn; | ||||
n = nIn; | n = nIn; | ||||
} | } | ||||
ADD_SERIALIZE_METHODS; | ADD_SERIALIZE_METHODS; | ||||
template <typename Stream, typename Operation> | template <typename Stream, typename Operation> | ||||
inline void SerializationOp(Stream &s, Operation ser_action) { | inline void SerializationOp(Stream &s, Operation ser_action) { | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | public: | ||||
* multiplying by 512 = 2^9, or equivalently shifting up by | * multiplying by 512 = 2^9, or equivalently shifting up by | ||||
* 9 bits. */ | * 9 bits. */ | ||||
static const int SEQUENCE_LOCKTIME_GRANULARITY = 9; | static const int SEQUENCE_LOCKTIME_GRANULARITY = 9; | ||||
CTxIn() { nSequence = SEQUENCE_FINAL; } | CTxIn() { nSequence = SEQUENCE_FINAL; } | ||||
explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn = CScript(), | explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn = CScript(), | ||||
uint32_t nSequenceIn = SEQUENCE_FINAL); | uint32_t nSequenceIn = SEQUENCE_FINAL); | ||||
CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn = CScript(), | CTxIn(TxHash hashPrevTx, uint32_t nOut, CScript scriptSigIn = CScript(), | ||||
uint32_t nSequenceIn = SEQUENCE_FINAL); | uint32_t nSequenceIn = SEQUENCE_FINAL); | ||||
ADD_SERIALIZE_METHODS; | ADD_SERIALIZE_METHODS; | ||||
template <typename Stream, typename Operation> | template <typename Stream, typename Operation> | ||||
inline void SerializationOp(Stream &s, Operation ser_action) { | inline void SerializationOp(Stream &s, Operation ser_action) { | ||||
READWRITE(prevout); | READWRITE(prevout); | ||||
READWRITE(*(CScriptBase *)(&scriptSig)); | READWRITE(*(CScriptBase *)(&scriptSig)); | ||||
▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | public: | ||||
// structure, including the hash. | // structure, including the hash. | ||||
const int32_t nVersion; | const int32_t nVersion; | ||||
const std::vector<CTxIn> vin; | const std::vector<CTxIn> vin; | ||||
const std::vector<CTxOut> vout; | const std::vector<CTxOut> vout; | ||||
const uint32_t nLockTime; | const uint32_t nLockTime; | ||||
private: | private: | ||||
/** Memory only. */ | /** Memory only. */ | ||||
const uint256 hash; | const TxHash hash; | ||||
uint256 ComputeHash() const; | TxHash ComputeHash() const; | ||||
public: | public: | ||||
/** Construct a CTransaction that qualifies as IsNull() */ | /** Construct a CTransaction that qualifies as IsNull() */ | ||||
CTransaction(); | CTransaction(); | ||||
/** Convert a CMutableTransaction into a CTransaction. */ | /** Convert a CMutableTransaction into a CTransaction. */ | ||||
CTransaction(const CMutableTransaction &tx); | CTransaction(const CMutableTransaction &tx); | ||||
CTransaction(CMutableTransaction &&tx); | CTransaction(CMutableTransaction &&tx); | ||||
template <typename Stream> inline void Serialize(Stream &s) const { | template <typename Stream> inline void Serialize(Stream &s) const { | ||||
SerializeTransaction(*this, s); | SerializeTransaction(*this, s); | ||||
} | } | ||||
/** This deserializing constructor is provided instead of an Unserialize | /** This deserializing constructor is provided instead of an Unserialize | ||||
* method. Unserialize is not possible, since it would require overwriting | * method. Unserialize is not possible, since it would require overwriting | ||||
* const fields. */ | * const fields. */ | ||||
template <typename Stream> | template <typename Stream> | ||||
CTransaction(deserialize_type, Stream &s) | CTransaction(deserialize_type, Stream &s) | ||||
: CTransaction(CMutableTransaction(deserialize, s)) {} | : CTransaction(CMutableTransaction(deserialize, s)) {} | ||||
bool IsNull() const { return vin.empty() && vout.empty(); } | bool IsNull() const { return vin.empty() && vout.empty(); } | ||||
const uint256 &GetId() const { return hash; } | const TxHash &GetId() const { return hash; } | ||||
// Compute a hash that includes both transaction and witness data | // Compute a hash that includes both transaction and witness data | ||||
uint256 GetHash() const; | TxHash GetHash() const; | ||||
// Return sum of txouts. | // Return sum of txouts. | ||||
Amount GetValueOut() const; | Amount GetValueOut() const; | ||||
// GetValueIn() is a method on CCoinsViewCache, because | // GetValueIn() is a method on CCoinsViewCache, because | ||||
// inputs must be known to compute value in. | // inputs must be known to compute value in. | ||||
// Compute priority, given priority of inputs and (optionally) tx size | // Compute priority, given priority of inputs and (optionally) tx size | ||||
double ComputePriority(double dPriorityInputs, | double ComputePriority(double dPriorityInputs, | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | struct CMutableTransaction { | ||||
template <typename Stream> | template <typename Stream> | ||||
CMutableTransaction(deserialize_type, Stream &s) { | CMutableTransaction(deserialize_type, Stream &s) { | ||||
Unserialize(s); | Unserialize(s); | ||||
} | } | ||||
/** Compute the hash of this CMutableTransaction. This is computed on the | /** Compute the hash of this CMutableTransaction. This is computed on the | ||||
* fly, as opposed to GetId() in CTransaction, which uses a cached result. | * fly, as opposed to GetId() in CTransaction, which uses a cached result. | ||||
*/ | */ | ||||
uint256 GetId() const; | TxHash GetId() const; | ||||
friend bool operator==(const CMutableTransaction &a, | friend bool operator==(const CMutableTransaction &a, | ||||
const CMutableTransaction &b) { | const CMutableTransaction &b) { | ||||
return a.GetId() == b.GetId(); | return a.GetId() == b.GetId(); | ||||
} | } | ||||
}; | }; | ||||
typedef std::shared_ptr<const CTransaction> CTransactionRef; | typedef std::shared_ptr<const CTransaction> CTransactionRef; | ||||
Show All 26 Lines |
It is not correct to use the TxHash in the outpoint. It should be an TxId , to identify the transaction we are spending from. The whole problem we are trying to solve here is that the TxHash is mutable. We should have TxId and TxHash to be the same thing at first, but if we ensure that the right one is used at the right place with the help of the type system, then it'll be easy to differentiate them in the future.