We need to monitor / intercept / inspect all bitcoin transactions that are being sent to certain rather small but ever changing list of Bitcoin addresses. Basically, we just need to run a custom code in the event of any new transaction being sent through Bitcoin P2P Network. What would be a reasonable technical approach to accomplish that task? Thanks!
Here is a simple architecture that allows you to run your custom Java code in the event of any new incoming Bitcoin transaction being broadcast through global Bitcoin P2P network.
Your Java application would use BitcoinJ library ( Maven ) in a wallet-less mode. Using BitcoinJ, your Java application connects to your own trusted Bitcoin Node only, and it is not directly connected to any other Bitcoin node.
Your node in its turn is connected to Bitcoin Network as usual. Having an intermediate Bitcoin Node running "out of the box" Bitcoin Core software allows for greater security, control and flexibility. For example, your node would only relay valid bitcoin transactions to your Java code. Also, your Java code could talk directly to your Bitcoin node through JSON-RPC API, if necessary. Also, you could enable advanced logging on a Bitcoin Node to help with any advanced troubleshooting, debugging, etc.
Here is the essentail part of the code:
mPeerGroup = new PeerGroup(MainNetParams.get());
mPeerGroup.addOnTransactionBroadcastListener(new OnTransactionBroadcastListener() {
public void onTransaction(Peer peer, final Transaction transaction) {
try {
//
// !!!! NEW BITCOIN TRANSACTION !!!!
//
// put your custom transaction processing logic here
// it is a good idea to keep it short here and just put TRX info into some sort of QUEUE
// and any heavy processing should be done asyncronously in a separate thread(s) that
// are connected to the same QUEUE
//
//
//
CallableStatement cstmt = conn.prepareCall("{call dbo.ProcessNewTransaction(?)}");
cstmt.setString("Hash", transaction.getHash().toString());
cstmt.execute();
} catch (SQLException e) {
logException(e);
}
mTrxCount ++;
printStatus();
}
});
mPeerGroup.addAddress(InetAddress.getByName(NODE_ADDRESS));
mPeerGroup.start();
Here is the complete Main.java
file that could be compiled and scheduled to run as a console Java application:
package com.yourcompany.BitcoinMonitor;
import org.bitcoinj.core.Peer;
import org.bitcoinj.core.PeerGroup;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.listeners.OnTransactionBroadcastListener;
import org.bitcoinj.params.MainNetParams;
import java.io.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.*;
public class Main {
// IP address of your own Bitcoin Node running standard Bitcoin Core daemon
private static final String NODE_ADDRESS = "10.10.20.20";
private static final String CONNECTION_STRING = "jdbc:sqlserver://localhost;databaseName=your_database_name; blah blah params";
private static PeerGroup mPeerGroup;
private static long mTrxCount = 0;
public static void main(String[] args) {
try {
init();
if(args.length == 0) {
logException(new Exception("Please enter the Auth options. Example: userName=LOGIN;password=PASS"));
}
String authOptions = args[0];
String connectionString = String.format(CONNECTION_STRING, authOptions);
final Connection conn = DriverManager.getConnection(connectionString);
if (conn == null) {
logException(new Exception("Connection error"));
System.exit(0);
}
logException(new Exception("Connected"));
mPeerGroup = new PeerGroup(MainNetParams.get());
mPeerGroup.addOnTransactionBroadcastListener(new OnTransactionBroadcastListener() {
public void onTransaction(Peer peer, final Transaction transaction) {
try {
//
// !!!! NEW BITCOIN TRANSACTION !!!!
//
// put your custom transaction processing logic here
// it is a good idea to keep it short here and just put TRX info into some sort of QUEUE
// and any heavy processing should be done asyncronously in a separate thread(s) that
// are connected to the same QUEUE
//
//
//
CallableStatement cstmt = conn.prepareCall("{call dbo.ProcessNewTransaction(?)}");
cstmt.setString("Hash", transaction.getHash().toString());
cstmt.execute();
} catch (SQLException e) {
logException(e);
}
mTrxCount ++;
printStatus();
}
});
mPeerGroup.addAddress(InetAddress.getByName(NODE_ADDRESS));
mPeerGroup.start();
while (true) {
if(!mPeerGroup.isRunning())
mPeerGroup.start();
try {
Thread.sleep(2000); // in milliseconds, so we sleep for 2 seconds here
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
} catch (UnknownHostException e) {
logException(e);
} catch (SQLException e) {
logException(e);
} catch (FileNotFoundException e) {
logException(e);
}
}
private static void init() throws FileNotFoundException {
// log file
System.setErr(new PrintStream(new File("java_service.log")));
}
private static void logException(Exception e) {
System.err.println(e.getMessage());
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
System.err.println(sw.toString());
System.out.println(e.getMessage());
}
private static void printStatus() {
String message = String.format("Global Transactions Received: %d", mTrxCount);
System.out.print("\r");
System.out.print(message);
}
}
FavScripts.com is a free tool to save your favorite scripts and commands, then quickly find and copy-paste your commands with just few clicks.
Boost your productivity with FavScripts.com!