Alrighty, the code’s done and this thing works, so let’s start diving into how I built it.

First up, let’s discuss some of the design thinking I did for the first few days before I wrote the first line of code. Since I’m an “old hat” developer new to the blockchain world and paradigm, this was a critical phase for me on this project.

Demo Video

Before I get into the actual discussion, here’s a demo video showing the web application and the NFC-enabled mobile app using the RESTful API on top of our smart contract. Hopefully it’ll give you a little context as I discuss things from here on.

Also, in case you missed it, here’s the post covering an overview of this project.

Demo video of a blockchain-based asset tracking solution built on Dragonchain

Get the Git

I won’t be getting into the actual code in this post, but if you want to start poking at it in the meantime, feel free to check it out below.

dragonchain-asset-tracker (this link opens in a new window) by Dragonchain-Community (this link opens in a new window)

A NodeJS smart contract, API server, web demo, and NFC-enabled Flutter mobile app demonstrating blockchain-enabled asset tracking.

General Considerations

The “Flow”

The first things I started thinking about were a) how New Balance and Cardano built their system and b) how to support that use case while remaining flexible to other potential logistical flows.

From what I’ve seen of the New Balance/Cardano process (I buy $10 shoes on sale from Old Navy; ain’t spending hundreds on a test), it looks something like this:

  1. New Balance manufactures shoes printed (sewn) with unique serial numbers
  2. New Balance packages an NFC-tagged hard card (like a credit card) in the box with each pair
    1. New Balance presumably creates a limited number of these cards to be associated with a limited number of “assets” (pairs of shoes) containing the product data to be created in their blockchain system
  3. A customer eventually buys a pair of these shoes, then:
    1. Logs into the New Balance special app (identity verified)
    2. Scans the NFC tag to get its ID
    3. Scans or enters the serial number for the shoes to claim ownership which then associates the NFC tag to the pair of shoes

This is a kind of “disconnected fulfillment” model. Note that the NFC tag is not associated with the individual pair of shoes and asset data on the chain until the customer receives the product, scans or enters the relevant information, and creates the association.

This approach makes sense particularly as a test of the blockchain-enabled authentication model that New Balance was going for.

It would be better (to me) to tag the shoes themselves, or at least to immediately attach the asset data and NFC tag data to the individual pair of shoes in some way, but that would have required a major retooling of the manufacturing and distribution process. That’s a lot to ask for a first attempt at the idea.

For my purposes, though, I built the system to support virtually any “flow” I could think of. This means that asset data can be created and associated with a physical product, then associated with a specific NFC tag, at virtually any point in the process of manufacture, distribution, or purchasing.

In the proof-of-concept demo I built, I tried to stick to a model as close to New Balance’s as I could.

The Data

I didn’t want to build this project so that it was tied explicitly to a product line like a pair of shoes.

In fact, an “asset” can really be… anything. It could be a pair of shoes or it could be a software license, an event ticket, or a document record.

To keep the system generic, I had to build some way to attach descriptive data of any kind outside of the basic asset and owner data our system requires at its core.

I called this “external data,” and it’s attached to both custodians and to assets (we’ll dive more into those two entities in a sec). It looks something like this:

{
    "id": "1573101332968",
    "data": {
      "name": "Nike HMD Runners - Other Custodian Test",
      "description": "The 2019 edition of the Nike Hand-Me-Down runners in bright ass blue and Hulk-pee green.",
      "color": "Blue/Green",
      "image_url": "https://herebedrgns.com/wp-content/uploads/2019/10/nike-hmd-bg.jpg"
    }
}

This is arbitrary data that can be associated with a basic asset or a custodian at any time (when the asset/custodian is created or at any time thereafter).

The external “id” field is also indexed by our smart contract (we’ll cover more on that in the next post) so that it becomes like a “foreign key” in traditional database terms.

In other words, we can lookup the asset data on the blockchain using the unique identifier implemented in a more traditional database system outside the blockchain.

The data can be anything you can stick in a JSON object. Note that it is NOT indexed since we can’t predict what data will be contained in it, so we can’t search our blockchain based on the external data object’s actual “data” field.

Performance Considerations

First up, note that I’ve built this entire project without relying on an external database. Our Dragonchain blockchain is the ONLY source of data.

This is probably not ideal in a production system for performance (at least in any system that requires fast writes and immediate reads of data).

Consider the nature of a blockchain: data on the chain is only available once its transactions have been written to a block, not as soon as the transactions are created.

You’ll notice in the demo video when I create new assets that it takes about 6 seconds for the action to complete and the data to refresh.

This is because Dragonchain implements 5 second block creation timing. To account for this and ensure that the data would be queryable when I refreshed it, I built in a 6 second delay to keep things simple (you could also implement a “query loop” to ask for the data until it becomes available, but I’m not sure that’s better).

In a production system, you’d probably want to utilize an interchained traditional database solution (like the postgresql interchain the Dragonchain team is currently working on) to make data available immediately for querying and further processing.

Object IDs

To identify individual assets, people, etc., we obviously need to have unique IDs to associate with them.

Since Dragonchain already generates UUIDs for every transaction, I made the choice to just use the request transaction’s ID as the ID for any asset, custodian, asset transfer request, etc.

In addition to simplifying things, this also means that we can save a BUNCH of custom indexing by adding a “response type” field (like “create asset,” “authorize asset transfer,” etc.) in the payload and using the built-in “invoker” tag that’s created for smart contract outputs (where the “invoker” is the request transaction’s ID). Nifty.

The only limitation I can think of to doing things this way is that we can’t “bulk create” assets, groups, custodians, or transfers in a single transaction. This is an acceptable tradeoff as far as I’m concerned.

