package jelectrum; import java.util.TreeMap; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.bitcoinj.core.Sha256Hash; import org.bitcoinj.core.Address; import org.bitcoinj.core.Transaction; import org.bitcoinj.core.TransactionInput; import org.bitcoinj.core.TransactionOutput; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import jelectrum.proto.Kraken.ProtoTxSummary; import jelectrum.proto.Kraken.ProtoTxInSummary; import jelectrum.proto.Kraken.ProtoTxOutSummary; public class TransactionSummary implements java.io.Serializable { private static final long serialVersionUID = 933384464831144891L; private Sha256Hash tx_hash; private TreeMap<Integer, TransactionOutSummary> outs; private TreeMap<Integer, TransactionInSummary> ins; private TreeSet<String> involved_addresses; public TransactionSummary(Transaction tx, TXUtil tx_util, Map<Sha256Hash, TransactionSummary> block_tx_map) { tx_hash = tx.getHash(); involved_addresses = new TreeSet<>(); ins = new TreeMap<>(); outs = new TreeMap<>(); for(TransactionOutput tx_out : tx.getOutputs()) { TransactionOutSummary os = new TransactionOutSummary(tx_out, tx_util); outs.put( tx_out.getIndex(), os ); String addr = os.getToAddress(); if (addr != null) involved_addresses.add(addr); } int idx=0; for(TransactionInput tx_in : tx.getInputs()) { TransactionInSummary is = new TransactionInSummary(tx_in, tx_util, block_tx_map); String addr = is.getFromAddress(); if (addr != null) involved_addresses.add(addr); ins.put(idx, is); idx++; } } public Sha256Hash getHash() { return tx_hash; } public Map<Integer, TransactionOutSummary> getOutputs(){ return ImmutableMap.copyOf(outs); } public Map<Integer, TransactionInSummary> getInputs(){ return ImmutableMap.copyOf(ins); } public Set<String> getAddresses(){ return ImmutableSet.copyOf(involved_addresses); } public ProtoTxSummary getProto() { ProtoTxSummary.Builder tx_b = ProtoTxSummary.newBuilder(); tx_b.setTxHash(getHash().toString()); tx_b.addAllInvolvedAddress(involved_addresses); Map<Integer,ProtoTxInSummary> mut_in = tx_b.getMutableIn(); Map<Integer,ProtoTxOutSummary> mut_out = tx_b.getMutableOut(); for(Map.Entry<Integer, TransactionInSummary> me : ins.entrySet()) { int idx = me.getKey(); TransactionInSummary in = me.getValue(); ProtoTxInSummary.Builder in_b = ProtoTxInSummary.newBuilder(); in_b.setIndex(idx); in_b.setIsCoinbase(in.isCoinbase()); if (!in.isCoinbase()) { in_b.setTxOutHash( in.getTxOutHash().toString()); in_b.setTxOutIndex( in.getTxOutIndex() ); if (in.getFromAddress() != null) { in_b.setFromAddress( in.getFromAddress() ); } } mut_in.put(idx, in_b.build()); } for(Map.Entry<Integer, TransactionOutSummary> me : outs.entrySet()) { int idx = me.getKey(); TransactionOutSummary out = me.getValue(); ProtoTxOutSummary.Builder out_b = ProtoTxOutSummary.newBuilder(); out_b.setIndex(idx); out_b.setValue(out.getValue()); if (out.getToAddress() != null) { out_b.setToAddress(out.getToAddress()); } mut_out.put(idx, out_b.build()); } return tx_b.build(); } public String toString() { StringBuilder sb = new StringBuilder(); sb.append("TX Summary: " + getHash()); sb.append('\n'); sb.append(" IN: " + getInputs().toString()); sb.append('\n'); sb.append(" OUT: " + getOutputs().toString()); sb.append('\n'); sb.append(" ADDRESSES: " + getAddresses().toString()); sb.append('\n'); return sb.toString(); } public static class TransactionOutSummary implements java.io.Serializable { private long value; private String to_address; public TransactionOutSummary(TransactionOutput tx_out, TXUtil tx_util) { value = tx_out.getValue().getValue(); Address addr = tx_util.getAddressForOutput(tx_out); if (addr != null) { to_address = addr.toString(); } } public String getToAddress() { return to_address; } public long getValue() { return value; } public String toString() { return "" + to_address + ":" + value; } } public class TransactionInSummary implements java.io.Serializable { private Sha256Hash tx_out_hash; private int tx_out_index; private boolean is_coinbase; private String from_address; public TransactionInSummary(TransactionInput tx_in, TXUtil tx_util, Map<Sha256Hash, TransactionSummary> block_tx_map) { if (tx_in.isCoinBase()) { is_coinbase=true; return; } tx_out_index = (int) tx_in.getOutpoint().getIndex(); tx_out_hash = tx_in.getOutpoint().getHash(); from_address = tx_util.getAddressForInputViaSummary(tx_in, true, block_tx_map); } public Sha256Hash getTxOutHash(){return tx_out_hash;} public int getTxOutIndex(){return tx_out_index;} public boolean isCoinbase(){return is_coinbase;} public String getFromAddress(){return from_address;} public String toString() { if (is_coinbase) return "coinbase"; return ""+from_address + " " + tx_out_hash + ":" + tx_out_index; } } }