Source: primitives/mtx.js

  1. /*!
  2. * mtx.js - mutable transaction object for bcoin
  3. * Copyright (c) 2014-2015, Fedor Indutny (MIT License)
  4. * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
  5. * https://github.com/bcoin-org/bcoin
  6. */
  7. 'use strict';
  8. const assert = require('bsert');
  9. const {encoding} = require('bufio');
  10. const {BufferMap} = require('buffer-map');
  11. const Script = require('../script/script');
  12. const TX = require('./tx');
  13. const Input = require('./input');
  14. const Output = require('./output');
  15. const Coin = require('./coin');
  16. const Outpoint = require('./outpoint');
  17. const CoinView = require('../coins/coinview');
  18. const Address = require('./address');
  19. const consensus = require('../protocol/consensus');
  20. const policy = require('../protocol/policy');
  21. const Amount = require('../btc/amount');
  22. const Stack = require('../script/stack');
  23. const util = require('../utils/util');
  24. const {inspectSymbol} = require('../utils');
  25. /**
  26. * MTX
  27. * A mutable transaction object.
  28. * @alias module:primitives.MTX
  29. * @extends TX
  30. * @property {Number} changeIndex
  31. * @property {CoinView} view
  32. */
  33. class MTX extends TX {
  34. /**
  35. * Create a mutable transaction.
  36. * @alias module:primitives.MTX
  37. * @constructor
  38. * @param {Object} options
  39. */
  40. constructor(options) {
  41. super();
  42. this.mutable = true;
  43. this.changeIndex = -1;
  44. this.view = new CoinView();
  45. if (options)
  46. this.fromOptions(options);
  47. }
  48. /**
  49. * Inject properties from options object.
  50. * @private
  51. * @param {Object} options
  52. */
  53. fromOptions(options) {
  54. if (options.version != null) {
  55. assert((options.version >>> 0) === options.version,
  56. 'Version must a be uint32.');
  57. this.version = options.version;
  58. }
  59. if (options.inputs) {
  60. assert(Array.isArray(options.inputs), 'Inputs must be an array.');
  61. for (const input of options.inputs)
  62. this.addInput(input);
  63. }
  64. if (options.outputs) {
  65. assert(Array.isArray(options.outputs), 'Outputs must be an array.');
  66. for (const output of options.outputs)
  67. this.addOutput(output);
  68. }
  69. if (options.locktime != null) {
  70. assert((options.locktime >>> 0) === options.locktime,
  71. 'Locktime must be a uint32.');
  72. this.locktime = options.locktime;
  73. }
  74. if (options.changeIndex != null) {
  75. if (options.changeIndex !== -1) {
  76. assert((options.changeIndex >>> 0) === options.changeIndex,
  77. 'Change index must be a uint32.');
  78. this.changeIndex = options.changeIndex;
  79. } else {
  80. this.changeIndex = -1;
  81. }
  82. }
  83. return this;
  84. }
  85. /**
  86. * Instantiate MTX from options.
  87. * @param {Object} options
  88. * @returns {MTX}
  89. */
  90. static fromOptions(options) {
  91. return new this().fromOptions(options);
  92. }
  93. /**
  94. * Clone the transaction. Note that
  95. * this will not carry over the view.
  96. * @returns {MTX}
  97. */
  98. clone() {
  99. const mtx = new this.constructor();
  100. mtx.inject(this);
  101. mtx.changeIndex = this.changeIndex;
  102. return mtx;
  103. }
  104. /**
  105. * Add an input to the transaction.
  106. * @param {Input|Object} options
  107. * @returns {Input}
  108. *
  109. * @example
  110. * mtx.addInput({ prevout: { hash: ... }, script: ... });
  111. * mtx.addInput(new Input());
  112. */
  113. addInput(options) {
  114. const input = Input.fromOptions(options);
  115. this.inputs.push(input);
  116. return input;
  117. }
  118. /**
  119. * Add an outpoint as an input.
  120. * @param {Outpoint|Object} outpoint
  121. * @returns {Input}
  122. *
  123. * @example
  124. * mtx.addOutpoint({ hash: ..., index: 0 });
  125. * mtx.addOutpoint(new Outpoint(hash, index));
  126. */
  127. addOutpoint(outpoint) {
  128. const prevout = Outpoint.fromOptions(outpoint);
  129. const input = Input.fromOutpoint(prevout);
  130. this.inputs.push(input);
  131. return input;
  132. }
  133. /**
  134. * Add a coin as an input. Note that this will
  135. * add the coin to the internal coin viewpoint.
  136. * @param {Coin} coin
  137. * @returns {Input}
  138. *
  139. * @example
  140. * mtx.addCoin(Coin.fromTX(tx, 0, -1));
  141. */
  142. addCoin(coin) {
  143. assert(coin instanceof Coin, 'Cannot add non-coin.');
  144. const input = Input.fromCoin(coin);
  145. this.inputs.push(input);
  146. this.view.addCoin(coin);
  147. return input;
  148. }
  149. /**
  150. * Add a transaction as an input. Note that
  151. * this will add the coin to the internal
  152. * coin viewpoint.
  153. * @param {TX} tx
  154. * @param {Number} index
  155. * @param {Number?} height
  156. * @returns {Input}
  157. *
  158. * @example
  159. * mtx.addTX(tx, 0);
  160. */
  161. addTX(tx, index, height) {
  162. assert(tx instanceof TX, 'Cannot add non-transaction.');
  163. if (height == null)
  164. height = -1;
  165. const input = Input.fromTX(tx, index);
  166. this.inputs.push(input);
  167. this.view.addIndex(tx, index, height);
  168. return input;
  169. }
  170. /**
  171. * Add an output.
  172. * @param {Address|Script|Output|Object} script - Script or output options.
  173. * @param {Amount?} value
  174. * @returns {Output}
  175. *
  176. * @example
  177. * mtx.addOutput(new Output());
  178. * mtx.addOutput({ address: ..., value: 100000 });
  179. * mtx.addOutput(address, 100000);
  180. * mtx.addOutput(script, 100000);
  181. */
  182. addOutput(script, value) {
  183. let output;
  184. if (value != null)
  185. output = Output.fromScript(script, value);
  186. else
  187. output = Output.fromOptions(script);
  188. this.outputs.push(output);
  189. return output;
  190. }
  191. /**
  192. * Verify all transaction inputs.
  193. * @param {VerifyFlags} [flags=STANDARD_VERIFY_FLAGS]
  194. * @returns {Boolean} Whether the inputs are valid.
  195. * @throws {ScriptError} on invalid inputs
  196. */
  197. check(flags) {
  198. return super.check(this.view, flags);
  199. }
  200. /**
  201. * Verify the transaction inputs on the worker pool
  202. * (if workers are enabled).
  203. * @param {VerifyFlags?} [flags=STANDARD_VERIFY_FLAGS]
  204. * @param {WorkerPool?} pool
  205. * @returns {Promise}
  206. */
  207. checkAsync(flags, pool) {
  208. return super.checkAsync(this.view, flags, pool);
  209. }
  210. /**
  211. * Verify all transaction inputs.
  212. * @param {VerifyFlags} [flags=STANDARD_VERIFY_FLAGS]
  213. * @returns {Boolean} Whether the inputs are valid.
  214. */
  215. verify(flags) {
  216. try {
  217. this.check(flags);
  218. } catch (e) {
  219. if (e.type === 'ScriptError')
  220. return false;
  221. throw e;
  222. }
  223. return true;
  224. }
  225. /**
  226. * Verify the transaction inputs on the worker pool
  227. * (if workers are enabled).
  228. * @param {VerifyFlags?} [flags=STANDARD_VERIFY_FLAGS]
  229. * @param {WorkerPool?} pool
  230. * @returns {Promise}
  231. */
  232. async verifyAsync(flags, pool) {
  233. try {
  234. await this.checkAsync(flags, pool);
  235. } catch (e) {
  236. if (e.type === 'ScriptError')
  237. return false;
  238. throw e;
  239. }
  240. return true;
  241. }
  242. /**
  243. * Calculate the fee for the transaction.
  244. * @returns {Amount} fee (zero if not all coins are available).
  245. */
  246. getFee() {
  247. return super.getFee(this.view);
  248. }
  249. /**
  250. * Calculate the total input value.
  251. * @returns {Amount} value
  252. */
  253. getInputValue() {
  254. return super.getInputValue(this.view);
  255. }
  256. /**
  257. * Get all input addresses.
  258. * @returns {Address[]} addresses
  259. */
  260. getInputAddresses() {
  261. return super.getInputAddresses(this.view);
  262. }
  263. /**
  264. * Get all addresses.
  265. * @returns {Address[]} addresses
  266. */
  267. getAddresses() {
  268. return super.getAddresses(this.view);
  269. }
  270. /**
  271. * Get all input address hashes.
  272. * @returns {Hash[]} hashes
  273. */
  274. getInputHashes(enc) {
  275. return super.getInputHashes(this.view, enc);
  276. }
  277. /**
  278. * Get all address hashes.
  279. * @returns {Hash[]} hashes
  280. */
  281. getHashes(enc) {
  282. return super.getHashes(this.view, enc);
  283. }
  284. /**
  285. * Test whether the transaction has
  286. * all coins available/filled.
  287. * @returns {Boolean}
  288. */
  289. hasCoins() {
  290. return super.hasCoins(this.view);
  291. }
  292. /**
  293. * Calculate virtual sigop count.
  294. * @param {VerifyFlags?} flags
  295. * @returns {Number} sigop count
  296. */
  297. getSigops(flags) {
  298. return super.getSigops(this.view, flags);
  299. }
  300. /**
  301. * Calculate sigops weight, taking into account witness programs.
  302. * @param {VerifyFlags?} flags
  303. * @returns {Number} sigop weight
  304. */
  305. getSigopsCost(flags) {
  306. return super.getSigopsCost(this.view, flags);
  307. }
  308. /**
  309. * Calculate the virtual size of the transaction
  310. * (weighted against bytes per sigop cost).
  311. * @returns {Number} vsize
  312. */
  313. getSigopsSize() {
  314. return super.getSigopsSize(this.getSigopsCost());
  315. }
  316. /**
  317. * Perform contextual checks to verify input, output,
  318. * and fee values, as well as coinbase spend maturity
  319. * (coinbases can only be spent 100 blocks or more
  320. * after they're created). Note that this function is
  321. * consensus critical.
  322. * @param {Number} height - Height at which the
  323. * transaction is being spent. In the mempool this is
  324. * the chain height plus one at the time it entered the pool.
  325. * @returns {Boolean}
  326. */
  327. verifyInputs(height) {
  328. const [fee] = this.checkInputs(height);
  329. return fee !== -1;
  330. }
  331. /**
  332. * Perform contextual checks to verify input, output,
  333. * and fee values, as well as coinbase spend maturity
  334. * (coinbases can only be spent 100 blocks or more
  335. * after they're created). Note that this function is
  336. * consensus critical.
  337. * @param {Number} height - Height at which the
  338. * transaction is being spent. In the mempool this is
  339. * the chain height plus one at the time it entered the pool.
  340. * @returns {Array} [fee, reason, score]
  341. */
  342. checkInputs(height) {
  343. return super.checkInputs(this.view, height);
  344. }
  345. /**
  346. * Build input script (or witness) templates (with
  347. * OP_0 in place of signatures).
  348. * @param {Number} index - Input index.
  349. * @param {Coin|Output} coin
  350. * @param {KeyRing} ring
  351. * @returns {Boolean} Whether the script was able to be built.
  352. */
  353. scriptInput(index, coin, ring) {
  354. const input = this.inputs[index];
  355. assert(input, 'Input does not exist.');
  356. assert(coin, 'No coin passed.');
  357. // Don't bother with any below calculation
  358. // if the output is already templated.
  359. if (input.script.raw.length !== 0
  360. || input.witness.items.length !== 0) {
  361. return true;
  362. }
  363. // Get the previous output's script
  364. const prev = coin.script;
  365. // This is easily the hardest part about
  366. // building a transaction with segwit:
  367. // figuring out where the redeem script
  368. // and witness redeem scripts go.
  369. const sh = prev.getScripthash();
  370. if (sh) {
  371. const redeem = ring.getRedeem(sh);
  372. if (!redeem)
  373. return false;
  374. // Witness program nested in regular P2SH.
  375. if (redeem.isProgram()) {
  376. // P2WSH nested within pay-to-scripthash.
  377. const wsh = redeem.getWitnessScripthash();
  378. if (wsh) {
  379. const wredeem = ring.getRedeem(wsh);
  380. if (!wredeem)
  381. return false;
  382. const witness = this.scriptVector(wredeem, ring);
  383. if (!witness)
  384. return false;
  385. witness.push(wredeem.toRaw());
  386. input.witness.fromStack(witness);
  387. input.script.fromItems([redeem.toRaw()]);
  388. return true;
  389. }
  390. // P2WPKH nested within pay-to-scripthash.
  391. const wpkh = redeem.getWitnessPubkeyhash();
  392. if (wpkh) {
  393. const pkh = Script.fromPubkeyhash(wpkh);
  394. const witness = this.scriptVector(pkh, ring);
  395. if (!witness)
  396. return false;
  397. input.witness.fromStack(witness);
  398. input.script.fromItems([redeem.toRaw()]);
  399. return true;
  400. }
  401. // Unknown witness program.
  402. return false;
  403. }
  404. // Regular P2SH.
  405. const vector = this.scriptVector(redeem, ring);
  406. if (!vector)
  407. return false;
  408. vector.push(redeem.toRaw());
  409. input.script.fromStack(vector);
  410. return true;
  411. }
  412. // Witness program.
  413. if (prev.isProgram()) {
  414. // Bare P2WSH.
  415. const wsh = prev.getWitnessScripthash();
  416. if (wsh) {
  417. const wredeem = ring.getRedeem(wsh);
  418. if (!wredeem)
  419. return false;
  420. const vector = this.scriptVector(wredeem, ring);
  421. if (!vector)
  422. return false;
  423. vector.push(wredeem.toRaw());
  424. input.witness.fromStack(vector);
  425. return true;
  426. }
  427. // Bare P2WPKH.
  428. const wpkh = prev.getWitnessPubkeyhash();
  429. if (wpkh) {
  430. const pkh = Script.fromPubkeyhash(wpkh);
  431. const vector = this.scriptVector(pkh, ring);
  432. if (!vector)
  433. return false;
  434. input.witness.fromStack(vector);
  435. return true;
  436. }
  437. // Bare... who knows?
  438. return false;
  439. }
  440. // Wow, a normal output! Praise be to Jengus and Gord.
  441. const vector = this.scriptVector(prev, ring);
  442. if (!vector)
  443. return false;
  444. input.script.fromStack(vector);
  445. return true;
  446. }
  447. /**
  448. * Build script for a single vector
  449. * based on a previous script.
  450. * @param {Script} prev
  451. * @param {Buffer} ring
  452. * @return {Stack}
  453. */
  454. scriptVector(prev, ring) {
  455. // P2PK
  456. const pk = prev.getPubkey();
  457. if (pk) {
  458. if (!pk.equals(ring.publicKey))
  459. return null;
  460. const stack = new Stack();
  461. stack.pushInt(0);
  462. return stack;
  463. }
  464. // P2PKH
  465. const pkh = prev.getPubkeyhash();
  466. if (pkh) {
  467. if (!pkh.equals(ring.getKeyHash()))
  468. return null;
  469. const stack = new Stack();
  470. stack.pushInt(0);
  471. stack.pushData(ring.publicKey);
  472. return stack;
  473. }
  474. // Multisig
  475. const [, n] = prev.getMultisig();
  476. if (n !== -1) {
  477. if (prev.indexOf(ring.publicKey) === -1)
  478. return null;
  479. // Technically we should create m signature slots,
  480. // but we create n signature slots so we can order
  481. // the signatures properly.
  482. const stack = new Stack();
  483. stack.pushInt(0);
  484. // Fill script with `n` signature slots.
  485. for (let i = 0; i < n; i++)
  486. stack.pushInt(0);
  487. return stack;
  488. }
  489. return null;
  490. }
  491. /**
  492. * Sign a transaction input on the worker pool
  493. * (if workers are enabled).
  494. * @param {Number} index
  495. * @param {Coin|Output} coin
  496. * @param {KeyRing} ring
  497. * @param {SighashType?} type
  498. * @param {WorkerPool?} pool
  499. * @returns {Promise}
  500. */
  501. async signInputAsync(index, coin, ring, type, pool) {
  502. if (!pool)
  503. return this.signInput(index, coin, ring, type);
  504. return await pool.signInput(this, index, coin, ring, type, pool);
  505. }
  506. /**
  507. * Sign an input.
  508. * @param {Number} index - Index of input being signed.
  509. * @param {Coin|Output} coin
  510. * @param {KeyRing} ring - Private key.
  511. * @param {SighashType} type
  512. * @returns {Boolean} Whether the input was able to be signed.
  513. */
  514. signInput(index, coin, ring, type) {
  515. const input = this.inputs[index];
  516. const key = ring.privateKey;
  517. assert(input, 'Input does not exist.');
  518. assert(coin, 'No coin passed.');
  519. // Get the previous output's script
  520. const value = coin.value;
  521. let prev = coin.script;
  522. let vector = input.script;
  523. let version = 0;
  524. let redeem = false;
  525. // Grab regular p2sh redeem script.
  526. if (prev.isScripthash()) {
  527. prev = input.script.getRedeem();
  528. if (!prev)
  529. throw new Error('Input has not been templated.');
  530. redeem = true;
  531. }
  532. // If the output script is a witness program,
  533. // we have to switch the vector to the witness
  534. // and potentially alter the length. Note that
  535. // witnesses are stack items, so the `dummy`
  536. // _has_ to be an empty buffer (what OP_0
  537. // pushes onto the stack).
  538. if (prev.isWitnessScripthash()) {
  539. prev = input.witness.getRedeem();
  540. if (!prev)
  541. throw new Error('Input has not been templated.');
  542. vector = input.witness;
  543. redeem = true;
  544. version = 1;
  545. } else {
  546. const wpkh = prev.getWitnessPubkeyhash();
  547. if (wpkh) {
  548. prev = Script.fromPubkeyhash(wpkh);
  549. vector = input.witness;
  550. redeem = false;
  551. version = 1;
  552. }
  553. }
  554. // Create our signature.
  555. const sig = this.signature(index, prev, value, key, type, version);
  556. if (redeem) {
  557. const stack = vector.toStack();
  558. const redeem = stack.pop();
  559. const result = this.signVector(prev, stack, sig, ring);
  560. if (!result)
  561. return false;
  562. result.push(redeem);
  563. vector.fromStack(result);
  564. return true;
  565. }
  566. const stack = vector.toStack();
  567. const result = this.signVector(prev, stack, sig, ring);
  568. if (!result)
  569. return false;
  570. vector.fromStack(result);
  571. return true;
  572. }
  573. /**
  574. * Add a signature to a vector
  575. * based on a previous script.
  576. * @param {Script} prev
  577. * @param {Stack} vector
  578. * @param {Buffer} sig
  579. * @param {KeyRing} ring
  580. * @return {Boolean}
  581. */
  582. signVector(prev, vector, sig, ring) {
  583. // P2PK
  584. const pk = prev.getPubkey();
  585. if (pk) {
  586. // Make sure the pubkey is ours.
  587. if (!ring.publicKey.equals(pk))
  588. return null;
  589. if (vector.length === 0)
  590. throw new Error('Input has not been templated.');
  591. // Already signed.
  592. if (vector.get(0).length > 0)
  593. return vector;
  594. vector.set(0, sig);
  595. return vector;
  596. }
  597. // P2PKH
  598. const pkh = prev.getPubkeyhash();
  599. if (pkh) {
  600. // Make sure the pubkey hash is ours.
  601. if (!ring.getKeyHash().equals(pkh))
  602. return null;
  603. if (vector.length !== 2)
  604. throw new Error('Input has not been templated.');
  605. if (vector.get(1).length === 0)
  606. throw new Error('Input has not been templated.');
  607. // Already signed.
  608. if (vector.get(0).length > 0)
  609. return vector;
  610. vector.set(0, sig);
  611. return vector;
  612. }
  613. // Multisig
  614. const [m, n] = prev.getMultisig();
  615. if (m !== -1) {
  616. if (vector.length < 2)
  617. throw new Error('Input has not been templated.');
  618. if (vector.get(0).length !== 0)
  619. throw new Error('Input has not been templated.');
  620. // Too many signature slots. Abort.
  621. if (vector.length - 1 > n)
  622. throw new Error('Input has not been templated.');
  623. // Count the number of current signatures.
  624. let total = 0;
  625. for (let i = 1; i < vector.length; i++) {
  626. const item = vector.get(i);
  627. if (item.length > 0)
  628. total += 1;
  629. }
  630. // Signatures are already finalized.
  631. if (total === m && vector.length - 1 === m)
  632. return vector;
  633. // Add some signature slots for us to use if
  634. // there was for some reason not enough.
  635. while (vector.length - 1 < n)
  636. vector.pushInt(0);
  637. // Grab the redeem script's keys to figure
  638. // out where our key should go.
  639. const keys = [];
  640. for (const op of prev.code) {
  641. if (op.data)
  642. keys.push(op.data);
  643. }
  644. // Find the key index so we can place
  645. // the signature in the same index.
  646. let keyIndex = -1;
  647. for (let i = 0; i < keys.length; i++) {
  648. const key = keys[i];
  649. if (key.equals(ring.publicKey)) {
  650. keyIndex = i;
  651. break;
  652. }
  653. }
  654. // Our public key is not in the prev_out
  655. // script. We tried to sign a transaction
  656. // that is not redeemable by us.
  657. if (keyIndex === -1)
  658. return null;
  659. // Offset key index by one to turn it into
  660. // "sig index". Accounts for OP_0 byte at
  661. // the start.
  662. keyIndex += 1;
  663. // Add our signature to the correct slot
  664. // and increment the total number of
  665. // signatures.
  666. if (keyIndex < vector.length && total < m) {
  667. if (vector.get(keyIndex).length === 0) {
  668. vector.set(keyIndex, sig);
  669. total += 1;
  670. }
  671. }
  672. // All signatures added. Finalize.
  673. if (total >= m) {
  674. // Remove empty slots left over.
  675. for (let i = vector.length - 1; i >= 1; i--) {
  676. const item = vector.get(i);
  677. if (item.length === 0)
  678. vector.remove(i);
  679. }
  680. // Remove signatures which are not required.
  681. // This should never happen.
  682. while (total > m) {
  683. vector.pop();
  684. total -= 1;
  685. }
  686. // Sanity checks.
  687. assert(total === m);
  688. assert(vector.length - 1 === m);
  689. }
  690. return vector;
  691. }
  692. return null;
  693. }
  694. /**
  695. * Test whether the transaction is fully-signed.
  696. * @returns {Boolean}
  697. */
  698. isSigned() {
  699. for (let i = 0; i < this.inputs.length; i++) {
  700. const {prevout} = this.inputs[i];
  701. const coin = this.view.getOutput(prevout);
  702. if (!coin)
  703. return false;
  704. if (!this.isInputSigned(i, coin))
  705. return false;
  706. }
  707. return true;
  708. }
  709. /**
  710. * Test whether an input is fully-signed.
  711. * @param {Number} index
  712. * @param {Coin|Output} coin
  713. * @returns {Boolean}
  714. */
  715. isInputSigned(index, coin) {
  716. const input = this.inputs[index];
  717. assert(input, 'Input does not exist.');
  718. assert(coin, 'No coin passed.');
  719. let prev = coin.script;
  720. let vector = input.script;
  721. let redeem = false;
  722. // Grab redeem script if possible.
  723. if (prev.isScripthash()) {
  724. prev = input.script.getRedeem();
  725. if (!prev)
  726. return false;
  727. redeem = true;
  728. }
  729. // If the output script is a witness program,
  730. // we have to switch the vector to the witness
  731. // and potentially alter the length.
  732. if (prev.isWitnessScripthash()) {
  733. prev = input.witness.getRedeem();
  734. if (!prev)
  735. return false;
  736. vector = input.witness;
  737. redeem = true;
  738. } else {
  739. const wpkh = prev.getWitnessPubkeyhash();
  740. if (wpkh) {
  741. prev = Script.fromPubkeyhash(wpkh);
  742. vector = input.witness;
  743. redeem = false;
  744. }
  745. }
  746. const stack = vector.toStack();
  747. if (redeem)
  748. stack.pop();
  749. return this.isVectorSigned(prev, stack);
  750. }
  751. /**
  752. * Test whether a vector is fully-signed.
  753. * @param {Script} prev
  754. * @param {Stack} vector
  755. * @returns {Boolean}
  756. */
  757. isVectorSigned(prev, vector) {
  758. if (prev.isPubkey()) {
  759. if (vector.length !== 1)
  760. return false;
  761. if (vector.get(0).length === 0)
  762. return false;
  763. return true;
  764. }
  765. if (prev.isPubkeyhash()) {
  766. if (vector.length !== 2)
  767. return false;
  768. if (vector.get(0).length === 0)
  769. return false;
  770. if (vector.get(1).length === 0)
  771. return false;
  772. return true;
  773. }
  774. const [m] = prev.getMultisig();
  775. if (m !== -1) {
  776. // Ensure we have the correct number
  777. // of required signatures.
  778. if (vector.length - 1 !== m)
  779. return false;
  780. // Ensure all members are signatures.
  781. for (let i = 1; i < vector.length; i++) {
  782. const item = vector.get(i);
  783. if (item.length === 0)
  784. return false;
  785. }
  786. return true;
  787. }
  788. return false;
  789. }
  790. /**
  791. * Build input scripts (or witnesses).
  792. * @param {KeyRing} ring - Address used to sign. The address
  793. * must be able to redeem the coin.
  794. * @returns {Number} Number of inputs templated.
  795. */
  796. template(ring) {
  797. if (Array.isArray(ring)) {
  798. let total = 0;
  799. for (const key of ring)
  800. total += this.template(key);
  801. return total;
  802. }
  803. let total = 0;
  804. for (let i = 0; i < this.inputs.length; i++) {
  805. const {prevout} = this.inputs[i];
  806. const coin = this.view.getOutput(prevout);
  807. if (!coin)
  808. continue;
  809. if (!ring.ownOutput(coin))
  810. continue;
  811. // Build script for input
  812. if (!this.scriptInput(i, coin, ring))
  813. continue;
  814. total += 1;
  815. }
  816. return total;
  817. }
  818. /**
  819. * Build input scripts (or witnesses) and sign the inputs.
  820. * @param {KeyRing} ring - Address used to sign. The address
  821. * must be able to redeem the coin.
  822. * @param {SighashType} type
  823. * @returns {Number} Number of inputs signed.
  824. */
  825. sign(ring, type) {
  826. if (Array.isArray(ring)) {
  827. let total = 0;
  828. for (const key of ring)
  829. total += this.sign(key, type);
  830. return total;
  831. }
  832. assert(ring.privateKey, 'No private key available.');
  833. let total = 0;
  834. for (let i = 0; i < this.inputs.length; i++) {
  835. const {prevout} = this.inputs[i];
  836. const coin = this.view.getOutput(prevout);
  837. if (!coin)
  838. continue;
  839. if (!ring.ownOutput(coin))
  840. continue;
  841. // Build script for input
  842. if (!this.scriptInput(i, coin, ring))
  843. continue;
  844. // Sign input
  845. if (!this.signInput(i, coin, ring, type))
  846. continue;
  847. total += 1;
  848. }
  849. return total;
  850. }
  851. /**
  852. * Sign the transaction inputs on the worker pool
  853. * (if workers are enabled).
  854. * @param {KeyRing} ring
  855. * @param {SighashType?} type
  856. * @param {WorkerPool?} pool
  857. * @returns {Promise}
  858. */
  859. async signAsync(ring, type, pool) {
  860. if (!pool)
  861. return this.sign(ring, type);
  862. return await pool.sign(this, ring, type);
  863. }
  864. /**
  865. * Estimate maximum possible size.
  866. * @param {Function?} estimate - Input script size estimator.
  867. * @returns {Number}
  868. */
  869. async estimateSize(estimate) {
  870. const scale = consensus.WITNESS_SCALE_FACTOR;
  871. let total = 0;
  872. // Calculate the size, minus the input scripts.
  873. total += 4;
  874. total += encoding.sizeVarint(this.inputs.length);
  875. total += this.inputs.length * 40;
  876. total += encoding.sizeVarint(this.outputs.length);
  877. for (const output of this.outputs)
  878. total += output.getSize();
  879. total += 4;
  880. // Add size for signatures and public keys
  881. for (const {prevout} of this.inputs) {
  882. const coin = this.view.getOutput(prevout);
  883. // We're out of luck here.
  884. // Just assume it's a p2pkh.
  885. if (!coin) {
  886. total += 110;
  887. continue;
  888. }
  889. // Previous output script.
  890. const prev = coin.script;
  891. // P2PK
  892. if (prev.isPubkey()) {
  893. // varint script size
  894. total += 1;
  895. // OP_PUSHDATA0 [signature]
  896. total += 1 + 73;
  897. continue;
  898. }
  899. // P2PKH
  900. if (prev.isPubkeyhash()) {
  901. // varint script size
  902. total += 1;
  903. // OP_PUSHDATA0 [signature]
  904. total += 1 + 73;
  905. // OP_PUSHDATA0 [key]
  906. total += 1 + 33;
  907. continue;
  908. }
  909. const [m] = prev.getMultisig();
  910. if (m !== -1) {
  911. let size = 0;
  912. // Bare Multisig
  913. // OP_0
  914. size += 1;
  915. // OP_PUSHDATA0 [signature] ...
  916. size += (1 + 73) * m;
  917. // varint len
  918. size += encoding.sizeVarint(size);
  919. total += size;
  920. continue;
  921. }
  922. // P2WPKH
  923. if (prev.isWitnessPubkeyhash()) {
  924. let size = 0;
  925. // varint-items-len
  926. size += 1;
  927. // varint-len [signature]
  928. size += 1 + 73;
  929. // varint-len [key]
  930. size += 1 + 33;
  931. // vsize
  932. size = (size + scale - 1) / scale | 0;
  933. total += size;
  934. continue;
  935. }
  936. // Call out to the custom estimator.
  937. if (estimate) {
  938. const size = await estimate(prev);
  939. if (size !== -1) {
  940. total += size;
  941. continue;
  942. }
  943. }
  944. // P2SH
  945. if (prev.isScripthash()) {
  946. // varint size
  947. total += 1;
  948. // 2-of-3 multisig input
  949. total += 149;
  950. continue;
  951. }
  952. // P2WSH
  953. if (prev.isWitnessScripthash()) {
  954. let size = 0;
  955. // varint-items-len
  956. size += 1;
  957. // 2-of-3 multisig input
  958. size += 149;
  959. // vsize
  960. size = (size + scale - 1) / scale | 0;
  961. total += size;
  962. continue;
  963. }
  964. // Unknown.
  965. total += 110;
  966. }
  967. return total;
  968. }
  969. /**
  970. * Select necessary coins based on total output value.
  971. * @param {Coin[]} coins
  972. * @param {Object?} options
  973. * @returns {CoinSelection}
  974. * @throws on not enough funds available.
  975. */
  976. selectCoins(coins, options) {
  977. const selector = new CoinSelector(this, options);
  978. return selector.select(coins);
  979. }
  980. /**
  981. * Attempt to subtract a fee from a single output.
  982. * @param {Number} index
  983. * @param {Amount} fee
  984. */
  985. subtractIndex(index, fee) {
  986. assert(typeof index === 'number');
  987. assert(typeof fee === 'number');
  988. const output = this.outputs[index];
  989. if (!output)
  990. throw new Error('Subtraction index does not exist.');
  991. if (output.value < fee + output.getDustThreshold())
  992. throw new Error('Could not subtract fee.');
  993. output.value -= fee;
  994. }
  995. /**
  996. * Attempt to subtract a fee from all outputs evenly.
  997. * @param {Amount} fee
  998. */
  999. subtractFee(fee) {
  1000. assert(typeof fee === 'number');
  1001. let outputs = 0;
  1002. for (const output of this.outputs) {
  1003. // Ignore nulldatas and
  1004. // other OP_RETURN scripts.
  1005. if (output.script.isUnspendable())
  1006. continue;
  1007. outputs += 1;
  1008. }
  1009. if (outputs === 0)
  1010. throw new Error('Could not subtract fee.');
  1011. const left = fee % outputs;
  1012. const share = (fee - left) / outputs;
  1013. // First pass, remove even shares.
  1014. for (const output of this.outputs) {
  1015. if (output.script.isUnspendable())
  1016. continue;
  1017. if (output.value < share + output.getDustThreshold())
  1018. throw new Error('Could not subtract fee.');
  1019. output.value -= share;
  1020. }
  1021. // Second pass, remove the remainder
  1022. // for the one unlucky output.
  1023. for (const output of this.outputs) {
  1024. if (output.script.isUnspendable())
  1025. continue;
  1026. if (output.value >= left + output.getDustThreshold()) {
  1027. output.value -= left;
  1028. return;
  1029. }
  1030. }
  1031. throw new Error('Could not subtract fee.');
  1032. }
  1033. /**
  1034. * Select coins and fill the inputs.
  1035. * @param {Coin[]} coins
  1036. * @param {Object} options - See {@link MTX#selectCoins} options.
  1037. * @returns {CoinSelector}
  1038. */
  1039. async fund(coins, options) {
  1040. assert(options, 'Options are required.');
  1041. assert(options.changeAddress, 'Change address is required.');
  1042. assert(this.inputs.length === 0, 'TX is already funded.');
  1043. // Select necessary coins.
  1044. const select = await this.selectCoins(coins, options);
  1045. // Add coins to transaction.
  1046. for (const coin of select.chosen)
  1047. this.addCoin(coin);
  1048. // Attempt to subtract fee.
  1049. if (select.subtractFee) {
  1050. const index = select.subtractIndex;
  1051. if (index !== -1)
  1052. this.subtractIndex(index, select.fee);
  1053. else
  1054. this.subtractFee(select.fee);
  1055. }
  1056. // Add a change output.
  1057. const output = new Output();
  1058. output.value = select.change;
  1059. output.script.fromAddress(select.changeAddress);
  1060. if (output.isDust(policy.MIN_RELAY)) {
  1061. // Do nothing. Change is added to fee.
  1062. this.changeIndex = -1;
  1063. assert.strictEqual(this.getFee(), select.fee + select.change);
  1064. } else {
  1065. this.outputs.push(output);
  1066. this.changeIndex = this.outputs.length - 1;
  1067. assert.strictEqual(this.getFee(), select.fee);
  1068. }
  1069. return select;
  1070. }
  1071. /**
  1072. * Sort inputs and outputs according to BIP69.
  1073. * @see https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki
  1074. */
  1075. sortMembers() {
  1076. let changeOutput = null;
  1077. if (this.changeIndex !== -1) {
  1078. changeOutput = this.outputs[this.changeIndex];
  1079. assert(changeOutput);
  1080. }
  1081. this.inputs.sort(sortInputs);
  1082. this.outputs.sort(sortOutputs);
  1083. if (this.changeIndex !== -1) {
  1084. this.changeIndex = this.outputs.indexOf(changeOutput);
  1085. assert(this.changeIndex !== -1);
  1086. }
  1087. }
  1088. /**
  1089. * Avoid fee sniping.
  1090. * @param {Number} - Current chain height.
  1091. * @see bitcoin/src/wallet/wallet.cpp
  1092. */
  1093. avoidFeeSniping(height) {
  1094. assert(typeof height === 'number', 'Must pass in height.');
  1095. if ((Math.random() * 10 | 0) === 0) {
  1096. height -= Math.random() * 100 | 0;
  1097. if (height < 0)
  1098. height = 0;
  1099. }
  1100. this.setLocktime(height);
  1101. }
  1102. /**
  1103. * Set locktime and sequences appropriately.
  1104. * @param {Number} locktime
  1105. */
  1106. setLocktime(locktime) {
  1107. assert((locktime >>> 0) === locktime, 'Locktime must be a uint32.');
  1108. assert(this.inputs.length > 0, 'Cannot set sequence with no inputs.');
  1109. for (const input of this.inputs) {
  1110. if (input.sequence === 0xffffffff)
  1111. input.sequence = 0xfffffffe;
  1112. }
  1113. this.locktime = locktime;
  1114. }
  1115. /**
  1116. * Set sequence locktime.
  1117. * @param {Number} index - Input index.
  1118. * @param {Number} locktime
  1119. * @param {Boolean?} seconds
  1120. */
  1121. setSequence(index, locktime, seconds) {
  1122. const input = this.inputs[index];
  1123. assert(input, 'Input does not exist.');
  1124. assert((locktime >>> 0) === locktime, 'Locktime must be a uint32.');
  1125. this.version = 2;
  1126. if (seconds) {
  1127. locktime >>>= consensus.SEQUENCE_GRANULARITY;
  1128. locktime &= consensus.SEQUENCE_MASK;
  1129. locktime |= consensus.SEQUENCE_TYPE_FLAG;
  1130. } else {
  1131. locktime &= consensus.SEQUENCE_MASK;
  1132. }
  1133. input.sequence = locktime;
  1134. }
  1135. /**
  1136. * Inspect the transaction.
  1137. * @returns {Object}
  1138. */
  1139. [inspectSymbol]() {
  1140. return this.format();
  1141. }
  1142. /**
  1143. * Inspect the transaction.
  1144. * @returns {Object}
  1145. */
  1146. format() {
  1147. return super.format(this.view);
  1148. }
  1149. /**
  1150. * Convert transaction to JSON.
  1151. * @returns {Object}
  1152. */
  1153. toJSON() {
  1154. return super.toJSON(null, this.view);
  1155. }
  1156. /**
  1157. * Convert transaction to JSON.
  1158. * @param {Network} network
  1159. * @returns {Object}
  1160. */
  1161. getJSON(network) {
  1162. return super.getJSON(network, this.view);
  1163. }
  1164. /**
  1165. * Inject properties from a json object
  1166. * @param {Object} json
  1167. */
  1168. fromJSON(json) {
  1169. super.fromJSON(json);
  1170. for (let i = 0; i < json.inputs.length; i++) {
  1171. const input = json.inputs[i];
  1172. const {prevout} = input;
  1173. if (!input.coin)
  1174. continue;
  1175. const coin = Coin.fromJSON(input.coin);
  1176. coin.hash = util.fromRev(prevout.hash);
  1177. coin.index = prevout.index;
  1178. this.view.addCoin(coin);
  1179. }
  1180. return this;
  1181. }
  1182. /**
  1183. * Instantiate a transaction from a
  1184. * jsonified transaction object.
  1185. * @param {Object} json - The jsonified transaction object.
  1186. * @returns {MTX}
  1187. */
  1188. static fromJSON(json) {
  1189. return new this().fromJSON(json);
  1190. }
  1191. /**
  1192. * Instantiate a transaction from a buffer reader.
  1193. * @param {BufferReader} br
  1194. * @returns {MTX}
  1195. */
  1196. static fromReader(br) {
  1197. return new this().fromReader(br);
  1198. }
  1199. /**
  1200. * Instantiate a transaction from a serialized Buffer.
  1201. * @param {Buffer} data
  1202. * @param {String?} enc - Encoding, can be `'hex'` or null.
  1203. * @returns {MTX}
  1204. */
  1205. static fromRaw(data, enc) {
  1206. if (typeof data === 'string')
  1207. data = Buffer.from(data, enc);
  1208. return new this().fromRaw(data);
  1209. }
  1210. /**
  1211. * Convert the MTX to a TX.
  1212. * @returns {TX}
  1213. */
  1214. toTX() {
  1215. return new TX().inject(this);
  1216. }
  1217. /**
  1218. * Convert the MTX to a TX.
  1219. * @returns {Array} [tx, view]
  1220. */
  1221. commit() {
  1222. return [this.toTX(), this.view];
  1223. }
  1224. /**
  1225. * Instantiate MTX from TX.
  1226. * @param {TX} tx
  1227. * @returns {MTX}
  1228. */
  1229. static fromTX(tx) {
  1230. return new this().inject(tx);
  1231. }
  1232. /**
  1233. * Test whether an object is an MTX.
  1234. * @param {Object} obj
  1235. * @returns {Boolean}
  1236. */
  1237. static isMTX(obj) {
  1238. return obj instanceof MTX;
  1239. }
  1240. }
  1241. /**
  1242. * Coin Selector
  1243. * @alias module:primitives.CoinSelector
  1244. */
  1245. class CoinSelector {
  1246. /**
  1247. * Create a coin selector.
  1248. * @constructor
  1249. * @param {TX} tx
  1250. * @param {Object?} options
  1251. */
  1252. constructor(tx, options) {
  1253. this.tx = tx.clone();
  1254. this.coins = [];
  1255. this.outputValue = 0;
  1256. this.index = 0;
  1257. this.chosen = [];
  1258. this.change = 0;
  1259. this.fee = CoinSelector.MIN_FEE;
  1260. this.selection = 'value';
  1261. this.subtractFee = false;
  1262. this.subtractIndex = -1;
  1263. this.height = -1;
  1264. this.depth = -1;
  1265. this.hardFee = -1;
  1266. this.rate = CoinSelector.FEE_RATE;
  1267. this.maxFee = -1;
  1268. this.round = false;
  1269. this.changeAddress = null;
  1270. this.inputs = new BufferMap();
  1271. // Needed for size estimation.
  1272. this.estimate = null;
  1273. this.injectInputs();
  1274. if (options)
  1275. this.fromOptions(options);
  1276. }
  1277. /**
  1278. * Initialize selector options.
  1279. * @param {Object} options
  1280. * @private
  1281. */
  1282. fromOptions(options) {
  1283. if (options.selection) {
  1284. assert(typeof options.selection === 'string');
  1285. this.selection = options.selection;
  1286. }
  1287. if (options.subtractFee != null) {
  1288. if (typeof options.subtractFee === 'number') {
  1289. assert(Number.isSafeInteger(options.subtractFee));
  1290. assert(options.subtractFee >= -1);
  1291. this.subtractIndex = options.subtractFee;
  1292. this.subtractFee = this.subtractIndex !== -1;
  1293. } else {
  1294. assert(typeof options.subtractFee === 'boolean');
  1295. this.subtractFee = options.subtractFee;
  1296. }
  1297. }
  1298. if (options.subtractIndex != null) {
  1299. assert(Number.isSafeInteger(options.subtractIndex));
  1300. assert(options.subtractIndex >= -1);
  1301. this.subtractIndex = options.subtractIndex;
  1302. this.subtractFee = this.subtractIndex !== -1;
  1303. }
  1304. if (options.height != null) {
  1305. assert(Number.isSafeInteger(options.height));
  1306. assert(options.height >= -1);
  1307. this.height = options.height;
  1308. }
  1309. if (options.confirmations != null) {
  1310. assert(Number.isSafeInteger(options.confirmations));
  1311. assert(options.confirmations >= -1);
  1312. this.depth = options.confirmations;
  1313. }
  1314. if (options.depth != null) {
  1315. assert(Number.isSafeInteger(options.depth));
  1316. assert(options.depth >= -1);
  1317. this.depth = options.depth;
  1318. }
  1319. if (options.hardFee != null) {
  1320. assert(Number.isSafeInteger(options.hardFee));
  1321. assert(options.hardFee >= -1);
  1322. this.hardFee = options.hardFee;
  1323. }
  1324. if (options.rate != null) {
  1325. assert(Number.isSafeInteger(options.rate));
  1326. assert(options.rate >= 0);
  1327. this.rate = options.rate;
  1328. }
  1329. if (options.maxFee != null) {
  1330. assert(Number.isSafeInteger(options.maxFee));
  1331. assert(options.maxFee >= -1);
  1332. this.maxFee = options.maxFee;
  1333. }
  1334. if (options.round != null) {
  1335. assert(typeof options.round === 'boolean');
  1336. this.round = options.round;
  1337. }
  1338. if (options.changeAddress) {
  1339. const addr = options.changeAddress;
  1340. if (typeof addr === 'string') {
  1341. this.changeAddress = Address.fromString(addr);
  1342. } else {
  1343. assert(addr instanceof Address);
  1344. this.changeAddress = addr;
  1345. }
  1346. }
  1347. if (options.estimate) {
  1348. assert(typeof options.estimate === 'function');
  1349. this.estimate = options.estimate;
  1350. }
  1351. if (options.inputs) {
  1352. assert(Array.isArray(options.inputs));
  1353. for (let i = 0; i < options.inputs.length; i++) {
  1354. const prevout = options.inputs[i];
  1355. assert(prevout && typeof prevout === 'object');
  1356. const {hash, index} = prevout;
  1357. assert(Buffer.isBuffer(hash));
  1358. assert(typeof index === 'number');
  1359. this.inputs.set(Outpoint.toKey(hash, index), i);
  1360. }
  1361. }
  1362. return this;
  1363. }
  1364. /**
  1365. * Attempt to inject existing inputs.
  1366. * @private
  1367. */
  1368. injectInputs() {
  1369. if (this.tx.inputs.length > 0) {
  1370. for (let i = 0; i < this.tx.inputs.length; i++) {
  1371. const {prevout} = this.tx.inputs[i];
  1372. this.inputs.set(prevout.toKey(), i);
  1373. }
  1374. }
  1375. }
  1376. /**
  1377. * Initialize the selector with coins to select from.
  1378. * @param {Coin[]} coins
  1379. */
  1380. init(coins) {
  1381. this.coins = coins.slice();
  1382. this.outputValue = this.tx.getOutputValue();
  1383. this.index = 0;
  1384. this.chosen = [];
  1385. this.change = 0;
  1386. this.fee = CoinSelector.MIN_FEE;
  1387. this.tx.inputs.length = 0;
  1388. switch (this.selection) {
  1389. case 'all':
  1390. case 'random':
  1391. this.coins.sort(sortRandom);
  1392. break;
  1393. case 'age':
  1394. this.coins.sort(sortAge);
  1395. break;
  1396. case 'value':
  1397. this.coins.sort(sortValue);
  1398. break;
  1399. default:
  1400. throw new FundingError(`Bad selection type: ${this.selection}.`);
  1401. }
  1402. }
  1403. /**
  1404. * Calculate total value required.
  1405. * @returns {Amount}
  1406. */
  1407. total() {
  1408. if (this.subtractFee)
  1409. return this.outputValue;
  1410. return this.outputValue + this.fee;
  1411. }
  1412. /**
  1413. * Test whether the selector has
  1414. * completely funded the transaction.
  1415. * @returns {Boolean}
  1416. */
  1417. isFull() {
  1418. return this.tx.getInputValue() >= this.total();
  1419. }
  1420. /**
  1421. * Test whether a coin is spendable
  1422. * with regards to the options.
  1423. * @param {Coin} coin
  1424. * @returns {Boolean}
  1425. */
  1426. isSpendable(coin) {
  1427. if (this.tx.view.hasEntry(coin))
  1428. return false;
  1429. if (this.height === -1)
  1430. return true;
  1431. if (coin.coinbase) {
  1432. if (coin.height === -1)
  1433. return false;
  1434. if (this.height + 1 < coin.height + consensus.COINBASE_MATURITY)
  1435. return false;
  1436. return true;
  1437. }
  1438. if (this.depth === -1)
  1439. return true;
  1440. const depth = coin.getDepth(this.height);
  1441. if (depth < this.depth)
  1442. return false;
  1443. return true;
  1444. }
  1445. /**
  1446. * Get the current fee based on a size.
  1447. * @param {Number} size
  1448. * @returns {Amount}
  1449. */
  1450. getFee(size) {
  1451. // This is mostly here for testing.
  1452. // i.e. A fee rounded to the nearest
  1453. // kb is easier to predict ahead of time.
  1454. if (this.round) {
  1455. const fee = policy.getRoundFee(size, this.rate);
  1456. return Math.min(fee, CoinSelector.MAX_FEE);
  1457. }
  1458. const fee = policy.getMinFee(size, this.rate);
  1459. return Math.min(fee, CoinSelector.MAX_FEE);
  1460. }
  1461. /**
  1462. * Fund the transaction with more
  1463. * coins if the `output value + fee`
  1464. * total was updated.
  1465. */
  1466. fund() {
  1467. // Ensure all preferred inputs first.
  1468. if (this.inputs.size > 0) {
  1469. const coins = [];
  1470. for (let i = 0; i < this.inputs.size; i++)
  1471. coins.push(null);
  1472. for (const coin of this.coins) {
  1473. const {hash, index} = coin;
  1474. const key = Outpoint.toKey(hash, index);
  1475. const i = this.inputs.get(key);
  1476. if (i != null) {
  1477. coins[i] = coin;
  1478. this.inputs.delete(key);
  1479. }
  1480. }
  1481. if (this.inputs.size > 0)
  1482. throw new Error('Could not resolve preferred inputs.');
  1483. for (const coin of coins) {
  1484. this.tx.addCoin(coin);
  1485. this.chosen.push(coin);
  1486. }
  1487. }
  1488. while (this.index < this.coins.length) {
  1489. const coin = this.coins[this.index++];
  1490. if (!this.isSpendable(coin))
  1491. continue;
  1492. this.tx.addCoin(coin);
  1493. this.chosen.push(coin);
  1494. if (this.selection === 'all')
  1495. continue;
  1496. if (this.isFull())
  1497. break;
  1498. }
  1499. }
  1500. /**
  1501. * Initiate selection from `coins`.
  1502. * @param {Coin[]} coins
  1503. * @returns {CoinSelector}
  1504. */
  1505. async select(coins) {
  1506. this.init(coins);
  1507. if (this.hardFee !== -1) {
  1508. this.selectHard();
  1509. } else {
  1510. // This is potentially asynchronous:
  1511. // it may invoke the size estimator
  1512. // required for redeem scripts (we
  1513. // may be calling out to a wallet
  1514. // or something similar).
  1515. await this.selectEstimate();
  1516. }
  1517. if (!this.isFull()) {
  1518. // Still failing to get enough funds.
  1519. throw new FundingError(
  1520. 'Not enough funds.',
  1521. this.tx.getInputValue(),
  1522. this.total());
  1523. }
  1524. // How much money is left after filling outputs.
  1525. this.change = this.tx.getInputValue() - this.total();
  1526. return this;
  1527. }
  1528. /**
  1529. * Initialize selection based on size estimate.
  1530. */
  1531. async selectEstimate() {
  1532. // Set minimum fee and do
  1533. // an initial round of funding.
  1534. this.fee = CoinSelector.MIN_FEE;
  1535. this.fund();
  1536. // Add dummy output for change.
  1537. const change = new Output();
  1538. if (this.changeAddress) {
  1539. change.script.fromAddress(this.changeAddress);
  1540. } else {
  1541. // In case we don't have a change address,
  1542. // we use a fake p2pkh output to gauge size.
  1543. change.script.fromPubkeyhash(Buffer.allocUnsafe(20));
  1544. }
  1545. this.tx.outputs.push(change);
  1546. // Keep recalculating the fee and funding
  1547. // until we reach some sort of equilibrium.
  1548. do {
  1549. const size = await this.tx.estimateSize(this.estimate);
  1550. this.fee = this.getFee(size);
  1551. if (this.maxFee > 0 && this.fee > this.maxFee)
  1552. throw new FundingError('Fee is too high.');
  1553. // Failed to get enough funds, add more coins.
  1554. if (!this.isFull())
  1555. this.fund();
  1556. } while (!this.isFull() && this.index < this.coins.length);
  1557. }
  1558. /**
  1559. * Initiate selection based on a hard fee.
  1560. */
  1561. selectHard() {
  1562. this.fee = Math.min(this.hardFee, CoinSelector.MAX_FEE);
  1563. this.fund();
  1564. }
  1565. }
  1566. /**
  1567. * Default fee rate
  1568. * for coin selection.
  1569. * @const {Amount}
  1570. * @default
  1571. */
  1572. CoinSelector.FEE_RATE = 10000;
  1573. /**
  1574. * Minimum fee to start with
  1575. * during coin selection.
  1576. * @const {Amount}
  1577. * @default
  1578. */
  1579. CoinSelector.MIN_FEE = 10000;
  1580. /**
  1581. * Maximum fee to allow
  1582. * after coin selection.
  1583. * @const {Amount}
  1584. * @default
  1585. */
  1586. CoinSelector.MAX_FEE = consensus.COIN / 10;
  1587. /**
  1588. * Funding Error
  1589. * An error thrown from the coin selector.
  1590. * @ignore
  1591. * @extends Error
  1592. * @property {String} message - Error message.
  1593. * @property {Amount} availableFunds
  1594. * @property {Amount} requiredFunds
  1595. */
  1596. class FundingError extends Error {
  1597. /**
  1598. * Create a funding error.
  1599. * @constructor
  1600. * @param {String} msg
  1601. * @param {Amount} available
  1602. * @param {Amount} required
  1603. */
  1604. constructor(msg, available, required) {
  1605. super();
  1606. this.type = 'FundingError';
  1607. this.message = msg;
  1608. this.availableFunds = -1;
  1609. this.requiredFunds = -1;
  1610. if (available != null) {
  1611. this.message += ` (available=${Amount.btc(available)},`;
  1612. this.message += ` required=${Amount.btc(required)})`;
  1613. this.availableFunds = available;
  1614. this.requiredFunds = required;
  1615. }
  1616. if (Error.captureStackTrace)
  1617. Error.captureStackTrace(this, FundingError);
  1618. }
  1619. }
  1620. /*
  1621. * Helpers
  1622. */
  1623. function sortAge(a, b) {
  1624. a = a.height === -1 ? 0x7fffffff : a.height;
  1625. b = b.height === -1 ? 0x7fffffff : b.height;
  1626. return a - b;
  1627. }
  1628. function sortRandom(a, b) {
  1629. return Math.random() > 0.5 ? 1 : -1;
  1630. }
  1631. function sortValue(a, b) {
  1632. if (a.height === -1 && b.height !== -1)
  1633. return 1;
  1634. if (a.height !== -1 && b.height === -1)
  1635. return -1;
  1636. return b.value - a.value;
  1637. }
  1638. function sortInputs(a, b) {
  1639. return a.compare(b);
  1640. }
  1641. function sortOutputs(a, b) {
  1642. return a.compare(b);
  1643. }
  1644. /*
  1645. * Expose
  1646. */
  1647. exports = MTX;
  1648. exports.MTX = MTX;
  1649. exports.Selector = CoinSelector;
  1650. exports.FundingError = FundingError;
  1651. module.exports = exports;