如何用分类帐签署比特币psbt?

问题描述 投票:1回答:1

我正在按照我在这里找到的内容尝试从bitcoinjs-lib签署Psbt交易:

https://github.com/helperbit/helperbit-wallet/blob/master/app/components/dashboard/bitcoin.service/ledger.ts

我已经检查了账本和bitcoinjsLib的compressedd publicKey返回相同的值。

我可以使用bitcoinjs-lib ECPair对其进行签名,但是当我尝试使用分类帐对其进行签名时,它始终无效。

有人可以帮我指出我在哪里做错了吗?

这是我的代码。

/* tslint:disable */
require('regenerator-runtime');
const { default: Transport } = require('@ledgerhq/hw-transport-node-hid')
const { default: AppBtc } = require('@ledgerhq/hw-app-btc');
import * as bitcoin from 'bitcoinjs-lib'
const mnemonics = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
// not used, but if someone want to test using their own ledger.
const NETWORK = bitcoin.networks.regtest;
const segwit = true;
const LOCK_TIME = 0;
const SIGHASH_ALL = 1;
const path = `m/12'/0'/55'`


export function toByteArray(hexString: string) {
    const Buffer = require('safe-buffer').Buffer;
    const result = Buffer.alloc(hexString.length / 2);
    let i = 0;
    while (hexString.length >= 2) {
        result[i] = parseInt(hexString.substring(0, 2), 16);
        i += 1;
        hexString = hexString.substring(2, hexString.length);
    }
    return result;
}

function toHexString(buffer: Buffer) {
    return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}


function compressPublicKey(pk: string): string {
    return toHexString(bitcoin.ECPair.fromPublicKey(toByteArray(pk)).publicKey);
}


