Socket
Socket
Sign inDemoInstall

bitcoinjs-lib

Package Overview
Dependencies
Maintainers
4
Versions
88
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bitcoinjs-lib - npm Package Compare versions

Comparing version 2.2.0 to 2.3.0

20

CHANGELOG.md

@@ -0,1 +1,21 @@

# 2.3.0
__added__
- Added `HDNode.prototype.isNeutered` (#536)
- Added `HDNode.prototype.derivePath` (#538)
- Added typeforce checking for `HDNode.prototype.derive*` (#539)
- Added `Transaction.prototype.isCoinbase` (#578)
- Added `Block.prototype.checkMerkleRoot` (#580)
- Added `Block.calculateMerkleRoot` (#580)
- Added `TransactionBuilder.prototype.setVersion` (#599)
- Added `script.isWitnessPubKeyHashOutput` (#602)
- Added `script.isWitnessScriptHashOutput` (#602)
- Added `script.witnessPubKeyHashOutput` (#602)
- Added `script.witnessScriptHashOutput` (#602)
- Added `script.witnessScriptHashInput` (#602)
__fixed__
- Fixed "BIP32 is undefined" when network list given to `HDNode` but no compatible version found (#550)
- Fixed `writePushDataInt` output to adhere to minimal data push policy (#617)
# 2.2.0

@@ -2,0 +22,0 @@ __added__

11

package.json
{
"name": "bitcoinjs-lib",
"version": "2.2.0",
"version": "2.3.0",
"description": "Client-side Bitcoin JavaScript library",

@@ -47,2 +47,5 @@ "main": "./src/index.js",

},
"files": [
"src"
],
"config": {

@@ -74,3 +77,3 @@ "blanket": {

"typeforce": "^1.6.2",
"wif": "^1.1.0"
"wif": "^2.0.1"
},

@@ -84,2 +87,3 @@ "devDependencies": {

"httpify": "^1.0.0",
"minimaldata": "^1.0.0",
"mocha": "^2.2.0",

@@ -90,3 +94,4 @@ "proxyquire": "^1.4.0",

"travis-cov": "^0.2.0"
}
},
"license": "MIT"
}

@@ -11,3 +11,3 @@ # BitcoinJS (bitcoinjs-lib)

The pure JavaScript Bitcoin library for node.js and browsers.
A continued implementation of the original `0.1.3` version used by over a million wallet users; the backbone for almost all Bitcoin web wallets in production today.
Used by over a million wallet users and the backbone for almost all Bitcoin web wallets in production today.

@@ -32,8 +32,6 @@

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.
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).
If you are looking for the original, it is tagged as `0.1.3`. Unless you need it for dependency reasons, it is strongly recommended that you use (or upgrade to) the newest version, which adds major functionality, cleans up the interface, fixes many bugs, and adds over 1,300 more tests.
## Installation

@@ -54,10 +52,9 @@

If you're familiar with how to use browserify, ignore this and proceed normally.
These steps are advisory only and allow you to use the API to its full extent.
These steps are advisory only, and may not be necessary for your application.
[Browserify](https://github.com/substack/node-browserify) is assumed to be installed for these steps.
From your repository, create a `foobar.js` file
From your repository, create an `index.js` file
``` javascript
var foobar = {
module.exports = {
base58: require('bs58'),

@@ -69,15 +66,16 @@ bitcoin: require('bitcoinjs-lib'),

}
```
module.exports = foobar
Install each of the above packages locally
``` bash
npm install bs58 bitcoinjs-lib ecurve bigi buffer
```
Each of these included packages are seperate to `bitcoinjs-lib`, and must be installed separately.
They are however used in the bitcoinjs-lib public API.
After installation, use browserify to compile `index.js` for use in the browser:
``` bash
$ browserify index.js --standalone foo > app.js
```
Using browserify, compile `foobar.js` for use in the browser:
You will now be able to use `<script src="app.js" />` in your browser, with each of the above exports accessible via the global `foo` object (or whatever you chose for the `--standalone` parameter above).
$ browserify foobar.js -s foobar > foobar.js
You will then be able to load `foobar.js` into your browser, with each of the dependencies above accessible from the global `foobar` object.
**NOTE**: See our package.json for the currently supported version of browserify used by this repository.

@@ -87,4 +85,18 @@

This is because of the function-name-duck-typing used in [typeforce](https://github.com/dcousens/typeforce).
Example:
``` bash
uglifyjs ... --mangle --reserved 'Array,BigInteger,Boolean,Buffer,ECPair,Function,Number,Point'
```
### Flow
Definitions for [Flow typechecker](https://flowtype.org/) are available in flow-typed repository.
[You can either download them directly](https://github.com/flowtype/flow-typed/blob/master/definitions/npm/bitcoinjs-lib_v2.x.x/flow_%3E%3Dv0.17.x/bitcoinjs-lib_v2.x.x.js) from the repo, or with 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
The definitions are complete and up to date with version 2.2.0. The definitions are maintained by [@runn1ng](https://github.com/runn1ng).
## Examples

@@ -94,16 +106,19 @@

- [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/basic.js#L8)
- [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/basic.js#L9)
- [Generate a address from a SHA256 hash](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/basic.js#L20)
- [Generate a address and WIF for Litecoin](https://github.com/bitcoin/bitcoinjs-lib/blob/master/test/integration/basic.js#L29)
- [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/basic.js#L43)
- [Create a Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/basic.js#L50)
- [Sign a Bitcoin message](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/advanced.js#L9)
- [Verify a Bitcoin message](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/advanced.js#L17)
- [Generate a address and WIF for Litecoin](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/basic.js#L30)
- [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/basic.js#L44)
- [Create a Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/basic.js#L51)
- [Sign a Bitcoin message](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/advanced.js#L8)
- [Verify a Bitcoin message](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/advanced.js#L16)
- [Create an OP RETURN transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/advanced.js#L24)
- [Create a 2-of-3 multisig P2SH address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/multisig.js#L8)
- [Spend from a 2-of-4 multisig P2SH address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/multisig.js#L22)
- [Generate a single-key stealth address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/crypto.js#L7)
- [Generate a dual-key stealth address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/crypto.js#L52)
- [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#L54)
- [Recover a Private key from duplicate R values in a signature](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/crypto.js#L101)
- [Create a 2-of-3 multisig P2SH address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/multisig.js#L9)
- [Spend from a 2-of-4 multisig P2SH address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/multisig.js#L25)
- [Generate a single-key stealth address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/stealth.js#L11)
- [Generate a dual-key stealth address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/stealth.js#L48)
- [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#L14)
- [Recover a Private key from duplicate R values in a signature](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/crypto.js#L60)
- [Create a CLTV locked transaction where the expiry is past](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/cltv.js#L36)
- [Create a CLTV locked transaction where the parties bypass the expiry](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/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/master/test/integration/cltv.js#L102)

@@ -118,6 +133,3 @@ 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)!

- [Blocktrail](https://www.blocktrail.com/)
- [Brainwallet](https://brainwallet.github.io)
- [Coinkite](https://coinkite.com)
- [Coinpunk](https://coinpunk.com)
- [Dark Wallet](https://darkwallet.unsystem.net)
- [Dark Wallet](https://www.darkwallet.is/)
- [DecentralBank](http://decentralbank.com/)

@@ -127,4 +139,2 @@ - [Dogechain Wallet](https://dogechain.info)

- [GreenAddress](https://greenaddress.it)
- [Hive Wallet](https://www.hivewallet.com)
- [QuickCoin](https://wallet.quickcoin.co)
- [Robocoin](https://wallet.robocoin.com)

@@ -137,8 +147,7 @@ - [Skyhook ATM](http://projectskyhook.com)

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.
Daniel Cousens, Wei Lu, JP Richardson and Kyle Drake lead the major refactor of the library from 0.1.3 to 1.0.0.
## Contributing

@@ -165,3 +174,3 @@

- [BIP66](https://github.com/bitcoinjs/bip66) - Strict DER signature decoding
- [BIP69](https://github.com/bitcoinjs/bip69) - Mnemonic generation for deterministic keys
- [BIP69](https://github.com/bitcoinjs/bip69) - Lexicographical Indexing of Transaction Inputs and Outputs
- [Base58](https://github.com/cryptocoinjs/bs58) - Base58 encoding/decoding

@@ -168,0 +177,0 @@ - [Base58 Check](https://github.com/bitcoinjs/bs58check) - Base58 check encoding/decoding

@@ -0,4 +1,6 @@

var createHash = require('create-hash')
var bufferutils = require('./bufferutils')
var bcrypto = require('./crypto')
var compare = require('buffer-compare')
var bufferCompare = require('buffer-compare')
var bufferReverse = require('buffer-reverse')

@@ -74,3 +76,3 @@ var Transaction = require('./transaction')

Block.prototype.getId = function () {
return [].reverse.call(this.getHash()).toString('hex')
return bufferReverse(this.getHash()).toString('hex')
}

@@ -136,9 +138,38 @@

Block.calculateMerkleRoot = function (transactions) {
var length = transactions.length
if (length === 0) throw TypeError('Cannot compute merkle root for zero transactions')
var hashes = transactions.map(function (transaction) { return transaction.getHash() })
while (length > 1) {
var j = 0
for (var i = 0; i < length; i += 2, ++j) {
var hasher = createHash('sha256')
hasher.update(hashes[i])
hasher.update(i + 1 !== length ? hashes[i + 1] : hashes[i])
hashes[j] = bcrypto.sha256(hasher.digest())
}
length = j
}
return hashes[0]
}
Block.prototype.checkMerkleRoot = function () {
if (!this.transactions) return false
var actualMerkleRoot = Block.calculateMerkleRoot(this.transactions)
return bufferCompare(this.merkleRoot, actualMerkleRoot) === 0
}
Block.prototype.checkProofOfWork = function () {
var hash = [].reverse.call(this.getHash())
var hash = bufferReverse(this.getHash())
var target = Block.calculateTarget(this.bits)
return compare(hash, target) <= 0
return bufferCompare(hash, target) <= 0
}
module.exports = Block

@@ -1,2 +0,2 @@

var opcodes = require('./opcodes')
var opcodes = require('./opcodes.json')

@@ -13,4 +13,4 @@ // https://github.com/feross/buffer/blob/master/index.js#L1127

return i < opcodes.OP_PUSHDATA1 ? 1
: i < 0xff ? 2
: i < 0xffff ? 3
: i <= 0xff ? 2
: i <= 0xffff ? 3
: 5

@@ -17,0 +17,0 @@ }

@@ -0,3 +1,3 @@

var baddress = require('./address')
var bcrypto = require('./crypto')
var bs58check = require('bs58check')
var ecdsa = require('./ecdsa')

@@ -61,15 +61,21 @@ var randomBytes = require('randombytes')

ECPair.fromWIF = function (string, network) {
network = network || NETWORKS.bitcoin
var buffer = bs58check.decode(string)
var decoded = wif.decode(string)
var version = decoded.version
// [network, ...]
if (types.Array(network)) {
var version = buffer[0]
network = network.filter(function (network) {
return version === network.wif
}).pop() || {}
}).pop()
if (!network) throw new Error('Unknown network version')
// network
} else {
network = network || NETWORKS.bitcoin
if (version !== network.wif) throw new Error('Invalid network version')
}
var decoded = wif.decodeRaw(network.wif, buffer)
var d = BigInteger.fromBuffer(decoded.d)
var d = BigInteger.fromBuffer(decoded.privateKey)

@@ -99,10 +105,3 @@ return new ECPair(d, null, {

ECPair.prototype.getAddress = function () {
var pubKey = this.getPublicKeyBuffer()
var pubKeyHash = bcrypto.hash160(pubKey)
var payload = new Buffer(21)
payload.writeUInt8(this.network.pubKeyHash, 0)
pubKeyHash.copy(payload, 1)
return bs58check.encode(payload)
return baddress.toBase58Check(bcrypto.hash160(this.getPublicKeyBuffer()), this.getNetwork().pubKeyHash)
}

@@ -109,0 +108,0 @@

@@ -67,4 +67,6 @@ var base58check = require('bs58check')

version === network.bip32.public
}).pop() || {}
}).pop()
if (!network) throw new Error('Unknown network version')
// otherwise, assume a network object (or default to bitcoin)

@@ -76,3 +78,3 @@ } else {

if (version !== network.bip32.private &&
version !== network.bip32.public) throw new Error('Invalid network')
version !== network.bip32.public) throw new Error('Invalid network version')

@@ -175,3 +177,3 @@ // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ...

var network = this.keyPair.network
var version = this.keyPair.d ? network.bip32.private : network.bip32.public
var version = (!this.isNeutered()) ? network.bip32.private : network.bip32.public
var buffer = new Buffer(78)

@@ -196,3 +198,3 @@

// 33 bytes: the public key or private key data
if (this.keyPair.d) {
if (!this.isNeutered()) {
// 0x00 + k for private keys

@@ -213,2 +215,4 @@ buffer.writeUInt8(0, 45)

HDNode.prototype.derive = function (index) {
typeforce(types.UInt32, index)
var isHardened = index >= HDNode.HIGHEST_BIT

@@ -219,3 +223,3 @@ var data = new Buffer(37)

if (isHardened) {
if (!this.keyPair.d) throw new TypeError('Could not derive hardened child key')
if (this.isNeutered()) throw new TypeError('Could not derive hardened child key')

@@ -248,3 +252,3 @@ // data = 0x00 || ser256(kpar) || ser32(index)

var derivedKeyPair
if (this.keyPair.d) {
if (!this.isNeutered()) {
// ki = parse256(IL) + kpar (mod n)

@@ -287,2 +291,4 @@ var ki = pIL.add(this.keyPair.d).mod(curve.n)

HDNode.prototype.deriveHardened = function (index) {
typeforce(types.UInt31, index)
// Only derives hardened private keys by default

@@ -292,4 +298,34 @@ return this.derive(index + HDNode.HIGHEST_BIT)

// Private === not neutered
// Public === neutered
HDNode.prototype.isNeutered = function () {
return !(this.keyPair.d)
}
HDNode.prototype.derivePath = function (path) {
typeforce(types.Bip32Path, path)
var splitPath = path.split('/')
if (splitPath[0] === 'm') {
if (this.parentFingerprint) {
throw new Error('Not a master node')
}
splitPath = splitPath.slice(1)
}
return splitPath.reduce(function (prevHd, indexStr) {
var index
if (indexStr.slice(-1) === "'") {
index = parseInt(indexStr.slice(0, -1), 10)
return prevHd.deriveHardened(index)
} else {
index = parseInt(indexStr, 10)
return prevHd.derive(index)
}
}, this)
}
HDNode.prototype.toString = HDNode.prototype.toBase58
module.exports = HDNode

@@ -14,4 +14,4 @@ module.exports = {

networks: require('./networks'),
opcodes: require('./opcodes'),
opcodes: require('./opcodes.json'),
script: require('./script')
}

@@ -6,3 +6,3 @@ var bip66 = require('bip66')

var OPS = require('./opcodes')
var OPS = require('./opcodes.json')
var REVERSE_OPS = (function () {

@@ -210,2 +210,18 @@ var result = {}

function isWitnessPubKeyHashOutput (script) {
var buffer = compile(script)
return buffer.length === 22 &&
buffer[0] === OPS.OP_0 &&
buffer[1] === 0x14
}
function isWitnessScriptHashOutput (script) {
var buffer = compile(script)
return buffer.length === 34 &&
buffer[0] === OPS.OP_0 &&
buffer[1] === 0x20
}
// allowIncomplete is to account for combining signatures

@@ -258,3 +274,7 @@ // See https://github.com/bitcoin/bitcoin/blob/f425050546644a36b0b8e0eb2f6934a3e0f6f80f/src/script/sign.cpp#L195-L197

if (isPubKeyHashOutput(chunks)) {
if (isWitnessPubKeyHashOutput(chunks)) {
return 'witnesspubkeyhash'
} else if (isWitnessScriptHashOutput(chunks)) {
return 'witnessscripthash'
} else if (isPubKeyHashOutput(chunks)) {
return 'pubkeyhash'

@@ -325,2 +345,16 @@ } else if (isScriptHashOutput(chunks)) {

// OP_0 {pubKeyHash}
function witnessPubKeyHashOutput (pubKeyHash) {
typeforce(types.Hash160bit, pubKeyHash)
return compile([OPS.OP_0, pubKeyHash])
}
// OP_0 {scriptHash}
function witnessScriptHashOutput (scriptHash) {
typeforce(types.Hash256bit, scriptHash)
return compile([OPS.OP_0, scriptHash])
}
// {signature}

@@ -351,2 +385,7 @@ function pubKeyInput (signature) {

// <scriptSig> {serialized scriptPubKey script}
function witnessScriptHashInput (scriptSig, scriptPubKey) {
return scriptHashInput(scriptSig, scriptPubKey)
}
// OP_0 [signatures ...]

@@ -391,5 +430,8 @@ function multisigInput (signatures, scriptPubKey) {

isScriptHashOutput: isScriptHashOutput,
isWitnessPubKeyHashOutput: isWitnessPubKeyHashOutput,
isWitnessScriptHashOutput: isWitnessScriptHashOutput,
isMultisigInput: isMultisigInput,
isMultisigOutput: isMultisigOutput,
isNullDataOutput: isNullDataOutput,
classifyOutput: classifyOutput,

@@ -400,2 +442,6 @@ classifyInput: classifyInput,

scriptHashOutput: scriptHashOutput,
witnessPubKeyHashOutput: witnessPubKeyHashOutput,
witnessScriptHashInput: witnessScriptHashInput,
witnessScriptHashOutput: witnessScriptHashOutput,
multisigOutput: multisigOutput,

@@ -402,0 +448,0 @@ pubKeyInput: pubKeyInput,

@@ -5,4 +5,5 @@ var baddress = require('./address')

var bufferEquals = require('buffer-equals')
var bufferReverse = require('buffer-reverse')
var networks = require('./networks')
var ops = require('./opcodes')
var ops = require('./opcodes.json')
var typeforce = require('typeforce')

@@ -48,82 +49,92 @@ var types = require('./types')

function extractInput (transaction, txIn, vin) {
var redeemScript
var scriptSig = txIn.script
var scriptSigChunks = bscript.decompile(scriptSig)
if (txIn.script.length === 0) return {}
var prevOutScript
var prevOutType = bscript.classifyInput(scriptSig, true)
var scriptType
var scriptSigChunks = bscript.decompile(txIn.script)
var prevOutType = bscript.classifyInput(scriptSigChunks, true)
// Re-classify if scriptHash
if (prevOutType === 'scripthash') {
redeemScript = scriptSigChunks.slice(-1)[0]
prevOutScript = bscript.scriptHashOutput(bcrypto.hash160(redeemScript))
function processScript (scriptType, scriptSigChunks, redeemScriptChunks) {
// ensure chunks are decompiled
scriptSigChunks = bscript.decompile(scriptSigChunks)
redeemScriptChunks = redeemScriptChunks ? bscript.decompile(redeemScriptChunks) : undefined
scriptSig = bscript.compile(scriptSigChunks.slice(0, -1))
scriptSigChunks = scriptSigChunks.slice(0, -1)
var hashType, pubKeys, signatures, prevOutScript, redeemScript, redeemScriptType, result, parsed
scriptType = bscript.classifyInput(scriptSig, true)
} else {
scriptType = prevOutType
}
switch (scriptType) {
case 'scripthash':
redeemScript = scriptSigChunks.slice(-1)[0]
scriptSigChunks = bscript.compile(scriptSigChunks.slice(0, -1))
// pre-empt redeemScript decompilation
var redeemScriptChunks
if (redeemScript) {
redeemScriptChunks = bscript.decompile(redeemScript)
}
redeemScriptType = bscript.classifyInput(scriptSigChunks, true)
prevOutScript = bscript.scriptHashOutput(bcrypto.hash160(redeemScript))
// Extract hashType, pubKeys and signatures
var hashType, parsed, pubKeys, signatures
result = processScript(redeemScriptType, scriptSigChunks, bscript.decompile(redeemScript))
switch (scriptType) {
case 'pubkeyhash':
parsed = ECSignature.parseScriptSignature(scriptSigChunks[0])
hashType = parsed.hashType
pubKeys = scriptSigChunks.slice(1)
signatures = [parsed.signature]
prevOutScript = bscript.pubKeyHashOutput(bcrypto.hash160(pubKeys[0]))
result.prevOutScript = prevOutScript
result.redeemScript = redeemScript
result.redeemScriptType = redeemScriptType
break
return result
case 'pubkey':
parsed = ECSignature.parseScriptSignature(scriptSigChunks[0])
hashType = parsed.hashType
signatures = [parsed.signature]
case 'pubkeyhash':
parsed = ECSignature.parseScriptSignature(scriptSigChunks[0])
hashType = parsed.hashType
pubKeys = scriptSigChunks.slice(1)
signatures = [parsed.signature]
prevOutScript = bscript.pubKeyHashOutput(bcrypto.hash160(pubKeys[0]))
if (redeemScript) {
pubKeys = redeemScriptChunks.slice(0, 1)
}
break
break
case 'pubkey':
parsed = ECSignature.parseScriptSignature(scriptSigChunks[0])
hashType = parsed.hashType
signatures = [parsed.signature]
case 'multisig':
signatures = scriptSigChunks.slice(1).map(function (chunk) {
if (chunk === ops.OP_0) return undefined
if (redeemScriptChunks) {
pubKeys = redeemScriptChunks.slice(0, 1)
}
var parsed = ECSignature.parseScriptSignature(chunk)
hashType = parsed.hashType
break
return parsed.signature
})
case 'multisig':
signatures = scriptSigChunks.slice(1).map(function (chunk) {
if (chunk === ops.OP_0) return undefined
if (redeemScript) {
pubKeys = redeemScriptChunks.slice(1, -2)
parsed = ECSignature.parseScriptSignature(chunk)
hashType = parsed.hashType
if (pubKeys.length !== signatures.length) {
signatures = fixMSSignatures(transaction, vin, pubKeys, signatures, redeemScript, hashType, redeemScript)
return parsed.signature
})
if (redeemScriptChunks) {
pubKeys = redeemScriptChunks.slice(1, -2)
if (pubKeys.length !== signatures.length) {
signatures = fixMSSignatures(transaction, vin, pubKeys, signatures, bscript.compile(redeemScriptChunks), hashType, redeemScript)
}
}
}
break
break
}
return {
hashType: hashType,
pubKeys: pubKeys,
signatures: signatures,
prevOutScript: prevOutScript,
redeemScript: redeemScript,
redeemScriptType: redeemScriptType
}
}
// Extract hashType, pubKeys, signatures and prevOutScript
var result = processScript(prevOutType, scriptSigChunks)
return {
hashType: hashType,
prevOutScript: prevOutScript,
hashType: result.hashType,
prevOutScript: result.prevOutScript,
prevOutType: prevOutType,
pubKeys: pubKeys,
redeemScript: redeemScript,
scriptType: scriptType,
signatures: signatures
pubKeys: result.pubKeys,
redeemScript: result.redeemScript,
redeemScriptType: result.redeemScriptType,
signatures: result.signatures
}

@@ -157,2 +168,9 @@ }

TransactionBuilder.prototype.setVersion = function (version) {
typeforce(types.UInt32, version)
// XXX: this might eventually become more complex depending on what the versions represent
this.tx.version = version
}
TransactionBuilder.fromTransaction = function (transaction, network) {

@@ -182,5 +200,2 @@ var txb = new TransactionBuilder(network)

// Ignore empty scripts
if (txIn.script.length === 0) return {}
return extractInput(transaction, txIn, vin)

@@ -196,3 +211,3 @@ })

// transaction hashs's are displayed in reverse order, un-reverse it
txHash = [].reverse.call(new Buffer(txHash, 'hex'))
txHash = bufferReverse(new Buffer(txHash, 'hex'))

@@ -296,2 +311,44 @@ // is it a Transaction object?

function buildFromInputData (input, scriptType, parentType, redeemScript, allowIncomplete) {
var scriptSig
switch (scriptType) {
case 'pubkeyhash':
var pkhSignature = input.signatures[0].toScriptSignature(input.hashType)
scriptSig = bscript.pubKeyHashInput(pkhSignature, input.pubKeys[0])
break
case 'pubkey':
var pkSignature = input.signatures[0].toScriptSignature(input.hashType)
scriptSig = bscript.pubKeyInput(pkSignature)
break
case 'multisig':
var msSignatures = input.signatures.map(function (signature) {
return signature && signature.toScriptSignature(input.hashType)
})
// fill in blanks with OP_0
if (allowIncomplete) {
for (var i = 0; i < msSignatures.length; ++i) {
msSignatures[i] = msSignatures[i] || ops.OP_0
}
// remove blank signatures
} else {
msSignatures = msSignatures.filter(function (x) { return x })
}
scriptSig = bscript.multisigInput(msSignatures, allowIncomplete ? undefined : redeemScript)
break
}
// wrap as scriptHash if necessary
if (parentType === 'scripthash') {
scriptSig = bscript.scriptHashInput(scriptSig, redeemScript)
}
return scriptSig
}
TransactionBuilder.prototype.__build = function (allowIncomplete) {

@@ -307,3 +364,3 @@ if (!allowIncomplete) {

this.inputs.forEach(function (input, index) {
var scriptType = input.scriptType
var scriptType = input.redeemScriptType || input.prevOutType
var scriptSig

@@ -320,47 +377,42 @@

if (input.signatures) {
switch (scriptType) {
case 'pubkeyhash':
var pkhSignature = input.signatures[0].toScriptSignature(input.hashType)
scriptSig = bscript.pubKeyHashInput(pkhSignature, input.pubKeys[0])
break
scriptSig = buildFromInputData(input, scriptType, input.prevOutType, input.redeemScript, allowIncomplete)
}
case 'multisig':
var msSignatures = input.signatures.map(function (signature) {
return signature && signature.toScriptSignature(input.hashType)
})
// did we build a scriptSig? Buffer('') is allowed
if (scriptSig) {
tx.setInputScript(index, scriptSig)
}
})
// fill in blanks with OP_0
if (allowIncomplete) {
for (var i = 0; i < msSignatures.length; ++i) {
msSignatures[i] = msSignatures[i] || ops.OP_0
}
return tx
}
// remove blank signatures
} else {
msSignatures = msSignatures.filter(function (x) { return x })
}
function extractFromOutputScript (outputScript, keyPair, kpPubKey) {
var scriptType = bscript.classifyOutput(outputScript)
var outputScriptChunks = bscript.decompile(outputScript)
var redeemScript = allowIncomplete ? undefined : input.redeemScript
scriptSig = bscript.multisigInput(msSignatures, redeemScript)
break
switch (scriptType) {
case 'pubkeyhash':
var pkh1 = outputScriptChunks[2]
var pkh2 = bcrypto.hash160(keyPair.getPublicKeyBuffer())
case 'pubkey':
var pkSignature = input.signatures[0].toScriptSignature(input.hashType)
scriptSig = bscript.pubKeyInput(pkSignature)
break
if (!bufferEquals(pkh1, pkh2)) throw new Error('privateKey cannot sign for this input')
return {
pubKeys: [kpPubKey],
scriptType: scriptType
}
}
// did we build a scriptSig?
if (scriptSig) {
// wrap as scriptHash if necessary
if (input.prevOutType === 'scripthash') {
scriptSig = bscript.scriptHashInput(scriptSig, input.redeemScript)
case 'pubkey':
return {
pubKeys: outputScriptChunks.slice(0, 1),
scriptType: scriptType
}
tx.setInputScript(index, scriptSig)
}
})
return tx
case 'multisig':
return {
pubKeys: outputScriptChunks.slice(1, -2),
scriptType: scriptType
}
}
}

@@ -378,3 +430,3 @@

input.pubKeys &&
input.scriptType &&
input.redeemScriptType &&
input.signatures &&

@@ -384,2 +436,3 @@ input.signatures.length === input.pubKeys.length

var kpPubKey = keyPair.getPublicKeyBuffer()
var signatureScript

@@ -407,30 +460,5 @@ // are we ready to sign?

var scriptType = bscript.classifyOutput(redeemScript)
var redeemScriptChunks = bscript.decompile(redeemScript)
var pubKeys
var extracted = extractFromOutputScript(redeemScript, keyPair, kpPubKey)
if (!extracted) throw new Error('RedeemScript not supported "' + bscript.toASM(redeemScript) + '"')
switch (scriptType) {
case 'multisig':
pubKeys = redeemScriptChunks.slice(1, -2)
break
case 'pubkeyhash':
var pkh1 = redeemScriptChunks[2]
var pkh2 = bcrypto.hash160(keyPair.getPublicKeyBuffer())
if (!bufferEquals(pkh1, pkh2)) throw new Error('privateKey cannot sign for this input')
pubKeys = [kpPubKey]
break
case 'pubkey':
pubKeys = redeemScriptChunks.slice(0, 1)
break
default:
throw new Error('RedeemScript not supported (' + scriptType + ')')
}
// if we don't have a prevOutScript, generate a P2SH script

@@ -442,6 +470,6 @@ if (!input.prevOutScript) {

input.pubKeys = pubKeys
input.pubKeys = extracted.pubKeys
input.redeemScript = redeemScript
input.scriptType = scriptType
input.signatures = pubKeys.map(function () { return undefined })
input.redeemScriptType = extracted.scriptType
input.signatures = extracted.pubKeys.map(function () { return undefined })
} else {

@@ -455,2 +483,3 @@ // pay-to-scriptHash is not possible without a redeemScript

input.prevOutType = 'pubkeyhash'
input.pubKeys = [kpPubKey]

@@ -469,3 +498,3 @@ input.scriptType = input.prevOutType

// ready to sign?
var signatureScript = input.redeemScript || input.prevOutScript
signatureScript = signatureScript || input.redeemScript || input.prevOutScript
var signatureHash = this.tx.hashForSignature(index, signatureScript, hashType)

@@ -478,4 +507,3 @@

var signature = keyPair.sign(signatureHash)
input.signatures[i] = signature
input.signatures[i] = keyPair.sign(signatureHash)

@@ -482,0 +510,0 @@ return true

var bcrypto = require('./crypto')
var bscript = require('./script')
var bufferutils = require('./bufferutils')
var opcodes = require('./opcodes')
var bufferReverse = require('buffer-reverse')
var opcodes = require('./opcodes.json')
var typeforce = require('typeforce')

@@ -84,7 +85,13 @@ var types = require('./types')

Transaction.isCoinbaseHash = function (buffer) {
return Array.prototype.every.call(buffer, function (x) {
return x === 0
})
typeforce(types.Hash256bit, buffer)
for (var i = 0; i < 32; ++i) {
if (buffer[i] !== 0) return false
}
return true
}
Transaction.prototype.isCoinbase = function () {
return this.ins.length === 1 && Transaction.isCoinbaseHash(this.ins[0].hash)
}
var EMPTY_SCRIPT = new Buffer(0)

@@ -165,2 +172,6 @@

var VALUE_UINT64_MAX = new Buffer('ffffffffffffffff', 'hex')
var BLANK_OUTPUT = {
script: EMPTY_SCRIPT,
valueBuffer: VALUE_UINT64_MAX
}

@@ -181,57 +192,51 @@ /**

var txTmp = this.clone()
// in case concatenating two scripts ends up with two codeseparators,
// or an extra one at the end, this prevents all those possible incompatibilities.
var hashScript = bscript.compile(bscript.decompile(prevOutScript).filter(function (x) {
// ignore OP_CODESEPARATOR
var ourScript = bscript.compile(bscript.decompile(prevOutScript).filter(function (x) {
return x !== opcodes.OP_CODESEPARATOR
}))
var i
// blank out other inputs' signatures
txTmp.ins.forEach(function (input) { input.script = EMPTY_SCRIPT })
txTmp.ins[inIndex].script = hashScript
var txTmp = this.clone()
// blank out some of the inputs
// SIGHASH_NONE: ignore all outputs? (wildcard payee)
if ((hashType & 0x1f) === Transaction.SIGHASH_NONE) {
// wildcard payee
txTmp.outs = []
// let the others update at will
// ignore sequence numbers (except at inIndex)
txTmp.ins.forEach(function (input, i) {
if (i !== inIndex) {
input.sequence = 0
}
if (i === inIndex) return
input.sequence = 0
})
// SIGHASH_SINGLE: ignore all outputs, except at the same index?
} else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE) {
var nOut = inIndex
// only lock-in the txOut payee at same index as txIn
// https://github.com/bitcoin/bitcoin/blob/master/src/test/sighash_tests.cpp#L60
if (nOut >= this.outs.length) return ONE
if (inIndex >= this.outs.length) return ONE
txTmp.outs = txTmp.outs.slice(0, nOut + 1)
// truncate outputs after
txTmp.outs.length = inIndex + 1
// blank all other outputs (clear scriptPubKey, value === -1)
var stubOut = {
script: EMPTY_SCRIPT,
valueBuffer: VALUE_UINT64_MAX
// "blank" outputs before
for (var i = 0; i < inIndex; i++) {
txTmp.outs[i] = BLANK_OUTPUT
}
for (i = 0; i < nOut; i++) {
txTmp.outs[i] = stubOut
}
// ignore sequence numbers (except at inIndex)
txTmp.ins.forEach(function (input, i) {
if (i === inIndex) return
// let the others update at will
txTmp.ins.forEach(function (input, i) {
if (i !== inIndex) {
input.sequence = 0
}
input.sequence = 0
})
}
// blank out other inputs completely, not recommended for open transactions
// SIGHASH_ANYONECANPAY: ignore inputs entirely?
if (hashType & Transaction.SIGHASH_ANYONECANPAY) {
txTmp.ins[0] = txTmp.ins[inIndex]
txTmp.ins = txTmp.ins.slice(0, 1)
txTmp.ins = [txTmp.ins[inIndex]]
txTmp.ins[0].script = ourScript
// SIGHASH_ALL: only ignore input scripts
} else {
// "blank" others input scripts
txTmp.ins.forEach(function (input) { input.script = EMPTY_SCRIPT })
txTmp.ins[inIndex].script = ourScript
}

@@ -242,3 +247,3 @@

buffer.writeInt32LE(hashType, buffer.length - 4)
txTmp.toBuffer().copy(buffer, 0)
txTmp.toBuffer(buffer, 0)

@@ -254,9 +259,9 @@ return bcrypto.hash256(buffer)

// transaction hash's are displayed in reverse order
return [].reverse.call(this.getHash()).toString('hex')
return bufferReverse(this.getHash()).toString('hex')
}
Transaction.prototype.toBuffer = function () {
var buffer = new Buffer(this.byteLength())
Transaction.prototype.toBuffer = function (buffer, initialOffset) {
if (!buffer) buffer = new Buffer(this.byteLength())
var offset = 0
var offset = initialOffset || 0
function writeSlice (slice) {

@@ -307,2 +312,5 @@ slice.copy(buffer, offset)

// avoid slicing unless necessary
if (initialOffset !== undefined) return buffer.slice(initialOffset, offset)
return buffer

@@ -309,0 +317,0 @@ }

@@ -15,5 +15,9 @@ var typeforce = require('typeforce')

var UINT53_MAX = Math.pow(2, 53) - 1
var UINT31_MAX = Math.pow(2, 31) - 1
function UInt2 (value) { return (value & 3) === value }
function UInt8 (value) { return (value & 0xff) === value }
function UInt32 (value) { return (value >>> 0) === value }
function UInt31 (value) {
return UInt32(value) && value <= UINT31_MAX
}
function UInt53 (value) {

@@ -26,2 +30,7 @@ return typeforce.Number(value) &&

function Bip32Path (value) {
return typeforce.String(value) &&
value.match(/^(m\/)?(\d+'?\/)*\d+'?$/)
}
// external dependent types

@@ -56,4 +65,6 @@ var BigInt = typeforce.quacksLike('BigInteger')

UInt8: UInt8,
UInt31: UInt31,
UInt32: UInt32,
UInt53: UInt53
UInt53: UInt53,
Bip32Path: Bip32Path
}

@@ -60,0 +71,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc