Blockchain for Asset Tracking

Jan 16, 2025

Introduction

A few days ago, I was hanging out with some friends, and since we're all engineers, we got onto the topic of AI and other "revolutionary" tech that ended up being scams in recent years. That reminded me of the first project I ever worked on professionally, so I thought I should write it down before it was lost to time.

During my last year of undergrad in 2017, a friend helped me land a summer internship at a small R&D startup on campus. After the interview, they offered me a full-time position, and I decided to accept as I had no other plans for that summer.

On my first day, they handed me a two-page document outlining a vague proposal for an asset-tracking blockchain, told me to get started, and basically left me alone to figure it out. It quickly became clear that I was in charge of everything: picking the tech stack, designing the architecture, writing all the code, and handling any other tasks that popped up. I was more or less on my own, with only a manager occasionally dropping by to see how things were going.

The Project

After putting everything together, I realized the project was a collaboration between the biggest telecom company in my country and a car manufacturer, and the plan was to create a small proof-of-concept asset tracker using blockchain as part of some European Industry 4.0 initiative. The goal was to track car parts from the moment they were produced at the factory, through transport, assembly, and the vehicle's entire lifespan. This meant the car manufacturer could reject a batch at any point if something went wrong during shipping, with every event recorded on a blockchain. Every participant would have their own node(s), giving them control over a portion of the ledger, and each party would only see the information relevant to them. Part providers might see status updates and IDs, while the manufacturer would get full details once the parts were installed.

Originally, the plan was to build at least a basic blockchain with some authentication, plus a REST API to trigger various smart contracts. We also needed a website to show how parts moved at each stage, and an Android app to demonstrate how a client might interact with those parts once they were in a car, covering things like warranty info, certificates, or recall notices for specific batches.

After a few meetings with the telco people, it became clear they weren't really technical, didn't care about how any of it worked under the hood, and found the whole blockchain concept way over their heads. So, I put together a high-level diagram that outlined all the operations they were asking for, and it took more than ten rounds of revisions before they finally gave me the green light to start building.

High-Level Design One of the later versions of the high-level design. The final iteration became overly complicated and hard to follow

Technology, Architecture and Development

Choosing the Right Chain

Conceptually, blockchain is pretty straightforward. It is a distributed ledger, essentially a slow database secured by the mutual distrust among participants. But making it work for this project was far more complicated than I expected.

I dove into everything I could find on blockchain, reading whitepapers, technical docs, and anything that might help me figure out which option could actually work. Choosing the right one wasn't just important; it was critical to the entire project. I tested all the major platforms, like Ethereum, and even explored some lesser-known ones, setting up nodes, experimenting with side chains, and learning Solidity to write smart contracts. It didn't take long to see how chaotic the blockchain world was back then. Scams were everywhere: pump-and-dumps, Ponzi schemes, burning tokens to inflate value, stealing from the top, and plain fraud. Most (if not all) projects felt more like elaborate money grabs than real solutions.

The biggest issue was the state of the technology at that point. Most platforms were buggy, barely documented, and still in early development. To make things worse, the project required a private, permissioned blockchain. After testing every option available, the only platform that came close to meeting the requirements was Hyperledger Fabric.

One invaluable tool was Hyperledger Composer (now deprecated), an online framework that allowed you to model the business logic as assets, participants, and transactions, including access control rules and complex queries. This model could later be exported and deployed to an instance of Hyperledger Fabric, which made it the easiest solution to prototype by far although later on the chaincode and logic would be migrated to more high-level SDKs.

System Design

Architecture Simplified architecture diagram illustrating the blockchain network, peers, ordering service, certificate authority, and backend microservices

Every blockchain user had an identity card containing all the cryptographic keys necessary to operate as a participant. To simplify blockchain interactions for non-technical end users who couldn't manage their own credentials, I built a Spring Boot backend service that wrapped participant identity management into an easy-to-use interface. This service was deployed on Dockerized Tomcat servers and abstracted the authentication and permission logic. It exposed a REST API secured with JWT authentication.

The first iteration of the solution used composer-rest-server with passport-jwt running in a Docker container, providing a REST interface between the backend service and the blockchain network. After importing an authentication card and creating an admin participant, new participants and their identities were derived using the Fabric CA. These identities were returned as .card files, which were then securely stored in a MySQL database.

The backend service required only a username and password to authenticate users and automated the entire identity management process, including generating, storing, and managing blockchain credentials and permissions on their behalf.

The network itself followed a standard Hyperledger Fabric setup with four peers, divided into two VPCs that communicated with each other. A key project requirement was that both the telco and the manufacturer/assembler needed their own peers. Even though everything was deployed in the same AWS account, this added complexity because peers had to communicate across the internet. This was achieved using the Gossip protocol, built on top of gRPC over HTTP/2 with TLS for secure communication. This configuration required assigning public IPs to each node, opening the correct ports, and extensive DNS glue in the configuration files. In those days, the Gossip protocol was somewhat unstable, resulting in considerable debugging efforts for wire-level issues.

To optimize performance, each peer was configured to use an instance of CouchDB as the world state database, enabling efficient querying and minimized expensive blockchain lookups for read requests, which made up around 90% of the network's traffic.

Initially, the Solo consensus protocol was used. As its name implies, Solo doesn't provide a true consensus mechanism; transactions are simply added to the ledger as they are received. Later, this was replaced with Kafka (Crash Fault Tolerant - CFT) as the ordering service. Kafka introduced a more robust approach but added complexity since it required both Kafka and ZooKeeper clusters. Also, it only supports CFT and does not tolerate Byzantine faults (malicious actors in the network). The consensus mechanism was deployed on orderer nodes (a primary and a backup), which collectively interacted with the Kafka cluster to process and order transactions as part of the ordering service.

In addition to the peer and orderer nodes, a Certificate Authority (CA) node was deployed to issue and manage the cryptographic certificates used by all participants.

Later in development, a Node-RED instance was added to process and insert MQTT messages from multiple IoT devices as blockchain transactions.

The final step before delivering the project involved rewriting most of the chaincode and removing the Composer services and dependencies, replacing them with native code from the Fabric SDK on the backend.

Deadlines and Scope Creep

The first major milestone came when I completed the base blockchain, smart contracts, and backend interfaces. To mark the occasion, I visited the telco to demonstrate the system and give a series of talks on corporate blockchain to some of their C-suite executives. The topics ranged from the state of blockchain at the time, how cryptocurrencies worked, a basic demonstration of a Proof of Work algorithm, and possible monetization strategies for the type of work I was doing.

When we reviewed the progress and the remaining tasks, which mainly involved building a web interface and a couple of Android apps to wrap the smart contract functionality I had written, I made the mistake of casually suggesting that it might be interesting to showcase the project in the physical world. I might have made things worse by mentioning that I could probably build some IoT sensors to mock the movements of parts during delivery.

I didn't expect anything to come of those offhand comments, but apparently, they were so pleased with the work at that point that they immediately extended the project to include building a scaled model of the part lifecycle along with IoT devices crammed with all sorts of sensors.

I proposed building the demo model out of Lego, which would have been by far the cheapest and coolest option, perfectly complementing the custom-built nature of the sensors. Unfortunately, the idea was shot down, and the work was outsourced by the telco to a third party for an insane amount of money. I get it. There was still a ton of programming and sensor development left on my plate, and from their perspective, they really didn't want me getting autistically sidetracked building Lego models instead of finishing the "core deliverables™".

Demo Model Original 3D mockup of the original part lifecycle model, featuring a circular track layout and placeholders for IoT sensors and part containers

Demo Model Final Photo of the completed physical demonstration model, showing plastic buildings, a track for toy trucks, and some IoT sensors

IoT

As part of the extended project, I had to build IoT sensors to be installed in the crates transporting the parts. Each crate was treated as a logical unit on the blockchain, similar to a lot, with a capacity of around 8 to 10 parts.

Part Containers Photos of large crates designed to hold multiple car parts, each container treated as a logical unit on the blockchain

There were a few specific requirements these sensors had to meet:

  • A battery life of at least 72 hours
  • Rugged and durable enough to survive direct impacts and bumps during transport
  • Equipped with a 3G/LTE modem and GPS
  • An impact sensor to detect shocks

After some research, I found the perfect solution in the Particle Asset Tracker Kit v2. The kit came with everything I needed: a Particle Electron (microcontroller with an STM32 Cortex M3 and a U-Blox 3G modem), a Flex PCB Antenna, a GPS module with a ceramic antenna, an accelerometer, and a hard plastic case with mount points for the boards.

Particle Asset Tracker Kit v2 components Particle Asset Tracker Kit v2 components

To expand its functionality, I added an Adafruit BME280 (temperature, humidity, and pressure sensor), a TSL2561 light sensor, and a PN532 NFC RFID Module V3. The NFC tags were meant to simulate GPS positions for demos and presentations in the physical model. The model itself consisted of plastic buildings, black tracks, and toy trucks that represented the parts' journey through the blockchain. I also included a small monochrome 128x64 OLED screen to display real-time sensor values and send status messages whenever data was transmitted to the Node-RED broker.

