Skip to content
This repository has been archived by the owner on Jan 14, 2018. It is now read-only.

Commit

Permalink
Closes #36 Send to multi sig addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
enriquez committed Jun 9, 2014
1 parent 0f306dd commit b2b2abd
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 6 deletions.
12 changes: 10 additions & 2 deletions app/js/workers/bitcoin_worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ var buildAndSignRawTransaction = function(seed, password, keyPair, inputs, outpu

for (var j=0; j<outputs.length; j++) {
var output = outputs[j];
transaction.addPayToPubKeyHashOutput(output.address, output.amount);
if (output.address.indexOf("1") === 0) {
transaction.addPayToPubKeyHashOutput(output.address, output.amount);
} else if (output.address.indexOf("3") === 0) {
transaction.addPayToScriptHashOutput(output.address, output.amount);
}
}

try {
Expand Down Expand Up @@ -87,7 +91,11 @@ var buildAndSignRawTransactionWithPrivateKey = function(seed, privateKey, inputs

for (var j=0; j<outputs.length; j++) {
var output = outputs[j];
transaction.addPayToPubKeyHashOutput(output.address, output.amount);
if (output.address.indexOf("1") === 0) {
transaction.addPayToPubKeyHashOutput(output.address, output.amount);
} else if (output.address.indexOf("3") === 0) {
transaction.addPayToScriptHashOutput(output.address, output.amount);
}
}

try {
Expand Down
40 changes: 39 additions & 1 deletion app/vendor/bitcoin/spec/BitcoinSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ describe("Bitcoin", function() {
toBe(true);
});

it("returns true given 3FbU6yRKMdRufy25jKVaMCvEm6RCh99vBH", function() {
expect(Bitcoin.Address.validate("3FbU6yRKMdRufy25jKVaMCvEm6RCh99vBH")).
toBe(true);
});

it("returns false with an invalid checksum", function() {
expect(Bitcoin.Address.validate("1Ert3c8pSdrkyjuBiwVcSSixZwQtMZ3Tew")).
toBe(false);
Expand Down Expand Up @@ -107,6 +112,14 @@ describe("Bitcoin", function() {
});
});

it("parses a multisig address", function() {
var actual = Bitcoin.parseCode('3FbU6yRKMdRufy25jKVaMCvEm6RCh99vBH');

expect(actual).toEqual({
address : '3FbU6yRKMdRufy25jKVaMCvEm6RCh99vBH'
});
});

it("parses a bitcoin address with the bitcoin: prefix", function() {
var actual = Bitcoin.parseCode('bitcoin:1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T');

Expand All @@ -115,6 +128,14 @@ describe("Bitcoin", function() {
});
});

it("parses a bitcoin multisig address with the bitcoin: prefix", function() {
var actual = Bitcoin.parseCode('bitcoin:3FbU6yRKMdRufy25jKVaMCvEm6RCh99vBH');

expect(actual).toEqual({
address : '3FbU6yRKMdRufy25jKVaMCvEm6RCh99vBH'
});
});

it("parses an address and amount", function() {
var actual = Bitcoin.parseCode('bitcoin:1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T?amount=0.0001');

Expand Down Expand Up @@ -266,7 +287,6 @@ describe("Bitcoin", function() {
});

it('returns hex if given BIP38 format uncompressed, ec multiply test vector 1', function() {
console.log('go');
expect(Bitcoin.PrivateKey.toHex('6PfQu77ygVyJLZjfvMLyhLMQbYnu5uguoJJ4kMCLqWwPEdfpwANVS76gTX', 'TestingOneTwoThree'))
.toEqual('a43a940577f4e97f5c4d39eb14ff083a98187c64ea7c99ef7ce460833959a519');
});
Expand Down Expand Up @@ -471,6 +491,24 @@ describe("Bitcoin", function() {

});

describe("#addPayToScriptHashOutput", function() {

it("adds a pay to script hash output with value 33.54 BTC", function() {
transaction.addPayToScriptHashOutput('3FbU6yRKMdRufy25jKVaMCvEm6RCh99vBH', 33.54);

var expected = '';
expected += '80fae9c700000000'; // value in satoshis. 8 byte little endian.
expected += '17'; // length of following script
expected += 'a9'; // OP_HASH160
expected += '14'; // length of following pubKeyHash
expected += '98851e780607057aec2a055d8a38e83b20c0d737'; // pubKeyHash (bitcoin address in hex with network and checksum bytes removed)
expected += '87'; // OP_EQUAL

expect(transaction.outputs[0]).toEqual(expected);
});

});

describe("#addPayToPubKeyHashOutput", function() {

it("adds a pay to pubkey hash output with value 33.54 BTC", function() {
Expand Down
32 changes: 29 additions & 3 deletions app/vendor/bitcoin/src/bitcoin.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Bitcoin.paranoia = 10;
Bitcoin.Address = function () { };

Bitcoin.Address.validate = function(address) {
var isValidFormat = /^1[1-9A-HJ-NP-Za-km-z]{27,33}/.test(address);
var isValidFormat = /^[13][1-9A-HJ-NP-Za-km-z]{27,33}/.test(address);

if (isValidFormat) {
var bits = sjcl.codec.base58.toBits(address),
Expand Down Expand Up @@ -41,7 +41,7 @@ Bitcoin.parseCode = function(code) {
return { address: code };
}

var matches = /^(?:bitcoin:)(?:\/\/)?(1[1-9A-HJ-NP-Za-km-z]{27,33})\??(.*)/.exec(code),
var matches = /^(?:bitcoin:)(?:\/\/)?([13][1-9A-HJ-NP-Za-km-z]{27,33})\??(.*)/.exec(code),
out = {};

if (matches && matches.length === 3) {
Expand Down Expand Up @@ -299,8 +299,34 @@ Bitcoin.Transaction = function() {

};

Bitcoin.Transaction.prototype.addPayToScriptHashOutput = function(address, amount) {
if (!Bitcoin.Address.validate(address) || address.indexOf("3") !== 0) {
throw "Invalid Bitcoin address";
}
if (amount < 0.00000001) {
throw "Invalid amount. Must be more than 0.00000001 BTC";
}

var output = '';

var value = this._btcTo8ByteLittleEndianHex(amount);

var script = 'a9'; // OP_HASH160
var pubKeyHash = this._bitcoinAddressToPubKeyHash(address);
script += this._byteLength(pubKeyHash);
script += pubKeyHash;
script += '87'; // OP_EQUAL

var scriptLength = this._byteLength(script);

output += value;
output += scriptLength;
output += script;
this.outputs.push(output);
}

Bitcoin.Transaction.prototype.addPayToPubKeyHashOutput = function(address, amount) {
if (!Bitcoin.Address.validate(address)) {
if (!Bitcoin.Address.validate(address) || address.indexOf("1") !== 0) {
throw "Invalid Bitcoin address";
}
if (amount < 0.00000001) {
Expand Down

0 comments on commit b2b2abd

Please sign in to comment.