bitcoinJ get transaction value

454 views Asked by At

I downloaded a lot of blockchain data using https://bitcoin.org, I took some file and I try to analyse it with bitcoinj library.

I would like to get information from every transaction: -who send bitcoins, -how much, -who receive bitcoins.

I use:

   <dependency>
      <groupId>org.bitcoinj</groupId>
      <artifactId>bitcoinj-core</artifactId>
      <version>0.15.10</version>
    </dependency>

I have a code:

NetworkParameters np = new MainNetParams();
Context.getOrCreate(MainNetParams.get());
BlockFileLoader loader = new BlockFileLoader(np,List.of(new File("test/resources/blk00450.dat")));

for (Block block : loader) {
  for (Transaction tx : block.getTransactions()) { 
    System.out.println("Transaction ID" + tx.getTxId().toString());
    for (TransactionInput ti : tx.getInputs()) {
      // how to get wallet addresses of inputs? 
    }

  
    // this code works for 99% of transactions but for some throws exceptions
    for (TransactionOutput to : tx.getOutputs()) {
      // sometimes this line throws: org.bitcoinj.script.ScriptException: Cannot cast this script to an address
      System.out.println("out address:" + to.getScriptPubKey().getToAddress(np));
      System.out.println("out value:" + to.getValue().toString());
    }
  }
}

Can you share some snippet that will work for all transactions in the blockchain?

1

There are 1 answers

0
mikemelon On

There are at least two type of transaction, P2PKH and P2SH. Your code would work well with P2PKH, but wouldn not work with P2SH. You can change the line from:

System.out.println("out address:" + to.getScriptPubKey().getToAddress(np));

to:

System.out.println("out address:" + to.getAddressFromP2PKHScript(np)!=null?to.getAddressFromP2PKHScript(np):to.getAddressFromP2SH(np));

The API of Bitcoin says the methods getAddressFromP2PKHScript() and getAddressFromP2SH() are deprecated, and I have not find suitable method.

However, P2SH means "Pay to Script Hash", which means it could contain two or more public keys to support multi-signature. Moreover, getAddressFromP2SH() returns only one address, perhaps this is the reason why it is deprecated.

I also wrote a convinient method to check the inputs and outputs of a block:

private void printCoinValueInOut(Block block) {
    Coin blockInputSum = Coin.ZERO;
    Coin blockOutputSum = Coin.ZERO;

    System.out.println("--------------------Block["+block.getHashAsString()+"]------"+block.getPrevBlockHash()+"------------------------");
    for(Transaction tx : block.getTransactions()) {
        Coin txInputSum = tx.getOutputSum();
        Coin txOutputSum = tx.getOutputSum();   
        blockInputSum = blockInputSum.add(txInputSum);  
        blockOutputSum = blockOutputSum.add(txOutputSum);
        System.out.println("Tx["+tx.getTxId()+"]:\t" + txInputSum + "(satoshi) IN, " + txOutputSum +  "(satoshi) OUT.");
    }
    System.out.println("Block total:\t" + blockInputSum + "(satoshi) IN, " + blockOutputSum +  "(satoshi) OUT. \n");
}