-
-
Save abrkn/e770e24455fbe0065f74 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var BitcoinTools = require('bitcoin-tools') | |
, debug = require('debug')('snow:bitcoin-sweep') | |
, BitcoinLib = require('bitcoinjs-lib') | |
, blockchaininfo = require('./blockchaininfo.js') | |
function reverseHex(hash) { | |
var res = '' | |
for (var i = 0; i < hash.length; i++) { | |
res = hash.substr(i * 2, 2) + res | |
} | |
return res | |
} | |
var SIGHASH_ALL = 1 | |
// See https://github.com/kyledrake/coinpunk/blob/master/public/js/coinpunk/models/wallet.js | |
module.exports = function(privKeys, destAddr, feeSatoshis, cb) { | |
var sourceAddrs = privKeys.map(BitcoinTools.addressFromPrivateKey) | |
, tx = new BitcoinLib.Transaction() | |
debug('gathering unspent outputs from blockchain.info...') | |
// Retrieve the unspent outputs for the source address | |
blockchaininfo.unspent(sourceAddrs, function(err, unspent) { | |
debug('found %s unspent outputs', unspent.length) | |
if (!unspent.length) return cb() | |
// Sum the unspent values | |
var value = unspent.reduce(function(p, c) { | |
return p + c.value | |
}, 0) | |
value = value - feeSatoshis | |
debug('will sweep %s BTC from the private key', value / 1e8) | |
tx.addOutput(destAddr, value) | |
// Add inputs | |
unspent.forEach(function(unspentOutput) { | |
// For some reason blockchain.info returns the unspent transaction | |
// hashes reversed. ABCDEF is returned EFCDAB | |
var hashReversed = reverseHex(unspentOutput.tx_hash) | |
// Add the input | |
tx.addInput({ hash: hashReversed }, unspentOutput.tx_output_n) | |
}) | |
unspent.forEach(function(unspentOutput, i) { | |
// Sign the input | |
var unspentOutScript = new BitcoinLib.Script(BitcoinLib.convert.hexToBytes(unspentOutput.script)) | |
// Determine which private key will need to sign the input | |
var pubKeyHash = unspentOutScript.simpleOutHash() | |
, pubKeyHashHex = BitcoinLib.convert.bytesToHex(pubKeyHash) | |
, key | |
privKeys.some(function(privKey) { | |
var privKeyEc = new BitcoinLib.Key(privKey) | |
, addr = privKeyEc.getBitcoinAddress() | |
, addrHashHex = BitcoinLib.convert.bytesToHex(addr.hash) | |
if (addrHashHex != pubKeyHashHex) return | |
key = privKeyEc | |
return true | |
}) | |
if (!key) { | |
return cb(new Error('No private key found for public key with hash ' + pubKeyHashHex)) | |
} | |
debug('signing input %s with priv key %s', i, key.toString('base58').substr(0, 6)) | |
var hash = tx.hashTransactionForSignature(unspentOutScript, i, SIGHASH_ALL) | |
, signature = key.sign(hash) | |
// Push the signature type | |
signature.push(SIGHASH_ALL) | |
tx.ins[i].script = BitcoinLib.Script.createInputScript(signature, key.getPub()) | |
}) | |
// Serialize the transaction, convert to hex and push | |
var hex = BitcoinLib.convert.bytesToHex(tx.serialize()) | |
debug('transaction (hex):\n%s', hex) | |
debug('pushing transaction...') | |
blockchaininfo.pushtx(hex, cb) | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment