Added some transaction methods, and removed all internal use of base64

This commit is contained in:
vub 2013-10-07 15:27:19 -04:00
parent 9922864da4
commit e43d23235b
10 changed files with 107 additions and 41 deletions

6
bitcoinjs-min.js vendored

File diff suppressed because one or more lines are too long

View file

@ -35,8 +35,8 @@ Address.prototype.toString = function () {
return base58.checkEncode(hash,this.version);
};
Address.prototype.getHashBase64 = function () {
return conv.bytesToBase64(this.hash);
Address.prototype.getHash = function () {
return conv.bytesToHex(this.hash);
};
Address.getVersion = function(string) {

View file

@ -2,6 +2,7 @@
// https://en.bitcoin.it/wiki/Base58Check_encoding
var BigInteger = require('./jsbn/jsbn');
var Crypto = require('./crypto-js/crypto');
var alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
var base = BigInteger.valueOf(58);
@ -36,6 +37,10 @@ module.exports.encode = function (input) {
return chars.reverse().join('');
},
module.exports.encodeHex = function (input) {
return Crypto.util.bytesToHex(module.exports.encode(input));
}
// decode a base58 string into a byte array
// input should be a base58 encoded string
// @return Array
@ -76,16 +81,24 @@ module.exports.decode = function (input) {
return bytes;
}
module.exports.checkEncode = function(x,vbyte,format) {
module.exports.decodeHex = function (input) {
return module.exports.decode(Crypto.util.hexToBytes(input));
}
module.exports.checkEncode = function(input, vbyte) {
vbyte = vbyte || 0;
var front = [vbyte].concat(x);
var front = [vbyte].concat(input);
var checksum = Crypto.SHA256(Crypto.SHA256(front, {asBytes: true}), {asBytes: true})
.slice(0,4);
return module.exports.encode(front.concat(checksum));
}
module.exports.checkDecode = function(x) {
var bytes = module.exports.decode(x),
module.exports.checkEncodeHex = function (input, vbyte) {
return Crypto.util.bytesToHex(module.exports.encode(input));
}
module.exports.checkDecode = function(input) {
var bytes = module.exports.decode(input),
front = bytes.slice(0,bytes.length-4),
back = bytes.slice(bytes.length-4);
var checksum = Crypto.SHA256(Crypto.SHA256(front,{asBytes: true}), {asBytes: true})
@ -98,4 +111,8 @@ module.exports.checkDecode = function(x) {
return o;
}
module.exports.checkDecodeHex = function (input) {
return module.exports.checkDecode(Crypto.util.hexToBytes(input));
}

View file

@ -22,9 +22,9 @@
buffer = buffer.concat(numToVarInt(tx.ins.length));
for (var i = 0; i < tx.ins.length; i++) {
var txin = tx.ins[i];
buffer = buffer.concat(Crypto.util.base64ToBytes(txin.outpoint.hash));
buffer = buffer.concat(Crypto.util.hexToBytes(txin.outpoint.hash));
buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(txin.index)]));
var scriptBytes = Crypto.util.base64ToBytes(txin.script);
var scriptBytes = Crypto.util.hexToBytes(txin.script);
buffer = buffer.concat(numToVarInt(scriptBytes.length));
buffer = buffer.concat(scriptBytes);
buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(txin.sequence)]));
@ -35,7 +35,7 @@
var valueHex = (new BigInteger(txout.value, 10)).toString(16);
while (valueHex.length < 16) valueHex = "0" + valueHex;
buffer = buffer.concat(Crypto.util.hexToBytes(valueHex));
var scriptBytes = Crypto.util.base64ToBytes(txout.script);
var scriptBytes = Crypto.util.hexToBytes(txout.script);
buffer = buffer.concat(numToVarInt(scriptBytes.length));
buffer = buffer.concat(scriptBytes);
}
@ -64,9 +64,9 @@
// Blank out other inputs' signatures
for (var i = 0; i < txTmp.ins.length; i++) {
txTmp.ins[i].script = Crypto.util.bytesToBase64([]);
txTmp.ins[i].script = Crypto.util.bytesToHex([]);
}
txTmp.ins[inIndex].script = Crypto.util.bytesToBase64(scriptCode);
txTmp.ins[inIndex].script = Crypto.util.bytesToHex(scriptCode);
// Blank out some of the outputs
if ((hashType & 0x1f) == SIGHASH_NONE) {

View file

@ -40,11 +40,13 @@ var ECKey = function (input) {
this.compressed = true;
} else {
// hex string?
// //wtf is base64 here for?
// Prepend zero byte to prevent interpretation as negative integer
this.priv = BigInteger.fromByteArrayUnsigned(conv.base64ToBytes(input));
this.priv = BigInteger.fromByteArrayUnsigned(Crypto.util.hexToBytes(input));
}
}
else if (input.constructor == [].constructor) {
this.priv = BigInteger.fromByteArrayUnsigned(input);
}
};
// TODO(shtylman) methods
@ -116,8 +118,8 @@ ECKey.prototype.setPub = function (pub) {
};
ECKey.prototype.toString = function (format) {
if (format === "base64") {
return conv.bytesToBase64(this.priv.toByteArrayUnsigned());
if (format === "base58") {
return base58.checkEncode(this.priv.toByteArrayUnsigned(),128);
} else {
return Crypto.util.bytesToHex(this.priv.toByteArrayUnsigned());
}

View file

@ -27,6 +27,7 @@ module.exports = {
Key: require('./eckey'),
Message: require('./message'),
BigInteger: require('./jsbn/jsbn'),
Crypto: require('./crypto-js/crypto'),
Script: require('./script'),
Opcode: require('./opcode'),
Transaction: require('./transaction').Transaction,

View file

@ -49,11 +49,11 @@ Message.signMessage = function (key, message, compressed) {
sig = [i].concat(rBa).concat(sBa);
return conv.bytesToBase64(sig);
return conv.bytesToHex(sig);
};
Message.verifyMessage = function (address, sig, message) {
sig = conv.base64ToBytes(sig);
sig = conv.hexToBytes(sig);
sig = ecdsa.parseSigCompact(sig);
var hash = Message.getHash(message);

View file

@ -6,7 +6,7 @@ var Script = function (data) {
if (!data) {
this.buffer = [];
} else if ("string" == typeof data) {
this.buffer = Crypto.util.base64ToBytes(data);
this.buffer = Crypto.util.hexToBytes(data);
} else if (util.isArray(data)) {
this.buffer = data;
} else if (data instanceof Script) {

View file

@ -85,7 +85,7 @@ Transaction.prototype.addOutput = function (address, value) {
if (value instanceof BigInteger) {
value = value.toByteArrayUnsigned().reverse();
while (value.length < 8) value.push(0);
} else if (Bitcoin.Util.isArray(value)) {
} else if (util.isArray(value)) {
// Nothing to do
}
@ -351,7 +351,7 @@ Transaction.prototype.getTotalOutValue = function () {
var totalValue = BigInteger.ZERO;
for (var j = 0; j < this.outs.length; j++) {
var txout = this.outs[j];
totalValue = totalValue.add(Bitcoin.Util.valueToBigInt(txout.value));
totalValue = totalValue.add(util.valueToBigInt(txout.value));
}
return totalValue;
};
@ -382,9 +382,9 @@ Transaction.prototype.calcImpact = function (wallet) {
var valueOut = BigInteger.ZERO;
for (var j = 0; j < this.outs.length; j++) {
var txout = this.outs[j];
var hash = Crypto.util.bytesToBase64(txout.script.simpleOutPubKeyHash());
var hash = Crypto.util.bytesToHex(txout.script.simpleOutPubKeyHash());
if (wallet.hasHash(hash)) {
valueOut = valueOut.add(Bitcoin.Util.valueToBigInt(txout.value));
valueOut = valueOut.add(util.valueToBigInt(txout.value));
}
}
@ -392,11 +392,11 @@ Transaction.prototype.calcImpact = function (wallet) {
var valueIn = BigInteger.ZERO;
for (var j = 0; j < this.ins.length; j++) {
var txin = this.ins[j];
var hash = Crypto.util.bytesToBase64(txin.script.simpleInPubKeyHash());
var hash = Crypto.util.bytesToHex(txin.script.simpleInPubKeyHash());
if (wallet.hasHash(hash)) {
var fromTx = wallet.txIndex[txin.outpoint.hash];
if (fromTx) {
valueIn = valueIn.add(Bitcoin.Util.valueToBigInt(fromTx.outs[txin.outpoint.index].value));
valueIn = valueIn.add(util.valueToBigInt(fromTx.outs[txin.outpoint.index].value));
}
}
}
@ -412,6 +412,11 @@ Transaction.prototype.calcImpact = function (wallet) {
};
}
};
/**
* Converts a serialized transaction into a transaction object
*/
Transaction.deserialize = function(buffer) {
var pos = 0;
var readAsInt = function(bytes) {
@ -443,7 +448,7 @@ Transaction.deserialize = function(buffer) {
for (var i = 0; i < ins; i++) {
obj.ins.push({
outpoint: {
hash: Bitcoin.Util.bytesToBase64(readBytes(32)),
hash: util.bytesToHex(readBytes(32)),
index: readAsInt(4)
},
script: new Script(readVarString()),
@ -461,6 +466,47 @@ Transaction.deserialize = function(buffer) {
return new Transaction(obj);
}
/**
* Signs a standard output at some index with the given key
*/
Transaction.prototype.sign = function(index, key, type) {
type = type || SIGHASH_ALL;
key = new Bitcoin.ECKey(key);
var pub = key.getPub(),
hash160 = Bitcoin.Util.sha256ripe160(pub),
script = Bitcoin.Script.createOutputScript(new Bitcoin.Address(hash160)),
hash = this.hashTransactionForSignature( script, index, type),
sig = key.sign(hash).concat([type]);
this.ins[i].script = Bitcoin.Script.createInputScript(sig,pub);
}
/**
* Signs a P2SH output at some index with the given key
*/
Transaction.prototype.p2shsign = function(index, script, key, type) {
script = new Bitcoin.Script(script);
key = new Bitcoin.ECKey(key);
type = type || SIGHASH_ALL;
var hash = this.hashTransactionForSignature(script, index, type),
sig = key.sign(hash).concat([type]);
return sig;
}
Transaction.prototype.multisign = Transaction.prototype.p2shsign;
// In progress
/*Transaction.prototype.validateInput = function(index,script,sig,pub) {
script = new Bitcoin.Script(script);
scriptBytes = bw.h2b(script),
scriptObj = new Bitcoin.Script(scriptBytes),
hash = txObj.hashTransactionForSignature(scriptObj,i,1);
return Bitcoin.ECDSA.verify(hash, bw.h2b(sig),
bw.h2b(pub));
}*/
var TransactionIn = function (data)
{

View file

@ -44,12 +44,12 @@ var Wallet = function () {
if (pub) {
if ("string" === typeof pub) {
pub = Crypto.util.base64ToBytes(pub);
pub = Crypto.util.hexToBytes(pub);
}
key.setPub(pub);
}
this.addressHashes.push(key.getBitcoinAddress().getHashBase64());
this.addressHashes.push(key.getBitcoinAddress().getHash());
};
/**
@ -77,13 +77,13 @@ var Wallet = function () {
/**
* Get the key chain.
*
* Returns an array of base64-encoded private values.
* Returns an array of hex-encoded private values.
*/
this.getKeys = function () {
var serializedWallet = [];
for (var i = 0; i < keys.length; i++) {
serializedWallet.push(keys[i].toString('base64'));
serializedWallet.push(keys[i].toString());
}
return serializedWallet;
@ -92,13 +92,13 @@ var Wallet = function () {
/**
* Get the public keys.
*
* Returns an array of base64-encoded public keys.
* Returns an array of hex-encoded public keys.
*/
this.getPubKeys = function () {
var pubs = [];
for (var i = 0; i < keys.length; i++) {
pubs.push(Crypto.util.bytesToBase64(keys[i].getPub()));
pubs.push(Crypto.util.bytesToHex(keys[i].getPub()));
}
return pubs;
@ -171,7 +171,7 @@ var Wallet = function () {
* to be signed as the second parameter.
*/
this.signWithKey = function (pubKeyHash, hash) {
pubKeyHash = conv.bytesToBase64(pubKeyHash);
pubKeyHash = conv.bytesToHex(pubKeyHash);
for (var i = 0; i < this.addressHashes.length; i++) {
if (this.addressHashes[i] == pubKeyHash) {
return keys[i].sign(hash);
@ -187,7 +187,7 @@ var Wallet = function () {
* wallet.
*/
this.getPubKeyFromHash = function (pubKeyHash) {
pubKeyHash = conv.bytesToBase64(pubKeyHash);
pubKeyHash = conv.bytesToHex(pubKeyHash);
for (var i = 0; i < this.addressHashes.length; i++) {
if (this.addressHashes[i] == pubKeyHash) {
return keys[i].getPub();
@ -222,8 +222,8 @@ Wallet.prototype.process = function (tx) {
for (j = 0; j < tx.out.length; j++) {
var raw_tx = tx.out[j];
var txout = new TransactionOut(raw_tx);
// this hash is the base64 hash of the pubkey which is the address the output when to
hash = conv.bytesToBase64(txout.script.simpleOutPubKeyHash());
// this hash is the hash of the pubkey which is the address the output when to
hash = conv.bytesToHex(txout.script.simpleOutPubKeyHash());
for (k = 0; k < this.addressHashes.length; k++) {
// if our address, then we add the unspent out to a list of unspent outputs
if (this.addressHashes[k] === hash) {
@ -245,7 +245,7 @@ Wallet.prototype.process = function (tx) {
var txin = new TransactionIn(raw_tx);
var pubkey = txin.script.simpleInPubKey();
hash = conv.bytesToBase64(util.sha256ripe160(pubkey));
hash = conv.bytesToHex(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++) {
@ -329,9 +329,9 @@ Wallet.prototype.clearTransactions = function () {
* 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);
if (Bitcoin.Util.isArray(hash)) hash = Crypto.util.bytesToHex(hash);
// TODO: Just create an object with base64 hashes as keys for faster lookup
// TODO: Just create an object with hashes as keys for faster lookup
for (var k = 0; k < this.addressHashes.length; k++) {
if (this.addressHashes[k] === hash) return true;
}