2018-07-17 09:36:38 -07:00
|
|
|
// Copyright (c) 2018 The Zcash developers
|
|
|
|
// Distributed under the MIT software license, see the accompanying
|
2019-07-18 07:16:09 -07:00
|
|
|
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
2018-07-17 09:36:38 -07:00
|
|
|
|
2020-10-27 04:46:32 -07:00
|
|
|
#ifndef ZCASH_TRANSACTION_BUILDER_H
|
|
|
|
#define ZCASH_TRANSACTION_BUILDER_H
|
2018-07-17 09:36:38 -07:00
|
|
|
|
2018-10-12 17:36:26 -07:00
|
|
|
#include "coins.h"
|
2018-07-17 09:36:38 -07:00
|
|
|
#include "consensus/params.h"
|
2018-07-30 03:03:29 -07:00
|
|
|
#include "keystore.h"
|
2018-07-17 09:36:38 -07:00
|
|
|
#include "primitives/transaction.h"
|
2020-07-09 00:40:06 -07:00
|
|
|
#include "random.h"
|
2018-07-30 03:03:29 -07:00
|
|
|
#include "script/script.h"
|
|
|
|
#include "script/standard.h"
|
2018-07-17 09:36:38 -07:00
|
|
|
#include "uint256.h"
|
|
|
|
#include "zcash/Address.hpp"
|
|
|
|
#include "zcash/IncrementalMerkleTree.hpp"
|
2018-10-12 17:36:26 -07:00
|
|
|
#include "zcash/JoinSplit.hpp"
|
2018-07-17 09:36:38 -07:00
|
|
|
#include "zcash/Note.hpp"
|
|
|
|
#include "zcash/NoteEncryption.hpp"
|
|
|
|
|
2020-10-20 17:39:13 -07:00
|
|
|
#include <optional>
|
2018-07-17 09:36:38 -07:00
|
|
|
|
2020-06-05 14:46:45 -07:00
|
|
|
#define NO_MEMO {{0xF6}}
|
|
|
|
|
2018-07-27 00:49:43 -07:00
|
|
|
struct SpendDescriptionInfo {
|
2018-07-30 06:26:29 -07:00
|
|
|
libzcash::SaplingExpandedSpendingKey expsk;
|
2018-07-17 09:36:38 -07:00
|
|
|
libzcash::SaplingNote note;
|
|
|
|
uint256 alpha;
|
|
|
|
uint256 anchor;
|
2018-08-01 09:41:36 -07:00
|
|
|
SaplingWitness witness;
|
2018-07-17 09:36:38 -07:00
|
|
|
|
|
|
|
SpendDescriptionInfo(
|
2018-07-30 06:26:29 -07:00
|
|
|
libzcash::SaplingExpandedSpendingKey expsk,
|
2018-07-17 09:36:38 -07:00
|
|
|
libzcash::SaplingNote note,
|
|
|
|
uint256 anchor,
|
2018-08-01 09:41:36 -07:00
|
|
|
SaplingWitness witness);
|
2018-07-17 09:36:38 -07:00
|
|
|
};
|
|
|
|
|
2018-07-27 00:49:43 -07:00
|
|
|
struct OutputDescriptionInfo {
|
2018-07-17 09:36:38 -07:00
|
|
|
uint256 ovk;
|
|
|
|
libzcash::SaplingNote note;
|
|
|
|
std::array<unsigned char, ZC_MEMO_SIZE> memo;
|
|
|
|
|
|
|
|
OutputDescriptionInfo(
|
|
|
|
uint256 ovk,
|
|
|
|
libzcash::SaplingNote note,
|
|
|
|
std::array<unsigned char, ZC_MEMO_SIZE> memo) : ovk(ovk), note(note), memo(memo) {}
|
2019-05-17 09:39:30 -07:00
|
|
|
|
2020-10-20 17:44:15 -07:00
|
|
|
std::optional<OutputDescription> Build(void* ctx);
|
2018-07-17 09:36:38 -07:00
|
|
|
};
|
|
|
|
|
2020-07-09 00:40:06 -07:00
|
|
|
struct JSDescriptionInfo {
|
|
|
|
Ed25519VerificationKey joinSplitPubKey;
|
|
|
|
uint256 anchor;
|
2020-12-20 18:18:35 -08:00
|
|
|
// We store references to these so they are correctly randomised for the caller.
|
|
|
|
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs;
|
|
|
|
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs;
|
2020-07-09 00:40:06 -07:00
|
|
|
CAmount vpub_old;
|
|
|
|
CAmount vpub_new;
|
|
|
|
|
|
|
|
JSDescriptionInfo(
|
|
|
|
Ed25519VerificationKey joinSplitPubKey,
|
|
|
|
uint256 anchor,
|
2020-12-20 18:18:35 -08:00
|
|
|
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
|
|
|
|
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
|
2020-07-09 00:40:06 -07:00
|
|
|
CAmount vpub_old,
|
|
|
|
CAmount vpub_new) : joinSplitPubKey(joinSplitPubKey), anchor(anchor), inputs(inputs), outputs(outputs), vpub_old(vpub_old), vpub_new(vpub_new) {}
|
|
|
|
|
|
|
|
JSDescription BuildDeterministic(
|
|
|
|
bool computeProof = true, // Set to false in some tests
|
|
|
|
uint256* esk = nullptr // payment disclosure
|
|
|
|
);
|
|
|
|
|
|
|
|
JSDescription BuildRandomized(
|
|
|
|
std::array<size_t, ZC_NUM_JS_INPUTS>& inputMap,
|
|
|
|
std::array<size_t, ZC_NUM_JS_OUTPUTS>& outputMap,
|
|
|
|
bool computeProof = true, // Set to false in some tests
|
|
|
|
uint256* esk = nullptr, // payment disclosure
|
|
|
|
std::function<int(int)> gen = GetRandInt
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2018-07-30 03:03:29 -07:00
|
|
|
struct TransparentInputInfo {
|
|
|
|
CScript scriptPubKey;
|
|
|
|
CAmount value;
|
|
|
|
|
|
|
|
TransparentInputInfo(
|
|
|
|
CScript scriptPubKey,
|
|
|
|
CAmount value) : scriptPubKey(scriptPubKey), value(value) {}
|
|
|
|
};
|
|
|
|
|
2018-10-30 13:12:40 -07:00
|
|
|
class TransactionBuilderResult {
|
|
|
|
private:
|
2020-10-20 17:44:15 -07:00
|
|
|
std::optional<CTransaction> maybeTx;
|
|
|
|
std::optional<std::string> maybeError;
|
2018-10-30 13:12:40 -07:00
|
|
|
public:
|
|
|
|
TransactionBuilderResult() = delete;
|
|
|
|
TransactionBuilderResult(const CTransaction& tx);
|
|
|
|
TransactionBuilderResult(const std::string& error);
|
|
|
|
bool IsTx();
|
|
|
|
bool IsError();
|
|
|
|
CTransaction GetTxOrThrow();
|
|
|
|
std::string GetError();
|
|
|
|
};
|
|
|
|
|
2018-07-17 09:36:38 -07:00
|
|
|
class TransactionBuilder
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
Consensus::Params consensusParams;
|
|
|
|
int nHeight;
|
2018-07-30 03:03:29 -07:00
|
|
|
const CKeyStore* keystore;
|
2018-10-12 17:36:26 -07:00
|
|
|
const CCoinsViewCache* coinsView;
|
|
|
|
CCriticalSection* cs_coinsView;
|
2018-07-17 09:36:38 -07:00
|
|
|
CMutableTransaction mtx;
|
2018-07-30 04:52:48 -07:00
|
|
|
CAmount fee = 10000;
|
2018-07-17 09:36:38 -07:00
|
|
|
|
|
|
|
std::vector<SpendDescriptionInfo> spends;
|
|
|
|
std::vector<OutputDescriptionInfo> outputs;
|
2018-10-12 17:36:26 -07:00
|
|
|
std::vector<libzcash::JSInput> jsInputs;
|
|
|
|
std::vector<libzcash::JSOutput> jsOutputs;
|
2018-07-30 03:03:29 -07:00
|
|
|
std::vector<TransparentInputInfo> tIns;
|
2018-07-17 09:36:38 -07:00
|
|
|
|
2020-10-20 17:44:15 -07:00
|
|
|
std::optional<std::pair<uint256, libzcash::SaplingPaymentAddress>> saplingChangeAddr;
|
|
|
|
std::optional<libzcash::SproutPaymentAddress> sproutChangeAddr;
|
|
|
|
std::optional<CTxDestination> tChangeAddr;
|
2018-07-30 04:36:42 -07:00
|
|
|
|
2018-07-17 09:36:38 -07:00
|
|
|
public:
|
2018-08-04 04:23:13 -07:00
|
|
|
TransactionBuilder() {}
|
2018-10-12 17:36:26 -07:00
|
|
|
TransactionBuilder(
|
|
|
|
const Consensus::Params& consensusParams,
|
|
|
|
int nHeight,
|
|
|
|
CKeyStore* keyStore = nullptr,
|
|
|
|
CCoinsViewCache* coinsView = nullptr,
|
|
|
|
CCriticalSection* cs_coinsView = nullptr);
|
2018-07-17 09:36:38 -07:00
|
|
|
|
2019-07-30 00:16:37 -07:00
|
|
|
void SetExpiryHeight(uint32_t nExpiryHeight);
|
|
|
|
|
2018-07-30 04:52:48 -07:00
|
|
|
void SetFee(CAmount fee);
|
|
|
|
|
2018-10-31 09:15:37 -07:00
|
|
|
// Throws if the anchor does not match the anchor used by
|
2018-07-27 00:46:38 -07:00
|
|
|
// previously-added Sapling spends.
|
2018-10-31 09:15:37 -07:00
|
|
|
void AddSaplingSpend(
|
2018-07-30 06:26:29 -07:00
|
|
|
libzcash::SaplingExpandedSpendingKey expsk,
|
2018-07-17 09:36:38 -07:00
|
|
|
libzcash::SaplingNote note,
|
|
|
|
uint256 anchor,
|
2018-08-01 09:41:36 -07:00
|
|
|
SaplingWitness witness);
|
2018-07-17 09:36:38 -07:00
|
|
|
|
|
|
|
void AddSaplingOutput(
|
2018-09-18 15:22:50 -07:00
|
|
|
uint256 ovk,
|
2018-07-17 09:36:38 -07:00
|
|
|
libzcash::SaplingPaymentAddress to,
|
|
|
|
CAmount value,
|
2020-06-05 14:46:45 -07:00
|
|
|
std::array<unsigned char, ZC_MEMO_SIZE> memo = NO_MEMO);
|
2018-07-17 09:36:38 -07:00
|
|
|
|
2018-10-12 17:36:26 -07:00
|
|
|
// Throws if the anchor does not match the anchor used by
|
|
|
|
// previously-added Sprout inputs.
|
|
|
|
void AddSproutInput(
|
|
|
|
libzcash::SproutSpendingKey sk,
|
|
|
|
libzcash::SproutNote note,
|
|
|
|
SproutWitness witness);
|
|
|
|
|
|
|
|
void AddSproutOutput(
|
|
|
|
libzcash::SproutPaymentAddress to,
|
|
|
|
CAmount value,
|
2020-06-05 14:46:45 -07:00
|
|
|
std::array<unsigned char, ZC_MEMO_SIZE> memo = NO_MEMO);
|
2018-10-12 17:36:26 -07:00
|
|
|
|
2018-07-30 03:03:29 -07:00
|
|
|
// Assumes that the value correctly corresponds to the provided UTXO.
|
|
|
|
void AddTransparentInput(COutPoint utxo, CScript scriptPubKey, CAmount value);
|
|
|
|
|
2020-02-21 07:45:03 -08:00
|
|
|
void AddTransparentOutput(const CTxDestination& to, CAmount value);
|
2018-07-30 03:03:29 -07:00
|
|
|
|
2018-09-18 15:22:50 -07:00
|
|
|
void SendChangeTo(libzcash::SaplingPaymentAddress changeAddr, uint256 ovk);
|
2018-07-30 04:36:42 -07:00
|
|
|
|
2018-10-12 17:36:26 -07:00
|
|
|
void SendChangeTo(libzcash::SproutPaymentAddress);
|
|
|
|
|
2018-10-31 09:15:37 -07:00
|
|
|
void SendChangeTo(CTxDestination& changeAddr);
|
2018-07-30 04:36:42 -07:00
|
|
|
|
2018-10-30 13:12:40 -07:00
|
|
|
TransactionBuilderResult Build();
|
2018-10-12 17:36:26 -07:00
|
|
|
|
|
|
|
private:
|
2019-02-28 10:19:36 -08:00
|
|
|
void CreateJSDescriptions();
|
2018-10-12 17:36:26 -07:00
|
|
|
|
|
|
|
void CreateJSDescription(
|
|
|
|
uint64_t vpub_old,
|
|
|
|
uint64_t vpub_new,
|
|
|
|
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> vjsin,
|
|
|
|
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> vjsout,
|
|
|
|
std::array<size_t, ZC_NUM_JS_INPUTS>& inputMap,
|
|
|
|
std::array<size_t, ZC_NUM_JS_OUTPUTS>& outputMap);
|
2018-07-17 09:36:38 -07:00
|
|
|
};
|
|
|
|
|
2020-10-27 04:46:32 -07:00
|
|
|
#endif // ZCASH_TRANSACTION_BUILDER_H
|