bitcoinjs-lib
Advanced tools
Comparing version 3.1.1 to 3.2.0
@@ -0,1 +1,10 @@ | ||
# 3.2.0 | ||
__added__ | ||
- Added `address.fromBech32/toBech32` (#846) | ||
# 3.1.0 | ||
__added__ | ||
- Added `Transaction.prototype.virtualSize` (#811) | ||
- Added `Transaction.prototype.weight` (#811) | ||
# 3.0.0 | ||
@@ -2,0 +11,0 @@ From this release users can expect out-of-the-box Segregated Witness support. |
{ | ||
"name": "bitcoinjs-lib", | ||
"version": "3.1.1", | ||
"version": "3.2.0", | ||
"description": "Client-side Bitcoin JavaScript library", | ||
@@ -54,2 +54,3 @@ "main": "./src/index.js", | ||
"dependencies": { | ||
"bech32": "0.0.3", | ||
"bigi": "^1.4.0", | ||
@@ -66,3 +67,3 @@ "bip66": "^1.1.0", | ||
"safe-buffer": "^5.0.1", | ||
"typeforce": "^1.8.7", | ||
"typeforce": "^1.11.3", | ||
"varuint-bitcoin": "^1.0.4", | ||
@@ -77,2 +78,3 @@ "wif": "^2.0.1" | ||
"coinselect": "^3.1.1", | ||
"dhttp": "^2.3.5", | ||
"minimaldata": "^1.0.2", | ||
@@ -79,0 +81,0 @@ "mocha": "^3.1.0", |
127
README.md
# BitcoinJS (bitcoinjs-lib) | ||
[![Build Status](https://travis-ci.org/bitcoinjs/bitcoinjs-lib.png?branch=master)](https://travis-ci.org/bitcoinjs/bitcoinjs-lib) | ||
@@ -9,3 +8,2 @@ [![NPM](https://img.shields.io/npm/v/bitcoinjs-lib.svg)](https://www.npmjs.org/package/bitcoinjs-lib) | ||
The pure JavaScript Bitcoin library for node.js and browsers. | ||
@@ -16,3 +14,2 @@ Used by over a million wallet users and the backbone for almost all Bitcoin web wallets in production today. | ||
## Features | ||
- Clean: Pure JavaScript, concise code, easy to read. | ||
@@ -32,3 +29,2 @@ - Tested: Coverage > 90%, third-party integration tests. | ||
## Should I use this in production? | ||
If you are thinking of using the master branch of this library in production, **stop**. | ||
@@ -39,15 +35,13 @@ 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 | ||
``` | ||
`npm install bitcoinjs-lib` | ||
## Setup | ||
### Node.js | ||
``` javascript | ||
var bitcoin = require('bitcoinjs-lib') | ||
``` | ||
var bitcoin = require('bitcoinjs-lib') | ||
### Browser | ||
If you're familiar with how to use browserify, ignore this and proceed normally. | ||
@@ -89,6 +83,22 @@ These steps are advisory only, and may not be necessary for your application. | ||
**NOTE**: If you expect this library to run on an iOS 10 device, ensure that you are using [buffer@5.0.5](https://www.npmjs.com/package/buffer) or greater. | ||
**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 for version `^3.0.0` of the library. | ||
``` bash | ||
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), users are advised to install the type declarations, as Intellisense uses that information to help you code (autocompletion, static analysis). | ||
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. | ||
@@ -104,24 +114,42 @@ | ||
## Examples | ||
The below examples are implemented as integration tests, they should be very easy to understand. | ||
Otherwise, pull requests are appreciated. | ||
Some examples interact (via HTTPS) with a 3rd Party Blockchain Provider (3PBP). | ||
The below examples are implemented as integration tests, they should be very easy to understand. Otherwise, pull requests are appreciated. | ||
- [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) | ||
- [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) | ||
- [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) | ||
- [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/basic.js#L9) | ||
- [Generate a address from a SHA256 hash](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/basic.js#L20) | ||
- [Generate a address and WIF for Litecoin](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/basic.js#L30) | ||
- [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/basic.js#L43) | ||
- [Create a Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/basic.js#L50) | ||
- [Create an OP RETURN transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/advanced.js#L24) | ||
- [Create a 2-of-3 multisig P2SH address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/multisig.js#L9) | ||
- [Spend from a 2-of-4 multisig P2SH address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/multisig.js#L25) | ||
- [Generate a single-key stealth address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/stealth.js) | ||
- [Generate a dual-key stealth address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/stealth.js) | ||
- [Create a BIP32 wallet external address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/8e1c69183f74acce06d6e35b614e504b18bb04e1/test/integration/bip32.js) | ||
- [Create a BIP44, bitcoin, account 0, external address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/8e1c69183f74acce06d6e35b614e504b18bb04e1/test/integration/bip32.js) | ||
- [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/8e1c69183f74acce06d6e35b614e504b18bb04e1/test/integration/bip32.js) | ||
- [Recover a Private key from duplicate R values in a signature](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/crypto.js) | ||
- [Create a CLTV locked transaction where the expiry is past](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/cltv.js#L36) | ||
- [Create a CLTV locked transaction where the parties bypass the expiry](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/cltv.js#L70) | ||
- [Create a CLTV locked transaction which fails due to expiry in the future](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/cltv.js#L102) | ||
- [Use BIP39 to generate a BIP32 wallet address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/dd3e501/test/integration/bip32.js) | ||
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)! | ||
@@ -131,3 +159,2 @@ | ||
## Projects utilizing BitcoinJS | ||
- [BitAddress](https://www.bitaddress.org) | ||
@@ -141,2 +168,3 @@ - [Blockchain.info](https://blockchain.info/wallet) | ||
- [GreenAddress](https://greenaddress.it) | ||
- [Helperbit](https://helperbit.com) | ||
- [Melis Wallet](https://melis.io) | ||
@@ -147,12 +175,3 @@ - [Robocoin](https://wallet.robocoin.com) | ||
## Contributors | ||
Stefan Thomas is the inventor and creator of this project. His pioneering work made Bitcoin web wallets possible. | ||
Daniel Cousens, Wei Lu, JP Richardson and Kyle Drake lead the major refactor of the library from 0.1.3 to 1.0.0. | ||
Since then, many people have contributed. [Click here](https://github.com/bitcoinjs/bitcoinjs-lib/graphs/contributors) to see the comprehensive list. | ||
## 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. | ||
@@ -165,8 +184,8 @@ | ||
$ npm test | ||
$ npm run-script coverage | ||
``` bash | ||
npm test | ||
npm run-script coverage | ||
``` | ||
## Complementing Libraries | ||
- [BIP21](https://github.com/bitcoinjs/bip21) - A BIP21 compatible URL encoding utility library | ||
@@ -180,5 +199,4 @@ - [BIP38](https://github.com/bitcoinjs/bip38) - Passphrase-protected private keys | ||
- [Base58 Check](https://github.com/bitcoinjs/bs58check) - Base58 check encoding/decoding | ||
- [BCoin](https://github.com/indutny/bcoin) - BIP37 / Bloom Filters / SPV client | ||
- [Bech32](https://github.com/bitcoinjs/bech32) - A BIP173 compliant Bech32 encoding library | ||
- [coinselect](https://github.com/bitcoinjs/coinselect) - A fee-optimizing, transaction input selection module for bitcoinjs-lib. | ||
- [insight](https://github.com/bitpay/insight) - A bitcoin blockchain API for web wallets. | ||
- [merkle-lib](https://github.com/bitcoinjs/merkle-lib) - A performance conscious library for merkle root and tree calculations. | ||
@@ -189,3 +207,3 @@ - [minimaldata](https://github.com/bitcoinjs/minimaldata) - A module to check bitcoin policy: SCRIPT_VERIFY_MINIMALDATA | ||
## Alternatives | ||
- [BCoin](https://github.com/indutny/bcoin) | ||
- [Bitcore](https://github.com/bitpay/bitcore) | ||
@@ -196,8 +214,1 @@ - [Cryptocoin](https://github.com/cryptocoinjs/cryptocoin) | ||
## LICENSE [MIT](LICENSE) | ||
## Copyright | ||
BitcoinJS (c) 2011-2016 bitcoinjs-lib contributors | ||
Released under MIT license |
var Buffer = require('safe-buffer').Buffer | ||
var bech32 = require('bech32') | ||
var bs58check = require('bs58check') | ||
@@ -10,2 +11,4 @@ var bscript = require('./script') | ||
var payload = bs58check.decode(address) | ||
// TODO: 4.0.0, move to "toOutputScript" | ||
if (payload.length < 21) throw new TypeError(address + ' is too short') | ||
@@ -17,5 +20,16 @@ if (payload.length > 21) throw new TypeError(address + ' is too long') | ||
return { hash: hash, version: version } | ||
return { version: version, hash: hash } | ||
} | ||
function fromBech32 (address) { | ||
var result = bech32.decode(address) | ||
var data = bech32.fromWords(result.words.slice(1)) | ||
return { | ||
version: result.words[0], | ||
prefix: result.prefix, | ||
data: Buffer.from(data) | ||
} | ||
} | ||
function toBase58Check (hash, version) { | ||
@@ -31,2 +45,9 @@ typeforce(types.tuple(types.Hash160bit, types.UInt8), arguments) | ||
function toBech32 (data, version, prefix) { | ||
var words = bech32.toWords(data) | ||
words.unshift(version) | ||
return bech32.encode(prefix, words) | ||
} | ||
function fromOutputScript (outputScript, network) { | ||
@@ -37,2 +58,4 @@ network = network || networks.bitcoin | ||
if (bscript.scriptHash.output.check(outputScript)) return toBase58Check(bscript.compile(outputScript).slice(2, 22), network.scriptHash) | ||
if (bscript.witnessPubKeyHash.output.check(outputScript)) return toBech32(bscript.compile(outputScript).slice(2, 22), 0, network.bech32) | ||
if (bscript.witnessScriptHash.output.check(outputScript)) return toBech32(bscript.compile(outputScript).slice(2, 34), 0, network.bech32) | ||
@@ -45,6 +68,24 @@ throw new Error(bscript.toASM(outputScript) + ' has no matching Address') | ||
var decode = fromBase58Check(address) | ||
if (decode.version === network.pubKeyHash) return bscript.pubKeyHash.output.encode(decode.hash) | ||
if (decode.version === network.scriptHash) return bscript.scriptHash.output.encode(decode.hash) | ||
var decode | ||
try { | ||
decode = fromBase58Check(address) | ||
} catch (e) {} | ||
if (decode) { | ||
if (decode.version === network.pubKeyHash) return bscript.pubKeyHash.output.encode(decode.hash) | ||
if (decode.version === network.scriptHash) return bscript.scriptHash.output.encode(decode.hash) | ||
} else { | ||
try { | ||
decode = fromBech32(address) | ||
} catch (e) {} | ||
if (decode) { | ||
if (decode.prefix !== network.bech32) throw new Error(address + ' has an invalid prefix') | ||
if (decode.version === 0) { | ||
if (decode.data.length === 20) return bscript.witnessPubKeyHash.output.encode(decode.data) | ||
if (decode.data.length === 32) return bscript.witnessScriptHash.output.encode(decode.data) | ||
} | ||
} | ||
} | ||
throw new Error(address + ' has no matching Script') | ||
@@ -55,5 +96,7 @@ } | ||
fromBase58Check: fromBase58Check, | ||
fromBech32: fromBech32, | ||
fromOutputScript: fromOutputScript, | ||
toBase58Check: toBase58Check, | ||
toBech32: toBech32, | ||
toOutputScript: toOutputScript | ||
} |
@@ -7,2 +7,3 @@ // https://en.bitcoin.it/wiki/List_of_address_prefixes | ||
messagePrefix: '\x18Bitcoin Signed Message:\n', | ||
bech32: 'bc', | ||
bip32: { | ||
@@ -18,2 +19,3 @@ public: 0x0488b21e, | ||
messagePrefix: '\x18Bitcoin Signed Message:\n', | ||
bech32: 'tb', | ||
bip32: { | ||
@@ -20,0 +22,0 @@ public: 0x043587cf, |
@@ -27,2 +27,9 @@ var Buffer = require('safe-buffer').Buffer | ||
function asMinimalOP (buffer) { | ||
if (buffer.length === 0) return OPS.OP_0 | ||
if (buffer.length !== 1) return | ||
if (buffer[0] >= 1 && buffer[0] <= 16) return OP_INT_BASE + buffer[0] | ||
if (buffer[0] === 0x81) return OPS.OP_1NEGATE | ||
} | ||
function compile (chunks) { | ||
@@ -38,3 +45,3 @@ // TODO: remove me | ||
// adhere to BIP62.3, minimal push policy | ||
if (chunk.length === 1 && (chunk[0] === 0x81 || (chunk[0] >= 1 && chunk[0] <= 16))) { | ||
if (chunk.length === 1 && asMinimalOP(chunk) !== undefined) { | ||
return accum + 1 | ||
@@ -57,4 +64,4 @@ } | ||
// adhere to BIP62.3, minimal push policy | ||
if (chunk.length === 1 && chunk[0] >= 1 && chunk[0] <= 16) { | ||
var opcode = OP_INT_BASE + chunk[0] | ||
var opcode = asMinimalOP(chunk) | ||
if (opcode !== undefined) { | ||
buffer.writeUInt8(opcode, offset) | ||
@@ -65,10 +72,3 @@ offset += 1 | ||
if (chunk.length === 1 && chunk[0] === 0x81) { | ||
buffer.writeUInt8(OPS.OP_1NEGATE, offset) | ||
offset += 1 | ||
return | ||
} | ||
offset += pushdata.encode(buffer, chunk.length, offset) | ||
chunk.copy(buffer, offset) | ||
@@ -114,3 +114,9 @@ offset += chunk.length | ||
chunks.push(data) | ||
// decompile minimally | ||
var op = asMinimalOP(data) | ||
if (op !== undefined) { | ||
chunks.push(op) | ||
} else { | ||
chunks.push(data) | ||
} | ||
@@ -135,3 +141,7 @@ // opcode | ||
// data? | ||
if (Buffer.isBuffer(chunk)) return chunk.toString('hex') | ||
if (Buffer.isBuffer(chunk)) { | ||
var op = asMinimalOP(chunk) | ||
if (op === undefined) return chunk.toString('hex') | ||
chunk = op | ||
} | ||
@@ -138,0 +148,0 @@ // opcode! |
@@ -42,3 +42,8 @@ // OP_0 [signatures ...] | ||
return [].concat(EMPTY_BUFFER, signatures) | ||
return [].concat(EMPTY_BUFFER, signatures.map(function (sig) { | ||
if (sig === OPS.OP_0) { | ||
return EMPTY_BUFFER | ||
} | ||
return sig | ||
})) | ||
} | ||
@@ -45,0 +50,0 @@ |
// {signature} | ||
var bscript = require('../../script') | ||
var types = require('../../types') | ||
var typeforce = require('typeforce') | ||
@@ -16,3 +15,3 @@ | ||
function encodeStack (signature) { | ||
typeforce(types.Buffer, signature) | ||
typeforce(bscript.isCanonicalSignature, signature) | ||
return [signature] | ||
@@ -19,0 +18,0 @@ } |
// {signature} {pubKey} | ||
var bscript = require('../../script') | ||
var types = require('../../types') | ||
var typeforce = require('typeforce') | ||
@@ -18,5 +17,7 @@ | ||
typeforce({ | ||
signature: types.Buffer, pubKey: types.Buffer | ||
signature: bscript.isCanonicalSignature, | ||
pubKey: bscript.isCanonicalPubKey | ||
}, { | ||
signature: signature, pubKey: pubKey | ||
signature: signature, | ||
pubKey: pubKey | ||
}) | ||
@@ -23,0 +24,0 @@ |
// {signature} {pubKey} | ||
var pkh = require('../pubkeyhash/input') | ||
var bscript = require('../../script') | ||
var typeforce = require('typeforce') | ||
function isCompressedCanonicalPubKey (pubKey) { | ||
return bscript.isCanonicalPubKey(pubKey) && pubKey.length === 33 | ||
} | ||
function check (script) { | ||
var chunks = bscript.decompile(script) | ||
return chunks.length === 2 && | ||
bscript.isCanonicalSignature(chunks[0]) && | ||
isCompressedCanonicalPubKey(chunks[1]) | ||
} | ||
check.toJSON = function () { return 'witnessPubKeyHash input' } | ||
function encodeStack (signature, pubKey) { | ||
typeforce({ | ||
signature: bscript.isCanonicalSignature, | ||
pubKey: isCompressedCanonicalPubKey | ||
}, { | ||
signature: signature, | ||
pubKey: pubKey | ||
}) | ||
return [signature, pubKey] | ||
} | ||
function decodeStack (stack) { | ||
typeforce(check, stack) | ||
return { | ||
signature: stack[0], | ||
pubKey: stack[1] | ||
} | ||
} | ||
module.exports = { | ||
check: pkh.check, | ||
decodeStack: pkh.decodeStack, | ||
encodeStack: pkh.encodeStack | ||
check: check, | ||
decodeStack: decodeStack, | ||
encodeStack: encodeStack | ||
} |
@@ -17,2 +17,10 @@ var Buffer = require('safe-buffer').Buffer | ||
function supportedType (type) { | ||
return SIGNABLE.indexOf(type) !== -1 | ||
} | ||
function supportedP2SHType (type) { | ||
return P2SH.indexOf(type) !== -1 | ||
} | ||
function extractChunks (type, chunks, script) { | ||
@@ -78,3 +86,3 @@ var pubKeys = [] | ||
var classifyWitness = bscript.classifyWitness(witnessStack) | ||
var classifyWitness = bscript.classifyWitness(witnessStack, true) | ||
if (classifyWitness === scriptTypes.P2WSH) { | ||
@@ -84,6 +92,7 @@ witnessScript = witnessStack[witnessStack.length - 1] | ||
p2wsh = true | ||
witness = true | ||
if (scriptSig.length === 0) { | ||
prevOutScript = bscript.witnessScriptHash.output.encode(bcrypto.sha256(witnessScript)) | ||
prevOutType = scriptTypes.P2WSH | ||
if (typeof redeemScript !== 'undefined') { | ||
if (redeemScript !== undefined) { | ||
throw new Error('Redeem script given when unnecessary') | ||
@@ -102,5 +111,6 @@ } | ||
if (SIGNABLE.indexOf(bscript.classifyOutput(witnessScript)) === -1) { | ||
if (!supportedType(bscript.classifyOutput(witnessScript))) { | ||
throw new Error('unsupported witness script') | ||
} | ||
script = witnessScript | ||
@@ -110,2 +120,3 @@ scriptType = witnessScriptType | ||
} else if (classifyWitness === scriptTypes.P2WPKH) { | ||
witness = true | ||
var key = witnessStack[witnessStack.length - 1] | ||
@@ -132,3 +143,3 @@ var keyHash = bcrypto.hash160(key) | ||
} else if (redeemScript) { | ||
if (P2SH.indexOf(redeemScriptType) === -1) { | ||
if (!supportedP2SHType(redeemScriptType)) { | ||
throw new Error('Bad redeemscript!') | ||
@@ -350,4 +361,6 @@ } | ||
if (witness && !types.Satoshi(witnessValue)) { | ||
throw new Error('Input was witness but not given witness value') | ||
if (witnessValue !== undefined || witness) { | ||
typeforce(types.Satoshi, witnessValue) | ||
if (input.value !== undefined && input.value !== witnessValue) throw new Error('Input didn\'t match witnessValue') | ||
input.value = witnessValue | ||
} | ||
@@ -393,3 +406,3 @@ | ||
return bscript.multisig.input.encodeStack(signatures /* see if it's necessary first */) | ||
return bscript.multisig.input.encodeStack(signatures) | ||
} | ||
@@ -401,3 +414,2 @@ } else { | ||
if (!allowIncomplete) throw new Error('Not enough signatures provided') | ||
return [] | ||
@@ -410,3 +422,4 @@ } | ||
var witness = [] | ||
if (SIGNABLE.indexOf(scriptType) !== -1) { | ||
if (supportedType(scriptType)) { | ||
sig = buildStack(scriptType, input.signatures, input.pubKeys, allowIncomplete) | ||
@@ -419,28 +432,36 @@ } | ||
// rejects unsignable scripts - it MUST be signable at this point. | ||
if (P2SH.indexOf(input.redeemScriptType) === -1) { | ||
if (!allowIncomplete && !supportedP2SHType(input.redeemScriptType)) { | ||
throw new Error('Impossible to sign this type') | ||
} | ||
p2sh = true | ||
if (SIGNABLE.indexOf(input.redeemScriptType) !== -1) { | ||
if (supportedType(input.redeemScriptType)) { | ||
sig = buildStack(input.redeemScriptType, input.signatures, input.pubKeys, allowIncomplete) | ||
} | ||
// If it wasn't SIGNABLE, it's witness, defer to that | ||
scriptType = input.redeemScriptType | ||
if (input.redeemScriptType) { | ||
p2sh = true | ||
scriptType = input.redeemScriptType | ||
} | ||
} | ||
if (scriptType === bscript.types.P2WPKH) { | ||
switch (scriptType) { | ||
// P2WPKH is a special case of P2PKH | ||
witness = buildStack(bscript.types.P2PKH, input.signatures, input.pubKeys, allowIncomplete) | ||
} else if (scriptType === bscript.types.P2WSH) { | ||
// We can remove this check later | ||
if (SIGNABLE.indexOf(input.witnessScriptType) !== -1) { | ||
witness = buildStack(input.witnessScriptType, input.signatures, input.pubKeys, allowIncomplete) | ||
witness.push(input.witnessScript) | ||
} else { | ||
// We can remove this error later when we have a guarantee prepareInput | ||
// rejects unsignble scripts - it MUST be signable at this point. | ||
throw new Error() | ||
} | ||
case bscript.types.P2WPKH: | ||
witness = buildStack(bscript.types.P2PKH, input.signatures, input.pubKeys, allowIncomplete) | ||
break | ||
scriptType = input.witnessScriptType | ||
case bscript.types.P2WSH: | ||
// We can remove this check later | ||
if (!allowIncomplete && !supportedType(input.witnessScriptType)) { | ||
throw new Error('Impossible to sign this type') | ||
} | ||
if (supportedType(input.witnessScriptType)) { | ||
witness = buildStack(input.witnessScriptType, input.signatures, input.pubKeys, allowIncomplete) | ||
witness.push(input.witnessScript) | ||
scriptType = input.witnessScriptType | ||
} | ||
break | ||
} | ||
@@ -592,3 +613,2 @@ | ||
this.prevTxMap[prevTxOut] = vin | ||
return vin | ||
@@ -632,3 +652,3 @@ } | ||
if (!allowIncomplete) { | ||
if (SIGNABLE.indexOf(result.type) === -1 && result.type !== bscript.types.P2WPKH) { | ||
if (!supportedType(result.type) && result.type !== bscript.types.P2WPKH) { | ||
throw new Error(result.type + ' not supported') | ||
@@ -644,3 +664,3 @@ } | ||
// do not rely on this, its merely a last resort | ||
if (this.__overMaximumFees(tx.byteLength())) { | ||
if (this.__overMaximumFees(tx.virtualSize())) { | ||
throw new Error('Transaction has absurd fees') | ||
@@ -686,3 +706,3 @@ } | ||
if (input.witness) { | ||
signatureHash = this.tx.hashForWitnessV0(vin, input.signScript, witnessValue, hashType) | ||
signatureHash = this.tx.hashForWitnessV0(vin, input.signScript, input.value, hashType) | ||
} else { | ||
@@ -695,2 +715,4 @@ signatureHash = this.tx.hashForSignature(vin, input.signScript, hashType) | ||
if (input.signatures[i]) throw new Error('Signature already exists') | ||
if (!keyPair.compressed && | ||
input.signType === scriptTypes.P2WPKH) throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH') | ||
@@ -697,0 +719,0 @@ input.signatures[i] = keyPair.sign(signatureHash).toScriptSignature(hashType) |
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
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
114978
2712
202
15
12
+ Addedbech32@0.0.3
+ Addedbech32@0.0.3(transitive)
Updatedtypeforce@^1.11.3