package com.google.bitcoin.core;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
public class GraphTransactionOutput extends TransactionOutput implements
Nodeable, GraphSaveable, Indexable, AddressListable {
private GraphTransaction transaction;
private Node node;
public int index;
GraphTransactionOutput(NetworkParameters params, byte[] scriptBytes) {
super(params, scriptBytes);
// TODO Auto-generated constructor stub
}
GraphTransactionOutput(NetworkParameters params, Transaction parent, BigInteger value, Address to) {
super(params,parent,value,to);
}
public byte[] getScriptBytes() {
if(scriptBytes==null){
scriptBytes=(byte[]) node.getProperty("scriptBytes");
}
return scriptBytes;
}
public GraphTransactionOutput(NetworkParameters params, Node n) {
super(params);
node=n;
transaction=null;
value=BigInteger.valueOf((Long) node.getProperty("value"));
// lazy load script bytes in getScriptBytes()
if(node.hasProperty("index")){
index=(Integer) node.getProperty("index");
}
else{
index=0;
}
}
public GraphTransactionOutput(NetworkParameters params, Transaction parent, byte[] payload,
int offset) throws ProtocolException {
super(params, parent, payload, offset);
}
public Node transactionNode(){
Relationship t=node.getSingleRelationship(GraphRelationships.TRANSACTION_OUTPUT, Direction.INCOMING);
if(t==null){
return null;
}
return t.getStartNode();
}
public GraphTransaction transaction(){
if(transaction==null){
Node n=transactionNode();
if(n==null){
throw new RuntimeException("Can't find parent transaction");
}
transaction=new GraphTransaction(params,n);
}
return transaction;
}
public GraphAddress address(){
Relationship r=node.getSingleRelationship(GraphRelationships.TO_ADDRESS, Direction.OUTGOING);
if(r==null){
return null;
}
try {
return new GraphAddress(r.getEndNode());
} catch (AddressFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
public GraphTransaction asInput(){
Relationship r=node().getSingleRelationship(GraphRelationships.TRANSACTION_INPUT,Direction.INCOMING);
if(r==null){
return null;
}
return new GraphTransaction(r.getStartNode());
}
public ArrayList<GraphTransaction> followTainted(int depth){
System.out.println("following tainted depth "+depth);
ArrayList<GraphTransaction> list=new ArrayList<GraphTransaction>();
GraphTransaction inp=asInput();
if(inp!=null){
list.add(inp);
}
if(depth<=0 || inp==null){
return list;
}
for(GraphTransactionOutput o2 : inp.outputs){
list.addAll(o2.followTainted(depth-1));
}
Collections.sort(list, Timeable.TIME_ORDER);
return list;
}
public void save(GraphDatabaseService graph) {
if(node==null){
node=graph.createNode();
}
node.setProperty("value",value.longValue());
try {
GraphAddress a=GraphAddress.findOrCreateAddress(graph, params, getToAddress().toString());
node.createRelationshipTo(a.node(), GraphRelationships.TO_ADDRESS);
} catch (AddressFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ScriptException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public Node node() {
// TODO Auto-generated method stub
return node;
}
@Override
public Integer index() {
// TODO Auto-generated method stub
return index;
}
@Override
public BigInteger value() {
// TODO Auto-generated method stub
return value;
}
public void save(){
save(node().getGraphDatabase());
}
}