PHP WebShell
Текущая директория: /opt/BitGoJS/modules/utxo-bin/src
Просмотр файла: AddressParser.ts
import * as utxolib from '@bitgo/utxo-lib';
import * as bech32 from 'bech32';
import { Parser, ParserNode } from './Parser';
import { getNetworkList, getNetworkName } from './args';
const bs58 = require('bs58');
const bs58check = require('bs58check');
const cashaddress = require('cashaddress');
function isPrintable(s: string): boolean {
// https://stackoverflow.com/a/66447494
return !s.match(/[\p{Cc}\p{Cn}\p{Cs}]+/gu);
}
export class AddressParser extends Parser {
constructor(
public params: {
network?: utxolib.Network;
all: boolean;
convert: boolean;
}
) {
super();
}
tryParseOpReturn(script: Buffer): ParserNode[] {
let data: Buffer[] | undefined;
try {
({ data } = utxolib.payments.embed({ output: script }));
} catch (e) {
// ignore
}
if (!data) {
return [];
}
return data.map((buf, i) => {
let utf8;
try {
utf8 = buf.toString('utf8');
} catch (e) {
// ignore
}
return this.node(`OP_RETURN ${i}`, `${buf.length} bytes`, [
this.node('hex', buf),
...(utf8 && isPrintable(utf8) ? [this.node('utf8', utf8)] : []),
]);
});
}
parseOutputScript(buffer: Buffer): ParserNode[] {
return [
this.node('scriptPubKey', `[${buffer.length}byte]`, [
this.node('type', utxolib.classify.output(buffer)),
this.node('hex', buffer.toString('hex')),
this.node('asm', utxolib.script.toASM(buffer), this.tryParseOpReturn(buffer)),
]),
];
}
parseBase58(address: string): ParserNode[] {
const payload = bs58.decode(address);
return [this.node('payload', payload)];
}
parseBase58Check(address: string): ParserNode[] {
const payload = bs58check.decode(address);
return [
this.node('payload', payload),
this.node('version', payload.readUInt8(0).toString('16')),
this.node('hash', payload.slice(1)),
];
}
parseWithBechLib(bechlib: bech32.BechLib, address: string): ParserNode[] {
const decoded = bechlib.decode(address);
return [
this.node('prefix', decoded.prefix),
this.node('words', Buffer.from(decoded.words)),
this.node('bytes', Buffer.from(bechlib.fromWords(decoded.words))),
];
}
parseBech32(address: string): ParserNode[] {
return this.parseWithBechLib(bech32.bech32, address);
}
parseBech32m(address: string): ParserNode[] {
return this.parseWithBechLib(bech32.bech32m, address);
}
parseCashaddr(address: string): ParserNode[] {
const payload = cashaddress.decode(address);
return [
this.node('prefix', payload.prefix),
this.node('version', payload.version),
this.node('hash', payload.hash),
];
}
convert(outputScript: Buffer): ParserNode {
function getWidth(list: readonly string[]): number {
return Math.max(...list.map((s) => s.length));
}
const networkWith = getWidth(getNetworkList().map(getNetworkName));
const addressFormatWith = getWidth(utxolib.addressFormat.addressFormats);
return this.node(
'converted',
undefined,
getNetworkList().flatMap((network) =>
utxolib.addressFormat.addressFormats
.filter((f) => utxolib.addressFormat.isSupportedAddressFormat(f, network))
.map((addressFormat) => {
const label = `${getNetworkName(network).padEnd(networkWith)} ${addressFormat.padEnd(addressFormatWith)}`;
try {
return this.node(
label,
utxolib.addressFormat.fromOutputScriptWithFormat(outputScript, addressFormat, network)
);
} catch (e) {
return this.node(label, 'undefined');
}
})
)
);
}
parseToBytes(input: string): ParserNode[] {
type Decoder = (address: string) => ParserNode[];
const decodeWith = (name: string, decoder: Decoder): ParserNode[] => {
try {
return [this.node(name, undefined, decoder(input))];
} catch (e) {
return this.params.all ? [this.node(name, undefined, [this.node('decodeError', String(e))])] : [];
}
};
return [
...decodeWith('base58', this.parseBase58.bind(this)),
...decodeWith('base58Check', this.parseBase58Check.bind(this)),
...decodeWith('bech32', this.parseBech32.bind(this)),
...decodeWith('bech32m', this.parseBech32m.bind(this)),
...decodeWith('cashaddr', this.parseCashaddr.bind(this)),
];
}
parse(input: string): ParserNode {
const networks = this.params.network ? [this.params.network] : getNetworkList();
type Match = {
network: utxolib.Network;
address: string;
addressFormat: utxolib.addressFormat.AddressFormat;
buffer: Buffer;
};
const matches: Match[] = networks.flatMap((network) => {
try {
const [addressFormat, buffer] = utxolib.addressFormat.toOutputScriptAndFormat(input, network);
const address = utxolib.addressFormat.fromOutputScriptWithFormat(buffer, addressFormat, network);
return [{ network, address, addressFormat, buffer }];
} catch (e) {
return [];
}
});
const firstMatch = matches[0];
const nodes: ParserNode[] = [];
nodes.push(...this.parseToBytes(input));
if (firstMatch) {
if (input !== firstMatch.address) {
nodes.push(this.node('normalized', firstMatch.address, this.parseToBytes(firstMatch.address)));
}
nodes.push(this.node('format', firstMatch.addressFormat));
nodes.push(this.node('outputScript', firstMatch.buffer, this.parseOutputScript(firstMatch.buffer)));
nodes.push(this.node('network', matches.map((m) => getNetworkName(m.network)).join(', ')));
if (this.params.all || this.params.convert) {
nodes.push(this.convert(firstMatch.buffer));
}
}
return this.node('address', input, nodes);
}
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!