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 | 1x 1x 334x 26x 308x 78x 230x 230x 33x 33x 33x 33x 33x 33x 197x 197x 197x 197x 5x 5x 1x 1x 1x 1x 1x 1x 1x 1x 4x 315x 315x 29x 11x 11x 22x 22x 22x 22x 5x 17x 14x 3x 8x 2x 6x 73x 13x 13x 11x 17x 17x 29x 17x 14x 14x 14x | import {ABIDecoder} from '../serializer/decoder'
import {ABIEncoder} from '../serializer/encoder'
import {ABISerializableObject} from '../serializer/serializable'
import {Base58} from '../base58'
import {isInstanceOf} from '../utils'
import {Bytes, KeyType} from '../'
export type PublicKeyType = PublicKey | string | {type: string; compressed: Uint8Array}
export class PublicKey implements ABISerializableObject {
static abiName = 'public_key'
/** Type, e.g. `K1` */
type: KeyType
/** Compressed public key point. */
data: Bytes
/** Create PublicKey object from representing types. */
static from(value: PublicKeyType) {
if (isInstanceOf(value, PublicKey)) {
return value
}
if (typeof value === 'object' && value.type && value.compressed) {
return new PublicKey(KeyType.from(value.type), new Bytes(value.compressed))
}
Iif (typeof value !== 'string') {
throw new Error('Invalid public key')
}
if (value.startsWith('PUB_')) {
const parts = value.split('_')
Iif (parts.length !== 3) {
throw new Error('Invalid public key string')
}
const type = KeyType.from(parts[1])
const size = type === KeyType.K1 || type === KeyType.R1 ? 33 : undefined
const data = Base58.decodeRipemd160Check(parts[2], size, type)
return new PublicKey(type, data)
} else if (value.startsWith('EOS') || value.length >= 50) {
// Legacy EOS key; leading zero bytes shorten the encoding, e.g. the null key
const encoded = value.startsWith('EOS') ? value.slice(3) : value.slice(-50)
const data = Base58.decodeRipemd160Check(encoded, 33)
return new PublicKey(KeyType.K1, data)
} else {
Ethrow new Error('Invalid public key string')
}
}
/** @internal */
static fromABI(decoder: ABIDecoder) {
const type = KeyType.from(decoder.readByte())
if (type == KeyType.WA) {
const startPos = decoder.getPosition()
decoder.advance(33) // key_data
decoder.advance(1) // user presence
decoder.advance(decoder.readVaruint32()) // rpid
const len = decoder.getPosition() - startPos
decoder.setPosition(startPos)
const data = Bytes.from(decoder.readArray(len))
return new PublicKey(KeyType.WA, data)
}
return new PublicKey(type, new Bytes(decoder.readArray(33)))
}
/** @internal */
constructor(type: KeyType, data: Bytes) {
this.type = type
this.data = data
}
/**
* Returns the core 33-byte compressed public key data as a Uint8Array.
* This is suitable for cryptographic operations like verification.
*/
getCompressedKeyBytes(): Uint8Array {
return this.type === KeyType.WA ? this.data.array.slice(0, 33) : this.data.array
}
equals(other: PublicKeyType) {
const otherKey = PublicKey.from(other)
return this.type === otherKey.type && this.data.equals(otherKey.data)
}
/** Compare with another key using the ordering nodeos enforces on authority keys. */
compare(other: PublicKeyType): number {
const otherKey = PublicKey.from(other)
const type = KeyType.indexFor(this.type)
const otherType = KeyType.indexFor(otherKey.type)
if (type !== otherType) {
return type < otherType ? -1 : 1
}
if (this.type === KeyType.WA) {
return compareWebAuthn(this.data.array, otherKey.data.array)
}
return compareBytes(this.data.array, otherKey.data.array)
}
/**
* Return Antelope/EOSIO legacy (`EOS<base58data>`) formatted key.
* @throws If the key type isn't `K1`
*/
toLegacyString(prefix = 'EOS') {
if (this.type !== KeyType.K1) {
throw new Error('Unable to create legacy formatted string for non-K1 key')
}
return `${prefix}${Base58.encodeRipemd160Check(this.data)}`
}
/** Return key in modern Antelope/EOSIO format (`PUB_<type>_<base58data>`) */
toString() {
return `PUB_${this.type}_${Base58.encodeRipemd160Check(this.data, this.type)}`
}
/** @internal */
toABI(encoder: ABIEncoder) {
encoder.writeByte(KeyType.indexFor(this.type))
encoder.writeArray(this.data.array)
}
/** @internal */
toJSON() {
return this.toString()
}
}
function compareBytes(a: Uint8Array, b: Uint8Array): number {
const length = Math.min(a.length, b.length)
for (let i = 0; i < length; i++) {
if (a[i] !== b[i]) {
return a[i] < b[i] ? -1 : 1
}
}
Iif (a.length === b.length) {
return 0
}
return a.length < b.length ? -1 : 1
}
function compareWebAuthn(a: Uint8Array, b: Uint8Array): number {
// fc compares (key, user presence, rpid) as a tuple, the rpid as a string.
const prefix = compareBytes(a.subarray(0, 34), b.subarray(0, 34))
if (prefix !== 0) {
return prefix
}
return compareBytes(readRpid(a), readRpid(b))
}
function readRpid(data: Uint8Array): Uint8Array {
// Skip the varuint32 that length-prefixes the rpid on the wire.
let offset = 34
while (data[offset] & 0x80) {
offset++
}
return data.subarray(offset + 1)
}
|