Programming the modules was relatively straightforward. Libraries for the GPS and accelerometer were available for Arduino, and Adafruit provided libraries for the other sensors. This meant I had about 95% of the software completed in less than eight hours, with only a few tweaks needed for animations using the Adafruit GFX library.

Development board Close-up view of the prototype development board showing the Particle Electron, accelerometer, buzzer, and other sensors wired together.

I wanted to design a custom PCB that integrated all the sensors, but my bosses didn't think it was worth spending time on something they didn't consider critical. In the end, I settled for creating a small PCB caddy to hold the sensors together.

First revision PCBs Stack of bare, first-revision printed circuit boards used to house multiple sensors and the OLED screen

First revision PCBs assembled First PCB revision after assembly, showing soldered components but with a missing ground connection that had to be patched

Second PCB Kicad Screenshot of the second PCB layout in KiCad, displaying component placements and circuit traces for the improved sensor board

Second PCB Kicad 3D Preview 3D render from KiCad showing the arranged components, footprints, and trace routing for the second revision of the PCB

Second PCB revision before assembly Newly fabricated second-revision PCBs arranged on a workbench, now with correct ground connections. The first prototype had been soldered using magnet wire while awaiting the final board shipment

For blockchain communication, I added an MQTT client to the Node-RED instance, with a simple per-device authentication scheme for requests. Messages were sent as strings, formatted into JSON objects, processed, and inserted into the blockchain, including the sensor Id and timing info.

Node-RED schema Screenshot of the Node-RED flow, showing MQTT inputs, JSON processing, and the subsequent publishing of data to the blockchain network

The frustrating part came when someone at the telco decided, after I had already built five or so sensors, that they should be integrated into the physical demo. They reached out to the company building the model and asked them to make it interactive. Their solution was to add black tracks for toy trucks to follow, and I was tasked with fitting the sensors into the trucks.

Black tracks Photograph of the black plastic tracks arranged on a surface, designed to guide toy trucks carrying the IoT sensor units

The maximum load the trucks could carry was around 200g, but the components without the case weighed approximately 210g. I had to remove the case and glue the parts directly to the truck's chassis, but the result was surprisingly acceptable. The modified trucks were able to move almost at full speed, the sensors successfully transmitted data, and the battery lasted long enough to complete a full demo of all the available smart contracts.

Weighed parts Electronic scale measuring the weight of the microcontroller, sensors, and other components to confirm their total mass before installation

In the end, I managed to get both sensor types working. I had to split the IoT codebase between the sensors installed in real trucks and those used in the physical demo. The demo sensors had their GPS modules disabled, and their NFC readers were pointed downward. Whenever the trucks passed over one of the tags placed around the model, they sent a fake event to the blockchain, which was displayed on a webpage in near real-time.

Web and Mobile Apps

Web Page

The webpage served as the primary interface for showcasing the system, whether during presentations to executives or as part of the exhibit in the visitors' center. It connected to the Spring Boot REST API backend to provide an interface for tracking and managing data related to parts, containers, vehicles, and events stored on the blockchain. Users could also add clients and technicians, configure IoT devices and container routes, and review event histories.

When I started working on the backend, my manager brought in two interns from my university to build the site as part of a program where they earned academic credits for their work. They decided to use React for the frontend, but I wasn't allowed to manage or guide them since my manager was supposed to oversee their progress. After about four months, their internship ended, and the code they delivered was completely broken, full of bugs, and unfinished. It didn't even come close to being functional, so I had to scrap it entirely.

To rebuild the site, my manager brought in another engineer to take charge of the frontend while I focused on the other million things I needed to finish. He decided to use Groovy and Grails for the site. It was my first time building websites with Groovy, but we worked well together and eventually became friends.

One particularly useful feature was the ability to reset the blockchain directly from the frontend. This triggered a backend call that ran a series of scripts to destroy all the Docker containers, recreate them, and bootstrap the blockchain with the necessary data. This included everything from setting up participants to instantiating the chaincode for the smart contracts. Since a blockchain is an immutable ledger that cannot be directly deleted, this approach provided an efficient way to completely destroy and rebuild the blockchain when needed.

Parts

Part Map Web - Part map

Part Information Web - Part information

Part History Web - Part history

Containers

Container Map Web - Container map

Container Information Web - Container information

Container History Web - Container history

Vehicles

Vehicle Information Web - Vehicle information

