PHP WebShell

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

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

import * as assert from 'assert';
import { BIP32Interface } from 'bip32';
import * as noble from '@noble/secp256k1';
import * as utxolib from '..';
import { getMainnet, Network, networks } from '../networks';

import {
  ChainCode,
  createPsbtForNetwork,
  fromOutput,
  fromOutputWithPrevTx,
  getExternalChainCode,
  isSegwit,
  NonWitnessWalletUnspent,
  outputScripts,
  RootWalletKeys,
  scriptTypeForChain,
  Unspent,
  UnspentWithPrevTx,
  UtxoTransaction,
  WalletUnspent,
} from '../bitgo';
import { fromOutputScript } from '../address';
import { createOutputScript2of3, createOutputScriptP2shP2pk } from '../bitgo/outputScripts';

import { getDefaultWalletKeys, getKey } from './keys';

export type InputType = outputScripts.ScriptType2Of3;

export function mockPrevTx(
  vout: number,
  outputScript: Buffer,
  value: bigint,
  network: Network
): UtxoTransaction<bigint> {
  const psbtFromNetwork = createPsbtForNetwork({ network });

  const keypair = getKey('mock-prev-tx');
  const pubkey = keypair.publicKey;
  assert(keypair.privateKey);
  const payment = utxolib.payments.p2wpkh({ pubkey });
  const destOutput = payment.output;
  if (!destOutput) throw new Error('Impossible, payment we just constructed has no output');

  for (let index = 0; index <= vout; index++) {
    if (index === vout) {
      psbtFromNetwork.addOutput({ script: outputScript, value });
    } else {
      psbtFromNetwork.addOutput({ script: destOutput, value });
    }
  }
  psbtFromNetwork.addInput({
    hash: Buffer.alloc(32, 0x01),
    index: 0,
    witnessUtxo: { script: destOutput, value: value * (BigInt(vout) + BigInt(1)) + BigInt(1000) },
  });
  psbtFromNetwork.signInput(0, {
    publicKey: pubkey,
    sign: (hash: Buffer, lowR?: boolean) =>
      Buffer.from(noble.signSync(hash, keypair.privateKey as Buffer, { canonical: !lowR, der: false })),
  });
  psbtFromNetwork.validateSignaturesOfAllInputs();
  psbtFromNetwork.finalizeAllInputs();
  return psbtFromNetwork.extractTransaction();
}

export const replayProtectionKeyPair = getKey('replay-protection');
const replayProtectionScriptPubKey = createOutputScriptP2shP2pk(replayProtectionKeyPair.publicKey).scriptPubKey;

export function isReplayProtectionUnspent<TNumber extends bigint | number>(
  u: Unspent<TNumber>,
  network: Network
): boolean {
  return u.address === fromOutputScript(replayProtectionScriptPubKey, network);
}

export function mockReplayProtectionUnspent<TNumber extends number | bigint>(
  network: Network,
  value: TNumber,
  { key = replayProtectionKeyPair, vout = 0 }: { key?: BIP32Interface; vout?: number } = {}
): UnspentWithPrevTx<TNumber> {
  const outputScript = createOutputScriptP2shP2pk(key.publicKey).scriptPubKey;
  const prevTransaction = mockPrevTx(vout, outputScript, BigInt(value), network);
  return { ...fromOutputWithPrevTx(prevTransaction, vout), value };
}

export function mockWalletUnspent<TNumber extends number | bigint>(
  network: Network,
  value: TNumber,
  {
    chain = 0,
    index = 0,
    keys = getDefaultWalletKeys(),
    vout = 0,
    id,
  }: { chain?: ChainCode; index?: number; keys?: RootWalletKeys; vout?: number; id?: string } = {}
): WalletUnspent<TNumber> | NonWitnessWalletUnspent<TNumber> {
  const derivedKeys = keys.deriveForChainAndIndex(chain, index);
  const address = fromOutputScript(
    createOutputScript2of3(derivedKeys.publicKeys, scriptTypeForChain(chain)).scriptPubKey,
    network
  );
  if (id && typeof id === 'string') {
    return { id, address, chain, index, value };
  } else {
    const prevTransaction = mockPrevTx(
      vout,
      createOutputScript2of3(derivedKeys.publicKeys, scriptTypeForChain(chain), network).scriptPubKey,
      BigInt(value),
      network
    );
    const unspent =
      isSegwit(chain) || getMainnet(network) === networks.zcash
        ? fromOutput(prevTransaction, vout)
        : fromOutputWithPrevTx(prevTransaction, vout);
    return {
      ...unspent,
      chain,
      index,
      value,
    };
  }
}

export function mockUnspents<TNumber extends number | bigint>(
  rootWalletKeys: RootWalletKeys,
  inputScriptTypes: (InputType | outputScripts.ScriptTypeP2shP2pk)[],
  testOutputAmount: TNumber,
  network: Network
): (Unspent<TNumber> | WalletUnspent<TNumber>)[] {
  return inputScriptTypes.map((t, i): Unspent<TNumber> => {
    if (outputScripts.isScriptType2Of3(t)) {
      return mockWalletUnspent(network, testOutputAmount, {
        keys: rootWalletKeys,
        chain: getExternalChainCode(t),
        vout: i,
      });
    } else if (t === outputScripts.scriptTypeP2shP2pk) {
      return mockReplayProtectionUnspent(network, testOutputAmount, {
        key: replayProtectionKeyPair,
        vout: i,
      });
    }
    throw new Error(`invalid input type ${t}`);
  });
}

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


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