PHP WebShell

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

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

import { decodeProprietaryKey, ProprietaryKey } from 'bip174/src/lib/proprietaryKeyVal';
import { PsbtInput } from 'bip174/src/lib/interfaces';
import { Psbt } from 'bitcoinjs-lib/src/psbt';

/**
 * bitgo proprietary key identifier
 */
export const PSBT_PROPRIETARY_IDENTIFIER = 'BITGO';

/**
 * subtype for proprietary keys that bitgo uses
 */
export enum ProprietaryKeySubtype {
  ZEC_CONSENSUS_BRANCH_ID = 0x00,
  MUSIG2_PARTICIPANT_PUB_KEYS = 0x01,
  MUSIG2_PUB_NONCE = 0x02,
  MUSIG2_PARTIAL_SIG = 0x03,
}

/**
 * Psbt proprietary keydata object.
 * <compact size uint identifier length> <bytes identifier> <compact size uint subtype> <bytes subkeydata>
 * => <bytes valuedata>
 */
export interface ProprietaryKeyValue {
  key: ProprietaryKey;
  value: Buffer;
}

/**
 * Psbt proprietary keydata object search fields.
 * <compact size uint identifier length> <bytes identifier> <compact size uint subtype> <bytes subkeydata>
 */
export interface ProprietaryKeySearch {
  identifier: string;
  subtype?: number;
  keydata?: Buffer;
  identifierEncoding?: BufferEncoding;
}

/**
 * Search any data from psbt proprietary key value against keydata.
 * Default identifierEncoding is utf-8 for identifier.
 */
export function getPsbtInputProprietaryKeyVals(
  input: PsbtInput,
  keySearch?: ProprietaryKeySearch
): ProprietaryKeyValue[] {
  if (!input.unknownKeyVals?.length) {
    return [];
  }
  if (keySearch && keySearch.subtype === undefined && Buffer.isBuffer(keySearch.keydata)) {
    throw new Error('invalid proprietary key search filter combination. subtype is required');
  }
  const keyVals = input.unknownKeyVals.map(({ key, value }, i) => {
    return { key: decodeProprietaryKey(key), value };
  });
  return keyVals.filter((keyVal) => {
    return (
      keySearch === undefined ||
      (keySearch.identifier === keyVal.key.identifier &&
        (keySearch.subtype === undefined ||
          (keySearch.subtype === keyVal.key.subtype &&
            (!Buffer.isBuffer(keySearch.keydata) || keySearch.keydata.equals(keyVal.key.keydata)))))
    );
  });
}

/**
 * @return partialSig/tapScriptSig/MUSIG2_PARTIAL_SIG count iff input is not finalized
 */
export function getPsbtInputSignatureCount(input: PsbtInput): number {
  if (isPsbtInputFinalized(input)) {
    throw new Error('Input is already finalized');
  }
  return Math.max(
    Array.isArray(input.partialSig) ? input.partialSig.length : 0,
    Array.isArray(input.tapScriptSig) ? input.tapScriptSig.length : 0,
    getPsbtInputProprietaryKeyVals(input, {
      identifier: PSBT_PROPRIETARY_IDENTIFIER,
      subtype: ProprietaryKeySubtype.MUSIG2_PARTIAL_SIG,
    }).length
  );
}

/**
 * @return true iff PSBT input is finalized
 */
export function isPsbtInputFinalized(input: PsbtInput): boolean {
  return Buffer.isBuffer(input.finalScriptSig) || Buffer.isBuffer(input.finalScriptWitness);
}

/**
 * @return true iff data starts with magic PSBT byte sequence
 * @param data byte array or hex string
 * */
export function isPsbt(data: Buffer | string): boolean {
  // https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#specification
  // 0x70736274 - ASCII for 'psbt'. 0xff - separator
  if (typeof data === 'string') {
    if (data.length < 10) {
      return false;
    }
    data = Buffer.from(data.slice(0, 10), 'hex');
  }
  return 5 <= data.length && data.readUInt32BE(0) === 0x70736274 && data.readUInt8(4) === 0xff;
}

/**
 * First checks if the input is already a buffer that starts with the magic PSBT byte sequence.
 * If not, it checks if the input is a base64- or hex-encoded string that starts with PSBT header.
 *
 * This function is useful when reading a file that could be in any of the above formats or when
 * dealing with a request that could contain a hex or base64 encoded PSBT.
 *
 * @param data
 * @return buffer that starts with the magic PSBT byte sequence
 * @throws Error when conversion is not possible
 */
export function toPsbtBuffer(data: Buffer | string): Buffer {
  if (Buffer.isBuffer(data)) {
    // we are dealing with a buffer that looks like a psbt already
    if (isPsbt(data)) {
      return data;
    }

    // we could be dealing with a buffer that could be a hex or base64 encoded psbt
    data = data.toString('ascii');
  }

  if (typeof data === 'string') {
    const encodings = ['hex', 'base64'] as const;
    for (const encoding of encodings) {
      let buffer: Buffer;
      try {
        buffer = Buffer.from(data, encoding);
      } catch (e) {
        continue;
      }
      if (isPsbt(buffer)) {
        return buffer;
      }
    }

    throw new Error(`data is not in any of the following formats: ${encodings.join(', ')}`);
  }

  throw new Error('data must be a buffer or a string');
}

/**
 * This function allows signing or validating a psbt with non-segwit inputs those do not contain nonWitnessUtxo.
 */
export function withUnsafeNonSegwit<T>(psbt: Psbt, fn: () => T, unsafe = true): T {
  (psbt as any).__CACHE.__UNSAFE_SIGN_NONSEGWIT = unsafe;
  (psbt as any).__CACHE.__WARN_UNSAFE_SIGN_NONSEGWIT = !unsafe;
  try {
    return fn();
  } finally {
    (psbt as any).__CACHE.__UNSAFE_SIGN_NONSEGWIT = false;
    (psbt as any).__CACHE.__WARN_UNSAFE_SIGN_NONSEGWIT = true;
  }
}

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


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