UNPKG

12.7 kBMarkdownView Raw
1# Transaction
2
3Bitcore provides a very simple API for creating transactions. We expect this API to be accessible for developers without knowing the working internals of bitcoin in deep detail. What follows is a small introduction to transactions with some basic knowledge required to use this API.
4
5A Transaction contains a set of inputs and a set of outputs. Each input contains a reference to another transaction's output, and a signature that allows the value referenced in that output to be used in this transaction.
6
7Note also that an output can be used only once. That's why there's a concept of "change address" in the bitcoin ecosystem: if an output of 10 BTC is available for me to spend, but I only need to transmit 1 BTC, I'll create a transaction with two outputs, one with 1 BTC that I want to spend, and the other with 9 BTC to a change address, so I can spend this 9 BTC with another private key that I own.
8
9So, in order to transmit a valid transaction, you must know what other transactions on the network store outputs that have not been spent and that are available for you to spend (meaning that you have the set of keys that can validate you own those funds). The unspent outputs are usually referred to as "utxo"s.
10
11Let's take a look at some very simple transactions:
12
13```javascript
14var transaction = new Transaction()
15 .from(utxos) // Feed information about what unspent outputs one can use
16 .to(address, amount) // Add an output with the given amount of satoshis
17 .change(address) // Sets up a change address where the rest of the funds will go
18 .sign(privkeySet) // Signs all the inputs it can
19```
20
21You can obtain the input and output total amounts of the transaction in satoshis by accessing the fields `inputAmount` and `outputAmount`.
22
23Now, this could just be serialized to hexadecimal ASCII values (`transaction.serialize()`) and sent over to the bitcoind reference client.
24
25```sh
26bitcoin-cli sendrawtransaction <serialized transaction>
27```
28
29You can also override the fee estimation with another amount, specified in satoshis:
30
31```javascript
32var transaction = new Transaction().fee(5430); // Minimum non-dust amount
33var transaction = new Transaction().fee(1e8); // Generous fee of 1 BTC
34```
35
36## Multisig Transactions
37
38To send a transaction to a multisig address, the API is the same as in the above example. To spend outputs that require multiple signatures, the process needs extra information: the public keys of the signers that can unlock that output.
39
40```javascript
41var multiSigTx = new Transaction()
42 .from(utxo, publicKeys, threshold)
43 .change(address)
44 .sign(myKeys);
45
46var serialized = multiSigTx.toObject();
47```
48
49This can be serialized and sent to another party, to complete with the needed signatures:
50
51```javascript
52var multiSigTx = new Transaction(serialized)
53 .sign(anotherSetOfKeys);
54
55assert(multiSigTx.isFullySigned());
56```
57
58Also, you can just send over the signature for your private key:
59
60```javascript
61var multiSigTx = new Transaction()
62 .from(utxo, publicKeys, threshold)
63 .change(address);
64
65var signature = multiSigTx.getSignatures(privateKey)[0];
66console.log(JSON.stringify(signature));
67console.log(signature.toObject());
68console.log(signature.signature.toString()); // Outputs a DER signature
69console.log(signature.sigtype);
70```
71
72Transfer that over the wire, and on the other side, apply it to a transaction:
73
74```javascript
75assert(transaction.isValidSignature(receivedSig));
76transaction.applySignature(receivedSig);
77```
78
79## Adding inputs
80
81Transaction inputs are instances of either [Input](https://github.com/bitpay/bitcore/tree/master/lib/transaction/input) or its subclasses. `Input` has some abstract methods, as there is no actual concept of a "signed input" in the bitcoin scripting system (just valid signatures for <tt>OP_CHECKSIG</tt> and similar opcodes). They are stored in the `input` property of `Transaction` instances.
82
83Bitcore contains two implementations of `Input`, one for spending _Pay to Public Key Hash_ outputs (called `PublicKeyHashInput`) and another to spend _Pay to Script Hash_ outputs for which the redeem script is a Multisig script (called `MultisigScriptHashInput`).
84
85All inputs have the following five properties:
86
87- `prevTxId`: a `Buffer` with the id of the transaction with the output this input is spending
88- `outputIndex`: a `number` the index of the output in the previous transaction
89- `sequenceNumber`: a `number`, the sequence number, see [bitcoin's developer guide on nLockTime and the sequence number](https://bitcoin.org/en/developer-guide#locktime-and-sequence-number).
90- `script`: the `Script` instance for this input. Usually called `scriptSig` in the bitcoin community.
91- `output`: if available, a `Output` instance of the output associated with this input.
92
93Both `PublicKeyHashInput` and `MultisigScriptHashInput` cache the information about signatures, even though this information could somehow be encoded in the script. Both need to have the `output` property set in order to calculate the `sighash` so signatures can be created.
94
95Some methods related to adding inputs are:
96
97- `from`: A high level interface to add an input from a UTXO. It has a series of variants:
98 - `from(utxo)`: add an input from an [Unspent Transaction Output](http://bitcore.io/guide/unspentoutput.html). Currently, only P2PKH outputs are supported.
99 - `from(utxos)`: same as above, but passing in an array of Unspent Outputs.
100 - `from(utxo, publicKeys, threshold)`: add an input that spends a UTXO with a P2SH output for a Multisig script. The `publicKeys` argument is an array of public keys, and `threshold` is the number of required signatures in the Multisig script.
101
102- `addInput`: Performs a series of checks on an input and appends it to the end of the `input` vector and updates the amount of incoming bitcoins of the transaction.
103- `uncheckedAddInput`: adds an input to the end of the `input` vector and updates the `inputAmount` without performing any checks.
104
105### PublicKeyHashInput
106
107This input uses the `script` property to mark the input as unsigned if the script is empty.
108
109### MultisigScriptHashInput
110
111This input contains a set of signatures in a `signatures` property, and each time a signature is added, a potentially partial and/or invalid script is created. The `isFullySigned` method will only return true if all needed signatures are already added and valid. If `addSignature` is added after all need signatures are already set, an exception will be thrown.
112
113## Signing a Transaction
114
115The following methods are used to manage signatures for a transaction:
116
117- `getSignatures`: takes an array of `PrivateKey` or strings from which a `PrivateKey` can be instantiated; the transaction to be signed; the kind of [signature hash to use](https://bitcoin.org/en/developer-guide#signature-hash-types). Returns an array of objects with the following properties:
118 - `signature`: an instance of [Signature](https://github.com/bitpay/bitcore/blob/master/lib/crypto/signature.js)
119 - `prevTxId`: this input's `prevTxId`,
120 - `outputIndex`: this input's `outputIndex`,
121 - `inputIndex`: this input's index in the transaction
122 - `sigtype`: the "sighash", the type of transaction hash used to calculate the signature
123 - `publicKey`: a `PublicKey` of the `PrivateKey` used to create the signature
124
125- `addSignature`: takes an element outputed by `getSignatures` and applies the signature to this input (modifies the script to include the new signature).
126- `clearSignatures`: removes all signatures for this input
127- `isFullySigned`: returns true if the input is fully signed
128
129## Handling Outputs
130
131Outputs can be added by:
132
133- The `addOutput(output)` method, which pushes an `Output` to the end of the `outputs` property and updates the `outputAmount` field. It also clears signatures (as the hash of the transaction may have changed) and updates the change output.
134- The `to(address, amount)` method, that adds an output with the script that corresponds to the given address. Builds an output and calls the `addOutput` method.
135- Specifying a [change address](#Fee_calculation)
136
137To remove all outputs, you can use `clearOutputs()`, which preserves change output configuration.
138
139## Serialization
140
141There are a series of methods used for serialization:
142
143- `toObject`: Returns a plain JavaScript object with no methods and enough information to fully restore the state of this transaction. Using other serialization methods (except for `toJSON`) will cause a some information to be lost.
144- `toJSON`: Will be called when using `JSON.stringify` to return JSON-encoded string using the output from `toObject`.
145- `toString` or `uncheckedSerialize`: Returns an hexadecimal serialization of the transaction, in the [serialization format for bitcoin](https://bitcoin.org/en/developer-reference#raw-transaction-format).
146- `serialize`: Does a series of checks before serializing the transaction
147- `inspect`: Returns a string with some information about the transaction (currently a string formatted as `<Transaction 000...000>`, that only shows the serialized value of the transaction.
148- `toBuffer`: Serializes the transaction for sending over the wire in the bitcoin network
149- `toBufferWriter`: Uses an already existing BufferWriter to copy over the serialized transaction
150
151## Serialization Checks
152
153When serializing, the bitcore library performs a series of checks. These can be disabled by providing an object to the `serialize` method with the checks that you'll like to skip.
154
155- `disableLargeFees` avoids checking that the fee is no more than `Transaction.FEE_PER_KB * Transaction.FEE_SECURITY_MARGIN * size_in_kb`.
156- `disableSmallFees` avoids checking that the fee is less than `Transaction.FEE_PER_KB * size_in_kb / Transaction.FEE_SECURITY_MARGIN`.
157- `disableIsFullySigned` does not check if all inputs are fully signed
158- `disableDustOutputs` does not check for dust outputs being generated
159- `disableMoreOutputThanInput` avoids checking that the sum of the output amounts is less than or equal to the sum of the amounts for the outputs being spent in the transaction
160
161These are the current default values in the bitcore library involved on these checks:
162
163- `Transaction.FEE_PER_KB`: `10000` (satoshis per kilobyte)
164- `Transaction.FEE_SECURITY_MARGIN`: `15`
165- `Transaction.DUST_AMOUNT`: `546` (satoshis)
166
167## Fee calculation
168
169When outputs' value don't sum up to the same amount that inputs, the difference in bitcoins goes to the miner of the block that includes this transaction. The concept of a "change address" usually is associated with this: an output with an address that can be spent by the creator of the transaction.
170
171For this reason, some methods in the Transaction class are provided:
172
173- `change(address)`: Set up the change address. This will set an internal `_changeScript` property that will store the change script associated with that address.
174- `fee(amount)`: Sets up the exact amount of fee to pay. If no change address is provided, this will raise an exception.
175- `getFee()`: returns the estimated fee amount to be paid, based on the size of the transaction, but disregarding the priority of the outputs.
176
177Internally, a `_changeIndex` property stores the index of the change output (so it can get updated when a new input or output is added).
178
179## Time-Locking transaction
180
181All bitcoin transactions contain a locktime field. The locktime indicates the earliest time a transaction can be added to the blockchain. Locktime allows signers to create time-locked transactions which will only become valid in the future, giving the signers a chance to change their minds. Locktime can be set in the form of a bitcoin block height (the transaction can only be included in a block with a higher height than specified) or a linux timestamp (transaction can only be confirmed after that time). For more information see [bitcoin's development guide section on locktime](https://bitcoin.org/en/developer-guide#locktime-and-sequence-number).
182
183In bitcore, you can set a `Transaction`'s locktime by using the methods `Transaction#lockUntilDate` and `Transaction#lockUntilBlockHeight`. You can also get a friendly version of the locktime field via `Transaction#getLockTime`;
184
185For example:
186
187```javascript
188var future = new Date(2025,10,30); // Sun Nov 30 2025
189var transaction = new Transaction()
190 .lockUntilDate(future);
191console.log(transaction.getLockTime());
192// output similar to: Sun Nov 30 2025 00:00:00 GMT-0300 (ART)
193```
194
195## Upcoming changes
196
197We're debating an API for Merge Avoidance, CoinJoin, Smart contracts, CoinSwap, and Stealth Addresses. We're expecting to have all of them by some time in 2015. Payment channel creation is available in the [bitcore-channel](https://github.com/bitpay/bitcore-channel) module.