Stefan Thomas
13 years ago
13 changed files with 1419 additions and 1419 deletions
@ -1,49 +1,49 @@ |
|||
Bitcoin.Address = function (bytes) { |
|||
if ("string" == typeof bytes) { |
|||
bytes = Bitcoin.Address.decodeString(bytes); |
|||
} |
|||
this.hash = bytes; |
|||
if ("string" == typeof bytes) { |
|||
bytes = Bitcoin.Address.decodeString(bytes); |
|||
} |
|||
this.hash = bytes; |
|||
|
|||
this.version = 0x00; |
|||
this.version = 0x00; |
|||
}; |
|||
|
|||
Bitcoin.Address.prototype.toString = function () { |
|||
// Get a copy of the hash
|
|||
var hash = this.hash.slice(0); |
|||
// Get a copy of the hash
|
|||
var hash = this.hash.slice(0); |
|||
|
|||
// Version
|
|||
hash.unshift(this.version); |
|||
// Version
|
|||
hash.unshift(this.version); |
|||
|
|||
var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); |
|||
var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); |
|||
|
|||
var bytes = hash.concat(checksum.slice(0,4)); |
|||
var bytes = hash.concat(checksum.slice(0,4)); |
|||
|
|||
return Bitcoin.Base58.encode(bytes); |
|||
return Bitcoin.Base58.encode(bytes); |
|||
}; |
|||
|
|||
Bitcoin.Address.prototype.getHashBase64 = function () { |
|||
return Crypto.util.bytesToBase64(this.hash); |
|||
return Crypto.util.bytesToBase64(this.hash); |
|||
}; |
|||
|
|||
Bitcoin.Address.decodeString = function (string) { |
|||
var bytes = Bitcoin.Base58.decode(string); |
|||
var bytes = Bitcoin.Base58.decode(string); |
|||
|
|||
var hash = bytes.slice(0, 21); |
|||
var hash = bytes.slice(0, 21); |
|||
|
|||
var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); |
|||
var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); |
|||
|
|||
if (checksum[0] != bytes[21] || |
|||
checksum[1] != bytes[22] || |
|||
checksum[2] != bytes[23] || |
|||
checksum[3] != bytes[24]) { |
|||
throw "Checksum validation failed!"; |
|||
} |
|||
if (checksum[0] != bytes[21] || |
|||
checksum[1] != bytes[22] || |
|||
checksum[2] != bytes[23] || |
|||
checksum[3] != bytes[24]) { |
|||
throw "Checksum validation failed!"; |
|||
} |
|||
|
|||
var version = hash.shift(); |
|||
var version = hash.shift(); |
|||
|
|||
if (version != 0) { |
|||
throw "Version "+version+" not supported!"; |
|||
} |
|||
if (version != 0) { |
|||
throw "Version "+version+" not supported!"; |
|||
} |
|||
|
|||
return hash; |
|||
return hash; |
|||
}; |
|||
|
@ -1,62 +1,62 @@ |
|||
Bitcoin.ECKey = (function () { |
|||
var ECDSA = Bitcoin.ECDSA; |
|||
var ecparams = getSECCurveByName("secp256k1"); |
|||
var rng = new SecureRandom(); |
|||
|
|||
var ECKey = function (input) { |
|||
if (!input) { |
|||
// Generate new key
|
|||
var n = ecparams.getN(); |
|||
this.priv = ECDSA.getBigRandom(n); |
|||
} else if (input instanceof BigInteger) { |
|||
// Input is a private key value
|
|||
this.priv = input; |
|||
} else if (Bitcoin.Util.isArray(input)) { |
|||
// Prepend zero byte to prevent interpretation as negative integer
|
|||
this.priv = BigInteger.fromByteArrayUnsigned(input); |
|||
} else if ("string" == typeof input) { |
|||
// Prepend zero byte to prevent interpretation as negative integer
|
|||
this.priv = BigInteger.fromByteArrayUnsigned(Crypto.util.base64ToBytes(input)); |
|||
} |
|||
}; |
|||
|
|||
ECKey.prototype.getPub = function () { |
|||
if (this.pub) return this.pub; |
|||
|
|||
return this.pub = ecparams.getG().multiply(this.priv).getEncoded(); |
|||
}; |
|||
|
|||
ECKey.prototype.getPubKeyHash = function () { |
|||
if (this.pubKeyHash) return this.pubKeyHash; |
|||
|
|||
return this.pubKeyHash = Bitcoin.Util.sha256ripe160(this.getPub()); |
|||
}; |
|||
|
|||
ECKey.prototype.getBitcoinAddress = function () { |
|||
var hash = this.getPubKeyHash(); |
|||
var addr = new Bitcoin.Address(hash); |
|||
return addr; |
|||
}; |
|||
var ECDSA = Bitcoin.ECDSA; |
|||
var ecparams = getSECCurveByName("secp256k1"); |
|||
var rng = new SecureRandom(); |
|||
|
|||
var ECKey = function (input) { |
|||
if (!input) { |
|||
// Generate new key
|
|||
var n = ecparams.getN(); |
|||
this.priv = ECDSA.getBigRandom(n); |
|||
} else if (input instanceof BigInteger) { |
|||
// Input is a private key value
|
|||
this.priv = input; |
|||
} else if (Bitcoin.Util.isArray(input)) { |
|||
// Prepend zero byte to prevent interpretation as negative integer
|
|||
this.priv = BigInteger.fromByteArrayUnsigned(input); |
|||
} else if ("string" == typeof input) { |
|||
// Prepend zero byte to prevent interpretation as negative integer
|
|||
this.priv = BigInteger.fromByteArrayUnsigned(Crypto.util.base64ToBytes(input)); |
|||
} |
|||
}; |
|||
|
|||
ECKey.prototype.getPub = function () { |
|||
if (this.pub) return this.pub; |
|||
|
|||
return this.pub = ecparams.getG().multiply(this.priv).getEncoded(); |
|||
}; |
|||
|
|||
ECKey.prototype.getPubKeyHash = function () { |
|||
if (this.pubKeyHash) return this.pubKeyHash; |
|||
|
|||
return this.pubKeyHash = Bitcoin.Util.sha256ripe160(this.getPub()); |
|||
}; |
|||
|
|||
ECKey.prototype.getBitcoinAddress = function () { |
|||
var hash = this.getPubKeyHash(); |
|||
var addr = new Bitcoin.Address(hash); |
|||
return addr; |
|||
}; |
|||
|
|||
ECKey.prototype.setPub = function (pub) { |
|||
this.pub = pub; |
|||
}; |
|||
|
|||
ECKey.prototype.toString = function (format) { |
|||
if (format === "base64") { |
|||
return Crypto.util.bytesToBase64(this.priv.toByteArrayUnsigned()); |
|||
} else { |
|||
return Crypto.util.bytesToHex(this.priv.toByteArrayUnsigned()); |
|||
} |
|||
}; |
|||
ECKey.prototype.toString = function (format) { |
|||
if (format === "base64") { |
|||
return Crypto.util.bytesToBase64(this.priv.toByteArrayUnsigned()); |
|||
} else { |
|||
return Crypto.util.bytesToHex(this.priv.toByteArrayUnsigned()); |
|||
} |
|||
}; |
|||
|
|||
ECKey.prototype.sign = function (hash) { |
|||
return ECDSA.sign(hash, this.priv); |
|||
}; |
|||
ECKey.prototype.sign = function (hash) { |
|||
return ECDSA.sign(hash, this.priv); |
|||
}; |
|||
|
|||
ECKey.prototype.verify = function (hash, sig) { |
|||
return ECDSA.verify(hash, sig, this.getPub()); |
|||
}; |
|||
ECKey.prototype.verify = function (hash, sig) { |
|||
return ECDSA.verify(hash, sig, this.getPub()); |
|||
}; |
|||
|
|||
return ECKey; |
|||
return ECKey; |
|||
})(); |
|||
|
@ -1,154 +1,154 @@ |
|||
(function () { |
|||
var Opcode = Bitcoin.Opcode = function (num) { |
|||
this.code = num; |
|||
}; |
|||
var Opcode = Bitcoin.Opcode = function (num) { |
|||
this.code = num; |
|||
}; |
|||
|
|||
Opcode.prototype.toString = function () { |
|||
return Opcode.reverseMap[this.code]; |
|||
}; |
|||
Opcode.prototype.toString = function () { |
|||
return Opcode.reverseMap[this.code]; |
|||
}; |
|||
|
|||
Opcode.map = { |
|||
// push value
|
|||
OP_0 : 0, |
|||
OP_FALSE : 0, |
|||
OP_PUSHDATA1 : 76, |
|||
OP_PUSHDATA2 : 77, |
|||
OP_PUSHDATA4 : 78, |
|||
OP_1NEGATE : 79, |
|||
OP_RESERVED : 80, |
|||
OP_1 : 81, |
|||
OP_TRUE : 81, |
|||
OP_2 : 82, |
|||
OP_3 : 83, |
|||
OP_4 : 84, |
|||
OP_5 : 85, |
|||
OP_6 : 86, |
|||
OP_7 : 87, |
|||
OP_8 : 88, |
|||
OP_9 : 89, |
|||
OP_10 : 90, |
|||
OP_11 : 91, |
|||
OP_12 : 92, |
|||
OP_13 : 93, |
|||
OP_14 : 94, |
|||
OP_15 : 95, |
|||
OP_16 : 96, |
|||
Opcode.map = { |
|||
// push value
|
|||
OP_0 : 0, |
|||
OP_FALSE : 0, |
|||
OP_PUSHDATA1 : 76, |
|||
OP_PUSHDATA2 : 77, |
|||
OP_PUSHDATA4 : 78, |
|||
OP_1NEGATE : 79, |
|||
OP_RESERVED : 80, |
|||
OP_1 : 81, |
|||
OP_TRUE : 81, |
|||
OP_2 : 82, |
|||
OP_3 : 83, |
|||
OP_4 : 84, |
|||
OP_5 : 85, |
|||
OP_6 : 86, |
|||
OP_7 : 87, |
|||
OP_8 : 88, |
|||
OP_9 : 89, |
|||
OP_10 : 90, |
|||
OP_11 : 91, |
|||
OP_12 : 92, |
|||
OP_13 : 93, |
|||
OP_14 : 94, |
|||
OP_15 : 95, |
|||
OP_16 : 96, |
|||
|
|||
// control
|
|||
OP_NOP : 97, |
|||
OP_VER : 98, |
|||
OP_IF : 99, |
|||
OP_NOTIF : 100, |
|||
OP_VERIF : 101, |
|||
OP_VERNOTIF : 102, |
|||
OP_ELSE : 103, |
|||
OP_ENDIF : 104, |
|||
OP_VERIFY : 105, |
|||
OP_RETURN : 106, |
|||
// control
|
|||
OP_NOP : 97, |
|||
OP_VER : 98, |
|||
OP_IF : 99, |
|||
OP_NOTIF : 100, |
|||
OP_VERIF : 101, |
|||
OP_VERNOTIF : 102, |
|||
OP_ELSE : 103, |
|||
OP_ENDIF : 104, |
|||
OP_VERIFY : 105, |
|||
OP_RETURN : 106, |
|||
|
|||
// stack ops
|
|||
OP_TOALTSTACK : 107, |
|||
OP_FROMALTSTACK : 108, |
|||
OP_2DROP : 109, |
|||
OP_2DUP : 110, |
|||
OP_3DUP : 111, |
|||
OP_2OVER : 112, |
|||
OP_2ROT : 113, |
|||
OP_2SWAP : 114, |
|||
OP_IFDUP : 115, |
|||
OP_DEPTH : 116, |
|||
OP_DROP : 117, |
|||
OP_DUP : 118, |
|||
OP_NIP : 119, |
|||
OP_OVER : 120, |
|||
OP_PICK : 121, |
|||
OP_ROLL : 122, |
|||
OP_ROT : 123, |
|||
OP_SWAP : 124, |
|||
OP_TUCK : 125, |
|||
// stack ops
|
|||
OP_TOALTSTACK : 107, |
|||
OP_FROMALTSTACK : 108, |
|||
OP_2DROP : 109, |
|||
OP_2DUP : 110, |
|||
OP_3DUP : 111, |
|||
OP_2OVER : 112, |
|||
OP_2ROT : 113, |
|||
OP_2SWAP : 114, |
|||
OP_IFDUP : 115, |
|||
OP_DEPTH : 116, |
|||
OP_DROP : 117, |
|||
OP_DUP : 118, |
|||
OP_NIP : 119, |
|||
OP_OVER : 120, |
|||
OP_PICK : 121, |
|||
OP_ROLL : 122, |
|||
OP_ROT : 123, |
|||
OP_SWAP : 124, |
|||
OP_TUCK : 125, |
|||
|
|||
// splice ops
|
|||
OP_CAT : 126, |
|||
OP_SUBSTR : 127, |
|||
OP_LEFT : 128, |
|||
OP_RIGHT : 129, |
|||
OP_SIZE : 130, |
|||
// splice ops
|
|||
OP_CAT : 126, |
|||
OP_SUBSTR : 127, |
|||
OP_LEFT : 128, |
|||
OP_RIGHT : 129, |
|||
OP_SIZE : 130, |
|||
|
|||
// bit logic
|
|||
OP_INVERT : 131, |
|||
OP_AND : 132, |
|||
OP_OR : 133, |
|||
OP_XOR : 134, |
|||
OP_EQUAL : 135, |
|||
OP_EQUALVERIFY : 136, |
|||
OP_RESERVED1 : 137, |
|||
OP_RESERVED2 : 138, |
|||
// bit logic
|
|||
OP_INVERT : 131, |
|||
OP_AND : 132, |
|||
OP_OR : 133, |
|||
OP_XOR : 134, |
|||
OP_EQUAL : 135, |
|||
OP_EQUALVERIFY : 136, |
|||
OP_RESERVED1 : 137, |
|||
OP_RESERVED2 : 138, |
|||
|
|||
// numeric
|
|||
OP_1ADD : 139, |
|||
OP_1SUB : 140, |
|||
OP_2MUL : 141, |
|||
OP_2DIV : 142, |
|||
OP_NEGATE : 143, |
|||
OP_ABS : 144, |
|||
OP_NOT : 145, |
|||
OP_0NOTEQUAL : 146, |
|||
// numeric
|
|||
OP_1ADD : 139, |
|||
OP_1SUB : 140, |
|||
OP_2MUL : 141, |
|||
OP_2DIV : 142, |
|||
OP_NEGATE : 143, |
|||
OP_ABS : 144, |
|||
OP_NOT : 145, |
|||
OP_0NOTEQUAL : 146, |
|||
|
|||
OP_ADD : 147, |
|||
OP_SUB : 148, |
|||
OP_MUL : 149, |
|||
OP_DIV : 150, |
|||
OP_MOD : 151, |
|||
OP_LSHIFT : 152, |
|||
OP_RSHIFT : 153, |
|||
OP_ADD : 147, |
|||
OP_SUB : 148, |
|||
OP_MUL : 149, |
|||
OP_DIV : 150, |
|||
OP_MOD : 151, |
|||
OP_LSHIFT : 152, |
|||
OP_RSHIFT : 153, |
|||
|
|||
OP_BOOLAND : 154, |
|||
OP_BOOLOR : 155, |
|||
OP_NUMEQUAL : 156, |
|||
OP_NUMEQUALVERIFY : 157, |
|||
OP_NUMNOTEQUAL : 158, |
|||
OP_LESSTHAN : 159, |
|||
OP_GREATERTHAN : 160, |
|||
OP_LESSTHANOREQUAL : 161, |
|||
OP_GREATERTHANOREQUAL : 162, |
|||
OP_MIN : 163, |
|||
OP_MAX : 164, |
|||
OP_BOOLAND : 154, |
|||
OP_BOOLOR : 155, |
|||
OP_NUMEQUAL : 156, |
|||
OP_NUMEQUALVERIFY : 157, |
|||
OP_NUMNOTEQUAL : 158, |
|||
OP_LESSTHAN : 159, |
|||
OP_GREATERTHAN : 160, |
|||
OP_LESSTHANOREQUAL : 161, |
|||
OP_GREATERTHANOREQUAL : 162, |
|||
OP_MIN : 163, |
|||
OP_MAX : 164, |
|||
|
|||
OP_WITHIN : 165, |
|||
OP_WITHIN : 165, |
|||
|
|||
// crypto
|
|||
OP_RIPEMD160 : 166, |
|||
OP_SHA1 : 167, |
|||
OP_SHA256 : 168, |
|||
OP_HASH160 : 169, |
|||
OP_HASH256 : 170, |
|||
OP_CODESEPARATOR : 171, |
|||
OP_CHECKSIG : 172, |
|||
OP_CHECKSIGVERIFY : 173, |
|||
OP_CHECKMULTISIG : 174, |
|||
OP_CHECKMULTISIGVERIFY : 175, |
|||
// crypto
|
|||
OP_RIPEMD160 : 166, |
|||
OP_SHA1 : 167, |
|||
OP_SHA256 : 168, |
|||
OP_HASH160 : 169, |
|||
OP_HASH256 : 170, |
|||
OP_CODESEPARATOR : 171, |
|||
OP_CHECKSIG : 172, |
|||
OP_CHECKSIGVERIFY : 173, |
|||
OP_CHECKMULTISIG : 174, |
|||
OP_CHECKMULTISIGVERIFY : 175, |
|||
|
|||
// expansion
|
|||
OP_NOP1 : 176, |
|||
OP_NOP2 : 177, |
|||
OP_NOP3 : 178, |
|||
OP_NOP4 : 179, |
|||
OP_NOP5 : 180, |
|||
OP_NOP6 : 181, |
|||
OP_NOP7 : 182, |
|||
OP_NOP8 : 183, |
|||
OP_NOP9 : 184, |
|||
OP_NOP10 : 185, |
|||
// expansion
|
|||
OP_NOP1 : 176, |
|||
OP_NOP2 : 177, |
|||
OP_NOP3 : 178, |
|||
OP_NOP4 : 179, |
|||
OP_NOP5 : 180, |
|||
OP_NOP6 : 181, |
|||
OP_NOP7 : 182, |
|||
OP_NOP8 : 183, |
|||
OP_NOP9 : 184, |
|||
OP_NOP10 : 185, |
|||
|
|||
// template matching params
|
|||
OP_PUBKEYHASH : 253, |
|||
OP_PUBKEY : 254, |
|||
OP_INVALIDOPCODE : 255, |
|||
}; |
|||
// template matching params
|
|||
OP_PUBKEYHASH : 253, |
|||
OP_PUBKEY : 254, |
|||
OP_INVALIDOPCODE : 255, |
|||
}; |
|||
|
|||
Opcode.reverseMap = []; |
|||
Opcode.reverseMap = []; |
|||
|
|||
for (var i in Opcode.map) { |
|||
Opcode.reverseMap[Opcode.map[i]] = i; |
|||
} |
|||
for (var i in Opcode.map) { |
|||
Opcode.reverseMap[Opcode.map[i]] = i; |
|||
} |
|||
})(); |
|||
|
@ -1,183 +1,183 @@ |
|||
(function () { |
|||
var Opcode = Bitcoin.Opcode; |
|||
|
|||
// Make opcodes available as pseudo-constants
|
|||
for (var i in Opcode.map) { |
|||
eval("var " + i + " = " + Opcode.map[i] + ";"); |
|||
} |
|||
|
|||
var Script = Bitcoin.Script = function (data) { |
|||
if (!data) { |
|||
this.buffer = []; |
|||
} else if ("string" == typeof data) { |
|||
this.buffer = Crypto.util.base64ToBytes(data); |
|||
} else if (Bitcoin.Util.isArray(data)) { |
|||
this.buffer = data; |
|||
} else if (data instanceof Script) { |
|||
this.buffer = data.buffer; |
|||
} else { |
|||
throw new Error("Invalid script"); |
|||
} |
|||
|
|||
this.parse(); |
|||
}; |
|||
|
|||
Script.prototype.parse = function () { |
|||
var self = this; |
|||
|
|||
this.chunks = []; |
|||
|
|||
// Cursor
|
|||
var i = 0; |
|||
|
|||
// Read n bytes and store result as a chunk
|
|||
function readChunk(n) { |
|||
self.chunks.push(self.buffer.slice(i, i + n)); |
|||
i += n; |
|||
}; |
|||
|
|||
while (i < this.buffer.length) { |
|||
var opcode = this.buffer[i++]; |
|||
if (opcode >= 0xF0) { |
|||
// Two byte opcode
|
|||
opcode = (opcode << 8) | this.buffer[i++]; |
|||
} |
|||
|
|||
var len; |
|||
if (opcode > 0 && opcode < OP_PUSHDATA1) { |
|||
// Read some bytes of data, opcode value is the length of data
|
|||
readChunk(opcode); |
|||
} else if (opcode == OP_PUSHDATA1) { |
|||
len = this.buffer[i++]; |
|||
readChunk(len); |
|||
} else if (opcode == OP_PUSHDATA2) { |
|||
len = (this.buffer[i++] << 8) | this.buffer[i++]; |
|||
readChunk(len); |
|||
} else if (opcode == OP_PUSHDATA4) { |
|||
len = (this.buffer[i++] << 24) | |
|||
(this.buffer[i++] << 16) | |
|||
(this.buffer[i++] << 8) | |
|||
this.buffer[i++]; |
|||
readChunk(len); |
|||
} else { |
|||
this.chunks.push(opcode); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
Script.prototype.getOutType = function () |
|||
{ |
|||
if (this.chunks.length == 5 && |
|||
this.chunks[0] == OP_DUP && |
|||
this.chunks[1] == OP_HASH160 && |
|||
this.chunks[3] == OP_EQUALVERIFY && |
|||
this.chunks[4] == OP_CHECKSIG) { |
|||
|
|||
// Transfer to Bitcoin address
|
|||
return 'Address'; |
|||
} else if (this.chunks.length == 2 && |
|||
this.chunks[1] == OP_CHECKSIG) { |
|||
|
|||
// Transfer to IP address
|
|||
return 'Pubkey'; |
|||
} else { |
|||
return 'Strange'; |
|||
} |
|||
}; |
|||
|
|||
Script.prototype.simpleOutPubKeyHash = function () |
|||
{ |
|||
switch (this.getOutType()) { |
|||
case 'Address': |
|||
return this.chunks[2]; |
|||
case 'Pubkey': |
|||
return Bitcoin.Util.sha256ripe160(this.chunks[0]); |
|||
default: |
|||
throw new Error("Encountered non-standard scriptPubKey"); |
|||
} |
|||
}; |
|||
|
|||
Script.prototype.getInType = function () |
|||
{ |
|||
if (this.chunks.length == 1) { |
|||
// Direct IP to IP transactions only have the public key in their scriptSig.
|
|||
return 'Pubkey'; |
|||
} else if (this.chunks.length == 2 && |
|||
Bitcoin.Util.isArray(this.chunks[0]) && |
|||
Bitcoin.Util.isArray(this.chunks[1])) { |
|||
return 'Address'; |
|||
} else { |
|||
console.log(this.chunks); |
|||
throw new Error("Encountered non-standard scriptSig"); |
|||
} |
|||
}; |
|||
|
|||
Script.prototype.simpleInPubKey = function () |
|||
{ |
|||
switch (this.getInType()) { |
|||
case 'Address': |
|||
return this.chunks[1]; |
|||
case 'Pubkey': |
|||
return this.chunks[0]; |
|||
default: |
|||
throw new Error("Encountered non-standard scriptSig"); |
|||
} |
|||
}; |
|||
|
|||
Script.prototype.simpleInPubKeyHash = function () |
|||
{ |
|||
return Bitcoin.Util.sha256ripe160(this.simpleInPubKey()); |
|||
}; |
|||
|
|||
Script.prototype.writeOp = function (opcode) |
|||
{ |
|||
this.buffer.push(opcode); |
|||
this.chunks.push(opcode); |
|||
}; |
|||
|
|||
Script.prototype.writeBytes = function (data) |
|||
{ |
|||
if (data.length < OP_PUSHDATA1) { |
|||
this.buffer.push(data.length); |
|||
} else if (data.length <= 0xff) { |
|||
this.buffer.push(OP_PUSHDATA1); |
|||
this.buffer.push(data.length); |
|||
} else if (data.length <= 0xffff) { |
|||
this.buffer.push(OP_PUSHDATA2); |
|||
this.buffer.push(data.length & 0xff); |
|||
this.buffer.push((data.length >>> 8) & 0xff); |
|||
} else { |
|||
this.buffer.push(OP_PUSHDATA4); |
|||
this.buffer.push(data.length & 0xff); |
|||
this.buffer.push((data.length >>> 8) & 0xff); |
|||
this.buffer.push((data.length >>> 16) & 0xff); |
|||
this.buffer.push((data.length >>> 24) & 0xff); |
|||
} |
|||
this.buffer = this.buffer.concat(data); |
|||
this.chunks.push(data); |
|||
}; |
|||
|
|||
Script.createOutputScript = function (address) |
|||
{ |
|||
var script = new Script(); |
|||
script.writeOp(OP_DUP); |
|||
script.writeOp(OP_HASH160); |
|||
script.writeBytes(address.hash); |
|||
script.writeOp(OP_EQUALVERIFY); |
|||
script.writeOp(OP_CHECKSIG); |
|||
return script; |
|||
}; |
|||
|
|||
Script.createInputScript = function (signature, pubKey) |
|||
{ |
|||
var script = new Script(); |
|||
script.writeBytes(signature); |
|||
script.writeBytes(pubKey); |
|||
return script; |
|||
}; |
|||
|
|||
Script.prototype.clone = function () |
|||
{ |
|||
return new Script(this.buffer); |
|||
}; |
|||
var Opcode = Bitcoin.Opcode; |
|||
|
|||
// Make opcodes available as pseudo-constants
|
|||
for (var i in Opcode.map) { |
|||
eval("var " + i + " = " + Opcode.map[i] + ";"); |
|||
} |
|||
|
|||
var Script = Bitcoin.Script = function (data) { |
|||
if (!data) { |
|||
this.buffer = []; |
|||
} else if ("string" == typeof data) { |
|||
this.buffer = Crypto.util.base64ToBytes(data); |
|||
} else if (Bitcoin.Util.isArray(data)) { |
|||
this.buffer = data; |
|||
} else if (data instanceof Script) { |
|||
this.buffer = data.buffer; |
|||
} else { |
|||
throw new Error("Invalid script"); |
|||
} |
|||
|
|||
this.parse(); |
|||
}; |
|||
|
|||
Script.prototype.parse = function () { |
|||
var self = this; |
|||
|
|||
this.chunks = []; |
|||
|
|||
// Cursor
|
|||
var i = 0; |
|||
|
|||
// Read n bytes and store result as a chunk
|
|||
function readChunk(n) { |
|||
self.chunks.push(self.buffer.slice(i, i + n)); |
|||
i += n; |
|||
}; |
|||
|
|||
while (i < this.buffer.length) { |
|||
var opcode = this.buffer[i++]; |
|||
if (opcode >= 0xF0) { |
|||
// Two byte opcode
|
|||
opcode = (opcode << 8) | this.buffer[i++]; |
|||
} |
|||
|
|||
var len; |
|||
if (opcode > 0 && opcode < OP_PUSHDATA1) { |
|||
// Read some bytes of data, opcode value is the length of data
|
|||
readChunk(opcode); |
|||
} else if (opcode == OP_PUSHDATA1) { |
|||
len = this.buffer[i++]; |
|||
readChunk(len); |
|||
} else if (opcode == OP_PUSHDATA2) { |
|||
len = (this.buffer[i++] << 8) | this.buffer[i++]; |
|||
readChunk(len); |
|||
} else if (opcode == OP_PUSHDATA4) { |
|||
len = (this.buffer[i++] << 24) | |
|||
(this.buffer[i++] << 16) | |
|||
(this.buffer[i++] << 8) | |
|||
this.buffer[i++]; |
|||
readChunk(len); |
|||
} else { |
|||
this.chunks.push(opcode); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
Script.prototype.getOutType = function () |
|||
{ |
|||
if (this.chunks.length == 5 && |
|||
this.chunks[0] == OP_DUP && |
|||
this.chunks[1] == OP_HASH160 && |
|||
this.chunks[3] == OP_EQUALVERIFY && |
|||
this.chunks[4] == OP_CHECKSIG) { |
|||
|
|||
// Transfer to Bitcoin address
|
|||
return 'Address'; |
|||
} else if (this.chunks.length == 2 && |
|||
this.chunks[1] == OP_CHECKSIG) { |
|||
|
|||
// Transfer to IP address
|
|||
return 'Pubkey'; |
|||
} else { |
|||
return 'Strange'; |
|||
} |
|||
}; |
|||
|
|||
Script.prototype.simpleOutPubKeyHash = function () |
|||
{ |
|||
switch (this.getOutType()) { |
|||
case 'Address': |
|||
return this.chunks[2]; |
|||
case 'Pubkey': |
|||
return Bitcoin.Util.sha256ripe160(this.chunks[0]); |
|||
default: |
|||
throw new Error("Encountered non-standard scriptPubKey"); |
|||
} |
|||
}; |
|||
|
|||
Script.prototype.getInType = function () |
|||
{ |
|||
if (this.chunks.length == 1) { |
|||
// Direct IP to IP transactions only have the public key in their scriptSig.
|
|||
return 'Pubkey'; |
|||
} else if (this.chunks.length == 2 && |
|||
Bitcoin.Util.isArray(this.chunks[0]) && |
|||
Bitcoin.Util.isArray(this.chunks[1])) { |
|||
return 'Address'; |
|||
} else { |
|||
console.log(this.chunks); |
|||
throw new Error("Encountered non-standard scriptSig"); |
|||
} |
|||
}; |
|||
|
|||
Script.prototype.simpleInPubKey = function () |
|||
{ |
|||
switch (this.getInType()) { |
|||
case 'Address': |
|||
return this.chunks[1]; |
|||
case 'Pubkey': |
|||
return this.chunks[0]; |
|||
default: |
|||
throw new Error("Encountered non-standard scriptSig"); |
|||
} |
|||
}; |
|||
|
|||
Script.prototype.simpleInPubKeyHash = function () |
|||
{ |
|||
return Bitcoin.Util.sha256ripe160(this.simpleInPubKey()); |
|||
}; |
|||
|
|||
Script.prototype.writeOp = function (opcode) |
|||
{ |
|||
this.buffer.push(opcode); |
|||
this.chunks.push(opcode); |
|||
}; |
|||
|
|||
Script.prototype.writeBytes = function (data) |
|||
{ |
|||
if (data.length < OP_PUSHDATA1) { |
|||
this.buffer.push(data.length); |
|||
} else if (data.length <= 0xff) { |
|||
this.buffer.push(OP_PUSHDATA1); |
|||
this.buffer.push(data.length); |
|||
} else if (data.length <= 0xffff) { |
|||
this.buffer.push(OP_PUSHDATA2); |
|||
this.buffer.push(data.length & 0xff); |
|||
this.buffer.push((data.length >>> 8) & 0xff); |
|||
} else { |
|||
this.buffer.push(OP_PUSHDATA4); |
|||
this.buffer.push(data.length & 0xff); |
|||
this.buffer.push((data.length >>> 8) & 0xff); |
|||
this.buffer.push((data.length >>> 16) & 0xff); |
|||
this.buffer.push((data.length >>> 24) & 0xff); |
|||
} |
|||
this.buffer = this.buffer.concat(data); |
|||
this.chunks.push(data); |
|||
}; |
|||
|
|||
Script.createOutputScript = function (address) |
|||
{ |
|||
var script = new Script(); |
|||
script.writeOp(OP_DUP); |
|||
script.writeOp(OP_HASH160); |
|||
script.writeBytes(address.hash); |
|||
script.writeOp(OP_EQUALVERIFY); |
|||
script.writeOp(OP_CHECKSIG); |
|||
return script; |
|||
}; |
|||
|
|||
Script.createInputScript = function (signature, pubKey) |
|||
{ |
|||
var script = new Script(); |
|||
script.writeBytes(signature); |
|||
script.writeBytes(pubKey); |
|||
return script; |
|||
}; |
|||
|
|||
Script.prototype.clone = function () |
|||
{ |
|||
return new Script(this.buffer); |
|||
}; |
|||
})(); |
|||
|
@ -1,245 +1,245 @@ |
|||
Bitcoin.Wallet = (function () { |
|||
var Script = Bitcoin.Script, |
|||
TransactionIn = Bitcoin.TransactionIn, |
|||
TransactionOut = Bitcoin.TransactionOut; |
|||
|
|||
var Wallet = function () { |
|||
// Keychain
|
|||
var keys = []; |
|||
this.addressHashes = []; |
|||
|
|||
// Transaction data
|
|||
this.txIndex = {}; |
|||
this.unspentOuts = []; |
|||
|
|||
// Other fields
|
|||
this.addressPointer = 0; |
|||
|
|||
this.addKey = function (key, pub) { |
|||
if (!(key instanceof Bitcoin.ECKey)) { |
|||
key = new Bitcoin.ECKey(key); |
|||
} |
|||
keys.push(key); |
|||
|
|||
if (pub) { |
|||
if ("string" === typeof pub) { |
|||
pub = Crypto.util.base64ToBytes(pub); |
|||
} |
|||
key.pub = pub; |
|||
} |
|||
|
|||
this.addressHashes.push(key.getBitcoinAddress().getHashBase64()); |
|||
}; |
|||
|
|||
this.addKeys = function (keys, pubs) { |
|||
if ("string" === typeof keys) { |
|||
keys = keys.split(','); |
|||
} |
|||
if ("string" === typeof pubs) { |
|||
pubs = pubs.split(','); |
|||
} |
|||
var i; |
|||
if (Array.isArray(pubs) && keys.length == pubs.length) { |
|||
for (i = 0; i < keys.length; i++) { |
|||
this.addKey(keys[i], pubs[i]); |
|||
} |
|||
} else { |
|||
for (i = 0; i < keys.length; i++) { |
|||
this.addKey(keys[i]); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
this.getKeys = function () { |
|||
var serializedWallet = []; |
|||
|
|||
for (var i = 0; i < keys.length; i++) { |
|||
serializedWallet.push(keys[i].toString('base64')); |
|||
} |
|||
|
|||
return serializedWallet; |
|||
}; |
|||
|
|||
this.getPubKeys = function () { |
|||
var pubs = []; |
|||
|
|||
for (var i = 0; i < keys.length; i++) { |
|||
pubs.push(Crypto.util.bytesToBase64(keys[i].getPub())); |
|||
} |
|||
|
|||
return pubs; |
|||
}; |
|||
|
|||
this.clear = function () { |
|||
keys = []; |
|||
}; |
|||
|
|||
this.getLength = function () { |
|||
return keys.length; |
|||
}; |
|||
|
|||
this.getAllAddresses = function () { |
|||
var addresses = []; |
|||
for (var i = 0; i < keys.length; i++) { |
|||
addresses.push(keys[i].getBitcoinAddress()); |
|||
} |
|||
return addresses; |
|||
}; |
|||
|
|||
this.getCurAddress = function () { |
|||
if (keys[this.addressPointer]) { |
|||
return keys[this.addressPointer].getBitcoinAddress(); |
|||
} else { |
|||
return null; |
|||
} |
|||
}; |
|||
|
|||
this.getNextAddress = function () { |
|||
this.addressPointer++; |
|||
if(!keys[this.addressPointer]) { |
|||
this.generateAddress(); |
|||
} |
|||
return keys[this.addressPointer].getBitcoinAddress(); |
|||
}; |
|||
|
|||
this.signWithKey = function (pubKeyHash, hash) { |
|||
pubKeyHash = Crypto.util.bytesToBase64(pubKeyHash); |
|||
for (var i = 0; i < this.addressHashes.length; i++) { |
|||
if (this.addressHashes[i] == pubKeyHash) { |
|||
return keys[i].sign(hash); |
|||
} |
|||
} |
|||
throw new Error("Missing key for signature"); |
|||
}; |
|||
|
|||
this.getPubKeyFromHash = function (pubKeyHash) { |
|||
pubKeyHash = Crypto.util.bytesToBase64(pubKeyHash); |
|||
for (var i = 0; i < this.addressHashes.length; i++) { |
|||
if (this.addressHashes[i] == pubKeyHash) { |
|||
return keys[i].getPub(); |
|||
} |
|||
} |
|||
throw new Error("Hash unknown"); |
|||
}; |
|||
}; |
|||
|
|||
Wallet.prototype.generateAddress = function () { |
|||
this.addKey(new Bitcoin.ECKey()); |
|||
}; |
|||
|
|||
Wallet.prototype.process = function (tx) { |
|||
if (this.txIndex[tx.hash]) return; |
|||
|
|||
var j; |
|||
var k; |
|||
var hash; |
|||
// Gather outputs
|
|||
for (j = 0; j < tx.outs.length; j++) { |
|||
var txout = new TransactionOut(tx.outs[j]); |
|||
hash = Crypto.util.bytesToBase64(txout.script.simpleOutPubKeyHash()); |
|||
for (k = 0; k < this.addressHashes.length; k++) { |
|||
if (this.addressHashes[k] === hash) { |
|||
this.unspentOuts.push({tx: tx, index: j, out: txout}); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Remove spent outputs
|
|||
for (j = 0; j < tx.ins.length; j++) { |
|||
var txin = new TransactionIn(tx.ins[j]); |
|||
var pubkey = txin.script.simpleInPubKey(); |
|||
hash = Crypto.util.bytesToBase64(Bitcoin.Util.sha256ripe160(pubkey)); |
|||
for (k = 0; k < this.addressHashes.length; k++) { |
|||
if (this.addressHashes[k] === hash) { |
|||
for (var l = 0; l < this.unspentOuts.length; l++) { |
|||
if (txin.outpoint.hash == this.unspentOuts[l].tx.hash && |
|||
txin.outpoint.index == this.unspentOuts[l].index) { |
|||
this.unspentOuts.splice(l, 1); |
|||
} |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
var Script = Bitcoin.Script, |
|||
TransactionIn = Bitcoin.TransactionIn, |
|||
TransactionOut = Bitcoin.TransactionOut; |
|||
|
|||
var Wallet = function () { |
|||
// Keychain
|
|||
var keys = []; |
|||
this.addressHashes = []; |
|||
|
|||
// Transaction data
|
|||
this.txIndex = {}; |
|||
this.unspentOuts = []; |
|||
|
|||
// Other fields
|
|||
this.addressPointer = 0; |
|||
|
|||
this.addKey = function (key, pub) { |
|||
if (!(key instanceof Bitcoin.ECKey)) { |
|||
key = new Bitcoin.ECKey(key); |
|||
} |
|||
keys.push(key); |
|||
|
|||
if (pub) { |
|||
if ("string" === typeof pub) { |
|||
pub = Crypto.util.base64ToBytes(pub); |
|||
} |
|||
key.pub = pub; |
|||
} |
|||
|
|||
// Index transaction
|
|||
this.txIndex[tx.hash] = tx; |
|||
this.addressHashes.push(key.getBitcoinAddress().getHashBase64()); |
|||
}; |
|||
|
|||
Wallet.prototype.getBalance = function () { |
|||
var balance = BigInteger.valueOf(0); |
|||
for (var i = 0; i < this.unspentOuts.length; i++) { |
|||
var txout = this.unspentOuts[i].out; |
|||
balance = balance.add(Bitcoin.Util.valueToBigInt(txout.value)); |
|||
this.addKeys = function (keys, pubs) { |
|||
if ("string" === typeof keys) { |
|||
keys = keys.split(','); |
|||
} |
|||
if ("string" === typeof pubs) { |
|||
pubs = pubs.split(','); |
|||
} |
|||
var i; |
|||
if (Array.isArray(pubs) && keys.length == pubs.length) { |
|||
for (i = 0; i < keys.length; i++) { |
|||
this.addKey(keys[i], pubs[i]); |
|||
} |
|||
return balance; |
|||
}; |
|||
|
|||
Wallet.prototype.createSend = function (address, sendValue, feeValue) { |
|||
var selectedOuts = []; |
|||
var txValue = sendValue.add(feeValue); |
|||
var availableValue = BigInteger.ZERO; |
|||
var i; |
|||
for (i = 0; i < this.unspentOuts.length; i++) { |
|||
selectedOuts.push(this.unspentOuts[i]); |
|||
availableValue = availableValue.add(Bitcoin.Util.valueToBigInt(this.unspentOuts[i].out.value)); |
|||
|
|||
if (availableValue.compareTo(txValue) >= 0) break; |
|||
} else { |
|||
for (i = 0; i < keys.length; i++) { |
|||
this.addKey(keys[i]); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
if (availableValue.compareTo(txValue) < 0) { |
|||
throw new Error('Insufficient funds.'); |
|||
} |
|||
|
|||
|
|||
var changeValue = availableValue.subtract(txValue); |
|||
this.getKeys = function () { |
|||
var serializedWallet = []; |
|||
|
|||
var sendTx = new Bitcoin.Transaction(); |
|||
for (var i = 0; i < keys.length; i++) { |
|||
serializedWallet.push(keys[i].toString('base64')); |
|||
} |
|||
|
|||
for (i = 0; i < selectedOuts.length; i++) { |
|||
sendTx.addInput(selectedOuts[i].tx, selectedOuts[i].index); |
|||
} |
|||
return serializedWallet; |
|||
}; |
|||
|
|||
sendTx.addOutput(address, sendValue); |
|||
if (changeValue.compareTo(BigInteger.ZERO) > 0) { |
|||
sendTx.addOutput(this.getNextAddress(), changeValue); |
|||
} |
|||
this.getPubKeys = function () { |
|||
var pubs = []; |
|||
|
|||
var hashType = 1; // SIGHASH_ALL
|
|||
for (var i = 0; i < keys.length; i++) { |
|||
pubs.push(Crypto.util.bytesToBase64(keys[i].getPub())); |
|||
} |
|||
|
|||
for (i = 0; i < sendTx.ins.length; i++) { |
|||
var hash = sendTx.hashTransactionForSignature(selectedOuts[i].out.script, i, hashType); |
|||
var pubKeyHash = selectedOuts[i].out.script.simpleOutPubKeyHash(); |
|||
var signature = this.signWithKey(pubKeyHash, hash); |
|||
return pubs; |
|||
}; |
|||
|
|||
// Append hash type
|
|||
signature.push(parseInt(hashType, 10)); |
|||
this.clear = function () { |
|||
keys = []; |
|||
}; |
|||
|
|||
sendTx.ins[i].script = Script.createInputScript(signature, this.getPubKeyFromHash(pubKeyHash)); |
|||
} |
|||
this.getLength = function () { |
|||
return keys.length; |
|||
}; |
|||
|
|||
return sendTx; |
|||
this.getAllAddresses = function () { |
|||
var addresses = []; |
|||
for (var i = 0; i < keys.length; i++) { |
|||
addresses.push(keys[i].getBitcoinAddress()); |
|||
} |
|||
return addresses; |
|||
}; |
|||
|
|||
Wallet.prototype.clearTransactions = function () { |
|||
this.txIndex = {}; |
|||
this.unspentOuts = []; |
|||
this.getCurAddress = function () { |
|||
if (keys[this.addressPointer]) { |
|||
return keys[this.addressPointer].getBitcoinAddress(); |
|||
} else { |
|||
return null; |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Check to see if a pubKeyHash belongs to this wallet. |
|||
*/ |
|||
Wallet.prototype.hasHash = function (hash) { |
|||
if (Bitcoin.Util.isArray(hash)) hash = Crypto.util.bytesToBase64(hash); |
|||
this.getNextAddress = function () { |
|||
this.addressPointer++; |
|||
if(!keys[this.addressPointer]) { |
|||
this.generateAddress(); |
|||
} |
|||
return keys[this.addressPointer].getBitcoinAddress(); |
|||
}; |
|||
|
|||
// TODO: Just create an object with base64 hashes as keys for faster lookup
|
|||
for (var k = 0; k < this.addressHashes.length; k++) { |
|||
if (this.addressHashes[k] === hash) return true; |
|||
this.signWithKey = function (pubKeyHash, hash) { |
|||
pubKeyHash = Crypto.util.bytesToBase64(pubKeyHash); |
|||
for (var i = 0; i < this.addressHashes.length; i++) { |
|||
if (this.addressHashes[i] == pubKeyHash) { |
|||
return keys[i].sign(hash); |
|||
} |
|||
return false; |
|||
} |
|||
throw new Error("Missing key for signature"); |
|||
}; |
|||
|
|||
return Wallet; |
|||
this.getPubKeyFromHash = function (pubKeyHash) { |
|||
pubKeyHash = Crypto.util.bytesToBase64(pubKeyHash); |
|||
for (var i = 0; i < this.addressHashes.length; i++) { |
|||
if (this.addressHashes[i] == pubKeyHash) { |
|||
return keys[i].getPub(); |
|||
} |
|||
} |
|||
throw new Error("Hash unknown"); |
|||
}; |
|||
}; |
|||
|
|||
Wallet.prototype.generateAddress = function () { |
|||
this.addKey(new Bitcoin.ECKey()); |
|||
}; |
|||
|
|||
Wallet.prototype.process = function (tx) { |
|||
if (this.txIndex[tx.hash]) return; |
|||
|
|||
var j; |
|||
var k; |
|||
var hash; |
|||
// Gather outputs
|
|||
for (j = 0; j < tx.outs.length; j++) { |
|||
var txout = new TransactionOut(tx.outs[j]); |
|||
hash = Crypto.util.bytesToBase64(txout.script.simpleOutPubKeyHash()); |
|||
for (k = 0; k < this.addressHashes.length; k++) { |
|||
if (this.addressHashes[k] === hash) { |
|||
this.unspentOuts.push({tx: tx, index: j, out: txout}); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Remove spent outputs
|
|||
for (j = 0; j < tx.ins.length; j++) { |
|||
var txin = new TransactionIn(tx.ins[j]); |
|||
var pubkey = txin.script.simpleInPubKey(); |
|||
hash = Crypto.util.bytesToBase64(Bitcoin.Util.sha256ripe160(pubkey)); |
|||
for (k = 0; k < this.addressHashes.length; k++) { |
|||
if (this.addressHashes[k] === hash) { |
|||
for (var l = 0; l < this.unspentOuts.length; l++) { |
|||
if (txin.outpoint.hash == this.unspentOuts[l].tx.hash && |
|||
txin.outpoint.index == this.unspentOuts[l].index) { |
|||
this.unspentOuts.splice(l, 1); |
|||
} |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Index transaction
|
|||
this.txIndex[tx.hash] = tx; |
|||
}; |
|||
|
|||
Wallet.prototype.getBalance = function () { |
|||
var balance = BigInteger.valueOf(0); |
|||
for (var i = 0; i < this.unspentOuts.length; i++) { |
|||
var txout = this.unspentOuts[i].out; |
|||
balance = balance.add(Bitcoin.Util.valueToBigInt(txout.value)); |
|||
} |
|||
return balance; |
|||
}; |
|||
|
|||
Wallet.prototype.createSend = function (address, sendValue, feeValue) { |
|||
var selectedOuts = []; |
|||
var txValue = sendValue.add(feeValue); |
|||
var availableValue = BigInteger.ZERO; |
|||
var i; |
|||
for (i = 0; i < this.unspentOuts.length; i++) { |
|||
selectedOuts.push(this.unspentOuts[i]); |
|||
availableValue = availableValue.add(Bitcoin.Util.valueToBigInt(this.unspentOuts[i].out.value)); |
|||
|
|||
if (availableValue.compareTo(txValue) >= 0) break; |
|||
} |
|||
|
|||
if (availableValue.compareTo(txValue) < 0) { |
|||
throw new Error('Insufficient funds.'); |
|||
} |
|||
|
|||
|
|||
var changeValue = availableValue.subtract(txValue); |
|||
|
|||
var sendTx = new Bitcoin.Transaction(); |
|||
|
|||
for (i = 0; i < selectedOuts.length; i++) { |
|||
sendTx.addInput(selectedOuts[i].tx, selectedOuts[i].index); |
|||
} |
|||
|
|||
sendTx.addOutput(address, sendValue); |
|||
if (changeValue.compareTo(BigInteger.ZERO) > 0) { |
|||
sendTx.addOutput(this.getNextAddress(), changeValue); |
|||
} |
|||
|
|||
var hashType = 1; // SIGHASH_ALL
|
|||
|
|||
for (i = 0; i < sendTx.ins.length; i++) { |
|||
var hash = sendTx.hashTransactionForSignature(selectedOuts[i].out.script, i, hashType); |
|||
var pubKeyHash = selectedOuts[i].out.script.simpleOutPubKeyHash(); |
|||
var signature = this.signWithKey(pubKeyHash, hash); |
|||
|
|||
// Append hash type
|
|||
signature.push(parseInt(hashType, 10)); |
|||
|
|||
sendTx.ins[i].script = Script.createInputScript(signature, this.getPubKeyFromHash(pubKeyHash)); |
|||
} |
|||
|
|||
return sendTx; |
|||
}; |
|||
|
|||
Wallet.prototype.clearTransactions = function () { |
|||
this.txIndex = {}; |
|||
this.unspentOuts = []; |
|||
}; |
|||
|
|||
/** |
|||
* Check to see if a pubKeyHash belongs to this wallet. |
|||
*/ |
|||
Wallet.prototype.hasHash = function (hash) { |
|||
if (Bitcoin.Util.isArray(hash)) hash = Crypto.util.bytesToBase64(hash); |
|||
|
|||
// TODO: Just create an object with base64 hashes as keys for faster lookup
|
|||
for (var k = 0; k < this.addressHashes.length; k++) { |
|||
if (this.addressHashes[k] === hash) return true; |
|||
} |
|||
return false; |
|||
}; |
|||
|
|||
return Wallet; |
|||
})(); |
|||
|
|||
|
Loading…
Reference in new issue