bitcoinjs-lib
Advanced tools
Comparing version 3.3.2 to 4.0.1
@@ -0,1 +1,59 @@ | ||
# 4.0.1 | ||
__fixed__ | ||
- Fixed `tiny-secp256k1` dependency version (used `ecurve`) (#1139) | ||
- Fixed `TransactionBuilder` throwing when trying to sign `P2WSH(P2WPKH)` (#1135) | ||
# 4.0.0 | ||
__added__ | ||
- Added [`bip32`](https://github.com/bitcoinjs/bip32) dependency as a primary export (#1073) | ||
- Added `ECPair.fromPrivateKey` (#1070) | ||
- Added `payments` export, with support for `p2pkh`, `p2pk`, `p2ms`, `p2sh`, `p2wpkh`, `p2wsh` and `embed` payment types (#1096, #1119) | ||
- Added `script.signature.encode/decode` for script signatures (#459) | ||
__changed__ | ||
- `ECPair.prototype.sign` now returns a 64-byte signature `Buffer`, not an `ECSignature` object (#1084) | ||
- `ECPair` (and all ECDSA code) now uses [`tiny-secp256k1`](http://github.com/bitcoinjs/tiny-secp256k1), which uses the [`libsecp256k1` library](https://github.com/bitcoin-core/secp256k1) (#1070) | ||
- `TransactionBuilder` internal variables are now `__` prefixed to discourage public usage (#1038) | ||
- `TransactionBuilder` now defaults to version 2 transaction versions (#1036) | ||
- `script.decompile` now returns `Buffer` or `null`, if decompilation failed (#1039) | ||
__fixed__ | ||
- Fixed `TransactionBuilder` rejecting uncompressed public keys to comply with BIP143 (#987) | ||
__removed__ | ||
- Removed Node 4/5 LTS support (#1080) | ||
- Removed `ECPair.fromPublicKeyBuffer`, use `ECPair.fromPublicKey` (#1070) | ||
- Removed `ECPair.prototype.getAddress`, use `payments.p2pkh` instead (#1085) | ||
- Removed `ECPair.prototype.getPrivateKey`, use `ECPair.prototype.privateKey` property (#1070) | ||
- Removed `ECPair.prototype.getPublicKey`, use `ECPair.prototype.publicKey` property (#1070) | ||
- Removed `ECPair.prototype.getNetwork`, use `ECPair.prototype.network` property (#1070) | ||
- Removed `ECSignature`, use `script.signature.encode/decode` instead (#459) | ||
- Removed `HDNode`, use `bip32` export instead (#1073) | ||
- Removed `bufferutils` (#1035) | ||
- Removed `networks.litecoin`, BYO non-Bitcoin networks instead (#1095) | ||
- Removed `script.isCanonicalSignature`, use `script.isCanonicalScriptSignature` instead (#1094) | ||
- Removed `script.*.input/output/check` functions (`templates`) (previously added in #681, #682) (#1119) | ||
- Removed dependency `bigi`, uses `bn.js` internally now (via `tiny-secp256k1`) (#1070, #1112) | ||
- Removed public access to `ECPair` constructor, use exported functions `ECPair.fromPrivateKey`, `ECPair.fromWIF`, `ECPair.makeRandom`, or `ECPair.fromPublicKey` (#1070) | ||
# 3.3.2 | ||
__fixed__ | ||
- Fixed `decodeStack` arbitrarily supporting non-Array arguments (#942) | ||
# 3.3.1 | ||
__changed__ | ||
- Increased the `TransactionBuilder` `maximumFeeRate` from 1000 to 2500 satoshis/byte. (#931) | ||
# 3.3.0 | ||
__added__ | ||
- Added `ECSignature.prototype.toRSBuffer`/`ECSignature.fromRSBuffer` (#915) | ||
- Added support to `TransactionBuilder` for 64-byte signatures via `.sign` (#915) | ||
- Added support to `TransactionBuilder` for the `.publicKey` standard as an alternative to `.getPublicKey()` (#915) | ||
# 3.2.1 | ||
__fixed__ | ||
- Fixed `script.scripthash.input.check` recursion (#898) | ||
- Fixed `TransactionBuilder` sometimes ignoring witness value (#901) | ||
- Fixed `script.witnessScriptHash.input` implementation (previously used the P2SH impl.) (#911) | ||
# 3.2.0 | ||
@@ -2,0 +60,0 @@ __added__ |
{ | ||
"name": "bitcoinjs-lib", | ||
"version": "3.3.2", | ||
"version": "4.0.1", | ||
"description": "Client-side Bitcoin JavaScript library", | ||
"main": "./src/index.js", | ||
"engines": { | ||
"node": ">=4.0.0" | ||
"node": ">=8.0.0" | ||
}, | ||
@@ -34,13 +34,13 @@ "keywords": [ | ||
"bech32": "^1.1.2", | ||
"bigi": "^1.4.0", | ||
"bip32": "^1.0.0", | ||
"bip66": "^1.1.0", | ||
"bitcoin-ops": "^1.3.0", | ||
"bitcoin-ops": "^1.4.0", | ||
"bs58check": "^2.0.0", | ||
"create-hash": "^1.1.0", | ||
"create-hmac": "^1.1.3", | ||
"ecurve": "^1.0.0", | ||
"merkle-lib": "^2.0.10", | ||
"pushdata-bitcoin": "^1.0.1", | ||
"randombytes": "^2.0.1", | ||
"safe-buffer": "^5.0.1", | ||
"safe-buffer": "^5.1.1", | ||
"tiny-secp256k1": "^1.0.0", | ||
"typeforce": "^1.11.3", | ||
@@ -51,16 +51,16 @@ "varuint-bitcoin": "^1.0.4", | ||
"devDependencies": { | ||
"async": "^2.0.1", | ||
"bip39": "^2.3.0", | ||
"bip65": "^1.0.1", | ||
"bip68": "^1.0.3", | ||
"bn.js": "^4.11.8", | ||
"bs58": "^4.0.0", | ||
"cb-http-client": "^0.2.0", | ||
"coinselect": "^3.1.1", | ||
"dhttp": "^2.3.5", | ||
"dhttp": "^2.5.0", | ||
"hoodwink": "^1.0.0", | ||
"minimaldata": "^1.0.2", | ||
"mocha": "^3.1.0", | ||
"nyc": "^10.2.0", | ||
"proxyquire": "^1.4.0", | ||
"sinon": "^1.12.2", | ||
"standard": "^9.0.2" | ||
"mocha": "^5.2.0", | ||
"nyc": "^11.8.0", | ||
"proxyquire": "^2.0.1", | ||
"standard": "^11.0.1" | ||
}, | ||
"license": "MIT" | ||
} |
195
README.md
# BitcoinJS (bitcoinjs-lib) | ||
[![Build Status](https://travis-ci.org/bitcoinjs/bitcoinjs-lib.png?branch=master)](https://travis-ci.org/bitcoinjs/bitcoinjs-lib) | ||
[![NPM](https://img.shields.io/npm/v/bitcoinjs-lib.svg)](https://www.npmjs.org/package/bitcoinjs-lib) | ||
[![tip for next commit](https://tip4commit.com/projects/735.svg)](http://tip4commit.com/projects/735) | ||
[![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) | ||
The pure JavaScript Bitcoin library for node.js and browsers. | ||
Estimated to be in use by over 15 million wallet users and is the backbone for almost all Bitcoin web wallets in production today. | ||
A javascript Bitcoin library for node.js and browsers. | ||
Released under the terms of the [MIT LICENSE](LICENSE). | ||
## Features | ||
- Clean: Pure JavaScript, concise code, easy to read. | ||
- Tested: Coverage > 90%, third-party integration tests. | ||
- Careful: Two person approval process for small, focused pull requests. | ||
- Compatible: Works on Node.js and all modern browsers. | ||
- Powerful: Support for advanced features, such as multi-sig, HD Wallets. | ||
- Secure: Strong random number generation, PGP signed releases, trusted developers. | ||
- Principled: No support for browsers with crap RNG (IE < 11) | ||
- Standardized: Node community coding style, Browserify, Node's stdlib and Buffers. | ||
- Fast: Optimized code, uses typed arrays instead of byte arrays for performance. | ||
- Experiment-friendly: Bitcoin Mainnet and Testnet support. | ||
- Altcoin-ready: Capable of working with bitcoin-derived cryptocurrencies (such as Dogecoin). | ||
## Should I use this in production? | ||
If you are thinking of using the master branch of this library in production, **stop**. | ||
If you are thinking of using the *master* branch of this library in production, **stop**. | ||
Master is not stable; it is our development branch, and [only tagged releases may be classified as stable](https://github.com/bitcoinjs/bitcoinjs-lib/tags). | ||
## Installation | ||
``` bash | ||
npm install bitcoinjs-lib | ||
``` | ||
## Can I trust this code? | ||
> Don't trust. Verify. | ||
## Setup | ||
### Node.js | ||
``` javascript | ||
var bitcoin = require('bitcoinjs-lib') | ||
``` | ||
We recommend every user of this library and the [bitcoinjs](https://github.com/bitcoinjs) ecosystem audit and verify any underlying code for its validity and suitability. | ||
### Browser | ||
If you're familiar with how to use browserify, ignore this and proceed normally. | ||
These steps are advisory only, and may not be suitable for your application. | ||
Mistakes and bugs happen, but with your help in resolving and reporting [issues](https://github.com/bitcoinjs/bitcoinjs-lib/issues), together we can produce open source software that is: | ||
[Browserify](https://github.com/substack/node-browserify) is assumed to be installed for these steps. | ||
- Easy to audit and verify, | ||
- Tested, with test coverage >95%, | ||
- Advanced and feature rich, | ||
- Standardized, using [standard](http://github.com/standard/standard) and Node `Buffer`'s throughout, and | ||
- Friendly, with a strong and helpful community, ready to answer questions. | ||
For your project, create an `index.js` file | ||
``` javascript | ||
let bitcoin = require('bitcoinjs-lib') | ||
## Documentation | ||
Presently, we do not have any formal documentation other than our [examples](#Examples), please [ask for help](https://github.com/bitcoinjs/bitcoinjs-lib/issues/new) if our examples aren't enough to guide you. | ||
// your code here | ||
function myFunction () { | ||
return bitcoin.ECPair.makeRandom().toWIF() | ||
} | ||
module.exports = { | ||
myFunction | ||
} | ||
``` | ||
Now, to compile for the browser: | ||
## Installation | ||
``` bash | ||
browserify index.js --standalone foo > app.js | ||
npm install bitcoinjs-lib | ||
``` | ||
You can now put `<script src="app.js" />` in your web page, using `foo.myFunction` to create a new Bitcoin private key. | ||
Typically we support the [Node Maintenance LTS version](https://github.com/nodejs/Release). | ||
If in doubt, see the [.travis.yml](.travis.yml) for what versions are used by our continuous integration tests. | ||
**NOTE**: If you uglify the javascript, you must exclude the following variable names from being mangled: `BigInteger`, `ECPair`, `Point`. | ||
This is because of the function-name-duck-typing used in [typeforce](https://github.com/dcousens/typeforce). | ||
**WARNING**: We presently don't provide any tooling to verify that the release on `npm` matches GitHub. As such, you should verify anything downloaded by `npm` against your own verified copy. | ||
Example: | ||
``` bash | ||
uglifyjs ... --mangle reserved=['BigInteger','ECPair','Point'] | ||
``` | ||
**NOTE**: This library tracks Node LTS features, if you need strict ES5, use [`--transform babelify`](https://github.com/babel/babelify) in conjunction with your `browserify` step (using an [`es2015`](http://babeljs.io/docs/plugins/preset-es2015/) preset). | ||
## Usage | ||
### Browser | ||
The recommended method of using `bitcoinjs-lib` in your browser is through [Browserify](https://github.com/substack/node-browserify). | ||
If you're familiar with how to use browserify, ignore this and carry on, otherwise, it is recommended to read the tutorial at http://browserify.org/. | ||
**NOTE**: We use Node Maintenance LTS features, if you need strict ES5, use [`--transform babelify`](https://github.com/babel/babelify) in conjunction with your `browserify` step (using an [`es2015`](http://babeljs.io/docs/plugins/preset-es2015/) preset). | ||
**NOTE**: If you expect this library to run on an iOS 10 device, ensure that you are using [buffer@5.0.5](https://github.com/feross/buffer/pull/155) or greater. | ||
### Typescript or VSCode users | ||
Type declarations for Typescript [are available](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/0897921174860ec3d5318992d2323b3ae8100a68/types/bitcoinjs-lib) for version `^3.0.0` of the library. | ||
### Typescript or VSCode users | ||
Type declarations for Typescript are available for version `^3.0.0` of the library. | ||
``` bash | ||
@@ -88,22 +61,21 @@ npm install @types/bitcoinjs-lib | ||
You can now use `bitcoinjs-lib` as a typescript compliant library. | ||
``` javascript | ||
import { HDNode, Transaction } from 'bitcoinjs-lib' | ||
``` | ||
For VSCode (and other editors), it is advised to install the type declarations, as Intellisense uses that information to help you code (autocompletion, static analysis). | ||
For VSCode (and other editors), users are advised to install the type declarations, as Intellisense uses that information to help you code (autocompletion, static analysis). | ||
**WARNING**: These Typescript definitions are not maintained by the maintainers of this repository, and are instead maintained at [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped). | ||
Please report any issues or problems there. | ||
Report any typescript related bugs at [@dlebrecht DefinitelyTyped fork](https://github.com/dlebrecht/DefinitelyTyped), submit PRs to [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) | ||
### Flow | ||
Definitions for [Flow typechecker](https://flowtype.org/) are available in flow-typed repository. | ||
[Flow-type](https://flowtype.org/) definitions for are available in the [flow-*typed* repository](https://github.com/flowtype/flow-typed/tree/master/definitions/npm/bitcoinjs-lib_v2.x.x) for version `^2.0.0` of the library. | ||
[You can either download them directly](https://github.com/flowtype/flow-typed/blob/master/definitions/npm/bitcoinjs-lib_v2.x.x/flow_v0.17.x-/bitcoinjs-lib_v2.x.x.js) from the repo, or with the flow-typed CLI | ||
You can [download them directly](https://github.com/flowtype/flow-typed/blob/master/definitions/npm/bitcoinjs-lib_v2.x.x/flow_v0.17.x-/bitcoinjs-lib_v2.x.x.js), or using the flow-typed CLI: | ||
# npm install -g flow-typed | ||
$ flow-typed install -f 0.27 bitcoinjs-lib@2.2.0 # 0.27 for flow version, 2.2.0 for bitcoinjs-lib version | ||
``` bash | ||
npm install -g flow-typed | ||
flow-typed install -f 0.27 bitcoinjs-lib@2.2.0 | ||
``` | ||
The definitions are complete and up to date with version 2.2.0. The definitions are maintained by [@runn1ng](https://github.com/runn1ng). | ||
These definitions are maintained by [@runn1ng](https://github.com/runn1ng). | ||
## Examples | ||
@@ -114,37 +86,41 @@ The below examples are implemented as integration tests, they should be very easy to understand. | ||
- [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L12) | ||
- [Generate an address from a SHA256 hash](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L19) | ||
- [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L29) | ||
- [Generate a 2-of-3 P2SH multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L36) | ||
- [Generate a SegWit address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L50) | ||
- [Generate a SegWit P2SH address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L60) | ||
- [Generate a SegWit 3-of-4 multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L71) | ||
- [Generate a SegWit 2-of-2 P2SH multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L86) | ||
- [Support the retrieval of transactions for an address (3rd party blockchain)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L100) | ||
- [Generate a Testnet address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L121) | ||
- [Generate a Litecoin address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L131) | ||
- [Create a 1-to-1 Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L14) | ||
- [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L22) | ||
- [Generate an address from a SHA256 hash](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L29) | ||
- [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L40) | ||
- [Generate a 2-of-3 P2SH multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L47) | ||
- [Generate a SegWit address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L60) | ||
- [Generate a SegWit P2SH address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L67) | ||
- [Generate a SegWit 3-of-4 multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L76) | ||
- [Generate a SegWit 2-of-2 P2SH multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L90) | ||
- [Support the retrieval of transactions for an address (3rd party blockchain)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L104) | ||
- [Generate a Testnet address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L123) | ||
- [Generate a Litecoin address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js#L133) | ||
- [Create a 1-to-1 Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L13) | ||
- [Create a 2-to-2 Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L28) | ||
- [Create (and broadcast via 3PBP) a typical Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L46) | ||
- [Create (and broadcast via 3PBP) a Transaction with an OP\_RETURN output](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L88) | ||
- [Create (and broadcast via 3PBP) a Transaction with a 2-of-4 P2SH(multisig) input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L115) | ||
- [Create (and broadcast via 3PBP) a Transaction with a SegWit P2SH(P2WPKH) input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L151) | ||
- [Create (and broadcast via 3PBP) a Transaction with a SegWit 3-of-4 P2SH(P2WSH(multisig)) input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L183) | ||
- [Import a BIP32 testnet xpriv and export to WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L8) | ||
- [Export a BIP32 xpriv, then import it](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L15) | ||
- [Export a BIP32 xpub](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L26) | ||
- [Create a BIP32, bitcoin, account 0, external address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L35) | ||
- [Create a BIP44, bitcoin, account 0, external address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L50) | ||
- [Create a BIP49, bitcoin testnet, account 0, external address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L66) | ||
- [Use BIP39 to generate BIP32 addresses](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L83) | ||
- [Create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/cltv.js#L37) | ||
- [Create (and broadcast via 3PBP) a Transaction where Alice and Bob can redeem the output at any time](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/cltv.js#L71) | ||
- [Create (but fail to broadcast via 3PBP) a Transaction where Alice attempts to redeem before the expiry](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/cltv.js#L104) | ||
- [Create (and broadcast via 3PBP) a typical Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L47) | ||
- [Create (and broadcast via 3PBP) a Transaction with an OP\_RETURN output](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L83) | ||
- [Create (and broadcast via 3PBP) a Transaction with a 2-of-4 P2SH(multisig) input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L105) | ||
- [Create (and broadcast via 3PBP) a Transaction with a SegWit P2SH(P2WPKH) input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L143) | ||
- [Create (and broadcast via 3PBP) a Transaction with a SegWit P2WPKH input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L174) | ||
- [Create (and broadcast via 3PBP) a Transaction with a SegWit P2PK input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L218) | ||
- [Create (and broadcast via 3PBP) a Transaction with a SegWit 3-of-4 P2SH(P2WSH(multisig)) input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L263) | ||
- [Verify a Transaction signature](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L304) | ||
- [Import a BIP32 testnet xpriv and export to WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L12) | ||
- [Export a BIP32 xpriv, then import it](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L20) | ||
- [Export a BIP32 xpub](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L31) | ||
- [Create a BIP32, bitcoin, account 0, external address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L40) | ||
- [Create a BIP44, bitcoin, account 0, external address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L55) | ||
- [Create a BIP49, bitcoin testnet, account 0, external address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L71) | ||
- [Use BIP39 to generate BIP32 addresses](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L86) | ||
- [Create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the past)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/cltv.js#L43) | ||
- [Create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the future)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/cltv.js#L88) | ||
- [Create (and broadcast via 3PBP) a Transaction where Alice and Bob can redeem the output at any time](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/cltv.js#L144) | ||
- [Create (but fail to broadcast via 3PBP) a Transaction where Alice attempts to redeem before the expiry](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/cltv.js#L190) | ||
- [Recover a private key from duplicate R values](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/crypto.js#L14) | ||
- [Recover a BIP32 parent private key from the parent public key, and a derived, non-hardened child private key](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/crypto.js#L115) | ||
- [Generate a single-key stealth address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/stealth.js#L70:) | ||
- [Generate a single-key stealth address (randomly)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/stealth.js#L89:) | ||
- [Recover parent recipient.d, if a derived private key is leaked (and nonce was revealed)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/stealth.js#L105) | ||
- [Generate a dual-key stealth address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/stealth.js#L122) | ||
- [Generate a dual-key stealth address (randomly)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/stealth.js#L145) | ||
- [Recover a BIP32 parent private key from the parent public key, and a derived, non-hardened child private key](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/crypto.js#L68) | ||
- [Generate a single-key stealth address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/stealth.js#L72) | ||
- [Generate a single-key stealth address (randomly)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/stealth.js#L91) | ||
- [Recover parent recipient.d, if a derived private key is leaked (and nonce was revealed)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/stealth.js#L107) | ||
- [Generate a dual-key stealth address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/stealth.js#L124) | ||
- [Generate a dual-key stealth address (randomly)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/stealth.js#L147) | ||
@@ -154,23 +130,6 @@ If you have a use case that you feel could be listed here, please [ask for it](https://github.com/bitcoinjs/bitcoinjs-lib/issues/new)! | ||
## Projects utilizing BitcoinJS | ||
- [BitAddress](https://www.bitaddress.org) | ||
- [Blockchain.info](https://blockchain.info/wallet) | ||
- [Blocktrail](https://www.blocktrail.com/) | ||
- [Dark Wallet](https://www.darkwallet.is/) | ||
- [DecentralBank](http://decentralbank.com/) | ||
- [Dogechain Wallet](https://dogechain.info) | ||
- [EI8HT Wallet](http://ei8.ht/) | ||
- [GreenAddress](https://greenaddress.it) | ||
- [Helperbit](https://helperbit.com) | ||
- [Melis Wallet](https://melis.io) | ||
- [Robocoin](https://wallet.robocoin.com) | ||
- [Skyhook ATM](http://projectskyhook.com) | ||
## Contributing | ||
We are always accepting of pull requests, but we do adhere to specific standards in regards to coding style, test driven development and commit messages. | ||
See [CONTRIBUTING.md](CONTRIBUTING.md). | ||
Please make your best effort to adhere to these when contributing to save on trivial corrections. | ||
### Running the test suite | ||
@@ -177,0 +136,0 @@ |
@@ -1,12 +0,12 @@ | ||
var Buffer = require('safe-buffer').Buffer | ||
var bech32 = require('bech32') | ||
var bs58check = require('bs58check') | ||
var bscript = require('./script') | ||
var btemplates = require('./templates') | ||
var networks = require('./networks') | ||
var typeforce = require('typeforce') | ||
var types = require('./types') | ||
const Buffer = require('safe-buffer').Buffer | ||
const bech32 = require('bech32') | ||
const bs58check = require('bs58check') | ||
const bscript = require('./script') | ||
const networks = require('./networks') | ||
const typeforce = require('typeforce') | ||
const types = require('./types') | ||
const payments = require('./payments') | ||
function fromBase58Check (address) { | ||
var payload = bs58check.decode(address) | ||
const payload = bs58check.decode(address) | ||
@@ -17,4 +17,4 @@ // TODO: 4.0.0, move to "toOutputScript" | ||
var version = payload.readUInt8(0) | ||
var hash = payload.slice(1) | ||
const version = payload.readUInt8(0) | ||
const hash = payload.slice(1) | ||
@@ -25,4 +25,4 @@ return { version: version, hash: hash } | ||
function fromBech32 (address) { | ||
var result = bech32.decode(address) | ||
var data = bech32.fromWords(result.words.slice(1)) | ||
const result = bech32.decode(address) | ||
const data = bech32.fromWords(result.words.slice(1)) | ||
@@ -39,3 +39,3 @@ return { | ||
var payload = Buffer.allocUnsafe(21) | ||
const payload = Buffer.allocUnsafe(21) | ||
payload.writeUInt8(version, 0) | ||
@@ -48,3 +48,3 @@ hash.copy(payload, 1) | ||
function toBech32 (data, version, prefix) { | ||
var words = bech32.toWords(data) | ||
const words = bech32.toWords(data) | ||
words.unshift(version) | ||
@@ -55,11 +55,11 @@ | ||
function fromOutputScript (outputScript, network) { | ||
function fromOutputScript (output, network) { | ||
network = network || networks.bitcoin | ||
if (btemplates.pubKeyHash.output.check(outputScript)) return toBase58Check(bscript.compile(outputScript).slice(3, 23), network.pubKeyHash) | ||
if (btemplates.scriptHash.output.check(outputScript)) return toBase58Check(bscript.compile(outputScript).slice(2, 22), network.scriptHash) | ||
if (btemplates.witnessPubKeyHash.output.check(outputScript)) return toBech32(bscript.compile(outputScript).slice(2, 22), 0, network.bech32) | ||
if (btemplates.witnessScriptHash.output.check(outputScript)) return toBech32(bscript.compile(outputScript).slice(2, 34), 0, network.bech32) | ||
try { return payments.p2pkh({ output, network }).address } catch (e) {} | ||
try { return payments.p2sh({ output, network }).address } catch (e) {} | ||
try { return payments.p2wpkh({ output, network }).address } catch (e) {} | ||
try { return payments.p2wsh({ output, network }).address } catch (e) {} | ||
throw new Error(bscript.toASM(outputScript) + ' has no matching Address') | ||
throw new Error(bscript.toASM(output) + ' has no matching Address') | ||
} | ||
@@ -70,3 +70,3 @@ | ||
var decode | ||
let decode | ||
try { | ||
@@ -77,4 +77,4 @@ decode = fromBase58Check(address) | ||
if (decode) { | ||
if (decode.version === network.pubKeyHash) return btemplates.pubKeyHash.output.encode(decode.hash) | ||
if (decode.version === network.scriptHash) return btemplates.scriptHash.output.encode(decode.hash) | ||
if (decode.version === network.pubKeyHash) return payments.p2pkh({ hash: decode.hash }).output | ||
if (decode.version === network.scriptHash) return payments.p2sh({ hash: decode.hash }).output | ||
} else { | ||
@@ -88,4 +88,4 @@ try { | ||
if (decode.version === 0) { | ||
if (decode.data.length === 20) return btemplates.witnessPubKeyHash.output.encode(decode.data) | ||
if (decode.data.length === 32) return btemplates.witnessScriptHash.output.encode(decode.data) | ||
if (decode.data.length === 20) return payments.p2wpkh({ hash: decode.data }).output | ||
if (decode.data.length === 32) return payments.p2wsh({ hash: decode.data }).output | ||
} | ||
@@ -92,0 +92,0 @@ } |
@@ -1,9 +0,9 @@ | ||
var Buffer = require('safe-buffer').Buffer | ||
var bcrypto = require('./crypto') | ||
var fastMerkleRoot = require('merkle-lib/fastRoot') | ||
var typeforce = require('typeforce') | ||
var types = require('./types') | ||
var varuint = require('varuint-bitcoin') | ||
const Buffer = require('safe-buffer').Buffer | ||
const bcrypto = require('./crypto') | ||
const fastMerkleRoot = require('merkle-lib/fastRoot') | ||
const typeforce = require('typeforce') | ||
const types = require('./types') | ||
const varuint = require('varuint-bitcoin') | ||
var Transaction = require('./transaction') | ||
const Transaction = require('./transaction') | ||
@@ -22,3 +22,3 @@ function Block () { | ||
var offset = 0 | ||
let offset = 0 | ||
function readSlice (n) { | ||
@@ -30,3 +30,3 @@ offset += n | ||
function readUInt32 () { | ||
var i = buffer.readUInt32LE(offset) | ||
const i = buffer.readUInt32LE(offset) | ||
offset += 4 | ||
@@ -37,3 +37,3 @@ return i | ||
function readInt32 () { | ||
var i = buffer.readInt32LE(offset) | ||
const i = buffer.readInt32LE(offset) | ||
offset += 4 | ||
@@ -43,3 +43,3 @@ return i | ||
var block = new Block() | ||
const block = new Block() | ||
block.version = readInt32() | ||
@@ -55,3 +55,3 @@ block.prevHash = readSlice(32) | ||
function readVarInt () { | ||
var vi = varuint.decode(buffer, offset) | ||
const vi = varuint.decode(buffer, offset) | ||
offset += varuint.decode.bytes | ||
@@ -62,3 +62,3 @@ return vi | ||
function readTransaction () { | ||
var tx = Transaction.fromBuffer(buffer.slice(offset), true) | ||
const tx = Transaction.fromBuffer(buffer.slice(offset), true) | ||
offset += tx.byteLength() | ||
@@ -68,7 +68,7 @@ return tx | ||
var nTransactions = readVarInt() | ||
const nTransactions = readVarInt() | ||
block.transactions = [] | ||
for (var i = 0; i < nTransactions; ++i) { | ||
var tx = readTransaction() | ||
const tx = readTransaction() | ||
block.transactions.push(tx) | ||
@@ -101,3 +101,3 @@ } | ||
Block.prototype.getUTCDate = function () { | ||
var date = new Date(0) // epoch | ||
const date = new Date(0) // epoch | ||
date.setUTCSeconds(this.timestamp) | ||
@@ -110,5 +110,5 @@ | ||
Block.prototype.toBuffer = function (headersOnly) { | ||
var buffer = Buffer.allocUnsafe(this.byteLength(headersOnly)) | ||
const buffer = Buffer.allocUnsafe(this.byteLength(headersOnly)) | ||
var offset = 0 | ||
let offset = 0 | ||
function writeSlice (slice) { | ||
@@ -141,3 +141,3 @@ slice.copy(buffer, offset) | ||
this.transactions.forEach(function (tx) { | ||
var txSize = tx.byteLength() // TODO: extract from toBuffer? | ||
const txSize = tx.byteLength() // TODO: extract from toBuffer? | ||
tx.toBuffer(buffer, offset) | ||
@@ -155,5 +155,5 @@ offset += txSize | ||
Block.calculateTarget = function (bits) { | ||
var exponent = ((bits & 0xff000000) >> 24) - 3 | ||
var mantissa = bits & 0x007fffff | ||
var target = Buffer.alloc(32, 0) | ||
const exponent = ((bits & 0xff000000) >> 24) - 3 | ||
const mantissa = bits & 0x007fffff | ||
const target = Buffer.alloc(32, 0) | ||
target.writeUInt32BE(mantissa, 28 - exponent) | ||
@@ -167,3 +167,3 @@ return target | ||
var hashes = transactions.map(function (transaction) { | ||
const hashes = transactions.map(function (transaction) { | ||
return transaction.getHash() | ||
@@ -178,3 +178,3 @@ }) | ||
var actualMerkleRoot = Block.calculateMerkleRoot(this.transactions) | ||
const actualMerkleRoot = Block.calculateMerkleRoot(this.transactions) | ||
return this.merkleRoot.compare(actualMerkleRoot) === 0 | ||
@@ -184,4 +184,4 @@ } | ||
Block.prototype.checkProofOfWork = function () { | ||
var hash = this.getHash().reverse() | ||
var target = Block.calculateTarget(this.bits) | ||
const hash = this.getHash().reverse() | ||
const target = Block.calculateTarget(this.bits) | ||
@@ -188,0 +188,0 @@ return hash.compare(target) <= 0 |
@@ -1,4 +0,1 @@ | ||
var pushdata = require('pushdata-bitcoin') | ||
var varuint = require('varuint-bitcoin') | ||
// https://github.com/feross/buffer/blob/master/index.js#L1127 | ||
@@ -13,8 +10,7 @@ function verifuint (value, max) { | ||
function readUInt64LE (buffer, offset) { | ||
var a = buffer.readUInt32LE(offset) | ||
var b = buffer.readUInt32LE(offset + 4) | ||
const a = buffer.readUInt32LE(offset) | ||
let b = buffer.readUInt32LE(offset + 4) | ||
b *= 0x100000000 | ||
verifuint(b + a, 0x001fffffffffffff) | ||
return b + a | ||
@@ -31,28 +27,5 @@ } | ||
// TODO: remove in 4.0.0? | ||
function readVarInt (buffer, offset) { | ||
var result = varuint.decode(buffer, offset) | ||
return { | ||
number: result, | ||
size: varuint.decode.bytes | ||
} | ||
} | ||
// TODO: remove in 4.0.0? | ||
function writeVarInt (buffer, number, offset) { | ||
varuint.encode(number, buffer, offset) | ||
return varuint.encode.bytes | ||
} | ||
module.exports = { | ||
pushDataSize: pushdata.encodingLength, | ||
readPushDataInt: pushdata.decode, | ||
readUInt64LE: readUInt64LE, | ||
readVarInt: readVarInt, | ||
varIntBuffer: varuint.encode, | ||
varIntSize: varuint.encodingLength, | ||
writePushDataInt: pushdata.encode, | ||
writeUInt64LE: writeUInt64LE, | ||
writeVarInt: writeVarInt | ||
writeUInt64LE: writeUInt64LE | ||
} |
@@ -1,2 +0,2 @@ | ||
var createHash = require('create-hash') | ||
const createHash = require('create-hash') | ||
@@ -3,0 +3,0 @@ function ripemd160 (buffer) { |
@@ -1,64 +0,69 @@ | ||
var baddress = require('./address') | ||
var bcrypto = require('./crypto') | ||
var ecdsa = require('./ecdsa') | ||
var randomBytes = require('randombytes') | ||
var typeforce = require('typeforce') | ||
var types = require('./types') | ||
var wif = require('wif') | ||
const ecc = require('tiny-secp256k1') | ||
const randomBytes = require('randombytes') | ||
const typeforce = require('typeforce') | ||
const types = require('./types') | ||
const wif = require('wif') | ||
var NETWORKS = require('./networks') | ||
var BigInteger = require('bigi') | ||
const NETWORKS = require('./networks') | ||
var ecurve = require('ecurve') | ||
var secp256k1 = ecdsa.__curve | ||
// TODO: why is the function name toJSON weird? | ||
function isPoint (x) { return ecc.isPoint(x) } | ||
const isOptions = typeforce.maybe(typeforce.compile({ | ||
compressed: types.maybe(types.Boolean), | ||
network: types.maybe(types.Network) | ||
})) | ||
function ECPair (d, Q, options) { | ||
if (options) { | ||
typeforce({ | ||
compressed: types.maybe(types.Boolean), | ||
network: types.maybe(types.Network) | ||
}, options) | ||
} | ||
options = options || {} | ||
if (d) { | ||
if (d.signum() <= 0) throw new Error('Private key must be greater than 0') | ||
if (d.compareTo(secp256k1.n) >= 0) throw new Error('Private key must be less than the curve order') | ||
if (Q) throw new TypeError('Unexpected publicKey parameter') | ||
this.compressed = options.compressed === undefined ? true : options.compressed | ||
this.network = options.network || NETWORKS.bitcoin | ||
this.d = d | ||
} else { | ||
typeforce(types.ECPoint, Q) | ||
this.__d = d || null | ||
this.__Q = null | ||
if (Q) this.__Q = ecc.pointCompress(Q, this.compressed) | ||
} | ||
this.__Q = Q | ||
} | ||
Object.defineProperty(ECPair.prototype, 'privateKey', { | ||
enumerable: false, | ||
get: function () { return this.__d } | ||
}) | ||
this.compressed = options.compressed === undefined ? true : options.compressed | ||
this.network = options.network || NETWORKS.bitcoin | ||
Object.defineProperty(ECPair.prototype, 'publicKey', { get: function () { | ||
if (!this.__Q) this.__Q = ecc.pointFromScalar(this.__d, this.compressed) | ||
return this.__Q | ||
}}) | ||
ECPair.prototype.toWIF = function () { | ||
if (!this.__d) throw new Error('Missing private key') | ||
return wif.encode(this.network.wif, this.__d, this.compressed) | ||
} | ||
Object.defineProperty(ECPair.prototype, 'Q', { | ||
get: function () { | ||
if (!this.__Q && this.d) { | ||
this.__Q = secp256k1.G.multiply(this.d) | ||
} | ||
ECPair.prototype.sign = function (hash) { | ||
if (!this.__d) throw new Error('Missing private key') | ||
return ecc.sign(hash, this.__d) | ||
} | ||
return this.__Q | ||
} | ||
}) | ||
ECPair.prototype.verify = function (hash, signature) { | ||
return ecc.verify(hash, this.publicKey, signature) | ||
} | ||
ECPair.fromPublicKeyBuffer = function (buffer, network) { | ||
var Q = ecurve.Point.decodeFrom(secp256k1, buffer) | ||
function fromPrivateKey (buffer, options) { | ||
typeforce(types.Buffer256bit, buffer) | ||
if (!ecc.isPrivate(buffer)) throw new TypeError('Private key not in range [1, n)') | ||
typeforce(isOptions, options) | ||
return new ECPair(null, Q, { | ||
compressed: Q.compressed, | ||
network: network | ||
}) | ||
return new ECPair(buffer, null, options) | ||
} | ||
ECPair.fromWIF = function (string, network) { | ||
var decoded = wif.decode(string) | ||
var version = decoded.version | ||
function fromPublicKey (buffer, options) { | ||
typeforce(isPoint, buffer) | ||
typeforce(isOptions, options) | ||
return new ECPair(null, buffer, options) | ||
} | ||
function fromWIF (string, network) { | ||
const decoded = wif.decode(string) | ||
const version = decoded.version | ||
// list of networks? | ||
@@ -79,5 +84,3 @@ if (types.Array(network)) { | ||
var d = BigInteger.fromBuffer(decoded.privateKey) | ||
return new ECPair(d, null, { | ||
return fromPrivateKey(decoded.privateKey, { | ||
compressed: decoded.compressed, | ||
@@ -88,46 +91,21 @@ network: network | ||
ECPair.makeRandom = function (options) { | ||
function makeRandom (options) { | ||
typeforce(isOptions, options) | ||
options = options || {} | ||
const rng = options.rng || randomBytes | ||
var rng = options.rng || randomBytes | ||
var d | ||
let d | ||
do { | ||
var buffer = rng(32) | ||
typeforce(types.Buffer256bit, buffer) | ||
d = rng(32) | ||
typeforce(types.Buffer256bit, d) | ||
} while (!ecc.isPrivate(d)) | ||
d = BigInteger.fromBuffer(buffer) | ||
} while (d.signum() <= 0 || d.compareTo(secp256k1.n) >= 0) | ||
return new ECPair(d, null, options) | ||
return fromPrivateKey(d, options) | ||
} | ||
ECPair.prototype.getAddress = function () { | ||
return baddress.toBase58Check(bcrypto.hash160(this.getPublicKeyBuffer()), this.getNetwork().pubKeyHash) | ||
module.exports = { | ||
makeRandom, | ||
fromPrivateKey, | ||
fromPublicKey, | ||
fromWIF | ||
} | ||
ECPair.prototype.getNetwork = function () { | ||
return this.network | ||
} | ||
ECPair.prototype.getPublicKeyBuffer = function () { | ||
return this.Q.getEncoded(this.compressed) | ||
} | ||
ECPair.prototype.sign = function (hash) { | ||
if (!this.d) throw new Error('Missing private key') | ||
return ecdsa.sign(hash, this.d) | ||
} | ||
ECPair.prototype.toWIF = function () { | ||
if (!this.d) throw new Error('Missing private key') | ||
return wif.encode(this.network.wif, this.d.toBuffer(32), this.compressed) | ||
} | ||
ECPair.prototype.verify = function (hash, signature) { | ||
return ecdsa.verify(hash, signature, this.Q) | ||
} | ||
module.exports = ECPair |
@@ -1,15 +0,6 @@ | ||
var script = require('./script') | ||
const script = require('./script') | ||
var templates = require('./templates') | ||
for (var key in templates) { | ||
script[key] = templates[key] | ||
} | ||
module.exports = { | ||
bufferutils: require('./bufferutils'), // TODO: remove in 4.0.0 | ||
Block: require('./block'), | ||
ECPair: require('./ecpair'), | ||
ECSignature: require('./ecsignature'), | ||
HDNode: require('./hdnode'), | ||
Transaction: require('./transaction'), | ||
@@ -19,6 +10,8 @@ TransactionBuilder: require('./transaction_builder'), | ||
address: require('./address'), | ||
bip32: require('bip32'), | ||
crypto: require('./crypto'), | ||
networks: require('./networks'), | ||
opcodes: require('bitcoin-ops'), | ||
payments: require('./payments'), | ||
script: script | ||
} |
@@ -26,13 +26,3 @@ // https://en.bitcoin.it/wiki/List_of_address_prefixes | ||
wif: 0xef | ||
}, | ||
litecoin: { | ||
messagePrefix: '\x19Litecoin Signed Message:\n', | ||
bip32: { | ||
public: 0x019da462, | ||
private: 0x019d9cfe | ||
}, | ||
pubKeyHash: 0x30, | ||
scriptHash: 0x32, | ||
wif: 0xb0 | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
var Buffer = require('safe-buffer').Buffer | ||
const Buffer = require('safe-buffer').Buffer | ||
@@ -7,3 +7,3 @@ function decode (buffer, maxLength, minimal) { | ||
var length = buffer.length | ||
const length = buffer.length | ||
if (length === 0) return 0 | ||
@@ -19,4 +19,4 @@ if (length > maxLength) throw new TypeError('Script number overflow') | ||
if (length === 5) { | ||
var a = buffer.readUInt32LE(0) | ||
var b = buffer.readUInt8(4) | ||
const a = buffer.readUInt32LE(0) | ||
const b = buffer.readUInt8(4) | ||
@@ -27,5 +27,4 @@ if (b & 0x80) return -(((b & ~0x80) * 0x100000000) + a) | ||
var result = 0 | ||
// 32-bit / 24-bit / 16-bit / 8-bit | ||
let result = 0 | ||
for (var i = 0; i < length; ++i) { | ||
@@ -41,14 +40,14 @@ result |= buffer[i] << (8 * i) | ||
return i > 0x7fffffff ? 5 | ||
: i > 0x7fffff ? 4 | ||
: i > 0x7fff ? 3 | ||
: i > 0x7f ? 2 | ||
: i > 0x00 ? 1 | ||
: 0 | ||
: i > 0x7fffff ? 4 | ||
: i > 0x7fff ? 3 | ||
: i > 0x7f ? 2 | ||
: i > 0x00 ? 1 | ||
: 0 | ||
} | ||
function encode (number) { | ||
var value = Math.abs(number) | ||
var size = scriptNumSize(value) | ||
var buffer = Buffer.allocUnsafe(size) | ||
var negative = number < 0 | ||
let value = Math.abs(number) | ||
const size = scriptNumSize(value) | ||
const buffer = Buffer.allocUnsafe(size) | ||
const negative = number < 0 | ||
@@ -55,0 +54,0 @@ for (var i = 0; i < size; ++i) { |
@@ -1,11 +0,12 @@ | ||
var Buffer = require('safe-buffer').Buffer | ||
var bip66 = require('bip66') | ||
var pushdata = require('pushdata-bitcoin') | ||
var typeforce = require('typeforce') | ||
var types = require('./types') | ||
var scriptNumber = require('./script_number') | ||
const Buffer = require('safe-buffer').Buffer | ||
const bip66 = require('bip66') | ||
const ecc = require('tiny-secp256k1') | ||
const pushdata = require('pushdata-bitcoin') | ||
const typeforce = require('typeforce') | ||
const types = require('./types') | ||
const scriptNumber = require('./script_number') | ||
var OPS = require('bitcoin-ops') | ||
var REVERSE_OPS = require('bitcoin-ops/map') | ||
var OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1 | ||
const OPS = require('bitcoin-ops') | ||
const REVERSE_OPS = require('bitcoin-ops/map') | ||
const OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1 | ||
@@ -40,3 +41,3 @@ function isOPInt (value) { | ||
var bufferSize = chunks.reduce(function (accum, chunk) { | ||
const bufferSize = chunks.reduce(function (accum, chunk) { | ||
// data chunk | ||
@@ -56,4 +57,4 @@ if (Buffer.isBuffer(chunk)) { | ||
var buffer = Buffer.allocUnsafe(bufferSize) | ||
var offset = 0 | ||
const buffer = Buffer.allocUnsafe(bufferSize) | ||
let offset = 0 | ||
@@ -64,3 +65,3 @@ chunks.forEach(function (chunk) { | ||
// adhere to BIP62.3, minimal push policy | ||
var opcode = asMinimalOP(chunk) | ||
const opcode = asMinimalOP(chunk) | ||
if (opcode !== undefined) { | ||
@@ -93,24 +94,24 @@ buffer.writeUInt8(opcode, offset) | ||
var chunks = [] | ||
var i = 0 | ||
const chunks = [] | ||
let i = 0 | ||
while (i < buffer.length) { | ||
var opcode = buffer[i] | ||
const opcode = buffer[i] | ||
// data chunk | ||
if ((opcode > OPS.OP_0) && (opcode <= OPS.OP_PUSHDATA4)) { | ||
var d = pushdata.decode(buffer, i) | ||
const d = pushdata.decode(buffer, i) | ||
// did reading a pushDataInt fail? empty script | ||
if (d === null) return [] | ||
// did reading a pushDataInt fail? | ||
if (d === null) return null | ||
i += d.size | ||
// attempt to read too much data? empty script | ||
if (i + d.number > buffer.length) return [] | ||
// attempt to read too much data? | ||
if (i + d.number > buffer.length) return null | ||
var data = buffer.slice(i, i + d.number) | ||
const data = buffer.slice(i, i + d.number) | ||
i += d.number | ||
// decompile minimally | ||
var op = asMinimalOP(data) | ||
const op = asMinimalOP(data) | ||
if (op !== undefined) { | ||
@@ -141,3 +142,3 @@ chunks.push(op) | ||
if (Buffer.isBuffer(chunk)) { | ||
var op = asMinimalOP(chunk) | ||
const op = asMinimalOP(chunk) | ||
if (op === undefined) return chunk.toString('hex') | ||
@@ -178,24 +179,13 @@ chunk = op | ||
function isCanonicalPubKey (buffer) { | ||
if (!Buffer.isBuffer(buffer)) return false | ||
if (buffer.length < 33) return false | ||
switch (buffer[0]) { | ||
case 0x02: | ||
case 0x03: | ||
return buffer.length === 33 | ||
case 0x04: | ||
return buffer.length === 65 | ||
} | ||
return false | ||
return ecc.isPoint(buffer) | ||
} | ||
function isDefinedHashType (hashType) { | ||
var hashTypeMod = hashType & ~0x80 | ||
const hashTypeMod = hashType & ~0x80 | ||
// return hashTypeMod > SIGHASH_ALL && hashTypeMod < SIGHASH_SINGLE | ||
// return hashTypeMod > SIGHASH_ALL && hashTypeMod < SIGHASH_SINGLE | ||
return hashTypeMod > 0x00 && hashTypeMod < 0x04 | ||
} | ||
function isCanonicalSignature (buffer) { | ||
function isCanonicalScriptSignature (buffer) { | ||
if (!Buffer.isBuffer(buffer)) return false | ||
@@ -215,7 +205,8 @@ if (!isDefinedHashType(buffer[buffer.length - 1])) return false | ||
number: require('./script_number'), | ||
signature: require('./script_signature'), | ||
isCanonicalPubKey: isCanonicalPubKey, | ||
isCanonicalSignature: isCanonicalSignature, | ||
isCanonicalScriptSignature: isCanonicalScriptSignature, | ||
isPushOnly: isPushOnly, | ||
isDefinedHashType: isDefinedHashType | ||
} |
// OP_0 [signatures ...] | ||
var Buffer = require('safe-buffer').Buffer | ||
var bscript = require('../../script') | ||
var p2mso = require('./output') | ||
var typeforce = require('typeforce') | ||
var OPS = require('bitcoin-ops') | ||
const bscript = require('../../script') | ||
const OPS = require('bitcoin-ops') | ||
function partialSignature (value) { | ||
return value === OPS.OP_0 || bscript.isCanonicalSignature(value) | ||
return value === OPS.OP_0 || bscript.isCanonicalScriptSignature(value) | ||
} | ||
function check (script, allowIncomplete) { | ||
var chunks = bscript.decompile(script) | ||
const chunks = bscript.decompile(script) | ||
if (chunks.length < 2) return false | ||
@@ -22,52 +19,6 @@ if (chunks[0] !== OPS.OP_0) return false | ||
return chunks.slice(1).every(bscript.isCanonicalSignature) | ||
return chunks.slice(1).every(bscript.isCanonicalScriptSignature) | ||
} | ||
check.toJSON = function () { return 'multisig input' } | ||
var EMPTY_BUFFER = Buffer.allocUnsafe(0) | ||
function encodeStack (signatures, scriptPubKey) { | ||
typeforce([partialSignature], signatures) | ||
if (scriptPubKey) { | ||
var scriptData = p2mso.decode(scriptPubKey) | ||
if (signatures.length < scriptData.m) { | ||
throw new TypeError('Not enough signatures provided') | ||
} | ||
if (signatures.length > scriptData.pubKeys.length) { | ||
throw new TypeError('Too many signatures provided') | ||
} | ||
} | ||
return [].concat(EMPTY_BUFFER, signatures.map(function (sig) { | ||
if (sig === OPS.OP_0) { | ||
return EMPTY_BUFFER | ||
} | ||
return sig | ||
})) | ||
} | ||
function encode (signatures, scriptPubKey) { | ||
return bscript.compile(encodeStack(signatures, scriptPubKey)) | ||
} | ||
function decodeStack (stack, allowIncomplete) { | ||
typeforce(typeforce.Array, stack) | ||
typeforce(check, stack, allowIncomplete) | ||
return stack.slice(1) | ||
} | ||
function decode (buffer, allowIncomplete) { | ||
var stack = bscript.decompile(buffer) | ||
return decodeStack(stack, allowIncomplete) | ||
} | ||
module.exports = { | ||
check: check, | ||
decode: decode, | ||
decodeStack: decodeStack, | ||
encode: encode, | ||
encodeStack: encodeStack | ||
} | ||
module.exports = { check } |
// m [pubKeys ...] n OP_CHECKMULTISIG | ||
var bscript = require('../../script') | ||
var types = require('../../types') | ||
var typeforce = require('typeforce') | ||
var OPS = require('bitcoin-ops') | ||
var OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1 | ||
const bscript = require('../../script') | ||
const types = require('../../types') | ||
const OPS = require('bitcoin-ops') | ||
const OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1 | ||
function check (script, allowIncomplete) { | ||
var chunks = bscript.decompile(script) | ||
const chunks = bscript.decompile(script) | ||
@@ -16,4 +15,4 @@ if (chunks.length < 4) return false | ||
if (!types.Number(chunks[chunks.length - 2])) return false | ||
var m = chunks[0] - OP_INT_BASE | ||
var n = chunks[chunks.length - 2] - OP_INT_BASE | ||
const m = chunks[0] - OP_INT_BASE | ||
const n = chunks[chunks.length - 2] - OP_INT_BASE | ||
@@ -26,3 +25,3 @@ if (m <= 0) return false | ||
var keys = chunks.slice(1, -2) | ||
const keys = chunks.slice(1, -2) | ||
return keys.every(bscript.isCanonicalPubKey) | ||
@@ -32,36 +31,2 @@ } | ||
function encode (m, pubKeys) { | ||
typeforce({ | ||
m: types.Number, | ||
pubKeys: [bscript.isCanonicalPubKey] | ||
}, { | ||
m: m, | ||
pubKeys: pubKeys | ||
}) | ||
var n = pubKeys.length | ||
if (n < m) throw new TypeError('Not enough pubKeys provided') | ||
return bscript.compile([].concat( | ||
OP_INT_BASE + m, | ||
pubKeys, | ||
OP_INT_BASE + n, | ||
OPS.OP_CHECKMULTISIG | ||
)) | ||
} | ||
function decode (buffer, allowIncomplete) { | ||
var chunks = bscript.decompile(buffer) | ||
typeforce(check, chunks, allowIncomplete) | ||
return { | ||
m: chunks[0] - OP_INT_BASE, | ||
pubKeys: chunks.slice(1, -2) | ||
} | ||
} | ||
module.exports = { | ||
check: check, | ||
decode: decode, | ||
encode: encode | ||
} | ||
module.exports = { check } |
// OP_RETURN {data} | ||
var bscript = require('../script') | ||
var types = require('../types') | ||
var typeforce = require('typeforce') | ||
var OPS = require('bitcoin-ops') | ||
const bscript = require('../script') | ||
const OPS = require('bitcoin-ops') | ||
function check (script) { | ||
var buffer = bscript.compile(script) | ||
const buffer = bscript.compile(script) | ||
@@ -16,20 +14,2 @@ return buffer.length > 1 && | ||
function encode (data) { | ||
typeforce(types.Buffer, data) | ||
return bscript.compile([OPS.OP_RETURN, data]) | ||
} | ||
function decode (buffer) { | ||
typeforce(check, buffer) | ||
return buffer.slice(2) | ||
} | ||
module.exports = { | ||
output: { | ||
check: check, | ||
decode: decode, | ||
encode: encode | ||
} | ||
} | ||
module.exports = { output: { check: check } } |
// {signature} | ||
var bscript = require('../../script') | ||
var typeforce = require('typeforce') | ||
const bscript = require('../../script') | ||
function check (script) { | ||
var chunks = bscript.decompile(script) | ||
const chunks = bscript.decompile(script) | ||
return chunks.length === 1 && | ||
bscript.isCanonicalSignature(chunks[0]) | ||
bscript.isCanonicalScriptSignature(chunks[0]) | ||
} | ||
check.toJSON = function () { return 'pubKey input' } | ||
function encodeStack (signature) { | ||
typeforce(bscript.isCanonicalSignature, signature) | ||
return [signature] | ||
} | ||
function encode (signature) { | ||
return bscript.compile(encodeStack(signature)) | ||
} | ||
function decodeStack (stack) { | ||
typeforce(typeforce.Array, stack) | ||
typeforce(check, stack) | ||
return stack[0] | ||
} | ||
function decode (buffer) { | ||
var stack = bscript.decompile(buffer) | ||
return decodeStack(stack) | ||
} | ||
module.exports = { | ||
check: check, | ||
decode: decode, | ||
decodeStack: decodeStack, | ||
encode: encode, | ||
encodeStack: encodeStack | ||
check: check | ||
} |
// {pubKey} OP_CHECKSIG | ||
var bscript = require('../../script') | ||
var typeforce = require('typeforce') | ||
var OPS = require('bitcoin-ops') | ||
const bscript = require('../../script') | ||
const OPS = require('bitcoin-ops') | ||
function check (script) { | ||
var chunks = bscript.decompile(script) | ||
const chunks = bscript.decompile(script) | ||
@@ -16,19 +15,2 @@ return chunks.length === 2 && | ||
function encode (pubKey) { | ||
typeforce(bscript.isCanonicalPubKey, pubKey) | ||
return bscript.compile([pubKey, OPS.OP_CHECKSIG]) | ||
} | ||
function decode (buffer) { | ||
var chunks = bscript.decompile(buffer) | ||
typeforce(check, chunks) | ||
return chunks[0] | ||
} | ||
module.exports = { | ||
check: check, | ||
decode: decode, | ||
encode: encode | ||
} | ||
module.exports = { check } |
// {signature} {pubKey} | ||
var bscript = require('../../script') | ||
var typeforce = require('typeforce') | ||
const bscript = require('../../script') | ||
function check (script) { | ||
var chunks = bscript.decompile(script) | ||
const chunks = bscript.decompile(script) | ||
return chunks.length === 2 && | ||
bscript.isCanonicalSignature(chunks[0]) && | ||
bscript.isCanonicalScriptSignature(chunks[0]) && | ||
bscript.isCanonicalPubKey(chunks[1]) | ||
@@ -15,39 +14,2 @@ } | ||
function encodeStack (signature, pubKey) { | ||
typeforce({ | ||
signature: bscript.isCanonicalSignature, | ||
pubKey: bscript.isCanonicalPubKey | ||
}, { | ||
signature: signature, | ||
pubKey: pubKey | ||
}) | ||
return [signature, pubKey] | ||
} | ||
function encode (signature, pubKey) { | ||
return bscript.compile(encodeStack(signature, pubKey)) | ||
} | ||
function decodeStack (stack) { | ||
typeforce(typeforce.Array, stack) | ||
typeforce(check, stack) | ||
return { | ||
signature: stack[0], | ||
pubKey: stack[1] | ||
} | ||
} | ||
function decode (buffer) { | ||
var stack = bscript.decompile(buffer) | ||
return decodeStack(stack) | ||
} | ||
module.exports = { | ||
check: check, | ||
decode: decode, | ||
decodeStack: decodeStack, | ||
encode: encode, | ||
encodeStack: encodeStack | ||
} | ||
module.exports = { check } |
// OP_DUP OP_HASH160 {pubKeyHash} OP_EQUALVERIFY OP_CHECKSIG | ||
var bscript = require('../../script') | ||
var types = require('../../types') | ||
var typeforce = require('typeforce') | ||
var OPS = require('bitcoin-ops') | ||
const bscript = require('../../script') | ||
const OPS = require('bitcoin-ops') | ||
function check (script) { | ||
var buffer = bscript.compile(script) | ||
const buffer = bscript.compile(script) | ||
@@ -20,24 +18,2 @@ return buffer.length === 25 && | ||
function encode (pubKeyHash) { | ||
typeforce(types.Hash160bit, pubKeyHash) | ||
return bscript.compile([ | ||
OPS.OP_DUP, | ||
OPS.OP_HASH160, | ||
pubKeyHash, | ||
OPS.OP_EQUALVERIFY, | ||
OPS.OP_CHECKSIG | ||
]) | ||
} | ||
function decode (buffer) { | ||
typeforce(check, buffer) | ||
return buffer.slice(3, 23) | ||
} | ||
module.exports = { | ||
check: check, | ||
decode: decode, | ||
encode: encode | ||
} | ||
module.exports = { check } |
// <scriptSig> {serialized scriptPubKey script} | ||
var Buffer = require('safe-buffer').Buffer | ||
var bscript = require('../../script') | ||
var typeforce = require('typeforce') | ||
const Buffer = require('safe-buffer').Buffer | ||
const bscript = require('../../script') | ||
var p2ms = require('../multisig/') | ||
var p2pk = require('../pubkey/') | ||
var p2pkh = require('../pubkeyhash/') | ||
var p2wpkho = require('../witnesspubkeyhash/output') | ||
var p2wsho = require('../witnessscripthash/output') | ||
const p2ms = require('../multisig/') | ||
const p2pk = require('../pubkey/') | ||
const p2pkh = require('../pubkeyhash/') | ||
const p2wpkho = require('../witnesspubkeyhash/output') | ||
const p2wsho = require('../witnessscripthash/output') | ||
function check (script, allowIncomplete) { | ||
var chunks = bscript.decompile(script) | ||
const chunks = bscript.decompile(script) | ||
if (chunks.length < 1) return false | ||
var lastChunk = chunks[chunks.length - 1] | ||
const lastChunk = chunks[chunks.length - 1] | ||
if (!Buffer.isBuffer(lastChunk)) return false | ||
var scriptSigChunks = bscript.decompile(bscript.compile(chunks.slice(0, -1))) | ||
var redeemScriptChunks = bscript.decompile(lastChunk) | ||
const scriptSigChunks = bscript.decompile(bscript.compile(chunks.slice(0, -1))) | ||
const redeemScriptChunks = bscript.decompile(lastChunk) | ||
// is redeemScript a valid script? | ||
if (redeemScriptChunks.length === 0) return false | ||
if (!redeemScriptChunks) return false | ||
@@ -49,38 +48,2 @@ // is redeemScriptSig push only? | ||
function encodeStack (redeemScriptStack, redeemScript) { | ||
var serializedScriptPubKey = bscript.compile(redeemScript) | ||
return [].concat(redeemScriptStack, serializedScriptPubKey) | ||
} | ||
function encode (redeemScriptSig, redeemScript) { | ||
var redeemScriptStack = bscript.decompile(redeemScriptSig) | ||
return bscript.compile(encodeStack(redeemScriptStack, redeemScript)) | ||
} | ||
function decodeStack (stack) { | ||
typeforce(typeforce.Array, stack) | ||
typeforce(check, stack) | ||
return { | ||
redeemScriptStack: stack.slice(0, -1), | ||
redeemScript: stack[stack.length - 1] | ||
} | ||
} | ||
function decode (buffer) { | ||
var stack = bscript.decompile(buffer) | ||
var result = decodeStack(stack) | ||
result.redeemScriptSig = bscript.compile(result.redeemScriptStack) | ||
delete result.redeemScriptStack | ||
return result | ||
} | ||
module.exports = { | ||
check: check, | ||
decode: decode, | ||
decodeStack: decodeStack, | ||
encode: encode, | ||
encodeStack: encodeStack | ||
} | ||
module.exports = { check } |
// OP_HASH160 {scriptHash} OP_EQUAL | ||
var bscript = require('../../script') | ||
var types = require('../../types') | ||
var typeforce = require('typeforce') | ||
var OPS = require('bitcoin-ops') | ||
const bscript = require('../../script') | ||
const OPS = require('bitcoin-ops') | ||
function check (script) { | ||
var buffer = bscript.compile(script) | ||
const buffer = bscript.compile(script) | ||
@@ -18,18 +16,2 @@ return buffer.length === 23 && | ||
function encode (scriptHash) { | ||
typeforce(types.Hash160bit, scriptHash) | ||
return bscript.compile([OPS.OP_HASH160, scriptHash, OPS.OP_EQUAL]) | ||
} | ||
function decode (buffer) { | ||
typeforce(check, buffer) | ||
return buffer.slice(2, 22) | ||
} | ||
module.exports = { | ||
check: check, | ||
decode: decode, | ||
encode: encode | ||
} | ||
module.exports = { check } |
// OP_RETURN {aa21a9ed} {commitment} | ||
var Buffer = require('safe-buffer').Buffer | ||
var bscript = require('../../script') | ||
var types = require('../../types') | ||
var typeforce = require('typeforce') | ||
var OPS = require('bitcoin-ops') | ||
const Buffer = require('safe-buffer').Buffer | ||
const bscript = require('../../script') | ||
const types = require('../../types') | ||
const typeforce = require('typeforce') | ||
const OPS = require('bitcoin-ops') | ||
var HEADER = Buffer.from('aa21a9ed', 'hex') | ||
const HEADER = Buffer.from('aa21a9ed', 'hex') | ||
function check (script) { | ||
var buffer = bscript.compile(script) | ||
const buffer = bscript.compile(script) | ||
@@ -25,3 +25,3 @@ return buffer.length > 37 && | ||
var buffer = Buffer.allocUnsafe(36) | ||
const buffer = Buffer.allocUnsafe(36) | ||
HEADER.copy(buffer, 0) | ||
@@ -28,0 +28,0 @@ commitment.copy(buffer, 4) |
// {signature} {pubKey} | ||
var bscript = require('../../script') | ||
var typeforce = require('typeforce') | ||
const bscript = require('../../script') | ||
@@ -11,6 +10,6 @@ function isCompressedCanonicalPubKey (pubKey) { | ||
function check (script) { | ||
var chunks = bscript.decompile(script) | ||
const chunks = bscript.decompile(script) | ||
return chunks.length === 2 && | ||
bscript.isCanonicalSignature(chunks[0]) && | ||
bscript.isCanonicalScriptSignature(chunks[0]) && | ||
isCompressedCanonicalPubKey(chunks[1]) | ||
@@ -20,28 +19,2 @@ } | ||
function encodeStack (signature, pubKey) { | ||
typeforce({ | ||
signature: bscript.isCanonicalSignature, | ||
pubKey: isCompressedCanonicalPubKey | ||
}, { | ||
signature: signature, | ||
pubKey: pubKey | ||
}) | ||
return [signature, pubKey] | ||
} | ||
function decodeStack (stack) { | ||
typeforce(typeforce.Array, stack) | ||
typeforce(check, stack) | ||
return { | ||
signature: stack[0], | ||
pubKey: stack[1] | ||
} | ||
} | ||
module.exports = { | ||
check: check, | ||
decodeStack: decodeStack, | ||
encodeStack: encodeStack | ||
} | ||
module.exports = { check } |
// OP_0 {pubKeyHash} | ||
var bscript = require('../../script') | ||
var types = require('../../types') | ||
var typeforce = require('typeforce') | ||
var OPS = require('bitcoin-ops') | ||
const bscript = require('../../script') | ||
const OPS = require('bitcoin-ops') | ||
function check (script) { | ||
var buffer = bscript.compile(script) | ||
const buffer = bscript.compile(script) | ||
@@ -17,18 +15,4 @@ return buffer.length === 22 && | ||
function encode (pubKeyHash) { | ||
typeforce(types.Hash160bit, pubKeyHash) | ||
return bscript.compile([OPS.OP_0, pubKeyHash]) | ||
} | ||
function decode (buffer) { | ||
typeforce(check, buffer) | ||
return buffer.slice(2) | ||
} | ||
module.exports = { | ||
check: check, | ||
decode: decode, | ||
encode: encode | ||
check | ||
} |
// <scriptSig> {serialized scriptPubKey script} | ||
var bscript = require('../../script') | ||
var types = require('../../types') | ||
var typeforce = require('typeforce') | ||
const bscript = require('../../script') | ||
const types = require('../../types') | ||
const typeforce = require('typeforce') | ||
var p2ms = require('../multisig/') | ||
var p2pk = require('../pubkey/') | ||
var p2pkh = require('../pubkeyhash/') | ||
const p2ms = require('../multisig/') | ||
const p2pk = require('../pubkey/') | ||
const p2pkh = require('../pubkeyhash/') | ||
@@ -15,11 +15,11 @@ function check (chunks, allowIncomplete) { | ||
var witnessScript = chunks[chunks.length - 1] | ||
const witnessScript = chunks[chunks.length - 1] | ||
if (!Buffer.isBuffer(witnessScript)) return false | ||
var witnessScriptChunks = bscript.decompile(witnessScript) | ||
const witnessScriptChunks = bscript.decompile(witnessScript) | ||
// is witnessScript a valid script? | ||
if (witnessScriptChunks.length === 0) return false | ||
if (!witnessScriptChunks || witnessScriptChunks.length === 0) return false | ||
var witnessRawScriptSig = bscript.compile(chunks.slice(0, -1)) | ||
const witnessRawScriptSig = bscript.compile(chunks.slice(0, -1)) | ||
@@ -40,27 +40,2 @@ // match types | ||
function encodeStack (witnessData, witnessScript) { | ||
typeforce({ | ||
witnessData: [types.Buffer], | ||
witnessScript: types.Buffer | ||
}, { | ||
witnessData: witnessData, | ||
witnessScript: witnessScript | ||
}) | ||
return [].concat(witnessData, witnessScript) | ||
} | ||
function decodeStack (stack) { | ||
typeforce(typeforce.Array, stack) | ||
typeforce(check, stack) | ||
return { | ||
witnessData: stack.slice(0, -1), | ||
witnessScript: stack[stack.length - 1] | ||
} | ||
} | ||
module.exports = { | ||
check: check, | ||
decodeStack: decodeStack, | ||
encodeStack: encodeStack | ||
} | ||
module.exports = { check } |
// OP_0 {scriptHash} | ||
var bscript = require('../../script') | ||
var types = require('../../types') | ||
var typeforce = require('typeforce') | ||
var OPS = require('bitcoin-ops') | ||
const bscript = require('../../script') | ||
const OPS = require('bitcoin-ops') | ||
function check (script) { | ||
var buffer = bscript.compile(script) | ||
const buffer = bscript.compile(script) | ||
@@ -17,18 +15,2 @@ return buffer.length === 34 && | ||
function encode (scriptHash) { | ||
typeforce(types.Hash256bit, scriptHash) | ||
return bscript.compile([OPS.OP_0, scriptHash]) | ||
} | ||
function decode (buffer) { | ||
typeforce(check, buffer) | ||
return buffer.slice(2) | ||
} | ||
module.exports = { | ||
check: check, | ||
decode: decode, | ||
encode: encode | ||
} | ||
module.exports = { check } |
@@ -1,174 +0,125 @@ | ||
var Buffer = require('safe-buffer').Buffer | ||
var baddress = require('./address') | ||
var bcrypto = require('./crypto') | ||
var bscript = require('./script') | ||
var btemplates = require('./templates') | ||
var networks = require('./networks') | ||
var ops = require('bitcoin-ops') | ||
var typeforce = require('typeforce') | ||
var types = require('./types') | ||
var scriptTypes = btemplates.types | ||
var SIGNABLE = [btemplates.types.P2PKH, btemplates.types.P2PK, btemplates.types.MULTISIG] | ||
var P2SH = SIGNABLE.concat([btemplates.types.P2WPKH, btemplates.types.P2WSH]) | ||
const Buffer = require('safe-buffer').Buffer | ||
const baddress = require('./address') | ||
const bcrypto = require('./crypto') | ||
const bscript = require('./script') | ||
const networks = require('./networks') | ||
const ops = require('bitcoin-ops') | ||
const payments = require('./payments') | ||
const typeforce = require('typeforce') | ||
const types = require('./types') | ||
const classify = require('./classify') | ||
const SCRIPT_TYPES = classify.types | ||
var ECPair = require('./ecpair') | ||
var ECSignature = require('./ecsignature') | ||
var Transaction = require('./transaction') | ||
const ECPair = require('./ecpair') | ||
const Transaction = require('./transaction') | ||
function supportedType (type) { | ||
return SIGNABLE.indexOf(type) !== -1 | ||
} | ||
function expandInput (scriptSig, witnessStack, type, scriptPubKey) { | ||
if (scriptSig.length === 0 && witnessStack.length === 0) return {} | ||
if (!type) { | ||
let ssType = classify.input(scriptSig, true) | ||
let wsType = classify.witness(witnessStack, true) | ||
if (ssType === SCRIPT_TYPES.NONSTANDARD) ssType = undefined | ||
if (wsType === SCRIPT_TYPES.NONSTANDARD) wsType = undefined | ||
type = ssType || wsType | ||
} | ||
function supportedP2SHType (type) { | ||
return P2SH.indexOf(type) !== -1 | ||
} | ||
function extractChunks (type, chunks, script) { | ||
var pubKeys = [] | ||
var signatures = [] | ||
switch (type) { | ||
case scriptTypes.P2PKH: | ||
// if (redeemScript) throw new Error('Nonstandard... P2SH(P2PKH)') | ||
pubKeys = chunks.slice(1) | ||
signatures = chunks.slice(0, 1) | ||
break | ||
case SCRIPT_TYPES.P2WPKH: { | ||
const { output, pubkey, signature } = payments.p2wpkh({ witness: witnessStack }) | ||
case scriptTypes.P2PK: | ||
pubKeys[0] = script ? btemplates.pubKey.output.decode(script) : undefined | ||
signatures = chunks.slice(0, 1) | ||
break | ||
case scriptTypes.MULTISIG: | ||
if (script) { | ||
var multisig = btemplates.multisig.output.decode(script) | ||
pubKeys = multisig.pubKeys | ||
return { | ||
prevOutScript: output, | ||
prevOutType: SCRIPT_TYPES.P2WPKH, | ||
pubkeys: [pubkey], | ||
signatures: [signature] | ||
} | ||
} | ||
signatures = chunks.slice(1).map(function (chunk) { | ||
return chunk.length === 0 ? undefined : chunk | ||
}) | ||
break | ||
} | ||
case SCRIPT_TYPES.P2PKH: { | ||
const { output, pubkey, signature } = payments.p2pkh({ input: scriptSig }) | ||
return { | ||
pubKeys: pubKeys, | ||
signatures: signatures | ||
} | ||
} | ||
function expandInput (scriptSig, witnessStack) { | ||
if (scriptSig.length === 0 && witnessStack.length === 0) return {} | ||
return { | ||
prevOutScript: output, | ||
prevOutType: SCRIPT_TYPES.P2PKH, | ||
pubkeys: [pubkey], | ||
signatures: [signature] | ||
} | ||
} | ||
var prevOutScript | ||
var prevOutType | ||
var scriptType | ||
var script | ||
var redeemScript | ||
var witnessScript | ||
var witnessScriptType | ||
var redeemScriptType | ||
var witness = false | ||
var p2wsh = false | ||
var p2sh = false | ||
var witnessProgram | ||
var chunks | ||
case SCRIPT_TYPES.P2PK: { | ||
const { signature } = payments.p2pk({ input: scriptSig }) | ||
var scriptSigChunks = bscript.decompile(scriptSig) | ||
var sigType = btemplates.classifyInput(scriptSigChunks, true) | ||
if (sigType === scriptTypes.P2SH) { | ||
p2sh = true | ||
redeemScript = scriptSigChunks[scriptSigChunks.length - 1] | ||
redeemScriptType = btemplates.classifyOutput(redeemScript) | ||
prevOutScript = btemplates.scriptHash.output.encode(bcrypto.hash160(redeemScript)) | ||
prevOutType = scriptTypes.P2SH | ||
script = redeemScript | ||
} | ||
var classifyWitness = btemplates.classifyWitness(witnessStack, true) | ||
if (classifyWitness === scriptTypes.P2WSH) { | ||
witnessScript = witnessStack[witnessStack.length - 1] | ||
witnessScriptType = btemplates.classifyOutput(witnessScript) | ||
p2wsh = true | ||
witness = true | ||
if (scriptSig.length === 0) { | ||
prevOutScript = btemplates.witnessScriptHash.output.encode(bcrypto.sha256(witnessScript)) | ||
prevOutType = scriptTypes.P2WSH | ||
if (redeemScript !== undefined) { | ||
throw new Error('Redeem script given when unnecessary') | ||
return { | ||
prevOutType: SCRIPT_TYPES.P2PK, | ||
pubkeys: [undefined], | ||
signatures: [signature] | ||
} | ||
// bare witness | ||
} else { | ||
if (!redeemScript) { | ||
throw new Error('No redeemScript provided for P2WSH, but scriptSig non-empty') | ||
} | ||
witnessProgram = btemplates.witnessScriptHash.output.encode(bcrypto.sha256(witnessScript)) | ||
if (!redeemScript.equals(witnessProgram)) { | ||
throw new Error('Redeem script didn\'t match witnessScript') | ||
} | ||
} | ||
if (!supportedType(btemplates.classifyOutput(witnessScript))) { | ||
throw new Error('unsupported witness script') | ||
} | ||
case SCRIPT_TYPES.MULTISIG: { | ||
const { pubkeys, signatures } = payments.p2ms({ | ||
input: scriptSig, | ||
output: scriptPubKey | ||
}, { allowIncomplete: true }) | ||
script = witnessScript | ||
scriptType = witnessScriptType | ||
chunks = witnessStack.slice(0, -1) | ||
} else if (classifyWitness === scriptTypes.P2WPKH) { | ||
witness = true | ||
var key = witnessStack[witnessStack.length - 1] | ||
var keyHash = bcrypto.hash160(key) | ||
if (scriptSig.length === 0) { | ||
prevOutScript = btemplates.witnessPubKeyHash.output.encode(keyHash) | ||
prevOutType = scriptTypes.P2WPKH | ||
if (typeof redeemScript !== 'undefined') { | ||
throw new Error('Redeem script given when unnecessary') | ||
return { | ||
prevOutType: SCRIPT_TYPES.MULTISIG, | ||
pubkeys: pubkeys, | ||
signatures: signatures | ||
} | ||
} else { | ||
if (!redeemScript) { | ||
throw new Error('No redeemScript provided for P2WPKH, but scriptSig wasn\'t empty') | ||
} | ||
witnessProgram = btemplates.witnessPubKeyHash.output.encode(keyHash) | ||
if (!redeemScript.equals(witnessProgram)) { | ||
throw new Error('Redeem script did not have the right witness program') | ||
} | ||
} | ||
} | ||
scriptType = scriptTypes.P2PKH | ||
chunks = witnessStack | ||
} else if (redeemScript) { | ||
if (!supportedP2SHType(redeemScriptType)) { | ||
throw new Error('Bad redeemscript!') | ||
} | ||
if (type === SCRIPT_TYPES.P2SH) { | ||
const { output, redeem } = payments.p2sh({ | ||
input: scriptSig, | ||
witness: witnessStack | ||
}) | ||
script = redeemScript | ||
scriptType = redeemScriptType | ||
chunks = scriptSigChunks.slice(0, -1) | ||
} else { | ||
prevOutType = scriptType = btemplates.classifyInput(scriptSig) | ||
chunks = scriptSigChunks | ||
} | ||
const outputType = classify.output(redeem.output) | ||
const expanded = expandInput(redeem.input, redeem.witness, outputType, redeem.output) | ||
if (!expanded.prevOutType) return {} | ||
var expanded = extractChunks(scriptType, chunks, script) | ||
return { | ||
prevOutScript: output, | ||
prevOutType: SCRIPT_TYPES.P2SH, | ||
redeemScript: redeem.output, | ||
redeemScriptType: expanded.prevOutType, | ||
witnessScript: expanded.witnessScript, | ||
witnessScriptType: expanded.witnessScriptType, | ||
var result = { | ||
pubKeys: expanded.pubKeys, | ||
signatures: expanded.signatures, | ||
prevOutScript: prevOutScript, | ||
prevOutType: prevOutType, | ||
signType: scriptType, | ||
signScript: script, | ||
witness: Boolean(witness) | ||
pubkeys: expanded.pubkeys, | ||
signatures: expanded.signatures | ||
} | ||
} | ||
if (p2sh) { | ||
result.redeemScript = redeemScript | ||
result.redeemScriptType = redeemScriptType | ||
if (type === SCRIPT_TYPES.P2WSH) { | ||
const { output, redeem } = payments.p2wsh({ | ||
input: scriptSig, | ||
witness: witnessStack | ||
}) | ||
const outputType = classify.output(redeem.output) | ||
let expanded | ||
if (outputType === SCRIPT_TYPES.P2WPKH) { | ||
expanded = expandInput(redeem.input, redeem.witness, outputType) | ||
} else { | ||
expanded = expandInput(bscript.compile(redeem.witness), [], outputType, redeem.output) | ||
} | ||
if (!expanded.prevOutType) return {} | ||
return { | ||
prevOutScript: output, | ||
prevOutType: SCRIPT_TYPES.P2WSH, | ||
witnessScript: redeem.output, | ||
witnessScriptType: expanded.prevOutType, | ||
pubkeys: expanded.pubkeys, | ||
signatures: expanded.signatures | ||
} | ||
} | ||
if (p2wsh) { | ||
result.witnessScript = witnessScript | ||
result.witnessScriptType = witnessScriptType | ||
return { | ||
prevOutType: SCRIPT_TYPES.NONSTANDARD, | ||
prevOutScript: scriptSig | ||
} | ||
return result | ||
} | ||
@@ -178,10 +129,10 @@ | ||
function fixMultisigOrder (input, transaction, vin) { | ||
if (input.redeemScriptType !== scriptTypes.MULTISIG || !input.redeemScript) return | ||
if (input.pubKeys.length === input.signatures.length) return | ||
if (input.redeemScriptType !== SCRIPT_TYPES.MULTISIG || !input.redeemScript) return | ||
if (input.pubkeys.length === input.signatures.length) return | ||
var unmatched = input.signatures.concat() | ||
const unmatched = input.signatures.concat() | ||
input.signatures = input.pubKeys.map(function (pubKey) { | ||
var keyPair = ECPair.fromPublicKeyBuffer(pubKey) | ||
var match | ||
input.signatures = input.pubkeys.map(function (pubKey) { | ||
const keyPair = ECPair.fromPublicKey(pubKey) | ||
let match | ||
@@ -194,4 +145,4 @@ // check for a signature | ||
// TODO: avoid O(n) hashForSignature | ||
var parsed = ECSignature.parseScriptSignature(signature) | ||
var hash = transaction.hashForSignature(vin, input.redeemScript, parsed.hashType) | ||
const parsed = bscript.signature.decode(signature) | ||
const hash = transaction.hashForSignature(vin, input.redeemScript, parsed.hashType) | ||
@@ -212,261 +163,274 @@ // skip if signature does not match pubKey | ||
function expandOutput (script, scriptType, ourPubKey) { | ||
function expandOutput (script, ourPubKey) { | ||
typeforce(types.Buffer, script) | ||
const type = classify.output(script) | ||
var scriptChunks = bscript.decompile(script) | ||
if (!scriptType) { | ||
scriptType = btemplates.classifyOutput(script) | ||
} | ||
switch (type) { | ||
case SCRIPT_TYPES.P2PKH: { | ||
if (!ourPubKey) return { type } | ||
var pubKeys = [] | ||
// does our hash160(pubKey) match the output scripts? | ||
const pkh1 = payments.p2pkh({ output: script }).hash | ||
const pkh2 = bcrypto.hash160(ourPubKey) | ||
if (!pkh1.equals(pkh2)) return { type } | ||
switch (scriptType) { | ||
// does our hash160(pubKey) match the output scripts? | ||
case scriptTypes.P2PKH: | ||
if (!ourPubKey) break | ||
return { | ||
type, | ||
pubkeys: [ourPubKey], | ||
signatures: [undefined] | ||
} | ||
} | ||
var pkh1 = scriptChunks[2] | ||
var pkh2 = bcrypto.hash160(ourPubKey) | ||
if (pkh1.equals(pkh2)) pubKeys = [ourPubKey] | ||
break | ||
case SCRIPT_TYPES.P2WPKH: { | ||
if (!ourPubKey) return { type } | ||
// does our hash160(pubKey) match the output scripts? | ||
case scriptTypes.P2WPKH: | ||
if (!ourPubKey) break | ||
// does our hash160(pubKey) match the output scripts? | ||
const wpkh1 = payments.p2wpkh({ output: script }).hash | ||
const wpkh2 = bcrypto.hash160(ourPubKey) | ||
if (!wpkh1.equals(wpkh2)) return { type } | ||
var wpkh1 = scriptChunks[1] | ||
var wpkh2 = bcrypto.hash160(ourPubKey) | ||
if (wpkh1.equals(wpkh2)) pubKeys = [ourPubKey] | ||
break | ||
return { | ||
type, | ||
pubkeys: [ourPubKey], | ||
signatures: [undefined] | ||
} | ||
} | ||
case scriptTypes.P2PK: | ||
pubKeys = scriptChunks.slice(0, 1) | ||
break | ||
case SCRIPT_TYPES.P2PK: { | ||
const p2pk = payments.p2pk({ output: script }) | ||
return { | ||
type, | ||
pubkeys: [p2pk.pubkey], | ||
signatures: [undefined] | ||
} | ||
} | ||
case scriptTypes.MULTISIG: | ||
pubKeys = scriptChunks.slice(1, -2) | ||
break | ||
default: return { scriptType: scriptType } | ||
case SCRIPT_TYPES.MULTISIG: { | ||
const p2ms = payments.p2ms({ output: script }) | ||
return { | ||
type, | ||
pubkeys: p2ms.pubkeys, | ||
signatures: p2ms.pubkeys.map(() => undefined) | ||
} | ||
} | ||
} | ||
return { | ||
pubKeys: pubKeys, | ||
scriptType: scriptType, | ||
signatures: pubKeys.map(function () { return undefined }) | ||
} | ||
return { type } | ||
} | ||
function checkP2SHInput (input, redeemScriptHash) { | ||
if (input.prevOutType) { | ||
if (input.prevOutType !== scriptTypes.P2SH) throw new Error('PrevOutScript must be P2SH') | ||
function prepareInput (input, ourPubKey, redeemScript, witnessValue, witnessScript) { | ||
if (redeemScript && witnessScript) { | ||
const p2wsh = payments.p2wsh({ redeem: { output: witnessScript } }) | ||
const p2wshAlt = payments.p2wsh({ output: redeemScript }) | ||
const p2sh = payments.p2sh({ redeem: { output: redeemScript } }) | ||
const p2shAlt = payments.p2sh({ redeem: p2wsh }) | ||
var prevOutScriptScriptHash = bscript.decompile(input.prevOutScript)[1] | ||
if (!prevOutScriptScriptHash.equals(redeemScriptHash)) throw new Error('Inconsistent hash160(RedeemScript)') | ||
} | ||
} | ||
// enforces P2SH(P2WSH(...)) | ||
if (!p2wsh.hash.equals(p2wshAlt.hash)) throw new Error('Witness script inconsistent with prevOutScript') | ||
if (!p2sh.hash.equals(p2shAlt.hash)) throw new Error('Redeem script inconsistent with prevOutScript') | ||
function checkP2WSHInput (input, witnessScriptHash) { | ||
if (input.prevOutType) { | ||
if (input.prevOutType !== scriptTypes.P2WSH) throw new Error('PrevOutScript must be P2WSH') | ||
const expanded = expandOutput(p2wsh.redeem.output, ourPubKey) | ||
if (!expanded.pubkeys) throw new Error(expanded.type + ' not supported as witnessScript (' + bscript.toASM(witnessScript) + ')') | ||
if (input.signatures && input.signatures.some(x => x)) { | ||
expanded.signatures = input.signatures | ||
} | ||
var scriptHash = bscript.decompile(input.prevOutScript)[1] | ||
if (!scriptHash.equals(witnessScriptHash)) throw new Error('Inconsistent sha25(WitnessScript)') | ||
} | ||
} | ||
let signScript = witnessScript | ||
if (expanded.type === SCRIPT_TYPES.P2WPKH) throw new Error('P2SH(P2WSH(P2WPKH)) is a consensus failure') | ||
function prepareInput (input, kpPubKey, redeemScript, witnessValue, witnessScript) { | ||
var expanded | ||
var prevOutType | ||
var prevOutScript | ||
return { | ||
redeemScript, | ||
redeemScriptType: SCRIPT_TYPES.P2WSH, | ||
var p2sh = false | ||
var p2shType | ||
var redeemScriptHash | ||
witnessScript, | ||
witnessScriptType: expanded.type, | ||
var witness = false | ||
var p2wsh = false | ||
var witnessType | ||
var witnessScriptHash | ||
prevOutType: SCRIPT_TYPES.P2SH, | ||
prevOutScript: p2sh.output, | ||
var signType | ||
var signScript | ||
hasWitness: true, | ||
signScript, | ||
signType: expanded.type, | ||
if (redeemScript && witnessScript) { | ||
redeemScriptHash = bcrypto.hash160(redeemScript) | ||
witnessScriptHash = bcrypto.sha256(witnessScript) | ||
checkP2SHInput(input, redeemScriptHash) | ||
pubkeys: expanded.pubkeys, | ||
signatures: expanded.signatures | ||
} | ||
} | ||
if (!redeemScript.equals(btemplates.witnessScriptHash.output.encode(witnessScriptHash))) throw new Error('Witness script inconsistent with redeem script') | ||
if (redeemScript) { | ||
const p2sh = payments.p2sh({ redeem: { output: redeemScript } }) | ||
expanded = expandOutput(witnessScript, undefined, kpPubKey) | ||
if (!expanded.pubKeys) throw new Error('WitnessScript not supported "' + bscript.toASM(redeemScript) + '"') | ||
if (input.prevOutScript) { | ||
let p2shAlt | ||
try { | ||
p2shAlt = payments.p2sh({ output: input.prevOutScript }) | ||
} catch (e) { throw new Error('PrevOutScript must be P2SH') } | ||
if (!p2sh.hash.equals(p2shAlt.hash)) throw new Error('Redeem script inconsistent with prevOutScript') | ||
} | ||
prevOutType = btemplates.types.P2SH | ||
prevOutScript = btemplates.scriptHash.output.encode(redeemScriptHash) | ||
p2sh = witness = p2wsh = true | ||
p2shType = btemplates.types.P2WSH | ||
signType = witnessType = expanded.scriptType | ||
signScript = witnessScript | ||
} else if (redeemScript) { | ||
redeemScriptHash = bcrypto.hash160(redeemScript) | ||
checkP2SHInput(input, redeemScriptHash) | ||
const expanded = expandOutput(p2sh.redeem.output, ourPubKey) | ||
if (!expanded.pubkeys) throw new Error(expanded.type + ' not supported as redeemScript (' + bscript.toASM(redeemScript) + ')') | ||
if (input.signatures && input.signatures.some(x => x)) { | ||
expanded.signatures = input.signatures | ||
} | ||
expanded = expandOutput(redeemScript, undefined, kpPubKey) | ||
if (!expanded.pubKeys) throw new Error('RedeemScript not supported "' + bscript.toASM(redeemScript) + '"') | ||
let signScript = redeemScript | ||
if (expanded.type === SCRIPT_TYPES.P2WPKH) { | ||
signScript = payments.p2pkh({ pubkey: expanded.pubkeys[0] }).output | ||
} | ||
prevOutType = btemplates.types.P2SH | ||
prevOutScript = btemplates.scriptHash.output.encode(redeemScriptHash) | ||
p2sh = true | ||
signType = p2shType = expanded.scriptType | ||
signScript = redeemScript | ||
witness = signType === btemplates.types.P2WPKH | ||
} else if (witnessScript) { | ||
witnessScriptHash = bcrypto.sha256(witnessScript) | ||
checkP2WSHInput(input, witnessScriptHash) | ||
return { | ||
redeemScript, | ||
redeemScriptType: expanded.type, | ||
expanded = expandOutput(witnessScript, undefined, kpPubKey) | ||
if (!expanded.pubKeys) throw new Error('WitnessScript not supported "' + bscript.toASM(redeemScript) + '"') | ||
prevOutType: SCRIPT_TYPES.P2SH, | ||
prevOutScript: p2sh.output, | ||
prevOutType = btemplates.types.P2WSH | ||
prevOutScript = btemplates.witnessScriptHash.output.encode(witnessScriptHash) | ||
witness = p2wsh = true | ||
signType = witnessType = expanded.scriptType | ||
signScript = witnessScript | ||
} else if (input.prevOutType) { | ||
// embedded scripts are not possible without a redeemScript | ||
if (input.prevOutType === scriptTypes.P2SH || | ||
input.prevOutType === scriptTypes.P2WSH) { | ||
throw new Error('PrevOutScript is ' + input.prevOutType + ', requires redeemScript') | ||
hasWitness: expanded.type === SCRIPT_TYPES.P2WPKH, | ||
signScript, | ||
signType: expanded.type, | ||
pubkeys: expanded.pubkeys, | ||
signatures: expanded.signatures | ||
} | ||
} | ||
prevOutType = input.prevOutType | ||
prevOutScript = input.prevOutScript | ||
expanded = expandOutput(input.prevOutScript, input.prevOutType, kpPubKey) | ||
if (!expanded.pubKeys) return | ||
if (witnessScript) { | ||
const p2wsh = payments.p2wsh({ redeem: { output: witnessScript } }) | ||
witness = (input.prevOutType === scriptTypes.P2WPKH) | ||
signType = prevOutType | ||
signScript = prevOutScript | ||
} else { | ||
prevOutScript = btemplates.pubKeyHash.output.encode(bcrypto.hash160(kpPubKey)) | ||
expanded = expandOutput(prevOutScript, scriptTypes.P2PKH, kpPubKey) | ||
if (input.prevOutScript) { | ||
const p2wshAlt = payments.p2wsh({ output: input.prevOutScript }) | ||
if (!p2wsh.hash.equals(p2wshAlt.hash)) throw new Error('Witness script inconsistent with prevOutScript') | ||
} | ||
prevOutType = scriptTypes.P2PKH | ||
witness = false | ||
signType = prevOutType | ||
signScript = prevOutScript | ||
} | ||
const expanded = expandOutput(p2wsh.redeem.output, ourPubKey) | ||
if (!expanded.pubkeys) throw new Error(expanded.type + ' not supported as witnessScript (' + bscript.toASM(witnessScript) + ')') | ||
if (input.signatures && input.signatures.some(x => x)) { | ||
expanded.signatures = input.signatures | ||
} | ||
if (signType === scriptTypes.P2WPKH) { | ||
signScript = btemplates.pubKeyHash.output.encode(btemplates.witnessPubKeyHash.output.decode(signScript)) | ||
} | ||
let signScript = witnessScript | ||
if (expanded.type === SCRIPT_TYPES.P2WPKH) throw new Error('P2WSH(P2WPKH) is a consensus failure') | ||
if (p2sh) { | ||
input.redeemScript = redeemScript | ||
input.redeemScriptType = p2shType | ||
} | ||
return { | ||
witnessScript, | ||
witnessScriptType: expanded.type, | ||
if (p2wsh) { | ||
input.witnessScript = witnessScript | ||
input.witnessScriptType = witnessType | ||
prevOutType: SCRIPT_TYPES.P2WSH, | ||
prevOutScript: p2wsh.output, | ||
hasWitness: true, | ||
signScript, | ||
signType: expanded.type, | ||
pubkeys: expanded.pubkeys, | ||
signatures: expanded.signatures | ||
} | ||
} | ||
input.pubKeys = expanded.pubKeys | ||
input.signatures = expanded.signatures | ||
input.signScript = signScript | ||
input.signType = signType | ||
input.prevOutScript = prevOutScript | ||
input.prevOutType = prevOutType | ||
input.witness = witness | ||
} | ||
if (input.prevOutType && input.prevOutScript) { | ||
// embedded scripts are not possible without extra information | ||
if (input.prevOutType === SCRIPT_TYPES.P2SH) throw new Error('PrevOutScript is ' + input.prevOutType + ', requires redeemScript') | ||
if (input.prevOutType === SCRIPT_TYPES.P2WSH) throw new Error('PrevOutScript is ' + input.prevOutType + ', requires witnessScript') | ||
if (!input.prevOutScript) throw new Error('PrevOutScript is missing') | ||
function buildStack (type, signatures, pubKeys, allowIncomplete) { | ||
if (type === scriptTypes.P2PKH) { | ||
if (signatures.length === 1 && Buffer.isBuffer(signatures[0]) && pubKeys.length === 1) return btemplates.pubKeyHash.input.encodeStack(signatures[0], pubKeys[0]) | ||
} else if (type === scriptTypes.P2PK) { | ||
if (signatures.length === 1 && Buffer.isBuffer(signatures[0])) return btemplates.pubKey.input.encodeStack(signatures[0]) | ||
} else if (type === scriptTypes.MULTISIG) { | ||
if (signatures.length > 0) { | ||
signatures = signatures.map(function (signature) { | ||
return signature || ops.OP_0 | ||
}) | ||
if (!allowIncomplete) { | ||
// remove blank signatures | ||
signatures = signatures.filter(function (x) { return x !== ops.OP_0 }) | ||
} | ||
const expanded = expandOutput(input.prevOutScript, ourPubKey) | ||
if (!expanded.pubkeys) throw new Error(expanded.type + ' not supported (' + bscript.toASM(input.prevOutScript) + ')') | ||
if (input.signatures && input.signatures.some(x => x)) { | ||
expanded.signatures = input.signatures | ||
} | ||
return btemplates.multisig.input.encodeStack(signatures) | ||
let signScript = input.prevOutScript | ||
if (expanded.type === SCRIPT_TYPES.P2WPKH) { | ||
signScript = payments.p2pkh({ pubkey: expanded.pubkeys[0] }).output | ||
} | ||
} else { | ||
throw new Error('Not yet supported') | ||
return { | ||
prevOutType: expanded.type, | ||
prevOutScript: input.prevOutScript, | ||
hasWitness: expanded.type === SCRIPT_TYPES.P2WPKH, | ||
signScript, | ||
signType: expanded.type, | ||
pubkeys: expanded.pubkeys, | ||
signatures: expanded.signatures | ||
} | ||
} | ||
if (!allowIncomplete) throw new Error('Not enough signatures provided') | ||
return [] | ||
} | ||
const prevOutScript = payments.p2pkh({ pubkey: ourPubKey }).output | ||
return { | ||
prevOutType: SCRIPT_TYPES.P2PKH, | ||
prevOutScript: prevOutScript, | ||
function buildInput (input, allowIncomplete) { | ||
var scriptType = input.prevOutType | ||
var sig = [] | ||
var witness = [] | ||
hasWitness: false, | ||
signScript: prevOutScript, | ||
signType: SCRIPT_TYPES.P2PKH, | ||
if (supportedType(scriptType)) { | ||
sig = buildStack(scriptType, input.signatures, input.pubKeys, allowIncomplete) | ||
pubkeys: [ourPubKey], | ||
signatures: [undefined] | ||
} | ||
} | ||
var p2sh = false | ||
if (scriptType === btemplates.types.P2SH) { | ||
// We can remove this error later when we have a guarantee prepareInput | ||
// rejects unsignable scripts - it MUST be signable at this point. | ||
if (!allowIncomplete && !supportedP2SHType(input.redeemScriptType)) { | ||
throw new Error('Impossible to sign this type') | ||
function build (type, input, allowIncomplete) { | ||
const pubkeys = input.pubkeys || [] | ||
let signatures = input.signatures || [] | ||
switch (type) { | ||
case SCRIPT_TYPES.P2PKH: { | ||
if (pubkeys.length === 0) break | ||
if (signatures.length === 0) break | ||
return payments.p2pkh({ pubkey: pubkeys[0], signature: signatures[0] }) | ||
} | ||
case SCRIPT_TYPES.P2WPKH: { | ||
if (pubkeys.length === 0) break | ||
if (signatures.length === 0) break | ||
if (supportedType(input.redeemScriptType)) { | ||
sig = buildStack(input.redeemScriptType, input.signatures, input.pubKeys, allowIncomplete) | ||
return payments.p2wpkh({ pubkey: pubkeys[0], signature: signatures[0] }) | ||
} | ||
case SCRIPT_TYPES.P2PK: { | ||
if (pubkeys.length === 0) break | ||
if (signatures.length === 0) break | ||
// If it wasn't SIGNABLE, it's witness, defer to that | ||
if (input.redeemScriptType) { | ||
p2sh = true | ||
scriptType = input.redeemScriptType | ||
return payments.p2pk({ signature: signatures[0] }) | ||
} | ||
} | ||
switch (scriptType) { | ||
// P2WPKH is a special case of P2PKH | ||
case btemplates.types.P2WPKH: | ||
witness = buildStack(btemplates.types.P2PKH, input.signatures, input.pubKeys, allowIncomplete) | ||
break | ||
case btemplates.types.P2WSH: | ||
// We can remove this check later | ||
if (!allowIncomplete && !supportedType(input.witnessScriptType)) { | ||
throw new Error('Impossible to sign this type') | ||
case SCRIPT_TYPES.MULTISIG: { | ||
if (allowIncomplete) { | ||
signatures = signatures.map(x => x || ops.OP_0) | ||
} else { | ||
signatures = signatures.filter(x => x) | ||
} | ||
if (supportedType(input.witnessScriptType)) { | ||
witness = buildStack(input.witnessScriptType, input.signatures, input.pubKeys, allowIncomplete) | ||
witness.push(input.witnessScript) | ||
scriptType = input.witnessScriptType | ||
} | ||
return payments.p2ms({ signatures }, { allowIncomplete }) | ||
} | ||
case SCRIPT_TYPES.P2SH: { | ||
const redeem = build(input.redeemScriptType, input, allowIncomplete) | ||
if (!redeem) return | ||
break | ||
} | ||
return payments.p2sh({ | ||
redeem: { | ||
output: redeem.output || input.redeemScript, | ||
input: redeem.input, | ||
witness: redeem.witness | ||
} | ||
}) | ||
} | ||
case SCRIPT_TYPES.P2WSH: { | ||
const redeem = build(input.witnessScriptType, input, allowIncomplete) | ||
if (!redeem) return | ||
// append redeemScript if necessary | ||
if (p2sh) { | ||
sig.push(input.redeemScript) | ||
return payments.p2wsh({ | ||
redeem: { | ||
output: input.witnessScript, | ||
input: redeem.input, | ||
witness: redeem.witness | ||
} | ||
}) | ||
} | ||
} | ||
return { | ||
type: scriptType, | ||
script: bscript.compile(sig), | ||
witness: witness | ||
} | ||
} | ||
function TransactionBuilder (network, maximumFeeRate) { | ||
this.prevTxMap = {} | ||
this.__prevTxSet = {} | ||
this.network = network || networks.bitcoin | ||
@@ -477,4 +441,5 @@ | ||
this.inputs = [] | ||
this.tx = new Transaction() | ||
this.__inputs = [] | ||
this.__tx = new Transaction() | ||
this.__tx.version = 2 | ||
} | ||
@@ -486,3 +451,3 @@ | ||
// if any signatures exist, throw | ||
if (this.inputs.some(function (input) { | ||
if (this.__inputs.some(function (input) { | ||
if (!input.signatures) return false | ||
@@ -495,3 +460,3 @@ | ||
this.tx.locktime = locktime | ||
this.__tx.locktime = locktime | ||
} | ||
@@ -503,7 +468,7 @@ | ||
// XXX: this might eventually become more complex depending on what the versions represent | ||
this.tx.version = version | ||
this.__tx.version = version | ||
} | ||
TransactionBuilder.fromTransaction = function (transaction, network) { | ||
var txb = new TransactionBuilder(network) | ||
const txb = new TransactionBuilder(network) | ||
@@ -529,3 +494,3 @@ // Copy transaction fields | ||
// fix some things not possible through the public API | ||
txb.inputs.forEach(function (input, i) { | ||
txb.__inputs.forEach(function (input, i) { | ||
fixMultisigOrder(input, transaction, i) | ||
@@ -542,3 +507,3 @@ }) | ||
var value | ||
let value | ||
@@ -552,3 +517,3 @@ // is it a hex string? | ||
} else if (txHash instanceof Transaction) { | ||
var txOut = txHash.outs[vout] | ||
const txOut = txHash.outs[vout] | ||
prevOutScript = txOut.script | ||
@@ -572,6 +537,6 @@ value = txOut.value | ||
var prevTxOut = txHash.toString('hex') + ':' + vout | ||
if (this.prevTxMap[prevTxOut] !== undefined) throw new Error('Duplicate TxOut: ' + prevTxOut) | ||
const prevTxOut = txHash.toString('hex') + ':' + vout | ||
if (this.__prevTxSet[prevTxOut] !== undefined) throw new Error('Duplicate TxOut: ' + prevTxOut) | ||
var input = {} | ||
let input = {} | ||
@@ -590,22 +555,21 @@ // derive what we can from the scriptSig | ||
if (!input.prevOutScript && options.prevOutScript) { | ||
var prevOutType | ||
let prevOutType | ||
if (!input.pubKeys && !input.signatures) { | ||
var expanded = expandOutput(options.prevOutScript) | ||
if (expanded.pubKeys) { | ||
input.pubKeys = expanded.pubKeys | ||
if (!input.pubkeys && !input.signatures) { | ||
const expanded = expandOutput(options.prevOutScript) | ||
if (expanded.pubkeys) { | ||
input.pubkeys = expanded.pubkeys | ||
input.signatures = expanded.signatures | ||
} | ||
prevOutType = expanded.scriptType | ||
prevOutType = expanded.type | ||
} | ||
input.prevOutScript = options.prevOutScript | ||
input.prevOutType = prevOutType || btemplates.classifyOutput(options.prevOutScript) | ||
input.prevOutType = prevOutType || classify.output(options.prevOutScript) | ||
} | ||
var vin = this.tx.addInput(txHash, vout, options.sequence, options.scriptSig) | ||
this.inputs[vin] = input | ||
this.prevTxMap[prevTxOut] = vin | ||
const vin = this.__tx.addInput(txHash, vout, options.sequence, options.scriptSig) | ||
this.__inputs[vin] = input | ||
this.__prevTxSet[prevTxOut] = true | ||
return vin | ||
@@ -619,3 +583,3 @@ } | ||
// Attempt to get a script if it's a base58 address string | ||
// Attempt to get a script if it's a base58 or bech32 address string | ||
if (typeof scriptPubKey === 'string') { | ||
@@ -625,3 +589,3 @@ scriptPubKey = baddress.toOutputScript(scriptPubKey, this.network) | ||
return this.tx.addOutput(scriptPubKey, value) | ||
return this.__tx.addOutput(scriptPubKey, value) | ||
} | ||
@@ -638,21 +602,20 @@ | ||
if (!allowIncomplete) { | ||
if (!this.tx.ins.length) throw new Error('Transaction has no inputs') | ||
if (!this.tx.outs.length) throw new Error('Transaction has no outputs') | ||
if (!this.__tx.ins.length) throw new Error('Transaction has no inputs') | ||
if (!this.__tx.outs.length) throw new Error('Transaction has no outputs') | ||
} | ||
var tx = this.tx.clone() | ||
// Create script signatures from inputs | ||
this.inputs.forEach(function (input, i) { | ||
var scriptType = input.witnessScriptType || input.redeemScriptType || input.prevOutType | ||
if (!scriptType && !allowIncomplete) throw new Error('Transaction is not complete') | ||
var result = buildInput(input, allowIncomplete) | ||
const tx = this.__tx.clone() | ||
// skip if no result | ||
if (!allowIncomplete) { | ||
if (!supportedType(result.type) && result.type !== btemplates.types.P2WPKH) { | ||
throw new Error(result.type + ' not supported') | ||
} | ||
// create script signatures from inputs | ||
this.__inputs.forEach(function (input, i) { | ||
if (!input.prevOutType && !allowIncomplete) throw new Error('Transaction is not complete') | ||
const result = build(input.prevOutType, input, allowIncomplete) | ||
if (!result) { | ||
if (!allowIncomplete && input.prevOutType === SCRIPT_TYPES.NONSTANDARD) throw new Error('Unknown input type') | ||
if (!allowIncomplete) throw new Error('Not enough information') | ||
return | ||
} | ||
tx.setInputScript(i, result.script) | ||
tx.setInputScript(i, result.input) | ||
tx.setWitness(i, result.witness) | ||
@@ -672,11 +635,11 @@ }) | ||
function canSign (input) { | ||
return input.prevOutScript !== undefined && | ||
input.signScript !== undefined && | ||
input.pubKeys !== undefined && | ||
return input.signScript !== undefined && | ||
input.signType !== undefined && | ||
input.pubkeys !== undefined && | ||
input.signatures !== undefined && | ||
input.signatures.length === input.pubKeys.length && | ||
input.pubKeys.length > 0 && | ||
input.signatures.length === input.pubkeys.length && | ||
input.pubkeys.length > 0 && | ||
( | ||
input.witness === false || | ||
(input.witness === true && input.value !== undefined) | ||
input.hasWitness === false || | ||
input.value !== undefined | ||
) | ||
@@ -688,6 +651,6 @@ } | ||
if (keyPair.network && keyPair.network !== this.network) throw new TypeError('Inconsistent network') | ||
if (!this.inputs[vin]) throw new Error('No input at index: ' + vin) | ||
if (!this.__inputs[vin]) throw new Error('No input at index: ' + vin) | ||
hashType = hashType || Transaction.SIGHASH_ALL | ||
var input = this.inputs[vin] | ||
const input = this.__inputs[vin] | ||
@@ -701,3 +664,3 @@ // if redeemScript was previously provided, enforce consistency | ||
var kpPubKey = keyPair.publicKey || keyPair.getPublicKeyBuffer() | ||
const ourPubKey = keyPair.publicKey || keyPair.getPublicKey() | ||
if (!canSign(input)) { | ||
@@ -710,3 +673,9 @@ if (witnessValue !== undefined) { | ||
if (!canSign(input)) prepareInput(input, kpPubKey, redeemScript, witnessValue, witnessScript) | ||
if (!canSign(input)) { | ||
const prepared = prepareInput(input, ourPubKey, redeemScript, witnessValue, witnessScript) | ||
// updates inline | ||
Object.assign(input, prepared) | ||
} | ||
if (!canSign(input)) throw Error(input.prevOutType + ' not supported') | ||
@@ -716,20 +685,21 @@ } | ||
// ready to sign | ||
var signatureHash | ||
if (input.witness) { | ||
signatureHash = this.tx.hashForWitnessV0(vin, input.signScript, input.value, hashType) | ||
let signatureHash | ||
if (input.hasWitness) { | ||
signatureHash = this.__tx.hashForWitnessV0(vin, input.signScript, input.value, hashType) | ||
} else { | ||
signatureHash = this.tx.hashForSignature(vin, input.signScript, hashType) | ||
signatureHash = this.__tx.hashForSignature(vin, input.signScript, hashType) | ||
} | ||
// enforce in order signing of public keys | ||
var signed = input.pubKeys.some(function (pubKey, i) { | ||
if (!kpPubKey.equals(pubKey)) return false | ||
const signed = input.pubkeys.some(function (pubKey, i) { | ||
if (!ourPubKey.equals(pubKey)) return false | ||
if (input.signatures[i]) throw new Error('Signature already exists') | ||
if (kpPubKey.length !== 33 && | ||
input.signType === scriptTypes.P2WPKH) throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH') | ||
var signature = keyPair.sign(signatureHash) | ||
if (Buffer.isBuffer(signature)) signature = ECSignature.fromRSBuffer(signature) | ||
// TODO: add tests | ||
if (ourPubKey.length !== 33 && input.hasWitness) { | ||
throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH') | ||
} | ||
input.signatures[i] = signature.toScriptSignature(hashType) | ||
const signature = keyPair.sign(signatureHash) | ||
input.signatures[i] = bscript.signature.encode(signature, hashType) | ||
return true | ||
@@ -746,3 +716,3 @@ }) | ||
TransactionBuilder.prototype.__canModifyInputs = function () { | ||
return this.inputs.every(function (input) { | ||
return this.__inputs.every(function (input) { | ||
// any signatures? | ||
@@ -753,3 +723,3 @@ if (input.signatures === undefined) return true | ||
if (!signature) return true | ||
var hashType = signatureHashType(signature) | ||
const hashType = signatureHashType(signature) | ||
@@ -764,6 +734,6 @@ // if SIGHASH_ANYONECANPAY is set, signatures would not | ||
TransactionBuilder.prototype.__canModifyOutputs = function () { | ||
var nInputs = this.tx.ins.length | ||
var nOutputs = this.tx.outs.length | ||
const nInputs = this.__tx.ins.length | ||
const nOutputs = this.__tx.outs.length | ||
return this.inputs.every(function (input) { | ||
return this.__inputs.every(function (input) { | ||
if (input.signatures === undefined) return true | ||
@@ -773,5 +743,5 @@ | ||
if (!signature) return true | ||
var hashType = signatureHashType(signature) | ||
const hashType = signatureHashType(signature) | ||
var hashTypeMod = hashType & 0x1f | ||
const hashTypeMod = hashType & 0x1f | ||
if (hashTypeMod === Transaction.SIGHASH_NONE) return true | ||
@@ -790,9 +760,9 @@ if (hashTypeMod === Transaction.SIGHASH_SINGLE) { | ||
// not all inputs will have .value defined | ||
var incoming = this.inputs.reduce(function (a, x) { return a + (x.value >>> 0) }, 0) | ||
const incoming = this.__inputs.reduce(function (a, x) { return a + (x.value >>> 0) }, 0) | ||
// but all outputs do, and if we have any input value | ||
// we can immediately determine if the outputs are too small | ||
var outgoing = this.tx.outs.reduce(function (a, x) { return a + x.value }, 0) | ||
var fee = incoming - outgoing | ||
var feeRate = fee / bytes | ||
const outgoing = this.__tx.outs.reduce(function (a, x) { return a + x.value }, 0) | ||
const fee = incoming - outgoing | ||
const feeRate = fee / bytes | ||
@@ -799,0 +769,0 @@ return feeRate > this.maximumFeeRate |
@@ -1,12 +0,12 @@ | ||
var Buffer = require('safe-buffer').Buffer | ||
var bcrypto = require('./crypto') | ||
var bscript = require('./script') | ||
var bufferutils = require('./bufferutils') | ||
var opcodes = require('bitcoin-ops') | ||
var typeforce = require('typeforce') | ||
var types = require('./types') | ||
var varuint = require('varuint-bitcoin') | ||
const Buffer = require('safe-buffer').Buffer | ||
const bcrypto = require('./crypto') | ||
const bscript = require('./script') | ||
const bufferutils = require('./bufferutils') | ||
const opcodes = require('bitcoin-ops') | ||
const typeforce = require('typeforce') | ||
const types = require('./types') | ||
const varuint = require('varuint-bitcoin') | ||
function varSliceSize (someScript) { | ||
var length = someScript.length | ||
const length = someScript.length | ||
@@ -17,3 +17,3 @@ return varuint.encodingLength(length) + length | ||
function vectorSize (someVector) { | ||
var length = someVector.length | ||
const length = someVector.length | ||
@@ -40,8 +40,8 @@ return varuint.encodingLength(length) + someVector.reduce(function (sum, witness) { | ||
var EMPTY_SCRIPT = Buffer.allocUnsafe(0) | ||
var EMPTY_WITNESS = [] | ||
var ZERO = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex') | ||
var ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex') | ||
var VALUE_UINT64_MAX = Buffer.from('ffffffffffffffff', 'hex') | ||
var BLANK_OUTPUT = { | ||
const EMPTY_SCRIPT = Buffer.allocUnsafe(0) | ||
const EMPTY_WITNESS = [] | ||
const ZERO = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex') | ||
const ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex') | ||
const VALUE_UINT64_MAX = Buffer.from('ffffffffffffffff', 'hex') | ||
const BLANK_OUTPUT = { | ||
script: EMPTY_SCRIPT, | ||
@@ -52,3 +52,3 @@ valueBuffer: VALUE_UINT64_MAX | ||
Transaction.fromBuffer = function (buffer, __noStrict) { | ||
var offset = 0 | ||
let offset = 0 | ||
function readSlice (n) { | ||
@@ -60,3 +60,3 @@ offset += n | ||
function readUInt32 () { | ||
var i = buffer.readUInt32LE(offset) | ||
const i = buffer.readUInt32LE(offset) | ||
offset += 4 | ||
@@ -67,3 +67,3 @@ return i | ||
function readInt32 () { | ||
var i = buffer.readInt32LE(offset) | ||
const i = buffer.readInt32LE(offset) | ||
offset += 4 | ||
@@ -74,3 +74,3 @@ return i | ||
function readUInt64 () { | ||
var i = bufferutils.readUInt64LE(buffer, offset) | ||
const i = bufferutils.readUInt64LE(buffer, offset) | ||
offset += 8 | ||
@@ -81,3 +81,3 @@ return i | ||
function readVarInt () { | ||
var vi = varuint.decode(buffer, offset) | ||
const vi = varuint.decode(buffer, offset) | ||
offset += varuint.decode.bytes | ||
@@ -92,4 +92,4 @@ return vi | ||
function readVector () { | ||
var count = readVarInt() | ||
var vector = [] | ||
const count = readVarInt() | ||
const vector = [] | ||
for (var i = 0; i < count; i++) vector.push(readVarSlice()) | ||
@@ -99,9 +99,9 @@ return vector | ||
var tx = new Transaction() | ||
const tx = new Transaction() | ||
tx.version = readInt32() | ||
var marker = buffer.readUInt8(offset) | ||
var flag = buffer.readUInt8(offset + 1) | ||
const marker = buffer.readUInt8(offset) | ||
const flag = buffer.readUInt8(offset + 1) | ||
var hasWitnesses = false | ||
let hasWitnesses = false | ||
if (marker === Transaction.ADVANCED_TRANSACTION_MARKER && | ||
@@ -113,3 +113,3 @@ flag === Transaction.ADVANCED_TRANSACTION_FLAG) { | ||
var vinLen = readVarInt() | ||
const vinLen = readVarInt() | ||
for (var i = 0; i < vinLen; ++i) { | ||
@@ -125,3 +125,3 @@ tx.ins.push({ | ||
var voutLen = readVarInt() | ||
const voutLen = readVarInt() | ||
for (i = 0; i < voutLen; ++i) { | ||
@@ -206,4 +206,4 @@ tx.outs.push({ | ||
Transaction.prototype.weight = function () { | ||
var base = this.__byteLength(false) | ||
var total = this.__byteLength(true) | ||
const base = this.__byteLength(false) | ||
const total = this.__byteLength(true) | ||
return base * 3 + total | ||
@@ -221,3 +221,3 @@ } | ||
Transaction.prototype.__byteLength = function (__allowWitness) { | ||
var hasWitnesses = __allowWitness && this.hasWitnesses() | ||
const hasWitnesses = __allowWitness && this.hasWitnesses() | ||
@@ -235,3 +235,3 @@ return ( | ||
Transaction.prototype.clone = function () { | ||
var newTx = new Transaction() | ||
const newTx = new Transaction() | ||
newTx.version = this.version | ||
@@ -275,7 +275,7 @@ newTx.locktime = this.locktime | ||
// ignore OP_CODESEPARATOR | ||
var ourScript = bscript.compile(bscript.decompile(prevOutScript).filter(function (x) { | ||
const ourScript = bscript.compile(bscript.decompile(prevOutScript).filter(function (x) { | ||
return x !== opcodes.OP_CODESEPARATOR | ||
})) | ||
var txTmp = this.clone() | ||
const txTmp = this.clone() | ||
@@ -327,3 +327,3 @@ // SIGHASH_NONE: ignore all outputs? (wildcard payee) | ||
// serialize and hash | ||
var buffer = Buffer.allocUnsafe(txTmp.__byteLength(false) + 4) | ||
const buffer = Buffer.allocUnsafe(txTmp.__byteLength(false) + 4) | ||
buffer.writeInt32LE(hashType, buffer.length - 4) | ||
@@ -338,3 +338,3 @@ txTmp.__toBuffer(buffer, 0, false) | ||
var tbuffer, toffset | ||
let tbuffer, toffset | ||
function writeSlice (slice) { toffset += slice.copy(tbuffer, toffset) } | ||
@@ -349,5 +349,5 @@ function writeUInt32 (i) { toffset = tbuffer.writeUInt32LE(i, toffset) } | ||
var hashOutputs = ZERO | ||
var hashPrevouts = ZERO | ||
var hashSequence = ZERO | ||
let hashOutputs = ZERO | ||
let hashPrevouts = ZERO | ||
let hashSequence = ZERO | ||
@@ -381,3 +381,3 @@ if (!(hashType & Transaction.SIGHASH_ANYONECANPAY)) { | ||
(hashType & 0x1f) !== Transaction.SIGHASH_NONE) { | ||
var txOutsSize = this.outs.reduce(function (sum, output) { | ||
const txOutsSize = this.outs.reduce(function (sum, output) { | ||
return sum + 8 + varSliceSize(output.script) | ||
@@ -396,3 +396,3 @@ }, 0) | ||
} else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE && inIndex < this.outs.length) { | ||
var output = this.outs[inIndex] | ||
const output = this.outs[inIndex] | ||
@@ -410,3 +410,3 @@ tbuffer = Buffer.allocUnsafe(8 + varSliceSize(output.script)) | ||
var input = this.ins[inIndex] | ||
const input = this.ins[inIndex] | ||
writeUInt32(this.version) | ||
@@ -442,3 +442,3 @@ writeSlice(hashPrevouts) | ||
var offset = initialOffset || 0 | ||
let offset = initialOffset || 0 | ||
function writeSlice (slice) { offset += slice.copy(buffer, offset) } | ||
@@ -458,3 +458,3 @@ function writeUInt8 (i) { offset = buffer.writeUInt8(i, offset) } | ||
var hasWitnesses = __allowWitness && this.hasWitnesses() | ||
const hasWitnesses = __allowWitness && this.hasWitnesses() | ||
@@ -461,0 +461,0 @@ if (hasWitnesses) { |
@@ -1,4 +0,4 @@ | ||
var typeforce = require('typeforce') | ||
const typeforce = require('typeforce') | ||
var UINT31_MAX = Math.pow(2, 31) - 1 | ||
const UINT31_MAX = Math.pow(2, 31) - 1 | ||
function UInt31 (value) { | ||
@@ -13,3 +13,3 @@ return typeforce.UInt32(value) && value <= UINT31_MAX | ||
var SATOSHI_MAX = 21 * 1e14 | ||
const SATOSHI_MAX = 21 * 1e14 | ||
function Satoshi (value) { | ||
@@ -20,8 +20,6 @@ return typeforce.UInt53(value) && value <= SATOSHI_MAX | ||
// external dependent types | ||
var BigInt = typeforce.quacksLike('BigInteger') | ||
var ECPoint = typeforce.quacksLike('Point') | ||
const ECPoint = typeforce.quacksLike('Point') | ||
// exposed, external API | ||
var ECSignature = typeforce.compile({ r: BigInt, s: BigInt }) | ||
var Network = typeforce.compile({ | ||
const Network = typeforce.compile({ | ||
messagePrefix: typeforce.oneOf(typeforce.Buffer, typeforce.String), | ||
@@ -38,8 +36,6 @@ bip32: { | ||
// extend typeforce types with ours | ||
var types = { | ||
BigInt: BigInt, | ||
const types = { | ||
BIP32Path: BIP32Path, | ||
Buffer256bit: typeforce.BufferN(32), | ||
ECPoint: ECPoint, | ||
ECSignature: ECSignature, | ||
Hash160bit: typeforce.BufferN(20), | ||
@@ -46,0 +42,0 @@ Hash256bit: typeforce.BufferN(32), |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
124568
50
2843
1
162
1
+ Addedbip32@^1.0.0
+ Addedtiny-secp256k1@^1.0.0
+ Addedbindings@1.5.0(transitive)
+ Addedbip32@1.0.4(transitive)
+ Addedbn.js@4.12.0(transitive)
+ Addedbrorand@1.1.0(transitive)
+ Addedelliptic@6.5.7(transitive)
+ Addedfile-uri-to-path@1.0.0(transitive)
+ Addedhash.js@1.1.7(transitive)
+ Addedhmac-drbg@1.0.1(transitive)
+ Addedminimalistic-assert@1.0.1(transitive)
+ Addedminimalistic-crypto-utils@1.0.1(transitive)
+ Addednan@2.20.0(transitive)
+ Addedtiny-secp256k1@1.1.6(transitive)
- Removedbigi@^1.4.0
- Removedecurve@^1.0.0
- Removedbigi@1.4.2(transitive)
- Removedecurve@1.0.6(transitive)
Updatedbitcoin-ops@^1.4.0
Updatedsafe-buffer@^5.1.1