PHP WebShell

Текущая директория: /opt/BitGoJS/modules/utxo-bin/src

Просмотр файла: ScriptParser.ts

import * as utxolib from '@bitgo/utxo-lib';
import { Miniscript } from '@bitgo/wasm-miniscript';

import { Parser, ParserNode } from './Parser';
import { parseUnknown } from './parseUnknown';

const paymentTypes = ['p2sh', 'p2shP2wsh', 'p2pkh', 'p2wpkh', 'p2wsh', 'p2ms'] as const;
type PaymentType = (typeof paymentTypes)[number];

function parsePaymentWithType(script: Buffer, type: PaymentType, network?: utxolib.Network): utxolib.Payment {
  switch (type) {
    case 'p2sh':
      return utxolib.payments.p2sh({ redeem: { output: script }, network });
    case 'p2shP2wsh':
      return utxolib.payments.p2sh({
        redeem: { output: utxolib.payments.p2wsh({ redeem: { output: script }, network }).output },
        network,
      });
    case 'p2pkh':
      return utxolib.payments.p2pkh({ output: script, network });
    case 'p2wpkh':
      return utxolib.payments.p2wpkh({ output: script, network });
    case 'p2wsh':
      return utxolib.payments.p2wsh({ output: script, network });
    case 'p2ms':
      return utxolib.payments.p2ms({ output: script, network });
  }
}

function asMiniscript(script: Buffer): Miniscript | undefined {
  const contexts = ['tap', 'segwitv0', 'legacy'] as const;
  for (const ctx of contexts) {
    try {
      return Miniscript.fromBitcoinScript(script, ctx);
    } catch (e) {
      continue;
    }
  }
  throw new Error('failed to parse as miniscript');
}

export class ScriptParser extends Parser {
  network: utxolib.Network;
  constructor({ network }: { network: utxolib.Network }) {
    super();
    this.network = network;
  }

  static toASM(script: Buffer, { insertNewlines = true } = {}): string | undefined {
    let parsed;
    try {
      parsed = utxolib.script.toASM(script);
    } catch (e) {
      return 'error';
    }

    if (parsed) {
      return insertNewlines ? ['', ...parsed.split(' ')].join('\n') : parsed;
    }
  }

  static classify(
    script: Buffer | undefined,
    witness: Buffer[] | undefined
  ): {
    input: string | undefined;
    output: string | undefined;
    witness: string | undefined;
  } {
    return {
      input: script ? utxolib.classify.input(script, /* allowIncomplete */ true) : undefined,
      output: script ? utxolib.classify.output(script) : undefined,
      witness: witness ? utxolib.classify.witness(witness) : undefined,
    };
  }

  parsePayment(type: PaymentType, payment: utxolib.Payment): ParserNode {
    return parseUnknown(
      this,
      `payment: ${type}`,
      { name: payment.name, ...payment },
      {
        omit: ['network'],
      }
    );
  }

  parseBufferAsPayment(script: Buffer): ParserNode[] {
    return paymentTypes.flatMap((type) => {
      try {
        return [this.parsePayment(type, parsePaymentWithType(script, type, this.network))];
      } catch (e) {
        return [];
      }
    });
  }

  parse(script: Buffer): ParserNode {
    const classification = ScriptParser.classify(script, undefined);
    const decompiled = utxolib.script.decompile(script);
    return this.node('script', `length ${script.length} bytes`, [
      this.nodeCatchError('miniscript', () => asMiniscript(script)?.toString()),
      this.node('classification', undefined, [
        this.node('input', classification.input),
        this.node('output', classification.output),
        this.node('witness', classification.witness),
      ]),
      this.node('asm', ScriptParser.toASM(script)),
      this.node('decompiled', undefined, decompiled ? decompiled.map((v, i) => this.node(i, v)) : undefined),
      ...this.parseBufferAsPayment(script),
    ]);
  }
}

Выполнить команду


Для локальной разработки. Не используйте в интернете!