Custom Indexes and the Smart Contract Heap

I’ll go into this in much more detail in the next post, but for now, I also had to think carefully about how to balance a couple of pressing needs for this system:

  1. How to query related asset data in the system arbitrarily (example: “give me all assets ever owned by custodian #1234” vs “give me every custodian who ever owned asset #1234” vs “give me custodian #1234’s current assets”)
  2. How to get the current state of any given “object” in the system (custodian, asset group, or asset)

To solve this problem, I made heavy use of both custom indexes (very performance/resource intensive) and something called the “smart contract heap” which lets us store the current state of pretty much anything we want in a deterministic way.

Object Design

The three main “objects” represented in our system are:

  1. Assets
  2. Asset Groups
  3. Custodians

Note: in the following examples, I display objects from the heap where we can maintain and adjust the current “state” of the object, not the original transaction data which, of course, can’t be altered.

Assets

An “asset” may be considered any kind of “thing,” from physical products to software licenses to certifications, that one custodian might create and transfer to another custodian.

{
  "id": "8f9813d9-a7ac-4c05-bec7-0d1324c7a999",
  "custodianId": "2a3203c1-5be2-4370-8661-1a4265f8d16c",
  "assetGroupId": "c973301f-20ff-459a-87f2-048444cd9a45",
  "assetGroupSupplyRecord": {
    "number": 2,
    "of": 10000
  },
  "last_transfer": {
    "id": "8f9813d9-a7ac-4c05-bec7-0d1324c7a999",
    "assetId": "8f9813d9-a7ac-4c05-bec7-0d1324c7a999",
    "assetTransferAuthorizationId": null,
    "fromCustodianId": null,
    "toCustodianId": "2a3203c1-5be2-4370-8661-1a4265f8d16c"
  },
  "current_transfer_authorization": {
    "id": "00254b32-f01e-49ac-afb3-afecde819752",
    "assetId": "8f9813d9-a7ac-4c05-bec7-0d1324c7a999",
    "fromCustodianId": "2a3203c1-5be2-4370-8661-1a4265f8d16c",
    "toCustodianId": "7e6727a0-c72d-40e2-915f-e0c12bdefcc1"
  },
  "current_external_data": {
    "id": "1573101332968",
    "data": {
      "name": "Nike HMD Runners - Other Custodian Test",
      "description": "The 2019 edition of the Nike Hand-Me-Down runners in bright ass blue and Hulk-pee green.",
      "color": "Blue/Green",
      "image_url": "https://herebedrgns.com/wp-content/uploads/2019/10/nike-hmd-bg.jpg"
    }
  }
}

Asset Groups

An “asset group” is an arbitrary grouping mechanism for individual assets. An asset must belong to an asset group. Asset groups also provide the option to create contract-enforced supply limits for assets (i.e., max supply of 1000 pairs of Nike HMD shoes).

{
    "id": "c973301f-20ff-459a-87f2-048444cd9a45",
    "custodianId": "2a3203c1-5be2-4370-8661-1a4265f8d16c",
    "name": "2019 Nike HMDs",
    "description": "2019 line of Nike Hand-Me-Downs",
    "maxSupply": 10000,
    "issuedSupply": 2
}

Custodians

A “custodian” is a person or entity who can take control – or custody – of an asset. There are three kinds of custodians:

  • Authority custodians are the only type of custodian able to create assets and control certain aspects of them (example: Nike Shoes). There can currently be only one authority custodian per instance of the smart contract.
  • Handler custodians are meant to represent intermediary custodians before an asset reaches its final intended owner (example: Foot Locker Store #1234)
  • Owner custodians are meant to represent the final owners of an asset though they may transfer those assets to any other custodian (example: John Doe)

{
    "id": "5c83e1cb-e1d0-4081-93b5-fdda8b71d1d8",
    "type": "owner",
    "current_external_data": {
      "id": "1234",
      "data": {
        "name": "John Doe",
        "description": ""
      }
    },
    "assets": [
      "1ec605a2-0bfb-4e57-b134-a1531d600189",
      "d675ef95-4d34-4af5-8a47-0a94d7021f05"
    ]
}

Asset Creation and Transfer Process

The asset management process I designed here was meant to:

  1. Be simple but robust
  2. Respect custodianship of assets at the smart contract level itself

On #2, my main concern was ensuring that only the current custodian of an asset may authorize its transfer to another custodian and to enforce this in the smart contract.

Even the authority cannot “force” an asset to be transferred.

Only the authority custodian for the contract can create an asset. The asset is then “transferred” in the same action to the authority custodian.

Then, to transfer an asset, we follow this process:

  1. The current custodian of an asset authorizes its transfer. The receiving custodian may be specified or the transfer may be left open to any custodian.
  2. The receiving custodian claims ownership of an asset that has been authorized for transfer.

As it turns out, during the build of this project I happened to look into the ERC-721 spec for building non-fungible tokens (NFTs) on the Ethereum blockchain…

What I designed based on “hunches” more than anything ended up resembling the ERC-721 spec VERY closely. We’re basically implementing NFTs on Dragonchain here.

Note: while our system here resembles the ERC-721 spec, it’s certainly not identical… don’t be trying to interchain ethereum NFTs with this without careful consideration and probably some revision.

Wrapping Up

What I originally thought was going to be a very simplistic application ended up being a bit more complex when designed to accommodate a variety of logistical workflows and to enforce true asset ownership.

Welcome to software development, John….

Still, it really isn’t that complex in the end. Custodians own and control the transfer of assets. That’s basically it, and the rest is just candy.

Let’s get past the design and theory, though, and start looking at the smart contract component in the next post.

Until next time,
John

Leave a comment

Your email address will not be published. Required fields are marked *