Skip to content

Commit

Permalink
Merge pull request bitcoinjs#206 from dcousens/base58rework
Browse files Browse the repository at this point in the history
Base58 Check rework
  • Loading branch information
kyledrake committed Jun 4, 2014
2 parents 2c5b9cf + 4c6385e commit 9b5dfbd
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 336 deletions.
12 changes: 9 additions & 3 deletions src/address.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ function Address(hash, version) {

// Import functions
Address.fromBase58Check = function(string) {
var decode = base58check.decode(string)
var payload = base58check.decode(string)
var version = payload.readUInt8(0)
var hash = payload.slice(1)

return new Address(decode.payload, decode.version)
return new Address(hash, version)
}

Address.fromScriptPubKey = function(script, network) {
Expand All @@ -51,7 +53,11 @@ Address.fromScriptPubKey = function(script, network) {

// Export functions
Address.prototype.toBase58Check = function () {
return base58check.encode(this.hash, this.version)
var payload = new Buffer(21)
payload.writeUInt8(this.version, 0)
this.hash.copy(payload, 1)

return base58check.encode(payload)
}

Address.prototype.toScriptPubKey = function() {
Expand Down
21 changes: 6 additions & 15 deletions src/base58check.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ var base58 = require('./base58')
var crypto = require('./crypto')

// Encode a buffer as a base58-check-encoded string
function encode(payload, version) {
var version = new Buffer([version])
var message = Buffer.concat([version, payload])
var checksum = crypto.hash256(message).slice(0, 4)
function encode(payload) {
var checksum = crypto.hash256(payload).slice(0, 4)

return base58.encode(Buffer.concat([
message,
payload,
checksum
]))
}
Expand All @@ -19,20 +17,13 @@ function encode(payload, version) {
function decode(string) {
var buffer = base58.decode(string)

var message = buffer.slice(0, -4)
var payload = buffer.slice(0, -4)
var checksum = buffer.slice(-4)
var newChecksum = crypto.hash256(message).slice(0, 4)
var newChecksum = crypto.hash256(payload).slice(0, 4)

assert.deepEqual(newChecksum, checksum, 'Invalid checksum')

var version = message.readUInt8(0)
var payload = message.slice(1)

return {
version: version,
payload: payload,
checksum: checksum
}
return payload
}

module.exports = {
Expand Down
22 changes: 15 additions & 7 deletions src/eckey.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ function ECKey(D, compressed) {

// Static constructors
ECKey.fromWIF = function(string) {
var decode = base58check.decode(string)
var payload = decode.payload
var payload = base58check.decode(string)
var compressed = false

// Ignore the version byte
payload = payload.slice(1)

if (payload.length === 33) {
assert.strictEqual(payload[32], 0x01, 'Invalid compression flag')

// Truncate the compression flag
payload = payload.slice(0, -1)
compressed = true
}
Expand All @@ -50,15 +53,20 @@ ECKey.makeRandom = function(compressed, rng) {
}

// Export functions
ECKey.prototype.toWIF = function(version) {
version = version || networks.bitcoin.wif
ECKey.prototype.toWIF = function(network) {
network = network || networks.bitcoin

var bufferLen = this.pub.compressed ? 34 : 33
var buffer = new Buffer(bufferLen)

buffer.writeUInt8(network.wif, 0)
this.D.toBuffer(32).copy(buffer, 1)

var buffer = this.D.toBuffer(32)
if (this.pub.compressed) {
buffer = Buffer.concat([buffer, new Buffer([0x01])])
buffer.writeUInt8(0x01, 33)
}

return base58check.encode(buffer, version)
return base58check.encode(buffer)
}

// Operations
Expand Down
6 changes: 3 additions & 3 deletions src/ecpubkey.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ ECPubKey.fromHex = function(hex) {
}

// Operations
ECPubKey.prototype.getAddress = function(version) {
version = version || networks.bitcoin.pubKeyHash
ECPubKey.prototype.getAddress = function(network) {
network = network || networks.bitcoin

return new Address(crypto.hash160(this.toBuffer()), version)
return new Address(crypto.hash160(this.toBuffer()), network.pubKeyHash)
}

ECPubKey.prototype.verify = function(hash, signature) {
Expand Down
22 changes: 4 additions & 18 deletions src/hdnode.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var assert = require('assert')
var base58 = require('./base58')
var base58check = require('./base58check')

var BigInteger = require('bigi')
var crypto = require('./crypto')
Expand Down Expand Up @@ -68,15 +68,7 @@ HDNode.fromSeedHex = function(hex, network) {
}

HDNode.fromBase58 = function(string) {
var buffer = base58.decode(string)

var payload = buffer.slice(0, -4)
var checksum = buffer.slice(-4)

var newChecksum = crypto.hash256(payload).slice(0, 4)
assert.deepEqual(newChecksum, checksum, 'Invalid checksum')

return HDNode.fromBuffer(payload)
return HDNode.fromBuffer(base58check.decode(string))
}

HDNode.fromBuffer = function(buffer) {
Expand Down Expand Up @@ -144,17 +136,11 @@ HDNode.prototype.getFingerprint = function() {
}

HDNode.prototype.getAddress = function() {
return this.pubKey.getAddress(this.network.pubKeyHash)
return this.pubKey.getAddress(this.network)
}

HDNode.prototype.toBase58 = function(isPrivate) {
var buffer = this.toBuffer(isPrivate)
var checksum = crypto.hash256(buffer).slice(0, 4)

return base58.encode(Buffer.concat([
buffer,
checksum
]))
return base58check.encode(this.toBuffer(isPrivate))
}

HDNode.prototype.toBuffer = function(isPrivate) {
Expand Down
7 changes: 3 additions & 4 deletions src/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@ function sign(key, message, network) {

// TODO: network could be implied from address
function verify(address, compactSig, message, network) {
if (typeof address === 'string') {
address = Address.fromBase58Check(address)
if (address instanceof Address) {
address = address.toString()
}

network = network || networks.bitcoin

var hash = magicHash(message, network)
Expand All @@ -49,7 +48,7 @@ function verify(address, compactSig, message, network) {
var Q = ecdsa.recoverPubKey(ecparams, e, parsed.signature, parsed.i)

var pubKey = new ECPubKey(Q, parsed.compressed)
return pubKey.getAddress(address.version).toString() === address.toString()
return pubKey.getAddress(network).toString() === address
}

module.exports = {
Expand Down
12 changes: 4 additions & 8 deletions test/base58check.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,16 @@ describe('base58check', function() {
fixtures.valid.forEach(function(f) {
it('can decode ' + f.string, function() {
var actual = base58check.decode(f.string)
var expected = {
version: f.decode.version || 0,
payload: h2b(f.decode.payload),
checksum: h2b(f.decode.checksum)
}
var expected = h2b(f.payload)

assert.deepEqual(actual, expected)
})
})

fixtures.invalid.forEach(function(f) {
it('throws on ' + f.description, function() {
it('throws on ' + f, function() {
assert.throws(function() {
base58check.decode(f.string)
base58check.decode(f)
}, /Invalid checksum/)
})
})
Expand All @@ -32,7 +28,7 @@ describe('base58check', function() {
describe('encode', function() {
fixtures.valid.forEach(function(f) {
it('can encode ' + f.string, function() {
var actual = base58check.encode(h2b(f.decode.payload), f.decode.version)
var actual = base58check.encode(h2b(f.payload))
var expected = f.string

assert.strictEqual(actual, expected)
Expand Down
6 changes: 3 additions & 3 deletions test/eckey.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
var assert = require('assert')
var crypto = require('../src/crypto')
var networks = require('../src/networks')

var BigInteger = require('bigi')
var ECKey = require('../src/eckey')

var fixtures = require('./fixtures/eckey.json')
var networks = require('../src/networks')

describe('ECKey', function() {
describe('constructor', function() {
Expand Down Expand Up @@ -66,8 +66,8 @@ describe('ECKey', function() {
f.WIFs.forEach(function(wif) {
it('exports ' + wif.string + ' correctly', function() {
var privKey = ECKey.fromWIF(wif.string)
var version = networks[wif.network].wif
var result = privKey.toWIF(version)
var network = networks[wif.network]
var result = privKey.toWIF(network)

assert.equal(result, wif.string)
})
Expand Down
5 changes: 3 additions & 2 deletions test/ecpubkey.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var assert = require('assert')
var crypto = require('../src/crypto')
var networks = require('../src/networks')
var sec = require('../src/sec')
var ecparams = sec('secp256k1')

Expand Down Expand Up @@ -71,9 +72,9 @@ describe('ECPubKey', function() {

it('supports alternative networks', function() {
var pubKey = new ECPubKey(Q)
var address = pubKey.getAddress(0x09)
var address = pubKey.getAddress(networks.testnet)

assert.equal(address.version, 0x09)
assert.equal(address.version, networks.testnet.pubKeyHash)
assert.equal(address.hash.toString('hex'), fixtures.compressed.hash160)
})
})
Expand Down
Loading

0 comments on commit 9b5dfbd

Please sign in to comment.