2019-03-11 14:39:38 +01:00
|
|
|
/*
|
|
|
|
|
* This file is part of the Flowee project
|
2024-03-13 17:02:19 +01:00
|
|
|
* Copyright (C) 2019-2024 Tom Zander <tom@flowee.org>
|
2019-03-11 14:39:38 +01:00
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
2024-01-22 19:32:15 +01:00
|
|
|
#ifndef FLOWEE_TRANSACTIONBUILDER_H
|
|
|
|
|
#define FLOWEE_TRANSACTIONBUILDER_H
|
2019-03-11 14:39:38 +01:00
|
|
|
|
2021-11-02 11:04:59 +01:00
|
|
|
#include "primitives/Tx.h"
|
2023-11-24 18:16:32 +01:00
|
|
|
#include "primitives/PrivateKey.h"
|
2020-05-28 22:34:49 +02:00
|
|
|
#include "primitives/script.h"
|
|
|
|
|
#include "uint256.h"
|
2019-03-11 14:39:38 +01:00
|
|
|
|
2022-07-06 21:56:34 +02:00
|
|
|
class PublicKey;
|
2020-05-28 22:34:49 +02:00
|
|
|
class CTransaction;
|
|
|
|
|
class TransactionBuilderPrivate;
|
2019-03-12 22:46:31 +01:00
|
|
|
|
2019-03-11 14:39:38 +01:00
|
|
|
/**
|
|
|
|
|
* This class allows anyone to create or extend Bitcoin (BCH) transactions.
|
|
|
|
|
*
|
|
|
|
|
* A transaction can be started from nothing, or a partially constructed transaction
|
|
|
|
|
* can be imported and build further.
|
|
|
|
|
*
|
|
|
|
|
* Bitcoin transactions are only final once all inputs are signed, which may take
|
|
|
|
|
* multiple people signing parts of that transaction. This builder allows building
|
|
|
|
|
* new but also importing and extending existing transactions.
|
|
|
|
|
*
|
|
|
|
|
* TODO when an action destroys an existing signature I should have a way to communicate
|
|
|
|
|
* this to the user of this class.
|
|
|
|
|
*/
|
|
|
|
|
class TransactionBuilder
|
|
|
|
|
{
|
|
|
|
|
public:
|
2021-04-19 16:09:42 +02:00
|
|
|
enum SignatureType {
|
|
|
|
|
ECDSA,
|
|
|
|
|
Schnorr
|
|
|
|
|
};
|
|
|
|
|
|
2021-05-04 16:57:55 +02:00
|
|
|
TransactionBuilder();
|
|
|
|
|
TransactionBuilder(const Tx &existingTx);
|
|
|
|
|
TransactionBuilder(const CTransaction &existingTx);
|
2020-05-28 22:34:49 +02:00
|
|
|
~TransactionBuilder();
|
2019-03-11 14:39:38 +01:00
|
|
|
|
2024-10-04 12:09:55 +02:00
|
|
|
void setFeeTarget(int satsPerKByte);
|
|
|
|
|
|
2019-03-11 14:39:38 +01:00
|
|
|
/**
|
|
|
|
|
* Add a new input and select it.
|
|
|
|
|
* This uses the default SignAllOutputs SignAllInputs sighash.
|
|
|
|
|
*/
|
|
|
|
|
int appendInput(const uint256 &txid, int outputIndex);
|
|
|
|
|
/**
|
|
|
|
|
* Select an input based on index.
|
|
|
|
|
* Please note that the first input is numbered as zero (0)
|
|
|
|
|
* @returns the input number we selected.
|
|
|
|
|
*/
|
|
|
|
|
int selectInput(int index);
|
|
|
|
|
|
2020-10-23 22:33:33 +02:00
|
|
|
int outputCount() const;
|
|
|
|
|
int inputCount() const;
|
|
|
|
|
|
2019-03-11 14:39:38 +01:00
|
|
|
/// SigHash type, the inputs part.
|
|
|
|
|
enum SignInputs {
|
|
|
|
|
/**
|
|
|
|
|
* This option signs all inputs, making it impossible to combine with other inputs after signing.
|
|
|
|
|
*
|
|
|
|
|
* This is not directly a signhash type as this is the default behaviour. When in doubt, use this.
|
|
|
|
|
*/
|
|
|
|
|
SignAllInputs = 0,
|
|
|
|
|
/**
|
|
|
|
|
* This option allows for full combining of this input with any other inputs, even after signing.
|
|
|
|
|
*
|
|
|
|
|
* This sighash flag, also called SIGHASH_ANYONECANPAY, is useful to combine different inputs
|
|
|
|
|
* from different parties and combine that into a valid transaction.
|
|
|
|
|
*
|
|
|
|
|
* Be careful about picking an good SignOutputs enum as picking NoOutput will essentially give your
|
|
|
|
|
* money to anyone that manages to mine the input first.
|
|
|
|
|
*/
|
|
|
|
|
SignOnlyThisInput = 0x80,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// SighHash type, the outputs part.
|
|
|
|
|
enum SignOutputs {
|
|
|
|
|
/**
|
|
|
|
|
* An input signed with this will disallow any change in all outputs.
|
|
|
|
|
* This sighash type, also called SIGHASH_ALL, signs all outputs, preventing any modification.
|
|
|
|
|
*/
|
|
|
|
|
SignAllOuputs = 1,
|
|
|
|
|
/**
|
|
|
|
|
* Put no requirement at all on the outputs to stay the same after signing.
|
|
|
|
|
*
|
|
|
|
|
* This sighash type, also called SIGHASH_NONE, signs only this input. Best used in
|
|
|
|
|
* combination with SignAllInputs because otherwise this input can be combined in another
|
|
|
|
|
* transaction and losses can occur.
|
|
|
|
|
*/
|
|
|
|
|
SignNoOutputs = 2,
|
|
|
|
|
/**
|
|
|
|
|
* Requires the input to be combined with one specific output.
|
|
|
|
|
* This sighash type, also called SIGHASH_SINGLE, signs the output from this transaction
|
|
|
|
|
* that has the same index as this input.
|
|
|
|
|
*
|
|
|
|
|
* Please be aware that if there is no output of the same number that this silently turns
|
|
|
|
|
* into a SignNoOutputs.
|
|
|
|
|
*
|
|
|
|
|
* It allows modifications of other outputs and the sequence number of other inputs.
|
|
|
|
|
*/
|
|
|
|
|
SignSingleOutput = 3,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
2019-03-13 20:32:18 +01:00
|
|
|
* Pushes the data needed for the current input to receive its signatures.
|
2019-03-11 14:39:38 +01:00
|
|
|
*
|
2019-03-13 20:32:18 +01:00
|
|
|
* Inputs use a signature to prove you own the money that this transaction spends. To make the
|
2024-09-07 10:34:59 +02:00
|
|
|
* signing secure it doesn't just take the private key, it also takes the prevOutScript and the value
|
2019-03-13 20:32:18 +01:00
|
|
|
* properties, which your wallet should supply you with.
|
|
|
|
|
*
|
|
|
|
|
* The SignInputs / SignOutputs options determine how flexible the signature is with regards to a
|
|
|
|
|
* changing transaction after final signing time.
|
|
|
|
|
*
|
|
|
|
|
* For instance a fundraiser may want to combine inputs from a lot of people into one transaction.
|
|
|
|
|
* Those inputs can then be signed individually using SignOnlyThisInput and later combined without
|
|
|
|
|
* breaking the signature.
|
|
|
|
|
*
|
|
|
|
|
* A common rule is that outputs or inputs not included in the transaction may be changed after signing
|
|
|
|
|
* and before the transaction is mined.
|
2019-03-11 14:39:38 +01:00
|
|
|
*
|
|
|
|
|
* In most cases you should be very careful to pick at least one output you care about that you
|
2019-03-13 20:32:18 +01:00
|
|
|
* will sign because that guarentees your money can only be spent with those outputs getting paid.
|
2019-03-11 14:39:38 +01:00
|
|
|
*
|
|
|
|
|
* The default is to sign all inputs and all outputs, which implies that the entire transaction
|
|
|
|
|
* is fully constructed before signatures are collected.
|
2019-03-13 20:32:18 +01:00
|
|
|
*
|
|
|
|
|
* Notice that actual signing only happens when calling createTransaction()
|
2019-03-11 14:39:38 +01:00
|
|
|
*/
|
2024-09-07 10:34:59 +02:00
|
|
|
void pushInputSignature(const PrivateKey &privKey, const CScript &prevOutScript, int64_t value, SignatureType type, SignInputs inputs = SignAllInputs, SignOutputs outputs = SignAllOuputs);
|
2019-03-11 14:39:38 +01:00
|
|
|
|
|
|
|
|
/// locking options.
|
|
|
|
|
enum LockingOptions {
|
|
|
|
|
/**
|
|
|
|
|
* No locking applied, transaction can be mined immediately and spent immediately after.
|
|
|
|
|
*/
|
|
|
|
|
NoLocking,
|
|
|
|
|
/**
|
|
|
|
|
* A transaction can be banned from mining till a certain block height.
|
|
|
|
|
*
|
|
|
|
|
* The value passed is the last block height the transaction is not allowed
|
|
|
|
|
* to be mined in.
|
|
|
|
|
*
|
|
|
|
|
* Please be aware that this allows the transaction to be double spend quite easy.
|
|
|
|
|
*/
|
|
|
|
|
LockMiningOnBlock,
|
|
|
|
|
/**
|
|
|
|
|
* A transaction can be banned from mining in a block until a certain time.
|
|
|
|
|
* The time is set in seconds since unix epoch, the time should only be in the future.
|
|
|
|
|
*
|
|
|
|
|
* Please be aware that this allows the transaction to be double spend quite easy.
|
|
|
|
|
*/
|
|
|
|
|
LockMiningOnTime,
|
|
|
|
|
/**
|
|
|
|
|
* A transaction *input* can be locked from being mined till a certain block height.
|
|
|
|
|
*
|
|
|
|
|
* This is only really useful in case the output you are spending used OP_CHECKSEQUENCEVERIFY
|
|
|
|
|
*/
|
|
|
|
|
RelativeSpendingLockOnBlocks,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A transaction *input* can be locked from being mined untill a certain time.
|
|
|
|
|
*
|
|
|
|
|
* This is only really useful in case the output you are spending used OP_CHECKSEQUENCEVERIFY
|
|
|
|
|
*/
|
|
|
|
|
RelativeSpendingLockOnTime
|
|
|
|
|
};
|
|
|
|
|
|
2019-03-28 20:23:09 +01:00
|
|
|
#if 0
|
2019-03-11 14:39:38 +01:00
|
|
|
/**
|
|
|
|
|
* Set the locking option on the current input.
|
|
|
|
|
*
|
|
|
|
|
* Please be aware that usage of the LockFromMiningBlock or LockFromMiningTime options
|
|
|
|
|
* are transaction-global options and will effect all outputs in one go.
|
|
|
|
|
*/
|
|
|
|
|
void setLocking(LockingOptions option, uint32_t value);
|
2019-03-28 20:23:09 +01:00
|
|
|
#endif
|
2019-03-13 20:32:18 +01:00
|
|
|
/// delete an input based on index. Updates current input index.
|
2019-03-11 14:39:38 +01:00
|
|
|
void deleteInput(int index);
|
|
|
|
|
|
|
|
|
|
/// Appends and selects an output.
|
2024-09-06 20:42:29 +02:00
|
|
|
/// returns current output index.
|
2024-09-07 10:34:59 +02:00
|
|
|
int appendOutput(int64_t value);
|
2019-03-11 14:39:38 +01:00
|
|
|
/// selects an output
|
2024-09-06 20:42:29 +02:00
|
|
|
/// returns current output index.
|
2019-03-11 14:39:38 +01:00
|
|
|
int selectOutput(int index);
|
|
|
|
|
|
2020-06-08 18:45:14 +02:00
|
|
|
/// update the output value on the selected output
|
|
|
|
|
void setOutputValue(int64_t value);
|
|
|
|
|
|
2024-10-04 12:09:55 +02:00
|
|
|
/**
|
|
|
|
|
* Use argument, or current output to take fee from.
|
|
|
|
|
* The transaction-fee is the difference between incoming in inputs and outgoing in outputs.
|
|
|
|
|
* In order to have the expected amount of fees paid, we should adjust an output to end up
|
|
|
|
|
* with the right amount of satoshi's fees paid per kbyte of transaction-size.
|
|
|
|
|
*
|
|
|
|
|
* This passes in the output to use, or with the default argument it uses the current selected output.
|
|
|
|
|
* Setting the index to a not existing output index will disable the fee adjustment feature.
|
|
|
|
|
*/
|
|
|
|
|
void setOutputFeeSource(int outputIndex = -1);
|
|
|
|
|
|
2019-03-11 14:39:38 +01:00
|
|
|
/**
|
|
|
|
|
* For the selected output a standard output script will be generated
|
2019-03-13 20:32:18 +01:00
|
|
|
* that sends the funds to the public-key-hash (aka bitcoin-address) passed.
|
2019-03-11 14:39:38 +01:00
|
|
|
*/
|
2022-07-06 21:52:47 +02:00
|
|
|
void pushOutputPay2Address(const KeyId &address);
|
2019-03-11 14:39:38 +01:00
|
|
|
|
2024-09-06 20:42:29 +02:00
|
|
|
/**
|
|
|
|
|
* Set the current output to use the new script.
|
|
|
|
|
* See pushOutputPay2Address() and pushOutputPay2Script() for convenience
|
|
|
|
|
* versions of this method.
|
|
|
|
|
*/
|
2019-10-09 19:36:29 +02:00
|
|
|
void pushOutputScript(const CScript &script);
|
|
|
|
|
|
2024-09-06 20:42:29 +02:00
|
|
|
/**
|
|
|
|
|
* For the selected output a standard output script will be generated
|
|
|
|
|
* that sends the funds to the pay to script-hash address passed.
|
|
|
|
|
*
|
|
|
|
|
* @code
|
|
|
|
|
CashAddress::Content c = CashAddress::decodeCashAddrContent(address, "bitcoincash");
|
|
|
|
|
if (c.type == CashAddress::SCRIPT_TYPE)
|
|
|
|
|
builder.pushOutputPay2Script(c.hash);
|
|
|
|
|
* @endcode
|
|
|
|
|
*/
|
|
|
|
|
void pushOutputPay2Script(const std::vector<uint8_t> &p2SHash);
|
2021-04-22 12:46:35 +02:00
|
|
|
|
2021-03-24 11:47:22 +01:00
|
|
|
/**
|
|
|
|
|
* For the selected output a standard output script will be generated
|
|
|
|
|
* that becomes a prunable (provable unspendable) output based on the OP_RETURN opcode.
|
|
|
|
|
*/
|
|
|
|
|
void pushOutputNullData(const std::vector<uint8_t> &data);
|
|
|
|
|
|
2019-03-13 20:32:18 +01:00
|
|
|
/// delete an output based on index. Updates current output index.
|
2019-03-11 14:39:38 +01:00
|
|
|
void deleteOutput(int index);
|
|
|
|
|
|
2024-09-07 10:34:59 +02:00
|
|
|
/**
|
|
|
|
|
* For the selected output, start a cashtoken with given category and bitfield.
|
|
|
|
|
* Note that if you state a commitment or amount is to be given, you should
|
|
|
|
|
* call the pushNftCommitment() or pushOutputFtValue() respectively.
|
|
|
|
|
*/
|
|
|
|
|
void startOutputToken(const uint256 &category, uint8_t bitfield);
|
|
|
|
|
/**
|
|
|
|
|
* For the selected output, add commitment data.
|
|
|
|
|
* This method throws if you have not started a token, or the bitfield did
|
|
|
|
|
* not include a commitment.
|
2026-05-14 14:40:17 +02:00
|
|
|
* We also throw if the size is larger than 128 bytes.
|
2024-09-07 10:34:59 +02:00
|
|
|
*/
|
|
|
|
|
void pushNftCommitment(const std::vector<uint8_t> &data);
|
|
|
|
|
/**
|
|
|
|
|
* For the selected output, add the number of fungible tokens this
|
|
|
|
|
* output includes.
|
|
|
|
|
* This method throws if you have not started a token, or the bitfield did
|
|
|
|
|
* not include an amount.
|
|
|
|
|
*/
|
|
|
|
|
void pushOutputFtAmount(uint64_t amount);
|
|
|
|
|
/**
|
|
|
|
|
* Remove the token data from the currently selected output.
|
|
|
|
|
*/
|
|
|
|
|
void clearOutputToken();
|
|
|
|
|
|
2019-03-13 20:32:18 +01:00
|
|
|
/**
|
|
|
|
|
* Render the state of the transaction, signing any inputs that we have signing data for.
|
2022-04-15 17:33:55 +02:00
|
|
|
*
|
|
|
|
|
* Inputs that did not explicitly got an pushInputSignature() called will not be signed and
|
|
|
|
|
* instead left unchanged.
|
|
|
|
|
*
|
|
|
|
|
* @see pushInputSignature()
|
|
|
|
|
* @see setAnonimize()
|
2019-03-13 20:32:18 +01:00
|
|
|
*
|
|
|
|
|
* @param optional pool to use for memory allocation.
|
|
|
|
|
*/
|
2024-10-04 12:09:55 +02:00
|
|
|
Tx createTransaction(const std::shared_ptr<Streaming::BufferPool> &pool = nullptr) const;
|
2019-03-11 14:39:38 +01:00
|
|
|
|
2022-04-15 17:33:55 +02:00
|
|
|
/// return if the transaction created by createTransaction() will be anonimized
|
|
|
|
|
bool anonimize() const;
|
|
|
|
|
/**
|
|
|
|
|
* By turning on the anonimize feature transactions created by createTransaction() will have their
|
|
|
|
|
* inputs and outputs sorted according to BIP69, which as the intention that wallet apps and concepts
|
|
|
|
|
* like change-address are at least obfuscated in their meaning. This is meant to highten the
|
|
|
|
|
* anonimity of the transaction.
|
|
|
|
|
*
|
|
|
|
|
* See https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki
|
|
|
|
|
*/
|
|
|
|
|
void setAnonimize(bool on);
|
2019-03-11 14:39:38 +01:00
|
|
|
|
2024-03-13 17:02:19 +01:00
|
|
|
/**
|
|
|
|
|
* Change the transaction version to \a txVersion.
|
|
|
|
|
* The transaction version passed into the builder is used otherwise, or the default (2) if the empty constructor is used.
|
|
|
|
|
*/
|
|
|
|
|
void setTransactionVersion(int txVersion);
|
|
|
|
|
/**
|
|
|
|
|
* Returns the transaction version.
|
|
|
|
|
*/
|
|
|
|
|
int transactionVersion() const;
|
|
|
|
|
|
2019-03-11 14:39:38 +01:00
|
|
|
private:
|
2022-04-15 17:33:55 +02:00
|
|
|
TransactionBuilder(const TransactionBuilder&) = delete;
|
|
|
|
|
TransactionBuilder &operator=(const TransactionBuilder&) = delete;
|
2020-05-28 22:34:49 +02:00
|
|
|
TransactionBuilderPrivate *d;
|
2019-03-11 14:39:38 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|