Browse Source

Added sign with keys method to transaction and did lots of small cleanups

hk-custom-address
vub 11 years ago
parent
commit
f53a4e3ffa
  1. 6
      bitcoinjs-min.js
  2. 37
      src/address.js
  3. 75
      src/script.js
  4. 82
      src/transaction.js
  5. 3
      src/util.js

6
bitcoinjs-min.js

File diff suppressed because one or more lines are too long

37
src/address.js

@ -1,6 +1,7 @@
var base58 = require('./base58');
var Crypto = require('./crypto-js/crypto');
var conv = require('./convert');
var util = require('./util');
var address_types = {
prod: 0,
@ -12,14 +13,18 @@ var p2sh_types = {
testnet: 196
};
var Address = function (bytes) {
var Address = function (bytes, version) {
if (typeof bytes === 'string') {
this.hash = base58.checkDecode(bytes);
this.version = this.hash.version;
this.hash =
bytes.length <= 34 ? base58.checkDecode(bytes)
: bytes.length <= 40 ? conv.hexToBytes(bytes)
: util.error('Bad input');
this.version = version || this.hash.version || 0;
}
else {
this.hash = bytes;
this.version = 0x00;
this.version = version || 0;
}
};
@ -29,35 +34,31 @@ var Address = function (bytes) {
* Returns the address as a base58-encoded string in the standardized format.
*/
Address.prototype.toString = function () {
// Get a copy of the hash
var hash = this.hash.slice(0);
return base58.checkEncode(hash,this.version);
return base58.checkEncode(this.hash.slice(0),this.version);
};
Address.prototype.getHash = function () {
return conv.bytesToHex(this.hash);
return conv.bytesToHex(this.hash);
};
Address.getVersion = function(string) {
return base58.decode(string)[0];
return base58.decode(string)[0];
}
// TODO(shtylman) isValid?
Address.validate = function(string) {
try {
base58.checkDecode(string);
} catch (e) {
return false;
}
return true;
try {
base58.checkDecode(string);
return true;
} catch (e) {
return false;
}
};
/**
* Parse a Bitcoin address contained in a string.
*/
Address.decodeString = function (string) {
return base58.checkDecode(string);
return base58.checkDecode(string);
};
module.exports = Address;

75
src/script.js

@ -118,57 +118,42 @@ Script.prototype.parse = function () {
* Any other script (no template matched).
*/
Script.prototype.getOutType = function () {
if (this.chunks[this.chunks.length-1] == Opcode.map.OP_CHECKMULTISIG && this.chunks[this.chunks.length-2] <= 3) {
// Transfer to M-OF-N
return 'Multisig';
} else if (this.chunks.length == 5 &&
this.chunks[0] == Opcode.map.OP_DUP &&
this.chunks[1] == Opcode.map.OP_HASH160 &&
this.chunks[3] == Opcode.map.OP_EQUALVERIFY &&
this.chunks[4] == Opcode.map.OP_CHECKSIG) {
// Transfer to Bitcoin address
return 'Address';
} else if (this.chunks.length == 2 &&
this.chunks[1] == Opcode.map.OP_CHECKSIG) {
// Transfer to IP address
return 'Pubkey';
} else {
return 'Strange';
}
if (this.chunks[this.chunks.length-1] == Opcode.map.OP_CHECKMULTISIG &&
this.chunks[this.chunks.length-2] <= 3) {
// Transfer to M-OF-N
return 'Multisig';
} else if (this.chunks.length == 5 &&
this.chunks[0] == Opcode.map.OP_DUP &&
this.chunks[1] == Opcode.map.OP_HASH160 &&
this.chunks[3] == Opcode.map.OP_EQUALVERIFY &&
this.chunks[4] == Opcode.map.OP_CHECKSIG) {
// Transfer to Bitcoin address
return 'Address';
} else if (this.chunks.length == 2 &&
this.chunks[1] == Opcode.map.OP_CHECKSIG) {
// Transfer to IP address
return 'Pubkey';
} else {
return 'Strange';
}
}
/**
* Returns the affected address hash for this output.
*
* For standard transactions, this will return the hash of the pubKey that
* can spend this output.
*
* In the future, for payToScriptHash outputs, this will return the
* scriptHash. Note that non-standard and standard payToScriptHash transactions
* look the same
*
* This method is useful for indexing transactions.
* Returns the address corresponding to this output in hash160 form.
* Assumes strange scripts are P2SH
*/
Script.prototype.simpleOutHash = function ()
{
switch (this.getOutType()) {
case 'Address':
return this.chunks[2];
case 'Pubkey':
return util.sha256ripe160(this.chunks[0]);
case 'Multisig':
return util.sha256ripe160(this.buffer);
default:
throw new Error("Encountered non-standard scriptPubKey: " + this.getOutType());
}
Script.prototype.toScriptHash = function () {
var outType = this.getOutType();
return outType == 'Address' ? this.chunks[2]
: outType == 'Pubkey' ? util.sha256ripe160(this.chunks[0])
: outType == 'Multisig' ? util.sha256ripe160(this.buffer)
: util.sha256ripe160(this.buffer)
};
/**
* Old name for Script#simpleOutHash.
*
* @deprecated
*/
Script.prototype.simpleOutPubKeyHash = Script.prototype.simpleOutHash;
Script.prototype.toAddress = function() {
return new Address(this.toScriptHash());
}
/**
* Compare the script to known templates of scriptSig.

82
src/transaction.js

@ -348,7 +348,7 @@ Transaction.prototype.getDescription = function (wallet) {
* Get the total amount of a transaction's outputs.
*/
Transaction.prototype.getTotalOutValue = function () {
return this.outs.reduce(function(t,o) { return t + o.value },0);
return this.outs.reduce(function(t,o) { return t + o.value },0);
};
/**
@ -468,6 +468,32 @@ Transaction.prototype.sign = function(index, key, type) {
this.ins[index].script = Script.createInputScript(sig,pub);
}
// Takes outputs of the form [{ output: 'txhash:index', address: 'address' },...]
Transaction.prototype.signWithKeys = function(keys, outputs, type) {
type = type || SIGHASH_ALL;
var addrdata = keys.map(function(key) {
key = new Bitcoin.Key(key);
return {
key: key,
address: key.getBitcoinAddress().toString()
}
});
var hmap = {};
for (var o in outputs) {
hmap[outputs[o].output] = outputs[o];
}
for (var i = 0; i < this.ins.length; i++) {
var outpoint = this.ins[i].outpoint.hash+':'+this.ins[i].outpoint.index,
histItem = hmap[outpoint];
if (!histItem) continue;
var thisInputAddrdata = addrdata.filter(function(a) {
return a.address == histItem.address;
});
if (thisInputAddrdata.length == 0) continue;
this.sign(i,thisInputAddrdata[0].key);
}
}
/**
* Signs a P2SH output at some index with the given key
*/
@ -483,7 +509,7 @@ Transaction.prototype.p2shsign = function(index, script, key, type) {
Transaction.prototype.multisign = Transaction.prototype.p2shsign;
Transaction.prototype.validateSig = function(index,script,sig,pub) {
Transaction.prototype.validateSig = function(index, script, sig, pub) {
script = new Script(script);
var hash = this.hashTransactionForSignature(script,index,1);
return ECDSA.verify(hash, conv.coerceToBytes(sig),
@ -491,33 +517,31 @@ Transaction.prototype.validateSig = function(index,script,sig,pub) {
}
var TransactionIn = function (data)
{
this.outpoint = data.outpoint;
if (data.script instanceof Script) {
this.script = data.script;
} else {
if (data.scriptSig) {
this.script = Script.fromScriptSig(data.scriptSig);
}
else {
this.script = new Script(data.script);
}
}
this.sequence = data.sequence;
var TransactionIn = function (data) {
if (typeof data == "string")
this.outpoint = { hash: data.split(':')[0], index: data.split(':')[1] }
else if (data.outpoint)
this.outpoint = data.outpoint
else
this.outpoint = { hash: data.hash, index: data.index }
if (data.scriptSig)
this.script = Script.fromScriptSig(data.scriptSig)
else
this.script = new Script(data.script)
this.sequence = data.sequence || 4294967295;
};
TransactionIn.prototype.clone = function ()
{
var newTxin = new TransactionIn({
outpoint: {
hash: this.outpoint.hash,
index: this.outpoint.index
},
script: this.script.clone(),
sequence: this.sequence
});
return newTxin;
TransactionIn.prototype.clone = function () {
return new TransactionIn({
outpoint: {
hash: this.outpoint.hash,
index: this.outpoint.index
},
script: this.script.clone(),
sequence: this.sequence
});
};
var TransactionOut = function (data) {
@ -526,8 +550,11 @@ var TransactionOut = function (data) {
: util.isArray(data.script) ? new Script(data.script)
: typeof data.script == "string" ? new Script(conv.hexToBytes(data.script))
: data.scriptPubKey ? Script.fromScriptSig(data.scriptPubKey)
: data.address ? Script.createOutputScript(data.address)
: new Script();
if (this.script.buffer.length > 0) this.address = this.script.toAddress();
this.value =
util.isArray(data.value) ? util.bytesToNum(data.value)
: "string" == typeof data.value ? parseInt(data.value)
@ -547,4 +574,3 @@ TransactionOut.prototype.clone = function ()
module.exports.Transaction = Transaction;
module.exports.TransactionIn = TransactionIn;
module.exports.TransactionOut = TransactionOut;

3
src/util.js

@ -114,5 +114,8 @@ module.exports = {
*/
sha256ripe160: function (data) {
return Crypto.RIPEMD160(Crypto.SHA256(data, {asBytes: true}), {asBytes: true});
},
error: function(msg) {
throw new Error(msg);
}
};

Loading…
Cancel
Save