X

Faster, Easier Development of Smart Contracts is Here Today with Blockchain App Builder for Oracle Blockchain Platform

Mark Rakhmilevich, and Todd Little

The Blockchain App Builder for the Oracle Blockchain Platform is a new component that extends our vision of making enterprise blockchains easy and quick. Since the initial release of the platform in 2018, our focus before has been on simplifying the infrastructure, configuration, integration, and operations tasks. Now we aim to bring the same ease and simplicity to building smart contracts that are at the heart of any enterprise blockchain.

The Blockchain App Builder (BAP) is designed to simplify and speed up the development of smart contracts for the Oracle Blockchain Platform, a production-ready, pre-assembled enterprise blockchain platform based on a Linux Foundation open source project Hyperledger Fabric. This series of blog posts will introduce the features provided and show how to use the tools.

With the deprecation of the Hyperledger Composer project, developers lacked blockchain development tooling to assist them in creating blockchain-based applications, particularly the actual chaincode (as smart contracts are known in the Oracle Blockchain Platform) that maps the ledger’s data model and handles the business logic. While Composer made it easy to quickly develop and test smart contracts, it had some significant limitations. The goal of our new tools is to help accelerate the development of blockchain applications while still providing the flexibility to use the Oracle Blockchain Platform to its fullest.

Blockchain App Builder Overview

Developing smart contracts for use in a blockchain application can be complicated and difficult. A smart contract executes in its own Docker container, making deploying, debugging, and testing more challenging. It needs to execute the same way across multiple nodes to ensure consistent results, and it relies on specific shim APIs to retrieve and persist the data. To simplify the development of smart contracts, the Blockchain App Builder includes a set of tools that aid in:

  • Creating smart contract projects, including scaffolding a project based on a specification file and automatic deployment of local Hyperledger Fabric network
  • Generating smart contract CRUD (Create, Read, Update, Delete) methods in Golang and TypeScript (a variant of JavaScript) based upon a specification file that defines the data model and validation rules for one or more assets, with the ability to then extend the generated methods with custom logic
  • Deploying those smart contracts to a local blockchain network or remote Oracle Blockchain Platform – either Cloud BaaS or on-premises Enterprise Edition
  • Testing and debugging the smart contract with line-by-line debugging support in Visual Studio Code, including easy testing of rich queries against the stateDB
  • Packaging the smart contract for production deployment into an Oracle Blockchain Platform network and all the subsequent chaincode lifecycle operations (install, instantiate, and upgrade)
  • Automatic regeneration of chaincode on specification updates to enable rapid turnaround for any changes or fixes

The tools currently provide two user interfaces:

  • A command line interface (CLI) that can be used to perform the above functions and automate the CI/CD pipeline
  • An extension for Visual Studio Code to provide an interactive development environment customized for developing smart contracts.

The basic flow for developing a smart contract with these tools is shown on the diagram below. First, you create a specification file that describes the assets or objects being maintained on the blockchain ledger. This specification file is then used to scaffold a smart contract project and generate source code for models and controllers for the assets specified in the file. The specification file allows defining the properties of the assets and any validation requirements for the properties.

Blockchain App Builder Flow

This results in a Model file, which contains the property definitions of all the assets defined in the specification file, and a Controller file, which defines all the behavior or methods for those assets. A specification file allows defining additional custom methods that the user needs to implement in order to provide the business logic of the smart contract. Even before those custom methods are implemented, though, the user can deploy and test the generated chaincode with the CRUD methods that were generated automatically.

Both the CLI and the VS Code extension allow scaffolding, deploying, and testing the smart contracts. Before we delve into the details, you naturally want to know how to get the Blockchain App Builder. Provision a new Blockchain Platform instance in Oracle Cloud using OCI Menu, and once the instance is ready, bring up the Console and navigate to the Developer Tools tab. Under this tab, the Blockchain App Builder page describes its features and provides download links for the CLI and VS Code extension (for which you need to installing VS Code itself) as well as two sample specification files (which are also included in the tool downloads.) Your existing gen2 Blockchain instances in OCI will be updated to include this page and the download links in a few weeks. For OBP Enterprise Edition users, we'll be providing a patch with this update as well.

Smart Contract Specification File

The starting point for creating a smart contract is to define the information that will be stored in the ledger. This is done via a YAML or JSON file, as in this simple example:

assets:
    - name: car               # Define the properties for a car
      properties:
          - name: vin         # Vehicle identification number
            type: string
            mandatory: true
            id: true          # Use the VIN as the ID for the car
          - name: make        # Manufacturer
            type: string
          - name: model       # Model name
            type: string
          - name: year        # Model year
            type: number
          - name: color       # Color
            type: string

This specification file defines the properties for an asset we call “car” which includes the Vehicle Identification Number (or VIN), the make, model, year, and color of the car. For each property, the type of the property is given. Notice that for vin, two additional attributes are defined for the property: mandatory: true indicating that the vin must be specified and can’t be left empty, and id: true indicating that the vin is used as the key or ID for the car.

A specification file can define multiple assets, and additional attributes of the properties are available to define things like validation rules to apply when the value of the property is provided. A simple example is a validation rule on year to indicate it must be a positive number or even that it must be greater than 1900.  The vin could have a validator that indicates it must be no more and no less than 17 characters. The objective is to declare these sorts of constraints or requirements in the specification file, so they can be checked in the generated code and don’t have to be checked by the user’s own application code.

