Annotations to Add Blockchain Capabilities to any Java Application

Annotations to Add Blockchain Capabilities to any Java Application

This is an annotation Jar I have created which adds Blockchain capabilites to any Java application (including Android apps). I wrapped up the alpha of this today, it works. I'll try to cover why, how & what it can be used for.

Creating a blockchain ledger can provide self validating data. However, there is coding overhead and discovery involved. Balancing the outgoing / incoming data and ensuring that the data is valid has it's challenges. In order to make adding blockchain abilities easy, I created this annotation preprocessor for Java applications. What that means is, very little code combines with the preprocessor annotations provides a lot of software mechanics, without writing them.

Why?

In the "wired" age, we have to trust not only software, we have to trust data. As we decentralize our data centers into multiple fall overs (redundancies), load balancing (multiple front doors) and such creatures as servlets (multiple exploitable mini server code chunks) the opportunities for bad actors increases. If one servlet, on one fall over is compromised then due to traffic volume the number of users can be affected may be quite high. This is of course in addition to the media dissection, bad publicity, leaving room for competitors to take customers. If one is in a regulated industry (SEC, FDA or other dealing with PII such as HIPAA) then the fallout is amplified for a private or public company.

This can be employed front end and/or back end.

With an annotated class of variables and a dash of business logic, one can create an entire block chain based self validating system. The business logic is clean, simple, easy to sustain and simple to add onto.


The image shows our example application. It is a simple implementation. There is a class "blockTest.java" which has our annotations. The compiler uses these annotations to derive and write a new class based on "blockTest". It will write a class, on it's own at compile time, called "testBlockChainClass.java" (the name defined in the BlockControl annotation) which will provide all of our heavy lifting. We then create a class called "BlockChainTest.java which extends the generated class, this is our business logic. As it extends BlockChainTest, all of our runtime, base variables, setters and getters are now accessible. The business logic that you see is all we need to create a fully functional blockchain system. It will add a ledger, create 5 records and send them to the ledger, and retrieve record #3. If we wanted to add a remote ledger or 2, it would be extremely simple (see API reference on ledgers below for how this is done). The basic architecture is as follows.


What can we use this for? Here a smart phone app verifies that the data within the local db and the remote ledgers are in alignment verifying that the remotes have not been tampered with, nor the local db.


There are times one does not want the blockchain mechanics to sit on the client side of a system for security and to avoid reverse engineering. The ledgers, validation and block chain mechanics can exist on the server side. The data may not be sent to the client if a compromised situation is determined.


Here is an implementation where an email server pumps incoming and outgoing emails to ledgers. The email server does not implement "fetch" so the data only goes one way to the ledgers. The ledgers are monitored by another application which verifies that the data has not been tampered with. Nothing has been modified, removed or artificially added. This is handy for heavily regulated environments where email, email chains must be retained in order for compliance. Due to the mechanics, the system provides verifiable proof that the emails are not altered, deleted or altered. The ledgers may be distributed to remote data centers to provide redundancy as can the auditing system.


In this case, a data acquisition system (for example pharma or diagnostics), retains all data and the paper trail for the raw data. It also does so for the data analytics. This ensures raw data and results have not been altered. This may be good for a regulated environment where not just the data, but the peoples actions must be ensured. Multiple ledgers exist after acquisition to verify data integrity. The same exists for data analysis. As the ledgers are additive, the historical sequence of events are stored to retain the events leading up to conclusions. All 4 remote ledgers are available for regulatory in order to validate integrity of the data and processes for compliance. This may also be beneficial in defending an IP portfolio.

The blockChain annotation system is not designed to exhibit the continuously degrading performance characteristic of cryptocurrency mining. Those systems are deliberately designed to become less and less responsive until the time / power cost required to discover the next magic number are prohibitive. In this tool set, that is avoided in order to provide usability. I suppose one can use this for crypto if they wanted to, however the goal of this is to be more general purpose.

The intent is to create a tool where the data is self validating and can leverage inference to audit the integrity of the run time software that creates it. It is intended to be flexible so it may be molded / adapted into an architecture rather than forcing the application architecture to be defined around it.

So where will this annotation processor go? I have no idea at this time. If there is interest (let me know if this thing sounds useful), and if I can make this worthwhile, then great! If not, then it was still a lot of fun to create.

(Lets get a bit more technical)

The block chain annotation processor right now only works with primitives.

Annotations: By adding simple annotations, the entire heavy lifting of multiple ledgers that co-validate data, with data that self validates within it's link in a blockchain can be added with a few @ symbols and a handful of API calls.

Using annotations in Eclipse

The mechanics will be similar in other IDE's and via command line compilation.

1) Include the jar in your project.


2) Add the jar to the build path.


3) Enable annotations for the project and reference the jar. In your project properties, enable annotation processing, then add the jar in the Factory Path.

Now every time the project builds, the annotations will direct the compiler to execute the BlockChain.jar preprocessor which will parse your annotated class and build the infrastructure for your projects business logic.

@BlockControl(ledgerClass = "myClassName", key = "mySecretKey")

The BlockControl annotation declares a class as a "Block Chain" class. It is a class with variables that are accessed via setters and getters (standard Java stuff). The ledgerClass becomes your business logic that you incorporate into your application, which extends the class containing the data elements (plus setters / getters). This will make more sense later on.

 @GetLedgerVariable

GetLedgerVariable denotes a getter which will provide a member variable value. The getter is 100% identical to any getter that anyone has ever made. By adding this annotation, that getter is now linked into the block chain. When you send your data out to the ledger(s) it will be pulled from this method.

@SetLedgerVariable

SetLedgerVariable denotes a setter which will set a member variable value. The setter, again is 100% identical to any setter that anyone has ever made. By adding this annotation, that setter is now linked into the block chain and will be called when data returns from the ledger(s), provided they are validated.

Your record structure class becomes a superClass which uses the ledgerClass annotation.

For example by declaring ledgerClass = "myClassName" in your class annotation, a new class will be auomatically created called "myClassName.java" in the same package. The preprocessor will use your annotations and create this class file with everything predone. This includes pulling values, pushing values, JSONifying data, block key checksumming and validation as wells as publishing/fetching to/from multiple ledgers. All of this can be accessed via a couple of API calls.

This is a section of what the class looks like with the annotations. Just simply primitive variables, setters and getters.


API Calls

I've tried to make the API calls as simple as possible. There are just a few in order to reduce code complexity.

createNewLedgerRecord();

The createNewLedgerRecord indicates that you will be pushing out a new record to the ledgers. It performs all of the required initialization and preparation of a new ledger entry, including the "rolling" key.

generateLedgerEntry();

The generateLedgerEntry call commits your data to the ledgers. When called, it will call your getters to get those current values. It will perform all of the work in order to create a valid link and build the payload (in JSON). One call to this, and the current state of your data is sent to all ledgers. Included are the rolling key which will move forward, which sits internally, ready for the next commit.


boolean fetchLedgerEntry(BigInteger);

The fetchLedgerEntry(BigInteger) API call will perform a lot of work for you. It will pull all records from all ledgers for the requested record. It will then validate that they are all in alignment. If even one ledger is out of sync an error is flagged and a LedgerExpection is thrown. It will not allow any mismatch between ledgers, they must be 100% in alignment. If the ledgers are in alignment, it will pull the data for the requested record, and extract all of the data as well as reconfirm that the block chain entry is accurate. It will also validate that the data has not been tampered with. If any checks fail, the data is zero'd out and an error is flagged. If there is no error, the the data within you class is auto filled with the validated data. The return value is true if the data passed validation, false if it failed.

We can set some values within the system via a few API calls, or leave them as they are built by the preprocessor.

setKey(String)

setKey sets the blockChain validation key. It will default to what is declared in the @BlockControl annotation. There is no limit to the size of the key. There is no limited character set.

setKeyLength(int)

