PHP WebShell

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

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

/* eslint-disable no-redeclare */
import { script, ScriptSignature, TxOutput } from 'bitcoinjs-lib';
import { isPlaceholderSignature, parseSignatureScript, UtxoTransaction } from '../../src/bitgo';
import { secp256k1 } from '@noble/curves/secp256k1';

const n = BigInt(secp256k1.CURVE.n);
const nDiv2 = n / BigInt(2);

function bytesToBigInt(bytes: Uint8Array): bigint {
  return BigInt(`0x${Buffer.from(bytes).toString('hex')}`);
}

function changeSignatureToHighS(signatureBuffer: Buffer): Buffer {
  if (!script.isCanonicalScriptSignature(signatureBuffer)) {
    throw new Error(`not canonical`);
  }
  const { signature, hashType } = ScriptSignature.decode(signatureBuffer);

  const r = signature.subarray(0, 32);
  const s = signature.subarray(32);

  if (r.length !== 32 || s.length !== 32) {
    throw new Error(`invalid scalar length`);
  }

  let ss = bytesToBigInt(s);

  if (ss > nDiv2) {
    throw new Error(`signature already has high s value`);
  }

  // convert to high-S
  ss = n - ss;

  const newSig = ScriptSignature.encode(
    Buffer.concat([r, Buffer.from(ss.toString(16).padStart(64, '0'), 'hex')]),
    hashType
  );
  if (!script.isCanonicalScriptSignature(newSig)) {
    throw new Error(`newSig not canonical`);
  }
  return newSig;
}

function changeSignatureScriptToHighS(script: Buffer, signature: Buffer): Buffer;
function changeSignatureScriptToHighS(witness: Buffer[], signature: Buffer): Buffer[];
function changeSignatureScriptToHighS(v: Buffer | Buffer[], signature: Buffer): Buffer | Buffer[] {
  const parts = Buffer.isBuffer(v) ? script.decompile(v) : v;
  if (!parts) {
    throw new Error(`could not decompile input`);
  }
  const newParts = parts.map((p) => {
    if (typeof p === 'number') {
      return p;
    }
    return p.equals(signature) ? changeSignatureToHighS(p) : Buffer.from(p);
  });
  return Buffer.isBuffer(v) ? script.compile(newParts) : (newParts as Buffer[]);
}

export function getTransactionWithHighS<TNumber extends number | bigint>(
  tx: UtxoTransaction<TNumber>,
  inputIndex: number
): UtxoTransaction<TNumber>[] {
  const parsed = parseSignatureScript(tx.ins[inputIndex]);
  switch (parsed.scriptType) {
    case 'p2sh':
    case 'p2shP2wsh':
    case 'p2wsh':
      break;
    default:
      return [];
  }
  return parsed.signatures.flatMap((signature) => {
    if (isPlaceholderSignature(signature)) {
      return [];
    }
    const cloned = tx.clone();
    cloned.ins[inputIndex].script = changeSignatureScriptToHighS(cloned.ins[inputIndex].script, signature);
    cloned.ins[inputIndex].witness = changeSignatureScriptToHighS(cloned.ins[inputIndex].witness, signature);
    if (parseSignatureScript(cloned.ins[inputIndex]).scriptType !== parsed.scriptType) {
      throw new Error(`could not parse modified input`);
    }
    return [cloned];
  });
}

/** Return transaction with script xored with 0xff for the given input */
export function getPrevOutsWithInvalidOutputScript<TNumber extends number | bigint>(
  prevOuts: TxOutput<TNumber>[],
  inputIndex: number
): TxOutput<TNumber>[] {
  return prevOuts.map((prevOut, i) => {
    return i === inputIndex
      ? {
          ...prevOut,
          script: prevOut.script.map((v) => v ^ 0xff) as typeof prevOut.script,
        }
      : prevOut;
  });
}

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


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