Merge branch 'beta' into mergemaster
# Conflicts: # src/main.cpp
This commit is contained in:
@@ -16,13 +16,12 @@ JSDescription::JSDescription(ZCJoinSplit& params,
|
||||
const boost::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
|
||||
CAmount vpub_old,
|
||||
CAmount vpub_new,
|
||||
bool computeProof) : vpub_old(vpub_old), vpub_new(vpub_new), anchor(anchor)
|
||||
bool computeProof,
|
||||
uint256 *esk // payment disclosure
|
||||
) : vpub_old(vpub_old), vpub_new(vpub_new), anchor(anchor)
|
||||
{
|
||||
boost::array<libzcash::Note, ZC_NUM_JS_OUTPUTS> notes;
|
||||
|
||||
if (computeProof) {
|
||||
params.loadProvingKey();
|
||||
}
|
||||
proof = params.prove(
|
||||
inputs,
|
||||
outputs,
|
||||
@@ -37,7 +36,8 @@ JSDescription::JSDescription(ZCJoinSplit& params,
|
||||
vpub_old,
|
||||
vpub_new,
|
||||
anchor,
|
||||
computeProof
|
||||
computeProof,
|
||||
esk // payment disclosure
|
||||
);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,9 @@ JSDescription JSDescription::Randomized(
|
||||
CAmount vpub_old,
|
||||
CAmount vpub_new,
|
||||
bool computeProof,
|
||||
std::function<int(int)> gen)
|
||||
uint256 *esk, // payment disclosure
|
||||
std::function<int(int)> gen
|
||||
)
|
||||
{
|
||||
// Randomize the order of the inputs and outputs
|
||||
inputMap = {0, 1};
|
||||
@@ -70,7 +72,9 @@ JSDescription JSDescription::Randomized(
|
||||
|
||||
return JSDescription(
|
||||
params, pubKeyHash, anchor, inputs, outputs,
|
||||
vpub_old, vpub_new, computeProof);
|
||||
vpub_old, vpub_new, computeProof,
|
||||
esk // payment disclosure
|
||||
);
|
||||
}
|
||||
|
||||
bool JSDescription::Verify(
|
||||
@@ -147,8 +151,9 @@ std::string CTxOut::ToString() const
|
||||
return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30));
|
||||
}
|
||||
|
||||
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::MIN_CURRENT_VERSION), nLockTime(0) {}
|
||||
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime),
|
||||
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::SPROUT_MIN_CURRENT_VERSION), fOverwintered(false), nVersionGroupId(0), nExpiryHeight(0), nLockTime(0) {}
|
||||
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), fOverwintered(tx.fOverwintered), nVersionGroupId(tx.nVersionGroupId), nExpiryHeight(tx.nExpiryHeight),
|
||||
vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime),
|
||||
vjoinsplit(tx.vjoinsplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig)
|
||||
{
|
||||
|
||||
@@ -164,19 +169,34 @@ void CTransaction::UpdateHash() const
|
||||
*const_cast<uint256*>(&hash) = SerializeHash(*this);
|
||||
}
|
||||
|
||||
CTransaction::CTransaction() : nVersion(CTransaction::MIN_CURRENT_VERSION), vin(), vout(), nLockTime(0), vjoinsplit(), joinSplitPubKey(), joinSplitSig() { }
|
||||
CTransaction::CTransaction() : nVersion(CTransaction::SPROUT_MIN_CURRENT_VERSION), fOverwintered(false), nVersionGroupId(0), nExpiryHeight(0), vin(), vout(), nLockTime(0), vjoinsplit(), joinSplitPubKey(), joinSplitSig() { }
|
||||
|
||||
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), vjoinsplit(tx.vjoinsplit),
|
||||
joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig)
|
||||
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), fOverwintered(tx.fOverwintered), nVersionGroupId(tx.nVersionGroupId), nExpiryHeight(tx.nExpiryHeight),
|
||||
vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime),
|
||||
vjoinsplit(tx.vjoinsplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig)
|
||||
{
|
||||
UpdateHash();
|
||||
}
|
||||
|
||||
// Protected constructor which only derived classes can call.
|
||||
// For developer testing only.
|
||||
CTransaction::CTransaction(
|
||||
const CMutableTransaction &tx,
|
||||
bool evilDeveloperFlag) : nVersion(tx.nVersion), fOverwintered(tx.fOverwintered), nVersionGroupId(tx.nVersionGroupId), nExpiryHeight(tx.nExpiryHeight),
|
||||
vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime),
|
||||
vjoinsplit(tx.vjoinsplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig)
|
||||
{
|
||||
assert(evilDeveloperFlag);
|
||||
}
|
||||
|
||||
CTransaction& CTransaction::operator=(const CTransaction &tx) {
|
||||
*const_cast<bool*>(&fOverwintered) = tx.fOverwintered;
|
||||
*const_cast<int*>(&nVersion) = tx.nVersion;
|
||||
*const_cast<uint32_t*>(&nVersionGroupId) = tx.nVersionGroupId;
|
||||
*const_cast<std::vector<CTxIn>*>(&vin) = tx.vin;
|
||||
*const_cast<std::vector<CTxOut>*>(&vout) = tx.vout;
|
||||
*const_cast<unsigned int*>(&nLockTime) = tx.nLockTime;
|
||||
*const_cast<uint32_t*>(&nExpiryHeight) = tx.nExpiryHeight;
|
||||
*const_cast<std::vector<JSDescription>*>(&vjoinsplit) = tx.vjoinsplit;
|
||||
*const_cast<uint256*>(&joinSplitPubKey) = tx.joinSplitPubKey;
|
||||
*const_cast<joinsplit_sig_t*>(&joinSplitSig) = tx.joinSplitSig;
|
||||
@@ -249,12 +269,24 @@ unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const
|
||||
std::string CTransaction::ToString() const
|
||||
{
|
||||
std::string str;
|
||||
str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%u, vout.size=%u, nLockTime=%u)\n",
|
||||
GetHash().ToString().substr(0,10),
|
||||
nVersion,
|
||||
vin.size(),
|
||||
vout.size(),
|
||||
nLockTime);
|
||||
if (!fOverwintered) {
|
||||
str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%u, vout.size=%u, nLockTime=%u)\n",
|
||||
GetHash().ToString().substr(0,10),
|
||||
nVersion,
|
||||
vin.size(),
|
||||
vout.size(),
|
||||
nLockTime);
|
||||
} else if (nVersion >= 3) {
|
||||
str += strprintf("CTransaction(hash=%s, ver=%d, fOverwintered=%d, nVersionGroupId=%08x, vin.size=%u, vout.size=%u, nLockTime=%u, nExpiryHeight=%u)\n",
|
||||
GetHash().ToString().substr(0,10),
|
||||
nVersion,
|
||||
fOverwintered,
|
||||
nVersionGroupId,
|
||||
vin.size(),
|
||||
vout.size(),
|
||||
nLockTime,
|
||||
nExpiryHeight);
|
||||
}
|
||||
for (unsigned int i = 0; i < vin.size(); i++)
|
||||
str += " " + vin[i].ToString() + "\n";
|
||||
for (unsigned int i = 0; i < vout.size(); i++)
|
||||
|
||||
@@ -81,7 +81,8 @@ public:
|
||||
const boost::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
|
||||
CAmount vpub_old,
|
||||
CAmount vpub_new,
|
||||
bool computeProof = true // Set to false in some tests
|
||||
bool computeProof = true, // Set to false in some tests
|
||||
uint256 *esk = nullptr // payment disclosure
|
||||
);
|
||||
|
||||
static JSDescription Randomized(
|
||||
@@ -100,6 +101,7 @@ public:
|
||||
CAmount vpub_old,
|
||||
CAmount vpub_new,
|
||||
bool computeProof = true, // Set to false in some tests
|
||||
uint256 *esk = nullptr, // payment disclosure
|
||||
std::function<int(int)> gen = GetRandInt
|
||||
);
|
||||
|
||||
@@ -310,6 +312,10 @@ public:
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
// Overwinter version group id
|
||||
static constexpr uint32_t OVERWINTER_VERSION_GROUP_ID = 0x03C48270;
|
||||
static_assert(OVERWINTER_VERSION_GROUP_ID != 0, "version group id must be non-zero as specified in ZIP 202");
|
||||
|
||||
struct CMutableTransaction;
|
||||
|
||||
/** The basic transaction that is broadcasted on the network and contained in
|
||||
@@ -322,14 +328,29 @@ private:
|
||||
const uint256 hash;
|
||||
void UpdateHash() const;
|
||||
|
||||
protected:
|
||||
/** Developer testing only. Set evilDeveloperFlag to true.
|
||||
* Convert a CMutableTransaction into a CTransaction without invoking UpdateHash()
|
||||
*/
|
||||
CTransaction(const CMutableTransaction &tx, bool evilDeveloperFlag);
|
||||
|
||||
public:
|
||||
typedef boost::array<unsigned char, 64> joinsplit_sig_t;
|
||||
|
||||
// Transactions that include a list of JoinSplits are version 2.
|
||||
static const int32_t MIN_CURRENT_VERSION = 1;
|
||||
static const int32_t MAX_CURRENT_VERSION = 2;
|
||||
// Transactions that include a list of JoinSplits are >= version 2.
|
||||
static const int32_t SPROUT_MIN_CURRENT_VERSION = 1;
|
||||
static const int32_t SPROUT_MAX_CURRENT_VERSION = 2;
|
||||
static const int32_t OVERWINTER_MIN_CURRENT_VERSION = 3;
|
||||
static const int32_t OVERWINTER_MAX_CURRENT_VERSION = 3;
|
||||
|
||||
static_assert(MIN_CURRENT_VERSION >= MIN_TX_VERSION,
|
||||
static_assert(SPROUT_MIN_CURRENT_VERSION >= SPROUT_MIN_TX_VERSION,
|
||||
"standard rule for tx version should be consistent with network rule");
|
||||
|
||||
static_assert(OVERWINTER_MIN_CURRENT_VERSION >= OVERWINTER_MIN_TX_VERSION,
|
||||
"standard rule for tx version should be consistent with network rule");
|
||||
|
||||
static_assert( (OVERWINTER_MAX_CURRENT_VERSION <= OVERWINTER_MAX_TX_VERSION &&
|
||||
OVERWINTER_MAX_CURRENT_VERSION >= OVERWINTER_MIN_CURRENT_VERSION),
|
||||
"standard rule for tx version should be consistent with network rule");
|
||||
|
||||
// The local variables are made const to prevent unintended modification
|
||||
@@ -337,10 +358,13 @@ public:
|
||||
// actually immutable; deserialization and assignment are implemented,
|
||||
// and bypass the constness. This is safe, as they update the entire
|
||||
// structure, including the hash.
|
||||
const bool fOverwintered;
|
||||
const int32_t nVersion;
|
||||
const uint32_t nVersionGroupId;
|
||||
const std::vector<CTxIn> vin;
|
||||
const std::vector<CTxOut> vout;
|
||||
const uint32_t nLockTime;
|
||||
const uint32_t nExpiryHeight;
|
||||
const std::vector<JSDescription> vjoinsplit;
|
||||
const uint256 joinSplitPubKey;
|
||||
const joinsplit_sig_t joinSplitSig = {{0}};
|
||||
@@ -357,11 +381,34 @@ public:
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(*const_cast<int32_t*>(&this->nVersion));
|
||||
if (ser_action.ForRead()) {
|
||||
// When deserializing, unpack the 4 byte header to extract fOverwintered and nVersion.
|
||||
uint32_t header;
|
||||
READWRITE(header);
|
||||
*const_cast<bool*>(&fOverwintered) = header >> 31;
|
||||
*const_cast<int32_t*>(&this->nVersion) = header & 0x7FFFFFFF;
|
||||
} else {
|
||||
uint32_t header = GetHeader();
|
||||
READWRITE(header);
|
||||
}
|
||||
nVersion = this->nVersion;
|
||||
if (fOverwintered) {
|
||||
READWRITE(*const_cast<uint32_t*>(&this->nVersionGroupId));
|
||||
}
|
||||
|
||||
bool isOverwinterV3 = fOverwintered &&
|
||||
nVersionGroupId == OVERWINTER_VERSION_GROUP_ID &&
|
||||
nVersion == 3;
|
||||
if (fOverwintered && !isOverwinterV3) {
|
||||
throw std::ios_base::failure("Unknown transaction format");
|
||||
}
|
||||
|
||||
READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
|
||||
READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
|
||||
READWRITE(*const_cast<uint32_t*>(&nLockTime));
|
||||
if (isOverwinterV3) {
|
||||
READWRITE(*const_cast<uint32_t*>(&nExpiryHeight));
|
||||
}
|
||||
if (nVersion >= 2) {
|
||||
READWRITE(*const_cast<std::vector<JSDescription>*>(&vjoinsplit));
|
||||
if (vjoinsplit.size() > 0) {
|
||||
@@ -381,6 +428,16 @@ public:
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint32_t GetHeader() const {
|
||||
// When serializing v1 and v2, the 4 byte header is nVersion
|
||||
uint32_t header = this->nVersion;
|
||||
// When serializing Overwintered tx, the 4 byte header is the combination of fOverwintered and nVersion
|
||||
if (fOverwintered) {
|
||||
header |= 1 << 31;
|
||||
}
|
||||
return header;
|
||||
}
|
||||
|
||||
// Return sum of txouts.
|
||||
CAmount GetValueOut() const;
|
||||
// GetValueIn() is a method on CCoinsViewCache, because
|
||||
@@ -416,10 +473,13 @@ public:
|
||||
/** A mutable version of CTransaction. */
|
||||
struct CMutableTransaction
|
||||
{
|
||||
bool fOverwintered;
|
||||
int32_t nVersion;
|
||||
uint32_t nVersionGroupId;
|
||||
std::vector<CTxIn> vin;
|
||||
std::vector<CTxOut> vout;
|
||||
uint32_t nLockTime;
|
||||
uint32_t nExpiryHeight;
|
||||
std::vector<JSDescription> vjoinsplit;
|
||||
uint256 joinSplitPubKey;
|
||||
CTransaction::joinsplit_sig_t joinSplitSig = {{0}};
|
||||
@@ -431,11 +491,39 @@ struct CMutableTransaction
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(this->nVersion);
|
||||
if (ser_action.ForRead()) {
|
||||
// When deserializing, unpack the 4 byte header to extract fOverwintered and nVersion.
|
||||
uint32_t header;
|
||||
READWRITE(header);
|
||||
fOverwintered = header >> 31;
|
||||
this->nVersion = header & 0x7FFFFFFF;
|
||||
} else {
|
||||
// When serializing v1 and v2, the 4 byte header is nVersion
|
||||
uint32_t header = this->nVersion;
|
||||
// When serializing Overwintered tx, the 4 byte header is the combination of fOverwintered and nVersion
|
||||
if (fOverwintered) {
|
||||
header |= 1 << 31;
|
||||
}
|
||||
READWRITE(header);
|
||||
}
|
||||
nVersion = this->nVersion;
|
||||
if (fOverwintered) {
|
||||
READWRITE(nVersionGroupId);
|
||||
}
|
||||
|
||||
bool isOverwinterV3 = fOverwintered &&
|
||||
nVersionGroupId == OVERWINTER_VERSION_GROUP_ID &&
|
||||
nVersion == 3;
|
||||
if (fOverwintered && !isOverwinterV3) {
|
||||
throw std::ios_base::failure("Unknown transaction format");
|
||||
}
|
||||
|
||||
READWRITE(vin);
|
||||
READWRITE(vout);
|
||||
READWRITE(nLockTime);
|
||||
if (isOverwinterV3) {
|
||||
READWRITE(nExpiryHeight);
|
||||
}
|
||||
if (nVersion >= 2) {
|
||||
READWRITE(vjoinsplit);
|
||||
if (vjoinsplit.size() > 0) {
|
||||
|
||||
Reference in New Issue
Block a user