async function main(): Promise<void> {
  const nonWitnessUtxo = '02000000000105e11d8c7970aff25a8a431c49397316ce80af25dca6ac395f172e2d7326d42e570100000017160014cccb96f2ec1b5a2b7081f96b78077488769e3d8efeffffff77bcf72d69888cc739341107028e1e8a302d507fe9ffb94c5359fb1e82f08f370100000017160014527aef9caa6e0a12ecea8ce255cb36427a2f451afeffffff3cad9140403d6ec68bc0cf0b261daa4a41d92f04bddad98fc05a305127c7145c00000000171600143ea2fa276d3de26e4e220a1e6d343a235edbaff6feffffff250152b93632b8e275aba954c894dcbc2c0124a5c1db10de3edc5a0fd2880cc30100000017160014954f8b16a236e5d76b1f6fb69ea821b370fba749feffffffafd0c8b8eab835303aa213a0390e40e25a152dc62889b32df6887dc147b4e29b000000001716001436c91ffd3fd014ca8955eaa97e14dc9fdbed08f4feffffff0200e1f5050000000017a914f1f02b570afafacde515fcd6862a50822b56973e876c515f000000000017a9141afb048a646910eb09136f1cb311774d6c63e8ed870247304402200bfc0495e92aece0807c4c709fc05df3725794e766f36d372f3b35714d376775022077f01d90848205088374c2d8a9e28aedbc9f46212ce83fad7ab5ba00e33130680121021e3bbec438d71dc4966c817ee8db61970bd2288799d9bad9a5f8dd3795e2b0410247304402202c871ca7260d427f07f0482f939aa6193785de9b6df8742cf48881bd0525c4e0022056d7f2621d17fcacb3abd2dad030618a74abb259e852c98d10c96b541876a8340121033c41c3f65f7dab256d1cb28b195ba27c7fc4b1bf2c75e17935dfe9a3846b8c580247304402206cfb872c56f3cab4fcad77f83fc953d037c091d7714c0e7eca1257b56dff57c2022024540ce39d13d55de9f626aee397bad27ef5434f8e57890a3012886c4a6bc1c80121025dec89fee179c0248b24fa2c88db9890a386b836485784d53d12df639fb1e1d6024730440220239dc8ac1c0692b2a4642318cbef810114818132721ab2ba403f037ac0732b3302207112d7d1592b22958184f311f25b8e7a90ac353316bea8af12eeb731e9b0dd540121021a13c8f4c8767317c3cd9d0f7e4d8d8509822ca6891f7cbcc33ec10139b461040247304402205a407877f002d6dc86a83b3c31880366fc3f82204eb7d61a4c3a34c03439592c02201200f52a858463e6547287b2f2964594c6c3233886e12d7d3b499ef59cca5713012102b05ca0a2dc317d82f64483d4087419122eb27e5646e8190a7bac6c5cbacadbe500000000';
  // this is the utxo with txid: 25ba0c45cadf92ded94432101d286975dcdb865df44b68da597910ea783cff74

  // ecpairs things.
  const ecPrivate = bitcoin.ECPair.fromPrivateKey(Buffer.from('64e897b5fac936a30a7a73e1c2892697c91b0705a8d061ea28e59f41d2876e0d', 'hex'), { network: NETWORK });
  const ecPublic = bitcoin.ECPair.fromPublicKey(ecPrivate.publicKey, { network: NETWORK });
  const p2wpkh = bitcoin.payments.p2wpkh({ pubkey: ecPublic.publicKey, network: NETWORK });
  const p2sh = bitcoin.payments.p2sh({ redeem: p2wpkh, network: NETWORK });
  const redeemScript = p2wpkh.output as Buffer;

  // psbt things.
  const psbt = new bitcoin.Psbt({ network: NETWORK });
  psbt.addInput({
    hash: '25ba0c45cadf92ded94432101d286975dcdb865df44b68da597910ea783cff74',
    index: 0,
    nonWitnessUtxo: Buffer.from(nonWitnessUtxo, 'hex'),
    redeemScript,
  });
  psbt.addOutput({
    address: '2MuhtGHkdxiL4BjFAAaYjq8Q2mwnCoYSebt',
    value: 4000,
  });

  const transport = await Transport.create();
  const btc = new AppBtc(transport);
    // fromBitcoinJsLib: p2sh.address,
  const fromLedger = await btc.getWalletPublicKey(path, { format: 'p2sh' });
  const ledgerPublicKey = compressPublicKey(fromLedger.publicKey);
  const bitcoinJsPublicKey = (ecPublic.publicKey as Buffer).toString('hex');
  console.log({ ledgerPublicKey, bitcoinJsPublicKey });
  // {
  //   ledgerPublicKey: '02c4ac4c11e08ffe8dce5b9d74d149ebab49949b195f67932be9dac6c810a6e6dc',
  //   bitcoinJsPublicKey: '02c4ac4c11e08ffe8dce5b9d74d149ebab49949b195f67932be9dac6c810a6e6dc'
  // }

  // signing with ledger.
  const txInput = await btc.splitTransaction(nonWitnessUtxo, segwit);
  const inputs = [[txInput, 0, redeemScript.toString('hex'), 0]]
  const paths = [path];
  const outshex = btc.serializeTransactionOutputs(btc.splitTransaction((psbt as any).__CACHE.__TX.toHex(), true)).toString('hex');
  const signatures = await btc.signP2SHTransaction(inputs, paths, outshex, LOCK_TIME, SIGHASH_ALL, segwit, 2);

  const signer = {
    network: NETWORK,
    publicKey: ecPublic.publicKey,
    sign: ($hash: Buffer) => {
      const signature = ecPrivate.sign($hash); // just for comparison.
      const s = signatures[0];
      const h = bitcoin.script.signature.decode(toByteArray(s));
      console.log({
        $hash: $hash.toString('hex'),
        signature: signature.toString('hex'),
        hsig: h.signature.toString('hex'),
      });
      // return signature;
      return h.signature;
    },
  } as unknown as bitcoin.ECPairInterface;
  psbt.signInput(0, signer);
  const validated = psbt.validateSignaturesOfInput(0);
  console.log({ validated });
  // { validated: false }
  // will be true if I used the signature from ecPrivate.sign($hash);

}

main();
javascript typescript blockchain bitcoin bitcoinlib
1个回答
0
投票

我猜是您在传递给toByteArray函数的字符串中有一个空格。此功能不修剪输入。也不会检查输入的长度是否为偶数。

© www.soinside.com 2019 - 2024. All rights reserved.