paulmillr / scure-btc-signer

Audited & minimal library for creating, signing & decoding Bitcoin transactions.
https://paulmillr.com/noble/#scure
MIT License
134 stars 33 forks source link

Can't loop over tx outputs: Wrong input index=2 at Transaction.checkInputIdx #35

Closed 1guzzy closed 1 year ago

1guzzy commented 1 year ago
public static getFee(rawtx): bigint {
        let tx = btc.Transaction.fromPSBT(Buffer.from(rawtx, 'hex'))
        console.log(tx)
        let inputs = []
        for (let i = 0; i < tx.inputsLength; i++) {
            inputs.push(tx.getInput(i))
        }
        console.log('inputs', inputs)
        let outputs = []
        for (let j = 0; j < tx.outputsLength; j++) {
            console.log({ j, outputsLength: tx.outputsLength })
            try {
                // outputs.push(tx.getOutput(j))
                const o = tx.getOutput(j)
                outputs = [...outputs, o]
            } catch (e) {
                console.log('e)
            }
        }
        console.log('outputs', outputs)

        const sumInputs = inputs.reduce((sum, input) => sum + input.witnessUtxo.amount, BigInt(0))
        const sumOutputs = outputs.reduce((sum, output) => sum + output.amount, BigInt(0))
        console.log(sumInputs, sumOutputs)
        const fee = sumInputs - sumOutputs

        console.log({ fee })

        return BigInt(fee)
    }

Looping over transaction outputs fails some of the time even though the index is clearly inbounds.

paulmillr commented 1 year ago

@1guzzy is there a rawtx you could give us?

1guzzy commented 1 year ago

yep!

70736274ff0100fd3101010000000398f8dab0b60c615e3cc682ff300ca59240a1476deab75b0943686aa001f8d11f0000000000fdfffffff531814c4825910beaadd164dd2cec9865ab559d35d984d5943d6ba1cec9ffbd0000000000fdffffff98f8dab0b60c615e3cc682ff300ca59240a1476deab75b0943686aa001f8d11f0100000000fdffffff045802000000000000225120efab8790669e6aff09ee5cb93e36d3c1a463d71865b374609219960c3405c9ae044c0000000000002251208d8cdb160981606956c6786512e870b8dac366877d2a88b3b0205026a6930b65210a000000000000225120efab8790669e6aff09ee5cb93e36d3c1a463d71865b374609219960c3405c9ae1c02000000000000225120d11b52ebc5e8a1d3010b1d1494ea526494e651bfe81d7e9ba3b7779623f954ba000000000001012b5c4e000000000000225120efab8790669e6aff09ee5cb93e36d3c1a463d71865b374609219960c3405c9ae0001012b210a0000000000002251208d8cdb160981606956c6786512e870b8dac366877d2a88b3b0205026a6930b650001012b1fb5000000000000225120efab8790669e6aff09ee5cb93e36d3c1a463d71865b374609219960c3405c9ae0000000000
1guzzy commented 1 year ago

I resorted to

public static getPSBTFee(psbt_hex: string): bigint {
        let tx = btc.Transaction.fromPSBT(Buffer.from(psbt_hex, 'hex'))

        let input_sats = BigInt(0)
        let output_sats = BigInt(0)

        // @ts-ignore
        tx.inputs.forEach((e) => {
            input_sats = input_sats + e.witnessUtxo.amount
        })

        // @ts-ignore
        tx.outputs.forEach((e) => {
            output_sats = output_sats + e.amount
        })

        const fee = input_sats - output_sats

        console.log({ fee })

        return fee
    }

works fine!

paulmillr commented 1 year ago

@1guzzy I have launched the code and everything worked just fine. Can't reproduce this.

import * as btc from '@scure/btc-signer';

let rawtx = '70736274ff0100fd3101010000000398f8dab0b60c615e3cc682ff300ca59240a1476deab75b0943686aa001f8d11f0000000000fdfffffff531814c4825910beaadd164dd2cec9865ab559d35d984d5943d6ba1cec9ffbd0000000000fdffffff98f8dab0b60c615e3cc682ff300ca59240a1476deab75b0943686aa001f8d11f0100000000fdffffff045802000000000000225120efab8790669e6aff09ee5cb93e36d3c1a463d71865b374609219960c3405c9ae044c0000000000002251208d8cdb160981606956c6786512e870b8dac366877d2a88b3b0205026a6930b65210a000000000000225120efab8790669e6aff09ee5cb93e36d3c1a463d71865b374609219960c3405c9ae1c02000000000000225120d11b52ebc5e8a1d3010b1d1494ea526494e651bfe81d7e9ba3b7779623f954ba000000000001012b5c4e000000000000225120efab8790669e6aff09ee5cb93e36d3c1a463d71865b374609219960c3405c9ae0001012b210a0000000000002251208d8cdb160981606956c6786512e870b8dac366877d2a88b3b0205026a6930b650001012b1fb5000000000000225120efab8790669e6aff09ee5cb93e36d3c1a463d71865b374609219960c3405c9ae0000000000';
let tx = btc.Transaction.fromPSBT(Buffer.from(rawtx, 'hex'))
console.log(tx)
let inputs = []
for (let i = 0; i < tx.inputsLength; i++) {
  inputs.push(tx.getInput(i))
}
console.log('inputs', inputs)
let outputs = []
for (let j = 0; j < tx.outputsLength; j++) {
  console.log({ j, outputsLength: tx.outputsLength })
  try {
    // outputs.push(tx.getOutput(j))
    const o = tx.getOutput(j)
    outputs = [...outputs, o]
  } catch (e) {
    console.log('ERROR', e)
  }
}
console.log('outputs', outputs)

const sumInputs = inputs.reduce((sum, input) => sum + input.witnessUtxo.amount, BigInt(0))
const sumOutputs = outputs.reduce((sum, output) => sum + output.amount, BigInt(0))
console.log(sumInputs, sumOutputs)
const fee = sumInputs - sumOutputs

console.log({ fee })