Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | 1x 1x 1x 1x 1x 1x 13x 13x 13x 1x 1x 1x 58x 1x 181x 122x 59x 59x 3736x 3736x 1x 3735x 200375x 200375x 200375x 3735x 1x 57x 57x 1x 18x 18x 18x 18x 18x 3x 15x 1x 157x 157x 157x 157x 157x 7x 150x 1x 71x 71x 71x 3931x 3931x 218269x 218269x 218269x 3931x 5346x 5346x 71x 72x 70x 2x 71x 71x 1x 3x 3x 3x 1x 66x 66x 66x 122x 122x 6538x 6538x 1x 6537x 175714x 175714x 175714x 6537x 4816x 121x 124x 4x 120x 121x 121x 223x 223x 121x 223x 21x 21x 21x | import {ripemd160, sha256} from 'hash.js'
import {arrayEquals} from './utils'
import {Bytes, BytesType} from './chain'
export namespace Base58 {
export enum ErrorCode {
E_CHECKSUM = 'E_CHECKSUM',
E_INVALID = 'E_INVALID',
}
export class DecodingError extends Error {
static __className = 'DecodingError'
constructor(
message: string,
public readonly code: ErrorCode,
public readonly info: Record<string, any> = {}
) {
super(message)
}
}
const chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
const charMap = new Int16Array(0xff).fill(-1)
for (let i = 0; i < 58; ++i) {
charMap[chars.charCodeAt(i)] = i
}
/** Decode a Base58 encoded string. */
export function decode(s: string, size?: number): Bytes {
if (size == null) {
return decodeVar(s)
}
const result = new Uint8Array(size)
for (let i = 0; i < s.length; ++i) {
let carry = charMap[s.charCodeAt(i)]
if (carry < 0) {
throw new DecodingError(
'Invalid Base58 character encountered',
ErrorCode.E_INVALID,
{char: s[i]}
)
}
for (let j = 0; j < size; ++j) {
const x = result[j] * 58 + carry
result[j] = x
carry = x >> 8
}
if (carry) {
throw new DecodingError('Base58 value is out of range', ErrorCode.E_INVALID)
}
}
result.reverse()
return new Bytes(result)
}
/** Decode a Base58Check encoded string. */
export function decodeCheck(encoded: string, size?: number) {
const decoded = decode(encoded, size != null ? size + 4 : size)
const data = decoded.array.subarray(0, -4)
const expected = decoded.array.subarray(-4)
const actual = dsha256Checksum(data)
if (!arrayEquals(expected, actual)) {
throw new DecodingError('Checksum mismatch', ErrorCode.E_CHECKSUM, {
actual,
expected,
data,
hash: 'double_sha256',
})
}
return new Bytes(data)
}
/** Decode a Base58Check encoded string that uses ripemd160 instead of double sha256 for the digest. */
export function decodeRipemd160Check(encoded: string, size?: number, suffix?: string) {
const decoded = decode(encoded, size != null ? size + 4 : size)
const data = decoded.array.subarray(0, -4)
const expected = decoded.array.subarray(-4)
const actual = ripemd160Checksum(data, suffix)
if (!arrayEquals(expected, actual)) {
throw new DecodingError('Checksum mismatch', ErrorCode.E_CHECKSUM, {
actual,
expected,
data,
hash: 'ripemd160',
})
}
return new Bytes(data)
}
/** Encode bytes to a Base58 string. */
export function encode(data: BytesType) {
data = Bytes.from(data)
const result = [] as number[]
for (const byte of data.array) {
let carry = byte
for (let j = 0; j < result.length; ++j) {
const x = (charMap[result[j]] << 8) + carry
result[j] = chars.charCodeAt(x % 58)
carry = (x / 58) | 0
}
while (carry) {
result.push(chars.charCodeAt(carry % 58))
carry = (carry / 58) | 0
}
}
for (const byte of data.array) {
if (byte) {
break
} else {
result.push('1'.charCodeAt(0))
}
}
result.reverse()
return String.fromCharCode(...result)
}
export function encodeCheck(data: BytesType) {
data = Bytes.from(data)
data = data.appending(dsha256Checksum(data.array))
return encode(data)
}
export function encodeRipemd160Check(data: BytesType, suffix?: string) {
data = Bytes.from(data)
data = data.appending(ripemd160Checksum(data.array, suffix))
return encode(data)
}
/** @internal */
function decodeVar(s: string) {
const result: number[] = []
for (let i = 0; i < s.length; ++i) {
let carry = charMap[s.charCodeAt(i)]
if (carry < 0) {
throw new DecodingError(
'Invalid Base58 character encountered',
ErrorCode.E_INVALID,
{char: s[i]}
)
}
for (let j = 0; j < result.length; ++j) {
const x = result[j] * 58 + carry
result[j] = x & 0xff
carry = x >> 8
}
if (carry) {
result.push(carry)
}
}
for (const ch of s) {
if (ch === '1') {
result.push(0)
} else {
break
}
}
result.reverse()
return Bytes.from(result)
}
/** @internal */
function ripemd160Checksum(data: Uint8Array, suffix?: string) {
const hash = ripemd160().update(data)
if (suffix) {
hash.update(suffix)
}
return new Uint8Array(hash.digest().slice(0, 4))
}
/** @internal */
function dsha256Checksum(data: Uint8Array) {
const round1 = sha256().update(data).digest()
const round2 = sha256().update(round1).digest()
return new Uint8Array(round2.slice(0, 4))
}
}
|