Added comments.
This commit is contained in:
parent
de21042bb7
commit
09e8c6e184
8 changed files with 392 additions and 33 deletions
|
@ -7,6 +7,11 @@ Bitcoin.Address = function (bytes) {
|
|||
this.version = 0x00;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize this object as a standard Bitcoin address.
|
||||
*
|
||||
* Returns the address as a base58-encoded string in the standardized format.
|
||||
*/
|
||||
Bitcoin.Address.prototype.toString = function () {
|
||||
// Get a copy of the hash
|
||||
var hash = this.hash.slice(0);
|
||||
|
@ -25,6 +30,9 @@ Bitcoin.Address.prototype.getHashBase64 = function () {
|
|||
return Crypto.util.bytesToBase64(this.hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a Bitcoin address contained in a string.
|
||||
*/
|
||||
Bitcoin.Address.decodeString = function (string) {
|
||||
var bytes = Bitcoin.Base58.decode(string);
|
||||
|
||||
|
|
58
src/ecdsa.js
58
src/ecdsa.js
|
@ -134,6 +134,11 @@ ECPointFp.prototype.isOnCurve = function () {
|
|||
return lhs.equals(rhs);
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate an elliptic curve point.
|
||||
*
|
||||
* See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive
|
||||
*/
|
||||
ECPointFp.prototype.validate = function () {
|
||||
var n = this.curve.getQ();
|
||||
|
||||
|
@ -228,25 +233,6 @@ Bitcoin.ECDSA = (function () {
|
|||
return ECDSA.serializeSig(r, s);
|
||||
},
|
||||
|
||||
serializeSig: function (r, s) {
|
||||
var rBa = r.toByteArrayUnsigned();
|
||||
var sBa = s.toByteArrayUnsigned();
|
||||
|
||||
var sequence = [];
|
||||
sequence.push(0x02); // INTEGER
|
||||
sequence.push(rBa.length);
|
||||
sequence = sequence.concat(rBa);
|
||||
|
||||
sequence.push(0x02); // INTEGER
|
||||
sequence.push(sBa.length);
|
||||
sequence = sequence.concat(sBa);
|
||||
|
||||
sequence.unshift(sequence.length);
|
||||
sequence.unshift(0x30) // SEQUENCE
|
||||
|
||||
return sequence;
|
||||
},
|
||||
|
||||
verify: function (hash, sig, pubkey) {
|
||||
var obj = ECDSA.parseSig(sig);
|
||||
var r = obj.r;
|
||||
|
@ -278,6 +264,40 @@ Bitcoin.ECDSA = (function () {
|
|||
return v.equals(r);
|
||||
},
|
||||
|
||||
/**
|
||||
* Serialize a signature into DER format.
|
||||
*
|
||||
* Takes two BigIntegers representing r and s and returns a byte array.
|
||||
*/
|
||||
serializeSig: function (r, s) {
|
||||
var rBa = r.toByteArrayUnsigned();
|
||||
var sBa = s.toByteArrayUnsigned();
|
||||
|
||||
var sequence = [];
|
||||
sequence.push(0x02); // INTEGER
|
||||
sequence.push(rBa.length);
|
||||
sequence = sequence.concat(rBa);
|
||||
|
||||
sequence.push(0x02); // INTEGER
|
||||
sequence.push(sBa.length);
|
||||
sequence = sequence.concat(sBa);
|
||||
|
||||
sequence.unshift(sequence.length);
|
||||
sequence.unshift(0x30); // SEQUENCE
|
||||
|
||||
return sequence;
|
||||
},
|
||||
|
||||
/**
|
||||
* Parses a byte array containing a DER-encoded signature.
|
||||
*
|
||||
* This function will return an object of the form:
|
||||
*
|
||||
* {
|
||||
* r: BigInteger,
|
||||
* s: BigInteger
|
||||
* }
|
||||
*/
|
||||
parseSig: function (sig) {
|
||||
var cursor;
|
||||
if (sig[0] != 0x30)
|
||||
|
|
|
@ -26,6 +26,12 @@ Bitcoin.ECKey = (function () {
|
|||
return this.pub = ecparams.getG().multiply(this.priv).getEncoded();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the pubKeyHash for this key.
|
||||
*
|
||||
* This is calculated as RIPE160(SHA256([encoded pubkey])) and returned as
|
||||
* a byte array.
|
||||
*/
|
||||
ECKey.prototype.getPubKeyHash = function () {
|
||||
if (this.pubKeyHash) return this.pubKeyHash;
|
||||
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* Implement the Paillier cryptosystem in JavaScript.
|
||||
*
|
||||
* Paillier is useful for multiparty calculation. It is not currently part of any
|
||||
* BitcoinJS-lib distribution, but it is included here for experimental use.
|
||||
*/
|
||||
Bitcoin.Paillier = (function () {
|
||||
var rng = new SecureRandom();
|
||||
var TWO = BigInteger.valueOf(2);
|
||||
|
|
127
src/script.js
127
src/script.js
|
@ -22,6 +22,17 @@
|
|||
this.parse();
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the parsed script representation.
|
||||
*
|
||||
* Each Script object stores the script in two formats. First as a raw byte
|
||||
* array and second as an array of "chunks", such as opcodes and pieces of
|
||||
* data.
|
||||
*
|
||||
* This method updates the chunks cache. Normally this is called by the
|
||||
* constructor and you don't need to worry about it. However, if you change
|
||||
* the script buffer manually, you should update the chunks using this method.
|
||||
*/
|
||||
Script.prototype.parse = function () {
|
||||
var self = this;
|
||||
|
||||
|
@ -65,6 +76,24 @@
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare the script to known templates of scriptPubKey.
|
||||
*
|
||||
* This method will compare the script to a small number of standard script
|
||||
* templates and return a string naming the detected type.
|
||||
*
|
||||
* Currently supported are:
|
||||
* Address:
|
||||
* Paying to a Bitcoin address which is the hash of a pubkey.
|
||||
* OP_DUP OP_HASH160 [pubKeyHash] OP_EQUALVERIFY OP_CHECKSIG
|
||||
*
|
||||
* Pubkey:
|
||||
* Paying to a public key directly.
|
||||
* [pubKey] OP_CHECKSIG
|
||||
*
|
||||
* Strange:
|
||||
* Any other script (no template matched).
|
||||
*/
|
||||
Script.prototype.getOutType = function ()
|
||||
{
|
||||
if (this.chunks.length == 5 &&
|
||||
|
@ -85,7 +114,19 @@
|
|||
}
|
||||
};
|
||||
|
||||
Script.prototype.simpleOutPubKeyHash = function ()
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
Script.prototype.simpleOutHash = function ()
|
||||
{
|
||||
switch (this.getOutType()) {
|
||||
case 'Address':
|
||||
|
@ -97,22 +138,64 @@
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Old name for Script#simpleOutHash.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
Script.prototype.simpleOutPubKeyHash = Script.prototype.simpleOutHash;
|
||||
|
||||
/**
|
||||
* Compare the script to known templates of scriptSig.
|
||||
*
|
||||
* This method will compare the script to a small number of standard script
|
||||
* templates and return a string naming the detected type.
|
||||
*
|
||||
* WARNING: Use this method with caution. It merely represents a heuristic
|
||||
* based on common transaction formats. A non-standard transaction could
|
||||
* very easily match one of these templates by accident.
|
||||
*
|
||||
* Currently supported are:
|
||||
* Address:
|
||||
* Paying to a Bitcoin address which is the hash of a pubkey.
|
||||
* [sig] [pubKey]
|
||||
*
|
||||
* Pubkey:
|
||||
* Paying to a public key directly.
|
||||
* [sig]
|
||||
*
|
||||
* Strange:
|
||||
* Any other script (no template matched).
|
||||
*/
|
||||
Script.prototype.getInType = function ()
|
||||
{
|
||||
if (this.chunks.length == 1 &&
|
||||
Bitcoin.Util.isArray(this.chunks[0])) {
|
||||
// Direct IP to IP transactions only have the public key in their scriptSig.
|
||||
// TODO: We could also check that the length of the data is 65 or 33.
|
||||
// Direct IP to IP transactions only have the signature in their scriptSig.
|
||||
// TODO: We could also check that the length of the data is correct.
|
||||
return 'Pubkey';
|
||||
} else if (this.chunks.length == 2 &&
|
||||
Bitcoin.Util.isArray(this.chunks[0]) &&
|
||||
Bitcoin.Util.isArray(this.chunks[1])) {
|
||||
return 'Address';
|
||||
} else {
|
||||
throw new Error("Encountered non-standard scriptSig");
|
||||
return 'Strange';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the affected public key for this input.
|
||||
*
|
||||
* This currently only works with payToPubKeyHash transactions. It will also
|
||||
* work in the future for standard payToScriptHash transactions that use a
|
||||
* single public key.
|
||||
*
|
||||
* However for multi-key and other complex transactions, this will only return
|
||||
* one of the keys or raise an error. Therefore, it is recommended for indexing
|
||||
* purposes to use Script#simpleInHash or Script#simpleOutHash instead.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
Script.prototype.simpleInPubKey = function ()
|
||||
{
|
||||
switch (this.getInType()) {
|
||||
|
@ -127,17 +210,45 @@
|
|||
}
|
||||
};
|
||||
|
||||
Script.prototype.simpleInPubKeyHash = function ()
|
||||
/**
|
||||
* Returns the affected address hash for this input.
|
||||
*
|
||||
* For standard transactions, this will return the hash of the pubKey that
|
||||
* can spend this output.
|
||||
*
|
||||
* In the future, for standard payToScriptHash inputs, this will return the
|
||||
* scriptHash.
|
||||
*
|
||||
* Note: This function provided for convenience. If you have the corresponding
|
||||
* scriptPubKey available, you are urged to use Script#simpleOutHash instead
|
||||
* as it is more reliable for non-standard payToScriptHash transactions.
|
||||
*
|
||||
* This method is useful for indexing transactions.
|
||||
*/
|
||||
Script.prototype.simpleInHash = function ()
|
||||
{
|
||||
return Bitcoin.Util.sha256ripe160(this.simpleInPubKey());
|
||||
};
|
||||
|
||||
/**
|
||||
* Old name for Script#simpleInHash.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
Script.prototype.simpleInPubKeyHash = Script.prototype.simpleInHash;
|
||||
|
||||
/**
|
||||
* Add an op code to the script.
|
||||
*/
|
||||
Script.prototype.writeOp = function (opcode)
|
||||
{
|
||||
this.buffer.push(opcode);
|
||||
this.chunks.push(opcode);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a data chunk to the script.
|
||||
*/
|
||||
Script.prototype.writeBytes = function (data)
|
||||
{
|
||||
if (data.length < OP_PUSHDATA1) {
|
||||
|
@ -160,6 +271,9 @@
|
|||
this.chunks.push(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a standard payToPubKeyHash output.
|
||||
*/
|
||||
Script.createOutputScript = function (address)
|
||||
{
|
||||
var script = new Script();
|
||||
|
@ -171,6 +285,9 @@
|
|||
return script;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a standard payToPubKeyHash input.
|
||||
*/
|
||||
Script.createInputScript = function (signature, pubKey)
|
||||
{
|
||||
var script = new Script();
|
||||
|
|
|
@ -28,6 +28,12 @@
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Turn transaction data into Transaction objects.
|
||||
*
|
||||
* Takes an array of plain JavaScript objects containing transaction data and
|
||||
* returns an array of Transaction objects.
|
||||
*/
|
||||
Transaction.objectify = function (txs) {
|
||||
var objs = [];
|
||||
for (var i = 0; i < txs.length; i++) {
|
||||
|
@ -36,6 +42,16 @@
|
|||
return objs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new txin.
|
||||
*
|
||||
* Can be called with an existing TransactionIn object to add it to the
|
||||
* transaction. Or it can be called with a Transaction object and an integer
|
||||
* output index, in which case a new TransactionIn object pointing to the
|
||||
* referenced output will be created.
|
||||
*
|
||||
* Note that this method does not sign the created input.
|
||||
*/
|
||||
Transaction.prototype.addInput = function (tx, outIndex) {
|
||||
if (arguments[0] instanceof TransactionIn) {
|
||||
this.ins.push(arguments[0]);
|
||||
|
@ -51,6 +67,14 @@
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new txout.
|
||||
*
|
||||
* Can be called with an existing TransactionOut object to add it to the
|
||||
* transaction. Or it can be called with an Address object and a BigInteger
|
||||
* for the amount, in which case a new TransactionOut object with those
|
||||
* values will be created.
|
||||
*/
|
||||
Transaction.prototype.addOutput = function (address, value) {
|
||||
if (arguments[0] instanceof TransactionOut) {
|
||||
this.outs.push(arguments[0]);
|
||||
|
@ -69,6 +93,13 @@
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize this transaction.
|
||||
*
|
||||
* Returns the transaction as a byte array in the standard Bitcoin binary
|
||||
* format. This method is byte-perfect, i.e. the resulting byte array can
|
||||
* be hashed to get the transaction's standard Bitcoin hash.
|
||||
*/
|
||||
Transaction.prototype.serialize = function ()
|
||||
{
|
||||
var buffer = [];
|
||||
|
@ -103,12 +134,22 @@
|
|||
var SIGHASH_SINGLE = 3;
|
||||
var SIGHASH_ANYONECANPAY = 80;
|
||||
|
||||
Transaction.prototype.hashTransactionForSignature = function (connectedScript, inIndex, hashType)
|
||||
/**
|
||||
* Hash transaction for signing a specific input.
|
||||
*
|
||||
* Bitcoin uses a different hash for each signed transaction input. This
|
||||
* method copies the transaction, makes the necessary changes based on the
|
||||
* hashType, serializes and finally hashes the result. This hash can then be
|
||||
* used to sign the transaction input in question.
|
||||
*/
|
||||
Transaction.prototype.hashTransactionForSignature =
|
||||
function (connectedScript, inIndex, hashType)
|
||||
{
|
||||
var txTmp = this.clone();
|
||||
|
||||
// In case concatenating two scripts ends up with two codeseparators,
|
||||
// or an extra one at the end, this prevents all those possible incompatibilities.
|
||||
// or an extra one at the end, this prevents all those possible
|
||||
// incompatibilities.
|
||||
/*scriptCode = scriptCode.filter(function (val) {
|
||||
return val !== OP_CODESEPARATOR;
|
||||
});*/
|
||||
|
@ -151,12 +192,18 @@
|
|||
return Crypto.SHA256(hash1, {asBytes: true});
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate and return the transaction's hash.
|
||||
*/
|
||||
Transaction.prototype.getHash = function ()
|
||||
{
|
||||
var buffer = this.serialize();
|
||||
return Crypto.SHA256(Crypto.SHA256(buffer, {asBytes: true}), {asBytes: true});
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a copy of this transaction object.
|
||||
*/
|
||||
Transaction.prototype.clone = function ()
|
||||
{
|
||||
var newTx = new Transaction();
|
||||
|
@ -175,6 +222,28 @@
|
|||
|
||||
/**
|
||||
* Analyze how this transaction affects a wallet.
|
||||
*
|
||||
* Returns an object with properties 'impact', 'type' and 'addr'.
|
||||
*
|
||||
* 'impact' is an object, see Transaction#calcImpact.
|
||||
*
|
||||
* 'type' can be one of the following:
|
||||
*
|
||||
* recv:
|
||||
* This is an incoming transaction, the wallet received money.
|
||||
* 'addr' contains the first address in the wallet that receives money
|
||||
* from this transaction.
|
||||
*
|
||||
* self:
|
||||
* This is an internal transaction, money was sent within the wallet.
|
||||
* 'addr' is undefined.
|
||||
*
|
||||
* sent:
|
||||
* This is an outgoing transaction, money was sent out from the wallet.
|
||||
* 'addr' contains the first external address, i.e. the recipient.
|
||||
*
|
||||
* other:
|
||||
* This method was unable to detect what the transaction does. Either it
|
||||
*/
|
||||
Transaction.prototype.analyze = function (wallet) {
|
||||
if (!(wallet instanceof Bitcoin.Wallet)) return null;
|
||||
|
@ -217,6 +286,9 @@
|
|||
analysis.type = 'self';
|
||||
} else if (allFromMe) {
|
||||
analysis.type = 'sent';
|
||||
// TODO: Right now, firstRecvHash is the first output, which - if the
|
||||
// transaction was not generated by this library could be the
|
||||
// change address.
|
||||
analysis.addr = new Bitcoin.Address(firstRecvHash);
|
||||
} else {
|
||||
analysis.type = "other";
|
||||
|
@ -225,6 +297,12 @@
|
|||
return analysis;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a human-readable version of the data returned by Transaction#analyze.
|
||||
*
|
||||
* This is merely a convenience function. Clients should consider implementing
|
||||
* this themselves based on their UI, I18N, etc.
|
||||
*/
|
||||
Transaction.prototype.getDescription = function (wallet) {
|
||||
var analysis = this.analyze(wallet);
|
||||
|
||||
|
@ -249,7 +327,10 @@
|
|||
}
|
||||
};
|
||||
|
||||
Transaction.prototype.getTotalValue = function () {
|
||||
/**
|
||||
* Get the total amount of a transaction's outputs.
|
||||
*/
|
||||
Transaction.prototype.getTotalOutValue = function () {
|
||||
var totalValue = BigInteger.ZERO;
|
||||
for (var j = 0; j < this.outs.length; j++) {
|
||||
var txout = this.outs[j];
|
||||
|
@ -258,6 +339,13 @@
|
|||
return totalValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Old name for Transaction#getTotalOutValue.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
Transaction.prototype.getTotalValue = Transaction.prototype.getTotalOutValue;
|
||||
|
||||
/**
|
||||
* Calculates the impact a transaction has on this wallet.
|
||||
*
|
||||
|
|
61
src/util.js
61
src/util.js
|
@ -38,10 +38,19 @@ for (var i = 0; i < names.length; ++i)
|
|||
|
||||
// Bitcoin utility functions
|
||||
Bitcoin.Util = {
|
||||
isArray: Array.isArray || function(o) {
|
||||
/**
|
||||
* Cross-browser compatibility version of Array.isArray.
|
||||
*/
|
||||
isArray: Array.isArray || function(o)
|
||||
{
|
||||
return Object.prototype.toString.call(o) === '[object Array]';
|
||||
},
|
||||
makeFilledArray: function (len, val) {
|
||||
|
||||
/**
|
||||
* Create an array of a certain length filled with a specific value.
|
||||
*/
|
||||
makeFilledArray: function (len, val)
|
||||
{
|
||||
var array = [];
|
||||
var i = 0;
|
||||
while (i < len) {
|
||||
|
@ -49,8 +58,16 @@ Bitcoin.Util = {
|
|||
}
|
||||
return array;
|
||||
},
|
||||
numToVarInt: function (i) {
|
||||
// TODO: THIS IS TOTALLY UNTESTED!
|
||||
|
||||
/**
|
||||
* Turn an integer into a "var_int".
|
||||
*
|
||||
* "var_int" is a variable length integer used by Bitcoin's binary format.
|
||||
*
|
||||
* Returns a byte array.
|
||||
*/
|
||||
numToVarInt: function (i)
|
||||
{
|
||||
if (i < 0xfd) {
|
||||
// unsigned char
|
||||
return [i];
|
||||
|
@ -65,12 +82,30 @@ Bitcoin.Util = {
|
|||
return [0xff].concat(Crypto.util.wordsToBytes([i >>> 32, i]));
|
||||
}
|
||||
},
|
||||
valueToBigInt: function (valueBuffer) {
|
||||
|
||||
/**
|
||||
* Parse a Bitcoin value byte array, returning a BigInteger.
|
||||
*/
|
||||
valueToBigInt: function (valueBuffer)
|
||||
{
|
||||
if (valueBuffer instanceof BigInteger) return valueBuffer;
|
||||
|
||||
// Prepend zero byte to prevent interpretation as negative integer
|
||||
return BigInteger.fromByteArrayUnsigned(valueBuffer);
|
||||
},
|
||||
|
||||
/**
|
||||
* Format a Bitcoin value as a string.
|
||||
*
|
||||
* Takes a BigInteger or byte-array and returns that amount of Bitcoins in a
|
||||
* nice standard formatting.
|
||||
*
|
||||
* Examples:
|
||||
* 12.3555
|
||||
* 0.1234
|
||||
* 900.99998888
|
||||
* 34.00
|
||||
*/
|
||||
formatValue: function (valueBuffer) {
|
||||
var value = this.valueToBigInt(valueBuffer).toString();
|
||||
var integerPart = value.length > 8 ? value.substr(0, value.length-8) : '0';
|
||||
|
@ -80,7 +115,16 @@ Bitcoin.Util = {
|
|||
while (decimalPart.length < 2) decimalPart += "0";
|
||||
return integerPart+"."+decimalPart;
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse a floating point string as a Bitcoin value.
|
||||
*
|
||||
* Keep in mind that parsing user input is messy. You should always display
|
||||
* the parsed value back to the user to make sure we understood his input
|
||||
* correctly.
|
||||
*/
|
||||
parseValue: function (valueString) {
|
||||
// TODO: Detect other number formats (e.g. comma as decimal separator)
|
||||
var valueComp = valueString.split('.');
|
||||
var integralPart = valueComp[0];
|
||||
var fractionalPart = valueComp[1] || "0";
|
||||
|
@ -91,6 +135,13 @@ Bitcoin.Util = {
|
|||
value = value.add(BigInteger.valueOf(parseInt(fractionalPart)));
|
||||
return value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculate RIPEMD160(SHA256(data)).
|
||||
*
|
||||
* Takes an arbitrary byte array as inputs and returns the hash as a byte
|
||||
* array.
|
||||
*/
|
||||
sha256ripe160: function (data) {
|
||||
return Crypto.RIPEMD160(Crypto.SHA256(data, {asBytes: true}), {asBytes: true});
|
||||
}
|
||||
|
|
|
@ -5,7 +5,15 @@ Bitcoin.Wallet = (function () {
|
|||
|
||||
var Wallet = function () {
|
||||
// Keychain
|
||||
//
|
||||
// The keychain is stored as a var in this closure to make accidental
|
||||
// serialization less likely.
|
||||
//
|
||||
// Any functions accessing this value therefore have to be defined in
|
||||
// the closure of this constructor.
|
||||
var keys = [];
|
||||
|
||||
// Public hashes of our keys
|
||||
this.addressHashes = [];
|
||||
|
||||
// Transaction data
|
||||
|
@ -15,6 +23,13 @@ Bitcoin.Wallet = (function () {
|
|||
// Other fields
|
||||
this.addressPointer = 0;
|
||||
|
||||
/**
|
||||
* Add a key to the keychain.
|
||||
*
|
||||
* The corresponding public key can be provided as a second parameter. This
|
||||
* adds it to the cache in the ECKey object and avoid the need to
|
||||
* expensively calculate it later.
|
||||
*/
|
||||
this.addKey = function (key, pub) {
|
||||
if (!(key instanceof Bitcoin.ECKey)) {
|
||||
key = new Bitcoin.ECKey(key);
|
||||
|
@ -31,6 +46,9 @@ Bitcoin.Wallet = (function () {
|
|||
this.addressHashes.push(key.getBitcoinAddress().getHashBase64());
|
||||
};
|
||||
|
||||
/**
|
||||
* Add multiple keys at once.
|
||||
*/
|
||||
this.addKeys = function (keys, pubs) {
|
||||
if ("string" === typeof keys) {
|
||||
keys = keys.split(',');
|
||||
|
@ -50,6 +68,11 @@ Bitcoin.Wallet = (function () {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the key chain.
|
||||
*
|
||||
* Returns an array of base64-encoded private values.
|
||||
*/
|
||||
this.getKeys = function () {
|
||||
var serializedWallet = [];
|
||||
|
||||
|
@ -60,6 +83,11 @@ Bitcoin.Wallet = (function () {
|
|||
return serializedWallet;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the public keys.
|
||||
*
|
||||
* Returns an array of base64-encoded public keys.
|
||||
*/
|
||||
this.getPubKeys = function () {
|
||||
var pubs = [];
|
||||
|
||||
|
@ -70,14 +98,25 @@ Bitcoin.Wallet = (function () {
|
|||
return pubs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete all keys.
|
||||
*/
|
||||
this.clear = function () {
|
||||
keys = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the number of keys in this wallet.
|
||||
*/
|
||||
this.getLength = function () {
|
||||
return keys.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the addresses for this wallet.
|
||||
*
|
||||
* Returns an array of Address objects.
|
||||
*/
|
||||
this.getAllAddresses = function () {
|
||||
var addresses = [];
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
|
@ -94,14 +133,26 @@ Bitcoin.Wallet = (function () {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Go to the next address.
|
||||
*
|
||||
* If there are no more new addresses available, one will be generated
|
||||
* automatically.
|
||||
*/
|
||||
this.getNextAddress = function () {
|
||||
this.addressPointer++;
|
||||
if(!keys[this.addressPointer]) {
|
||||
if (!keys[this.addressPointer]) {
|
||||
this.generateAddress();
|
||||
}
|
||||
return keys[this.addressPointer].getBitcoinAddress();
|
||||
};
|
||||
|
||||
/**
|
||||
* Sign a hash with a key.
|
||||
*
|
||||
* This method expects the pubKeyHash as the first parameter and the hash
|
||||
* to be signed as the second parameter.
|
||||
*/
|
||||
this.signWithKey = function (pubKeyHash, hash) {
|
||||
pubKeyHash = Crypto.util.bytesToBase64(pubKeyHash);
|
||||
for (var i = 0; i < this.addressHashes.length; i++) {
|
||||
|
@ -112,6 +163,12 @@ Bitcoin.Wallet = (function () {
|
|||
throw new Error("Missing key for signature");
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the corresponding pubKey for a pubKeyHash.
|
||||
*
|
||||
* This function only works if the pubKey in question is part of this
|
||||
* wallet.
|
||||
*/
|
||||
this.getPubKeyFromHash = function (pubKeyHash) {
|
||||
pubKeyHash = Crypto.util.bytesToBase64(pubKeyHash);
|
||||
for (var i = 0; i < this.addressHashes.length; i++) {
|
||||
|
@ -127,6 +184,12 @@ Bitcoin.Wallet = (function () {
|
|||
this.addKey(new Bitcoin.ECKey());
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a transaction to the wallet's processed transaction.
|
||||
*
|
||||
* This will add a transaction to the wallet, updating its balance and
|
||||
* available unspent outputs.
|
||||
*/
|
||||
Wallet.prototype.process = function (tx) {
|
||||
if (this.txIndex[tx.hash]) return;
|
||||
|
||||
|
|
Loading…
Reference in a new issue