PHP WebShell

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

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

import assert from 'assert';

import * as utxolib from '@bitgo/utxo-lib';
import { BIP32Interface, ECPair, ECPairInterface } from '@bitgo/utxo-lib';
import { Descriptor } from '@bitgo/wasm-miniscript';

import { PsbtParams, parse, toUtxoPsbt, toWrappedPsbt, ParsedDescriptorTransaction } from '../../../src/descriptor';
import { getFixture, getKeyTriple } from '../../../src/testutil';
import {
  DescriptorTemplate,
  getDescriptor,
  getPsbtParams,
  mockPsbt,
  mockPsbtDefault,
  toPlainObjectFromPsbt,
  toPlainObjectFromTx,
} from '../../../src/testutil/descriptor';
import { getNewSignatureCount, signWithKey } from '../../../src/descriptor/psbt/sign';

function normalize(v: unknown): unknown {
  if (typeof v === 'bigint') {
    return v.toString();
  }
  if (v instanceof Descriptor) {
    return v.toString();
  }
  if (v instanceof Buffer) {
    return v.toString('hex');
  }
  if (v instanceof utxolib.Psbt) {
    return toPlainObjectFromPsbt(v);
  }
  if (v instanceof utxolib.Transaction) {
    return toPlainObjectFromTx(v);
  }
  if (Array.isArray(v)) {
    return v.map(normalize);
  }
  if (typeof v === 'object' && v !== null) {
    return Object.fromEntries(Object.entries(v).flatMap(([k, v]) => (v === undefined ? [] : [[k, normalize(v)]])));
  }
  return v;
}

async function assertEqualsFixture(t: string, filename: string, value: unknown) {
  filename = __dirname + '/fixtures/' + t + '.' + filename;
  const nv = normalize(value);
  assert.deepStrictEqual(nv, await getFixture(filename, nv));
}

const selfKeys = getKeyTriple('a');
const otherKeys = getKeyTriple('b');

function toPlain(k: BIP32Interface): ECPairInterface {
  assert.ok(k.privateKey);
  return ECPair.fromPrivateKey(k.privateKey);
}

type PsbtStage = {
  name: string;
  keys: (BIP32Interface | ECPairInterface)[];
  final?: boolean;
};

type FixtureStage = {
  psbt: utxolib.bitgo.UtxoPsbt;
  networkTx?: utxolib.Transaction<bigint>;
  networkTxBuffer?: Buffer;
};

function getStages(
  psbt: utxolib.bitgo.UtxoPsbt,
  parsed: ParsedDescriptorTransaction,
  stages: PsbtStage[]
): Record<string, FixtureStage> {
  return Object.fromEntries(
    stages.map((stage) => {
      const psbtStageWrapped = toWrappedPsbt(psbt);
      for (const key of stage.keys) {
        assert(getNewSignatureCount(signWithKey(psbtStageWrapped, key)) > 0, 'No new signatures were created');
      }
      const psbtStage = toUtxoPsbt(psbtStageWrapped, utxolib.networks.bitcoin);
      let psbtFinal: utxolib.bitgo.UtxoPsbt | undefined;
      let networkTx: utxolib.bitgo.UtxoTransaction<bigint> | undefined;
      let networkTxBuffer: Buffer | undefined;
      if (stage.final) {
        psbtStageWrapped.finalize();
        psbtFinal = toUtxoPsbt(psbtStageWrapped, utxolib.networks.bitcoin);
        networkTx = psbtFinal.extractTransaction();
        networkTxBuffer = networkTx.toBuffer();
      }
      return [
        stage.name,
        {
          psbt: psbtStage,
          parsed,
          psbtFinal,
          networkTx,
          networkTxBuffer,
        },
      ];
    })
  );
}

type TestParams = {
  descriptorSelf: Descriptor;
  stages: PsbtStage[];
} & (
  | {
      psbtParams: Partial<PsbtParams>;
    }
  | {
      psbt: utxolib.bitgo.UtxoPsbt;
    }
);

function describeCreatePsbt(name: string, testParams: TestParams) {
  describe(`createPsbt ${name}`, function () {
    it('creates psbt with expected properties', async function () {
      const psbtUnsigned =
        'psbt' in testParams
          ? testParams.psbt
          : mockPsbtDefault({
              descriptorSelf: testParams.descriptorSelf,
              descriptorOther: getDescriptor('Wsh2Of3', otherKeys),
              params: testParams.psbtParams,
            });
      const descriptorMap = new Map([['self', testParams.descriptorSelf]]);
      const parsed = parse(psbtUnsigned, descriptorMap, utxolib.networks.bitcoin);
      assert.strictEqual(parsed.spendAmount, psbtUnsigned.txOutputs[1].value);
      await assertEqualsFixture(name, 'psbtStages.json', getStages(psbtUnsigned, parsed, testParams.stages));
    });
  });
}

const defaultStagesCombinedAB: PsbtStage[] = [
  { name: 'unsigned', keys: [] },
  { name: 'signedA', keys: selfKeys.slice(0, 1) },
  { name: 'signedAB', keys: selfKeys.slice(0, 2), final: true },
];

function getDefaultStagesSeparateAB({ plain = false } = {}): PsbtStage[] {
  const keys = plain ? selfKeys.map(toPlain) : selfKeys;
  return [
    { name: 'unsigned', keys: [] },
    { name: 'signedA', keys: keys.slice(0, 1) },
    { name: 'signedB', keys: keys.slice(1, 2), final: true },
  ];
}

function describeCreatePsbt2Of3(t: DescriptorTemplate) {
  describeCreatePsbt(t, {
    descriptorSelf: getDescriptor(t, selfKeys),
    psbtParams: getPsbtParams(t),
    stages: defaultStagesCombinedAB,
  });
}

describeCreatePsbt2Of3('Wsh2Of3');
describeCreatePsbt2Of3('Wsh2Of3CltvDrop');
describeCreatePsbt2Of3('Tr2Of3-NoKeyPath');
describeCreatePsbt('Tr1Of3-NoKeyPath-Tree', {
  descriptorSelf: getDescriptor('Tr1Of3-NoKeyPath-Tree', selfKeys),
  psbtParams: {},
  stages: getDefaultStagesSeparateAB(),
});
describeCreatePsbt('Tr1Of3-NoKeyPath-Tree-PlainKeys', {
  descriptorSelf: getDescriptor('Tr1Of3-NoKeyPath-Tree-Plain', selfKeys),
  psbtParams: {},
  stages: getDefaultStagesSeparateAB({ plain: true }),
});

{
  const descriptorSelf = getDescriptor('Wsh2Of3', selfKeys);
  const descriptorOther = getDescriptor('Wsh2Of3', otherKeys);
  describeCreatePsbt('Wsh2Of3-CustomInputSequence', {
    descriptorSelf,
    psbt: mockPsbt(
      [
        { descriptor: descriptorSelf, index: 0 },
        { descriptor: descriptorSelf, index: 1, id: { vout: 1 }, sequence: 123 },
      ],
      [
        {
          descriptor: descriptorOther,
          index: 0,
          value: BigInt(4e5),
          external: true,
        },
        { descriptor: descriptorSelf, index: 0, value: BigInt(4e5) },
      ]
    ),
    stages: defaultStagesCombinedAB,
  });
}

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


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