Vehicle History Web - Vehicle history

General Event Tracker

General Events Web - General events with browser notifications

Blockchain Management

Blockchain Management Web - Blockchain management

Blockchain Timer Web - Blockchain reset timer

Client App

The client application served as an after-sales tool, enabling users to access detailed information about their vehicles stored on the blockchain. It showcased the complete lifecycle of parts, such as rearview mirrors and sunroofs, including cryptographically signed and validated part certificates. Originally designed for containers earlier in the supply chain, the tracking functionality was extended to cover parts after their installation in the vehicle.

The app also included a section for tracking vehicle events, such as notifications for expired warranties or part recalls. During presentations, these scenarios were simulated, allowing attendees to explore the functionality on demo devices.

Client Vehicle Information Client App - Vehicle management

Client Part Information Client App - Part management

Demo App

At first, the project was only supposed to include a website and a client app, but as the presentations became more complex, I was asked to make the process easier. The website provided full access to the blockchain's functionality, allowing users to execute all the smart contracts with custom inputs. However, it quickly became clear during early showcases that this setup wasn't practical. Presenters frequently made mistakes while entering data, and the process involved too many tedious steps, which quickly bored the attendees.

To address this, I developed an Android app to streamline the process. The app let presenters scan QR codes I had designed and printed, enabling them to complete each step with the press of a button. It worked by sending predefined REST calls to the backend with the correct parameters, often combining several calls into a single logical action. The app automated the entire part lifecycle, including loading parts into containers, simulating the transport of containers to an assembly plant with IoT calls and GPS data, unloading trucks and containers, assembling vehicles, generating valid or invalid part certificates, and handling vehicle operations like selling a car or repairing an installed part, which updated its status on the blockchain.

Demo Container Demo App - Container

Demo Part Demo App - Part

Demo Vehicle Demo App - Vehicle

Putting Everything Together and Delivering the Project

After months of grueling work, the project was finally delivered, and I was asked to write some copy for its presentation. The telco even commissioned a video from a production company, and the project was showcased at the 2018 Mobile World Congress in Barcelona as an example of Industry 4.0 technology. There were no issues during the presentation, and the project had its own booth where it was demonstrated to the public.

Despite my role in building the system, I wasn't invited to attend the event, which was disappointing, to say the least 😔.

Although the project was just a proof of concept to validate the feasibility of using blockchain to track assets, there was an understanding that, if successful, it could evolve into a real-world pilot and eventually a commercial product. Unfortunately, a falling-out between participants on their side put any future development on hold, and the project was eventually canceled.

In the end, the telco joined a consortium of companies that promised to build their own blockchain technology from scratch. The last time I checked, after several years, they still hadn't delivered anything.

Lessons Learned and Conclusions

As I mentioned earlier, this was the first project I worked on professionally. At first, it didn't seem like the company cared much about it (even though they later used it to get acquired by a bank), so they pretty much threw me to the wolves with the whole thing.

I made so many mistakes that I could probably write a few more posts just about those, but the most important one was not asserting myself at the beginning. I let the project grow out of scope, wasted a lot of time waiting for others to make decisions, and allowed people to steer things when they weren't invested in the technical side. By the end, when it was time to create a tight, time-constrained demo, I had to throw out or bypass half the chaincode and boil everything down to just a handful of simplified steps. I also should have asked for more help. I ended up working an insane number of extra hours on something that felt like it didn't matter much to anyone. At the same time, I was the most junior person in the company, so no one really took me seriously.

There were plenty of moments where it felt like the project was doomed, especially with the lack of working examples and the unfinished state of the technology. Deadlines were often dropped on us out of nowhere. I remember one time having to present on a Monday and spending the entire Sunday night working; I even convinced some friends from university and work to help me code fake coordinates into IoT sensors, solder toy trucks with sensors inside, and assemble everything by five in the morning. At some point, my manager even dropped by my house to check in and ended up driving two of us straight to the presentation.

The biggest lesson I learned about blockchain is that it's a total fraud. There are two types: the kind that powered the crypto and altcoin boom, which turned into nothing but confidence scams, and the kind that's technically useful but impossible to implement on a global production scale. Companies fundamentally mistrust each other, their partnerships are held together by bravado and serial incompetence, and the technology itself requires good-faith actors, which are in short supply.

In the end, the project was fun, exhausting, and a huge learning experience. If you're just starting out, I'd seriously recommend working at a startup first. You'll get to do a bit of everything before settling into the quiet desperation of corporate life 👨🏼‍💼.