Added sign with keys method to transaction and did lots of small cleanups
This commit is contained in:
parent
917822541c
commit
f53a4e3ffa
5 changed files with 109 additions and 94 deletions
6
bitcoinjs-min.js
vendored
6
bitcoinjs-min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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…
Add table
Reference in a new issue