The keyLength determines the number of bytes within the block control validation. The default value is 128 bytes (1024 bits). You may set any value from 64 to 1024 bytes in length (8192 bits).

setLedgerTool(LedgerTool)

A ledger tool is use to create and verify a payload of a set of values. One can create a ledger tool, then use setLedgerTool to link it in so it is used. That way, custom validation can be created. Alternatively one can rely on their "key" as set within the BlockControl annotation.

Ledgers

A ledger can be a local database, flat file, SQL database, remote server, realm db or other thing one can think up. There is also no limit at this time to the number and types of ledgers you may connect. For example, you may use an SQL db on a mobile phone which also publishes to a remote server via 443 (secure comms). You may have a dozen remotes which will then all be part of the data validation.

Here is a simple example of the how this is utilized. This is an entire block chain system in it's entirety that leverages this annotation system.


This small class does the following. It creates an instance of a ledger (this one is just local / in memory). We then add some records, and retrieve element #3. The addRecord method creates a new ledger record, sets the values, then publishes the ledger entry. If we wanted to add 2 more ledgers, one may be a local database and the other would be a remote, we would simply make the following change.


By simply adding 2 more ledgers, we gain the following. We now have an SQL db which is a ledger, and a remote ledger. When we generate a ledger entry it is stored in all 3 ledger for us. When we "fetch" record #3, the data will be validated between all 3 ledgers ensuring that none have altered or missing data. We create and register the ledgers, no other code changes are required. In order to perform all of the data distribution, retching, validation and setting our variables no other code is added. Simply add LedgerDestinations and the heavy lifting occurs in the background.


Ledgers implement an interface called "LedgerDestination".

LedgerDestination has 3 methods for you to override.

public void publish(BigInteger index,String Payload)

Data comes out of the blockChain tools when you generate a ledger entry to these ledger implementations. You can then code anything you want in them. You can make them in memory (unwise), databases, URL's or whatever. The data is passed as the parameter is a JSON payload in a string. It can be parsed at the endpoint where it is stored into column names or however one feels it should be stored. The index should be unique, it will increment.

public String fetch(BigInteger index)

This call is requested when we need to retrieve data. Here you perform a get from your storage, the return value is a JSON string set to be similar format to what was saved.

public BigInteger getNextIndex()

If the application restarts we do need to know the next index available. NOTE: this will likely change along with internals. It can simply be grabbing the last unique index value from your db.

LedgerTool

You may use your own ledger tool which create the validation, and verifies the data which is returned from the ledgers. A ledger tool implements the LedgerTool interface. The LedgerTool interface needs 3 methods, prepareLedgerEntry, createLedgerEntry and verifyLedgerEntry.

The simple architecture would look like the following.


byte[] prepareLedgerEntry(byte[] previousBlockCheck)

Initialization is performed here. The previous block check value is provided so it may be used to generate a logical back link into the chain which already exists. This new block check value should be used for the following operation.

byte[] createLedger(BigInteger index,String ledgerKey, Object theItem)

index is the absolute index of this element within the ledger where it will reside. ledgerKey is the key denoted in the BlockControl annotation. It may be used or ignored and be replaced with a different key you use within your ledger tool. The last parameter is the item to be added to the payload. You should use this object as part of your validation key creation. The response is what the current validation value is. When the data is committed to the ledgers, this value is the contents of the "BlockCheck" entry. The createLedger will be called for every value which will exist in the resulting payload.

boolean verifyLedgerEntry(BigInteger index, String payload)

the index is the absolute index of this element within the ledger. The payload is the JSON payload that has been validated as uniform between ledgers. the verifyLedgerEntry will not be even called if the ledgers are not in agreement. You will need to parse the payload and perform whatever validation you need to verify the "BlockCheck" entry in the payload.

- fin - on this one, for now. If this looks useful, do let me know. Thanks.


(C) 2018 Andy Pal

Andy, thanks for sharing!

Like
Reply

To view or add a comment, sign in

More articles by Andy Pal

Others also viewed

Explore content categories