From 1325b3f34a15fc03c74a23771a907c555879a935 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 30 Oct 2014 10:38:14 -0300 Subject: [PATCH 1/5] pull balance and tx proposal generation --- util/swipeWallet.js | 109 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100755 util/swipeWallet.js diff --git a/util/swipeWallet.js b/util/swipeWallet.js new file mode 100755 index 000000000..a7fd0d652 --- /dev/null +++ b/util/swipeWallet.js @@ -0,0 +1,109 @@ +#!/usr/bin/env node + +'use strict'; +var copay = require('../copay'); +var program = require('commander'); +var _ = require('lodash'); +var config = require('../config'); +var version = require('../version').version; +var sinon = require('sinon'); +var bitcore = require('bitcore'); +var readline = require('readline'); + +var rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); +var args = process.argv; + +var destAddr = args[2]; +var DFLT_FEE = 0.0001 * bitcore.util.COIN; + +var requiredCopayers = parseInt(args[3]); +var extPrivKeys = args.slice(4); +var totalCopayers = extPrivKeys.length; + +var addr = new bitcore.Address(destAddr); +if (!addr.isValid()){ + console.log('\tBad destination address'); //TODO + process.exit(1); +} + +var networkName = addr.network().name; +console.log('\tNetwork: %s\n\tDestination Address:%s\n\tRequired copayers: %d\n\tTotal copayers: %d\n\tKeys:', networkName, destAddr, requiredCopayers, totalCopayers, extPrivKeys); //TODO + + +console.log('\n ----------------------------'); + + +var opts = {}; + +opts.networkName = networkName || 'testnet'; +opts.publicKeyRing = new copay.PublicKeyRing({ + networkName: networkName, + requiredCopayers: requiredCopayers, + totalCopayers: totalCopayers, +}); + + +_.each(extPrivKeys, function(extPrivKey, i) { + console.log('\tAdding key:', i); + + var privateKey = new copay.PrivateKey({ + networkName: networkName, + extendedPrivateKeyString: extPrivKeys[i], + }); + + if (!i) + opts.privateKey = privateKey; + + opts.publicKeyRing.addCopayer( + privateKey.deriveBIP45Branch().extendedPublicKeyString(), + 'public key ' + i + ); +}) +console.log('\t### PublicKeyRing Initialized'); + +opts.txProposals = new copay.TxProposals({ + networkName: networkName, +}); + + +opts.requiredCopayers = requiredCopayers; +opts.totalCopayers = totalCopayers; +opts.network = { + setHexNonce: sinon.stub(), + setHexNonces: sinon.stub(), + send: sinon.stub(), +}; +// opts.networkOpts = { +// 'livenet': config.network.livenet, +// 'testnet': config.network.testnet, +// }; +opts.blockchainOpts = { + 'livenet': config.network.livenet, + 'testnet': config.network.testnet, +}; + +opts.spendUnconfirmed = true; +opts.version = version; +// opts.reconnectDelay = opts.reconnectDelay || this.walletDefaults.reconnectDelay; + +var wallet = new copay.Wallet(opts); +console.log('Wallet created. Scanning for funds'); +wallet.updateIndexes(function(){ + console.log('Scan done.'); //TODO + wallet.getBalance(function(err, balance, balanceByAddr){ + console.log('\n\n\n\n### TOTAL BALANCE: %d SATOSHIS',balance); //TODO + console.log('Balance per address:',balanceByAddr); //TODO + + // rl.question("Should we swipe the wallet? (`yes` to continue)", function(answer) { + // }); + + var amount = balance - DFLT_FEE; + + wallet.createTx(destAddr, amount, '', {}, function(err, ntxid){ +console.log('[swipeWallet.js.96]', err, ntxid); //TODO + }); + }); +}); From b402a5a1057978fbb78f199ceec368173c5a0706 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 30 Oct 2014 11:14:42 -0300 Subject: [PATCH 2/5] swipe working --- util/swipeWallet.js | 135 ++++++++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 54 deletions(-) diff --git a/util/swipeWallet.js b/util/swipeWallet.js index a7fd0d652..6b8aee08b 100755 --- a/util/swipeWallet.js +++ b/util/swipeWallet.js @@ -24,86 +24,113 @@ var extPrivKeys = args.slice(4); var totalCopayers = extPrivKeys.length; var addr = new bitcore.Address(destAddr); -if (!addr.isValid()){ +if (!addr.isValid()) { console.log('\tBad destination address'); //TODO process.exit(1); } - var networkName = addr.network().name; console.log('\tNetwork: %s\n\tDestination Address:%s\n\tRequired copayers: %d\n\tTotal copayers: %d\n\tKeys:', networkName, destAddr, requiredCopayers, totalCopayers, extPrivKeys); //TODO - - console.log('\n ----------------------------'); -var opts = {}; +function createWallet(networkName, extPrivKeys, index) { -opts.networkName = networkName || 'testnet'; -opts.publicKeyRing = new copay.PublicKeyRing({ - networkName: networkName, - requiredCopayers: requiredCopayers, - totalCopayers: totalCopayers, -}); + var opts = {}; - -_.each(extPrivKeys, function(extPrivKey, i) { - console.log('\tAdding key:', i); - - var privateKey = new copay.PrivateKey({ + opts.networkName = networkName || 'testnet'; + opts.publicKeyRing = new copay.PublicKeyRing({ networkName: networkName, - extendedPrivateKeyString: extPrivKeys[i], + requiredCopayers: requiredCopayers, + totalCopayers: totalCopayers, }); - if (!i) - opts.privateKey = privateKey; - opts.publicKeyRing.addCopayer( - privateKey.deriveBIP45Branch().extendedPublicKeyString(), - 'public key ' + i - ); -}) -console.log('\t### PublicKeyRing Initialized'); + _.each(extPrivKeys, function(extPrivKey, i) { + console.log('\tAdding key:', i); -opts.txProposals = new copay.TxProposals({ - networkName: networkName, + var privateKey = new copay.PrivateKey({ + networkName: networkName, + extendedPrivateKeyString: extPrivKeys[i], + }); + + if (i === index) + opts.privateKey = privateKey; + + opts.publicKeyRing.addCopayer( + privateKey.deriveBIP45Branch().extendedPublicKeyString(), + 'public key ' + i + ); + }) + console.log('\t### PublicKeyRing Initialized'); + + opts.txProposals = new copay.TxProposals({ + networkName: networkName, + }); + + + opts.requiredCopayers = requiredCopayers; + opts.totalCopayers = totalCopayers; + opts.network = { + setHexNonce: sinon.stub(), + setHexNonces: sinon.stub(), + send: sinon.stub(), + }; + // opts.networkOpts = { + // 'livenet': config.network.livenet, + // 'testnet': config.network.testnet, + // }; + opts.blockchainOpts = { + 'livenet': config.network.livenet, + 'testnet': config.network.testnet, + }; + opts.spendUnconfirmed = true; + opts.version = version; + // opts.reconnectDelay = opts.reconnectDelay || this.walletDefaults.reconnectDelay; + + return new copay.Wallet(opts); +} + + +console.log('## CREATING ALL WALLETS'); //TODO +var w = []; +_.each(extPrivKeys, function(extPrivKey, i) { + w.push(createWallet(networkName, extPrivKeys, i)); }); +console.log(' => %d Wallets created', w.length); +console.log('\n\n## Scanning for funds'); -opts.requiredCopayers = requiredCopayers; -opts.totalCopayers = totalCopayers; -opts.network = { - setHexNonce: sinon.stub(), - setHexNonces: sinon.stub(), - send: sinon.stub(), -}; -// opts.networkOpts = { -// 'livenet': config.network.livenet, -// 'testnet': config.network.testnet, -// }; -opts.blockchainOpts = { - 'livenet': config.network.livenet, - 'testnet': config.network.testnet, -}; +var firstWallet = w.pop(); -opts.spendUnconfirmed = true; -opts.version = version; -// opts.reconnectDelay = opts.reconnectDelay || this.walletDefaults.reconnectDelay; - -var wallet = new copay.Wallet(opts); -console.log('Wallet created. Scanning for funds'); -wallet.updateIndexes(function(){ +firstWallet.updateIndexes(function() { console.log('Scan done.'); //TODO - wallet.getBalance(function(err, balance, balanceByAddr){ - console.log('\n\n\n\n### TOTAL BALANCE: %d SATOSHIS',balance); //TODO - console.log('Balance per address:',balanceByAddr); //TODO + firstWallet.getBalance(function(err, balance, balanceByAddr) { + console.log('\n\n\n\n### TOTAL BALANCE: %d SATOSHIS', balance); //TODO + console.log('Balance per address:', balanceByAddr); //TODO // rl.question("Should we swipe the wallet? (`yes` to continue)", function(answer) { // }); var amount = balance - DFLT_FEE; + firstWallet.createTx(destAddr, amount, '', {}, function(err, ntxid) { + console.log('\n\t### Tx Proposal Created... With copayer 0 signature.'); - wallet.createTx(destAddr, amount, '', {}, function(err, ntxid){ -console.log('[swipeWallet.js.96]', err, ntxid); //TODO + var l = w.length; + _.each(w, function(dummy,i){ + console.log('\t Signing with copayer', i + 1); + w[i].txProposals=firstWallet.txProposals; + w[i].sign(ntxid, function(err){ + console.log('\t Signed!'); + firstWallet.txProposals = firstWallet.txProposals; + if (i == l - 1){ + console.log('\t ALL SIGNED'); + firstWallet.sendTx(ntxid,function(txid){ + console.log('\t ####### SENT TXID:', txid); + process.exit(1); + }); + } + }) + }) }); }); }); From c427d59cfdf0e6751baec445c6b65f4055c813cd Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 30 Oct 2014 11:24:34 -0300 Subject: [PATCH 3/5] add quorum check and confimation --- util/swipeWallet.js | 49 +++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/util/swipeWallet.js b/util/swipeWallet.js index 6b8aee08b..9be913409 100755 --- a/util/swipeWallet.js +++ b/util/swipeWallet.js @@ -108,29 +108,38 @@ firstWallet.updateIndexes(function() { console.log('\n\n\n\n### TOTAL BALANCE: %d SATOSHIS', balance); //TODO console.log('Balance per address:', balanceByAddr); //TODO - // rl.question("Should we swipe the wallet? (`yes` to continue)", function(answer) { - // }); + if (!balance) { + console.log('Could not find any balance from the generated wallet'); //TODO + process.exit(1); + } - var amount = balance - DFLT_FEE; - firstWallet.createTx(destAddr, amount, '', {}, function(err, ntxid) { - console.log('\n\t### Tx Proposal Created... With copayer 0 signature.'); + rl.question("Should we swipe the wallet? (`yes` to continue)", function(answer) { + if (answer!== 'yes') + process.exit(1); - var l = w.length; - _.each(w, function(dummy,i){ - console.log('\t Signing with copayer', i + 1); - w[i].txProposals=firstWallet.txProposals; - w[i].sign(ntxid, function(err){ - console.log('\t Signed!'); - firstWallet.txProposals = firstWallet.txProposals; - if (i == l - 1){ - console.log('\t ALL SIGNED'); - firstWallet.sendTx(ntxid,function(txid){ - console.log('\t ####### SENT TXID:', txid); - process.exit(1); - }); - } + var amount = balance - DFLT_FEE; + firstWallet.createTx(destAddr, amount, '', {}, function(err, ntxid) { + console.log('\n\t### Tx Proposal Created... With copayer 0 signature.'); + + var l = w.length; + _.each(w, function(dummy, i) { + console.log('\t Signing with copayer', i + 1); + w[i].txProposals = firstWallet.txProposals; + w[i].sign(ntxid, function(err) { + console.log('\t Signed!'); + firstWallet.txProposals = firstWallet.txProposals; + + var p = firstWallet.txProposals.getTxProposal(ntxid); + if (p.builder.isFullySigned()) { + console.log('\t FULLY SIGNED. BROADCASTING NOW....'); + firstWallet.sendTx(ntxid, function(txid) { + console.log('\t ####### SENT TXID:', txid); + process.exit(1); + }); + } + }) }) - }) + }); }); }); }); From 4a7a31e8e95d8a59d574004b59e3e9c2af08c224 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 30 Oct 2014 11:49:05 -0300 Subject: [PATCH 4/5] add help --- util/swipeWallet.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/util/swipeWallet.js b/util/swipeWallet.js index 9be913409..737491ecf 100755 --- a/util/swipeWallet.js +++ b/util/swipeWallet.js @@ -19,6 +19,12 @@ var args = process.argv; var destAddr = args[2]; var DFLT_FEE = 0.0001 * bitcore.util.COIN; +if (!args[4]) { + console.log('\n\tusage: swipeWallet.js [ ...]'); + console.log('\t e.g.: ./swipeWallet.js mxBVchwitGLXBHtT4Vah7DdP8J9M23ftE6 2 tprv8ZgxMBicQKsPejj9Xpky8M7NFv7szxqszBR2VvZTEkBTCCXZLtJfQwRxhUycNCu4sqyZepx8AfT1vuJr949np1gxYbZaJK3R9qekYPCZiJz tprv8ZgxMBicQKsPdWe14mn5SPY4zjG7fJnrmhkVZgTHQfYp91Kf1Lxof38KBQJiis4xv2zvZ2pVHgLn4GFRDUd8kR2HkMxDqLDNWTmnKqp95mZ tprv8ZgxMBicQKsPdzoFwT72Lwhr6n48ZyPahTAhPNaoAP4srVA1mcfPon7GWQaiwfAWesWACHm3aCBLYNGNPVKSU3E9vr1cLiBoMkayZiARywe'); + process.exit(1); +} + var requiredCopayers = parseInt(args[3]); var extPrivKeys = args.slice(4); var totalCopayers = extPrivKeys.length; @@ -113,7 +119,7 @@ firstWallet.updateIndexes(function() { process.exit(1); } - rl.question("Should we swipe the wallet? (`yes` to continue)", function(answer) { + rl.question("\n\tShould I swipe the wallet (destination address" + destAddr + ")?\n\t(`yes` to continue)\n\t", function(answer) { if (answer!== 'yes') process.exit(1); From 9f881087a26ec39342e783ae204fc7fb2193cdd3 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Thu, 30 Oct 2014 16:45:44 -0300 Subject: [PATCH 5/5] support for wallets 1-1 --- util/swipeWallet.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/util/swipeWallet.js b/util/swipeWallet.js index 737491ecf..388637c74 100755 --- a/util/swipeWallet.js +++ b/util/swipeWallet.js @@ -127,6 +127,13 @@ firstWallet.updateIndexes(function() { firstWallet.createTx(destAddr, amount, '', {}, function(err, ntxid) { console.log('\n\t### Tx Proposal Created... With copayer 0 signature.'); + if (requiredCopayers ===1) { + firstWallet.sendTx(ntxid, function(txid) { + console.log('\t ####### SENT TXID:', txid); + process.exit(1); + }); + } + var l = w.length; _.each(w, function(dummy, i) { console.log('\t Signing with copayer', i + 1);