assets:
     - name: car            # Define the properties for a car
       properties:
        - name: vin         # Vehicle identification number
          type: string
          mandatory: true
          id: true
          validate: min(17),max(17)   # Always 17 characters 
        - name: make        # Manufacturer
          type: string
          mandatory: true
          validate: /^\s*(cheverolet|ford|general\smotors|toyota|hyundai|tesla|tata|fiat|volkswagen|peugeot)\s*$/I  
        - name: model       # Model name
          type: string
          mandatory: true
        - name: year        # Model year
          type: number
          mandatory: true
          validate: min(1910),max(2020) 
        - name: color       # Color - no validation as color names are innumerable
          type: string
          mandatory: true
        - name: owner       # Owners's email address
          type: string
          validate: email() # Validate it as a valid email address 
        - name: price       # Current price of the vehicle
          type: number
          validate: positive()  
        - name: lastSold    # Date of the last sale of this car
          type: date  

Here is a slightly more complete version of the car asset definition. In this updated specification file, we added:

❶ A validator to make sure the vin is exactly 17 characters

❷ A validator on make limiting the property to one of a set of values, effectively an enum, using a regular expression

❸ A validator on year to make sure the date is between 1910 and 2020

❹ A new string property owner that must conform to a valid email address

❺ A new property price that must always be a positive number

❻ A new date property lastSold

These validators and type specifications eliminate the need for the chaincode developer to perform all these validations themselves in their implementation. If the validations don’t pass or the type of data doesn’t match the specified type, the requested operation fails with a validation failure.

Automatic Code Generation from Declarative Specification

Given the above specification file, we can use the “ochain init” command to scaffold a smart contract project. For the examples in this blog post, I’ll focus on TypeScript-based chaincode, even though the tools currently support both TypeScript and Golang. Once the chaincode project has been initialized (scaffolded), the project folder will include the following directories and files:

/home/obptools/mycar2/dist
/home/obptools/mycar2/lib
/home/obptools/mycar2/main.ts
/home/obptools/mycar2/node_modules
/home/obptools/mycar2/package.json
/home/obptools/mycar2/package-lock.json
/home/obptools/mycar2/README.md
/home/obptools/mycar2/src
/home/obptools/mycar2/src/mycar2.controller.ts
/home/obptools/mycar2/src/mycar2.mode.ts
/home/obptools/mycar2/tests
/home/obptools/mycar2/tsconfig.json


The generated model and controller files are located in <projectHome>/src. Inside that folder are two TypeScript files: one, the model that defines the persistent properties of the assets as defined in the specification file, and the other, which defines the behaviors or methods for the assets container in the specification file.

Let’s examine the generated model file from the above specification file:

import * as yup from 'yup';
import { Id, Mandatory, Validate, Default } from ';../lib/decorators'
import { OchainModel } from '../lib/ochain-model';
 
@Id('vin')
export class Car extends OchainModel<Car> {
 
    public readonly assetType = 'mycar2.car';
 
    @Mandatory()
    @Validate(yup.string().min(17).max(17))
    public vin: string;
 
    @Validate(yup.string().matches(/^\s*(cheverolet|ford|general\smotors|toyota|hyundai|tesla|tata|fiat|volkswagen|peugeot)\s*$/i))
    public make: string;
 
    @Validate(yup.string())
    public model: string;
 
    @Mandatory()
    @Validate(yup.number().min(1910).max(2020))
    public year: number;
 
    @Mandatory()
    @Validate(yup.string())
    public color: string;
 
    @Validate(yup.string().email())
    public owner: string;
 
    @Validate(yup.number().positive())
    public price: number;
 
    @Validate(yup.date())
    public lastSold: Date;
 

This generated file provides the definition of the Car asset. It uses annotations to define specific requirements for any given property. For example, the:

   @Validate(yup.string().min(17).max(17))

on the vin property indicates that it must be at least 17 characters in length and no more than 17 characters in length. Likewise, the:

   @Validate(yup.number().positive())

on the price property indicates that it must be a positive number, as was specified in the specification file. Type validation occurs automatically without any additional information required in the specification file. So, the yup.number() annotation indicates that the property must be a number. The positive() annotation on price indicates the number must be a positive number. 

If we examine the generated controller file, we can see the CRUD method implementations:

import * as yup from 'yup';
import { Validator } from '../lib/decorators';
import { OchainController } from '../lib/ochain-controller';
import { Car } from './fabcar.model';

export class FabcarController extends OchainController {     public async init(params: any) {
        return;
    }

    //-----------------------------------------------------------------------------
    // Car
    //-----------------------------------------------------------------------------

    @Validator(Car)

    public async createCar(asset: Car) {
        return await asset.save();
    }

    public async getCarById(id: string) {
        const asset = await Car.get(id);
        return asset;
    }

    @Validator(Car)

    public async updateCar(asset: Car) {
        return await asset.update();
    }

    public async deleteCar(id: string) {
        const result = await Car.delete(id);
        return result;
    }
}

At this point, we have a ready-to-run, ready-to-test smart contract. 

Now that we’ve seen how to model an asset, in the next post, I’ll describe how to use the Oracle Blockchain App Builder to run and test the smart contract and how to extend it to add custom functions. 

To learn more about blockchain and Oracle Blockchain Platform, visit the Oracle Blockchain page.

Join the discussion

Comments ( 1 )
  • Jacob Cole Thursday, October 29, 2020
    Smart contracts are lines of code that are stored on a blockchain and automatically execute when predetermined terms and conditions are met. At the most basic level, they are programs that run as they've been set up to run by the people who developed them.
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.