Introduce vpour to CTransaction.

Transactions of version 2 and above contain a `vpour` field which is a vector of `CPourTx`
objects that embody our protocol. We introduce serialization primitives for boost::array
(we intend for changing the amount of inputs and outputs in the circuit to be simple).

SIGHASH_* operations hash this field like any other for now.
This commit is contained in:
Sean Bowe
2015-12-29 17:56:05 -07:00
parent 74e519aa2d
commit 5884044ba9
7 changed files with 725 additions and 503 deletions

View File

@@ -60,7 +60,7 @@ std::string CTxOut::ToString() const
}
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {}
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), vpour(tx.vpour) {}
uint256 CMutableTransaction::GetHash() const
{
@@ -72,9 +72,9 @@ void CTransaction::UpdateHash() const
*const_cast<uint256*>(&hash) = SerializeHash(*this);
}
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { }
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0), vpour() { }
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), vpour(tx.vpour) {
UpdateHash();
}
@@ -83,6 +83,7 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) {
*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<std::vector<CPourTx>*>(&vpour) = tx.vpour;
*const_cast<uint256*>(&hash) = tx.hash;
return *this;
}

View File

@@ -11,6 +11,100 @@
#include "serialize.h"
#include "uint256.h"
#include <boost/array.hpp>
class CPourTx
{
public:
// These values 'enter from' and 'exit to' the value
// pool, respectively.
CAmount vpub_old;
CAmount vpub_new;
// These scripts are used to bind a Pour to the outer
// transaction it is placed in. The Pour will
// authenticate the hash of the scriptPubKey, and the
// provided scriptSig with be appended during
// transaction verification.
CScript scriptPubKey;
CScript scriptSig;
// Pours are always anchored to a root in the bucket
// commitment tree at some point in the blockchain
// history or in the history of the current
// transaction.
uint256 anchor;
// Serials are used to prevent double-spends. They
// are derived from the secrets placed in the bucket
// and the secret spend-authority key known by the
// spender.
boost::array<uint256, 2> serials;
// Bucket commitments are introduced into the commitment
// tree, blinding the public about the values and
// destinations involved in the Pour. The presence of a
// commitment in the bucket commitment tree is required
// to spend it.
boost::array<uint256, 2> commitments;
// Ciphertexts
// These are encrypted using ECIES. They are used to
// transfer metadata and seeds to generate trapdoors
// for the recipient to spend the value.
boost::array<std::vector<unsigned char>, 2> ciphertexts;
// MACs
// The verification of the pour requires these MACs
// to be provided as an input.
boost::array<uint256, 2> macs;
// Pour proof
// This is a zk-SNARK which ensures that this pour is valid.
std::string proof;
CPourTx(): vpub_old(0), vpub_new(0), scriptPubKey(), scriptSig(), anchor(), serials(), commitments(), ciphertexts(), macs(), proof() {
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(vpub_old);
READWRITE(vpub_new);
READWRITE(scriptPubKey);
READWRITE(scriptSig);
READWRITE(anchor);
READWRITE(serials);
READWRITE(commitments);
READWRITE(ciphertexts);
READWRITE(macs);
READWRITE(proof);
}
friend bool operator==(const CPourTx& a, const CPourTx& b)
{
return (
a.vpub_old == b.vpub_old &&
a.vpub_new == b.vpub_new &&
a.scriptPubKey == b.scriptPubKey &&
a.scriptSig == b.scriptSig &&
a.anchor == b.anchor &&
a.serials == b.serials &&
a.commitments == b.commitments &&
a.ciphertexts == b.ciphertexts &&
a.macs == b.macs &&
a.proof == b.proof
);
}
friend bool operator!=(const CPourTx& a, const CPourTx& b)
{
return !(a == b);
}
};
/** An outpoint - a combination of a transaction hash and an index n into its vout */
class COutPoint
{
@@ -192,6 +286,7 @@ public:
const std::vector<CTxIn> vin;
const std::vector<CTxOut> vout;
const uint32_t nLockTime;
const std::vector<CPourTx> vpour;
/** Construct a CTransaction that qualifies as IsNull() */
CTransaction();
@@ -210,6 +305,9 @@ public:
READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
READWRITE(*const_cast<uint32_t*>(&nLockTime));
if (nVersion >= 2) {
READWRITE(*const_cast<std::vector<CPourTx>*>(&vpour));
}
if (ser_action.ForRead())
UpdateHash();
}
@@ -258,6 +356,7 @@ struct CMutableTransaction
std::vector<CTxIn> vin;
std::vector<CTxOut> vout;
uint32_t nLockTime;
std::vector<CPourTx> vpour;
CMutableTransaction();
CMutableTransaction(const CTransaction& tx);
@@ -271,6 +370,9 @@ struct CMutableTransaction
READWRITE(vin);
READWRITE(vout);
READWRITE(nLockTime);
if (nVersion >= 2) {
READWRITE(vpour);
}
}
/** Compute the hash of this CMutableTransaction. This is computed on the