|
2 | 2 | // Originally written by Mike Hearn for BitcoinJ |
3 | 3 | // Copyright (c) 2011 Google Inc |
4 | 4 | // Ported to JavaScript by Stefan Thomas |
| 5 | +// Merged Buffer refactorings from base58-native by Stephen Pair |
| 6 | +// Copyright (c) 2013 BitPay Inc |
5 | 7 |
|
6 | 8 | var BigInteger = require('./jsbn/jsbn') |
7 | 9 |
|
8 | | -// FIXME: ? This is a Base58Check alphabet |
9 | | -var alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" |
10 | | -var base = BigInteger.valueOf(58) |
11 | | - |
12 | | -var alphabetMap = {} |
13 | | -for (var i=0; i<alphabet.length; ++i) { |
14 | | - var chr = alphabet[i] |
15 | | - alphabetMap[chr] = BigInteger.valueOf(i) |
| 10 | +var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' |
| 11 | +var ALPHABET_BUF = new Buffer(ALPHABET, 'ascii') |
| 12 | +var ALPHABET_MAP = {} |
| 13 | +for(var i = 0; i < ALPHABET.length; i++) { |
| 14 | + ALPHABET_MAP[ALPHABET[i]] = BigInteger.valueOf(i) |
16 | 15 | } |
| 16 | +var BASE = BigInteger.valueOf(58) |
17 | 17 |
|
18 | | -// encode a byte array into a base58 encoded String |
19 | | -// @return String |
20 | 18 | function encode(buffer) { |
21 | 19 | var bi = BigInteger.fromByteArrayUnsigned(buffer) |
22 | | - var chars = [] |
| 20 | + var result = new Buffer(buffer.length << 1) |
23 | 21 |
|
24 | | - while (bi.compareTo(base) >= 0) { |
25 | | - var mod = bi.mod(base) |
26 | | - bi = bi.subtract(mod).divide(base) |
| 22 | + var i = result.length - 1 |
| 23 | + while (bi.compareTo(BigInteger.ZERO) > 0) { |
| 24 | + var remainder = bi.mod(BASE) |
| 25 | + bi = bi.divide(BASE) |
27 | 26 |
|
28 | | - chars.push(alphabet[mod.intValue()]) |
| 27 | + result[i] = ALPHABET_BUF[remainder.intValue()] |
| 28 | + i-- |
29 | 29 | } |
30 | 30 |
|
31 | | - chars.push(alphabet[bi.intValue()]) |
32 | | - |
33 | | - // Convert leading zeros too. |
34 | | - for (var i=0; i<buffer.length; i++) { |
35 | | - if (buffer[i] !== 0x00) break |
36 | | - |
37 | | - chars.push(alphabet[0]) |
| 31 | + // deal with leading zeros |
| 32 | + var j = 0 |
| 33 | + while (buffer[j] === 0) { |
| 34 | + result[i] = ALPHABET_BUF[0] |
| 35 | + j++ |
| 36 | + i-- |
38 | 37 | } |
39 | 38 |
|
40 | | - return chars.reverse().join('') |
| 39 | + return result.slice(i + 1, result.length).toString('ascii') |
41 | 40 | } |
42 | 41 |
|
43 | | -// decode a base58 encoded String into a byte array |
44 | | -// @return Array |
45 | | -function decode(str) { |
46 | | - var num = BigInteger.valueOf(0) |
47 | | - |
48 | | - var leading_zero = 0 |
49 | | - var seen_other = false |
| 42 | +function decode(string) { |
| 43 | + if (string.length === 0) return new Buffer(0) |
50 | 44 |
|
51 | | - for (var i=0; i<str.length; ++i) { |
52 | | - var chr = str[i] |
53 | | - var bi = alphabetMap[chr] |
| 45 | + var num = BigInteger.ZERO.clone() |
54 | 46 |
|
55 | | - // if we encounter an invalid character, decoding fails |
56 | | - if (bi === undefined) { |
57 | | - throw new Error('invalid base58 string: ' + str) |
58 | | - } |
59 | | - |
60 | | - num = num.multiply(base).add(bi) |
61 | | - |
62 | | - if (chr === '1' && !seen_other) { |
63 | | - ++leading_zero |
64 | | - } else { |
65 | | - seen_other = true |
66 | | - } |
| 47 | + for (var i = 0; i < string.length; i++) { |
| 48 | + num = num.multiply(BASE) |
| 49 | + num = num.add(ALPHABET_MAP[string.charAt(i)]) |
67 | 50 | } |
68 | 51 |
|
69 | | - var bytes = num.toByteArrayUnsigned() |
70 | | - |
71 | | - // remove leading zeros |
72 | | - while (leading_zero-- > 0) { |
73 | | - bytes.unshift(0) |
| 52 | + // deal with leading zeros |
| 53 | + var i = 0 |
| 54 | + while ((i < string.length) && (string[i] === ALPHABET[0])) { |
| 55 | + i++ |
74 | 56 | } |
75 | 57 |
|
76 | | - return new Buffer(bytes) |
| 58 | + // FIXME: If BigInteger supported buffers, this could be a copy |
| 59 | + var buffer = new Buffer(num.toByteArrayUnsigned()) |
| 60 | + var padding = new Buffer(i) |
| 61 | + padding.fill(0) |
| 62 | + |
| 63 | + return Buffer.concat([padding, buffer]) |
77 | 64 | } |
78 | 65 |
|
79 | 66 | module.exports = { |
|
0 commit comments