2

I would to get the fee when I search for a transaction using getrawtransaction, but the JSON-RPC does not return this.

https://chainquery.com/bitcoin-api/getrawtransaction

So to achieve this, my idea is to:

  1. Call getrawtransaction for each vin, and save the output value for each one.
  2. Sum all the output value for the vins, and subtract the sum of the vout values to give you the remainder.

I know this will work, but I dislike having to call getrawtransaction for each vin (as this JSON-RPC call will be made 200+ times for some transactions).

Is there a more efficient way? Or is this currently the only way to calculate the fee for a transaction using bitcoin-cli?

Aside: Why doesn't getrawtransaction return a fee field, like the transactions in getrawmempool and getblocktemplate do?

  • Also looking at how to do this more efficiently... I'm wondering if we trawl the blockchain backwards (say from block 500 down to 200) we might be able to practise some sort of memoisation? – GrayedFox Mar 14 '18 at 7:07
1

To calculate fees. Take sum of all vouts.For every vin there will be prev txid and outputindex, Get this txid with getrawtransaction or some other way,go to vouts of this new tx at index, here you will get amount, Repeat this for every vin. Take sum of this vins. Take difference between vin and vout you will get fees.

To avoid calling ever time you need to store txids somewhere or user something like insight.

0

From experience, the vin and vout elements all have a "value" field - you just need to sum up the vin values and substract the sum of the vout values.

  • Only the transaction outputs have values. The values of the inputs are inferred by the outputs they reference. – Jestin Jan 6 '17 at 21:30
  • You are right - I was looking at the output from a 3rd party provider and got confused. Thanks for pointing this out. – Alex Jan 7 '17 at 13:33
0

There is a way to make these calls more efficient and it's through doing some memoisation.

There's no way around having to make the getRawTransaction call on each unique transaction at least once - but that doesn't mean we need to do it again!

Here is how I've done it for the blockscrape project I'm working on:

const api = require('./api/api.js')

let transactions = {}

const storeTransaction = (tx, vout) => { transactions[tx] = vout }

const transactionExists = (tx) => transactions[tx] ? true : false

const retrieveTransacton = (tx) => transactions[tx]

// loop through the outputs of a tx, greedily returning the value of an output tx where n matches vOutIdx
const getMatchingTransactionValue = async (txHash, voutIndex) => {
  let tx = undefined
  let voutArray = undefined

  if (transactionExists(txHash)) {
    voutArray = retrieveTransacton(txHash)
  } else {
    tx = await api.getRawTransaction(txHash)
    voutArray = JSON.parse(tx).vout
    storeTransaction(txHash, voutArray)
  }

  for (let i = 0; i < voutArray.length; i++) {
    if (voutArray[i].n === voutIndex) {
      return voutArray[i].value
    }
  }
}

The api file is just a wrapper for spawning a child process and executing api specific arguments (i.e. litecoin-cli getrawtransaction txhash 1) - which are themselves wrapped into a promise (hence using the await keyword).

The key to taking advantage of the memoisation is that you'll need to traverse whatever blocks you need backwards -- otherwise you'll be storing transactions in memory and never find a match.

This is because all transactions on the blockchain reference both inputs and outputs and we need to work with the outputs (later transactions) in order to calculate the fee - which means if we work backwards, we will likely store many transactions which are referenced by past blocks (but we won't ever find transactions which are referenced in the vout array of future blocks, since our program has no knowledge of them yet as they are in the "future").

Of course, this is one of the advantages of working with historical data - when we know, in reality, those transactions do exist, we just need to adapt our program to reflect this fact :)

  • Apologies for the technical nature of this answer - I just realised I'm on bitcoin.so and not the core stack overflow (programmers) section. I will leave it as it still might be of some use to the OP or readers. – GrayedFox Mar 14 '18 at 13:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.