Blockchain can be used to build a trail of trusted actions. A chain of events built on trust or agreements between parties. In Fabric lingo: a smart contract.

Post 2: test an application that calls some functions .

 

I try to show the technology, with some explanation. In post 1 (it took me a while to get here - almost a year between the initial work and this part) I just showed it as an intro for a blockchain related series.

 

The example is an application that lets you maintain a set of cars, some attributes, value and owner.

 

{
  ID: 'asset1',
  Color: 'blue',
  Size: 5,
  Owner: 'Tomoko',
  AppraisedValue: 300,
  },
  {
  ID: 'asset2',
  Color: 'red',
  Size: 5,
  Owner: 'Brad',
  AppraisedValue: 400,
  },
  {
  ID: 'asset3',
  Color: 'green',
  Size: 10,
  Owner: 'Jin Soo',
  AppraisedValue: 500,
  },
  {
  ID: 'asset4',
  Color: 'yellow',
  Size: 10,
  Owner: 'Max',
  AppraisedValue: 600,
  },
  {
  ID: 'asset5',
  Color: 'black',
  Size: 15,
  Owner: 'Adriana',
  AppraisedValue: 700,
  },
  {
  ID: 'asset6',
  Color: 'white',
  Size: 15,
  Owner: 'Michel',
  AppraisedValue: 800,
  }

 

 

Preparation

 

I did a fresh Hypercare Fabric install, then followed the tutorial.

First action is to prime the distributed blockchain, simulating two organisations, each running an instance.

Easy, because everything is done with a script.

At that point you end up with two empty chains. Instances that contain a start point (genesis) and with an established trust (a channel) between org1 and 2.

 

Set Up a Smart Contract

 

A smart contract is a rusted executable piece of code. An API that allows to create and maintain data on the chain.

The example contract (in javascript for this tutorial) has these functions:

 

class AssetTransfer extends Contract {
    // CreateAsset issues a new asset to the world state with given details.
    async CreateAsset(ctx, id, color, size, owner, appraisedValue) {}

    // ReadAsset returns the asset stored in the world state with given id.
    async ReadAsset(ctx, id) {}

    // UpdateAsset updates an existing asset in the world state with provided parameters.
    async UpdateAsset(ctx, id, color, size, owner, appraisedValue) {}

    // DeleteAsset deletes an given asset from the world state.
    async DeleteAsset(ctx, id) {}

    // AssetExists returns true when asset with given ID exists in world state.
    async AssetExists(ctx, id) {}

    // TransferAsset updates the owner field of asset with given id in the world state.
    async TransferAsset(ctx, id, newOwner) {}

    // GetAllAssets returns all assets found in the world state.
    async GetAllAssets(ctx) {}
}

 

To deploy this executable contract to the chain, you first have to let organisations approve it.

Once the majority of organizations  (peers) have approved, it can be committed. It will then be physically deployed to all ledgers and can be executed by any peer.

Results of object manipulations (transactions) are synchronised.

 

Application

 

You run the application against the channel where it's approved on, using your organisation's peer instance.

I have left almost all infrastructure calls out. That makes it easier to see what the code is doing.

The application has a single function, that exercises the full API of the smart contract.

The result can be seen in the screen capture above.

 

// Build a network instance based on the channel where the smart contract is deployed
const network = await gateway.getNetwork(channelName);

// Get the contract from the network.
const contract = network.getContract(chaincodeName);

// Initialize a set of asset data on the channel using the chaincode 'InitLedger' function.
// This type of transaction would only be run once by an application the first time it was started after it
// deployed the first time. Any updates to the chaincode deployed later would likely not need to run
// an "init" type function.
console.log('\n--> Submit Transaction: InitLedger, function creates the initial set of assets on the ledger');
await contract.submitTransaction('InitLedger');
console.log('*** Result: committed');

// Let's try a query type operation (function).
// This will be sent to just one peer and the results will be shown.
console.log('\n--> Evaluate Transaction: GetAllAssets, function returns all the current assets on the ledger');
let result = await contract.evaluateTransaction('GetAllAssets');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);

// Now let's try to submit a transaction.
// This will be sent to both peers and if both peers endorse the transaction, the endorsed proposal will be sent
// to the orderer to be committed by each of the peer's to the channel ledger.
console.log('\n--> Submit Transaction: CreateAsset, creates new asset with ID, color, owner, size, and appraisedValue arguments');
result = await contract.submitTransaction('CreateAsset', 'asset13', 'yellow', '5', 'Tom', '1300');
// The "submitTransaction" returns the value generated by the chaincode. Notice how we normally do not
// look at this value as the chaincodes are not returning a value. So for demonstration purposes we
// have the javascript version of the chaincode return a value on the function 'CreateAsset'.
// This value will be the same as the 'ReadAsset' results for the newly created asset.
// The other chaincode versions could be updated to also return a value.
// Having the chaincode return a value after after doing a create or update could avoid the application
// from making an "evaluateTransaction" call to get information on the asset added by the chaincode
// during the create or update.
console.log(`*** Result committed: ${prettyJSONString(result.toString())}`);

console.log('\n--> Evaluate Transaction: ReadAsset, function returns an asset with a given assetID');
result = await contract.evaluateTransaction('ReadAsset', 'asset13');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);

console.log('\n--> Evaluate Transaction: AssetExists, function returns "true" if an asset with given assetID exist');
result = await contract.evaluateTransaction('AssetExists', 'asset1');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);

console.log('\n--> Submit Transaction: UpdateAsset asset1, change the appraisedValue to 350');
await contract.submitTransaction('UpdateAsset', 'asset1', 'blue', '5', 'Tomoko', '350');
console.log('*** Result: committed');

console.log('\n--> Evaluate Transaction: ReadAsset, function returns "asset1" attributes');
result = await contract.evaluateTransaction('ReadAsset', 'asset1');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);

try {
    // How about we try a transactions where the executing chaincode throws an error
    // Notice how the submitTransaction will throw an error containing the error thrown by the chaincode
    console.log('\n--> Submit Transaction: UpdateAsset asset70, asset70 does not exist and should return an error');
    await contract.submitTransaction('UpdateAsset', 'asset70', 'blue', '5', 'Tomoko', '300');
    console.log('******** FAILED to return an error');
  } catch (error) {
    console.log(`*** Successfully caught the error: \n    ${error}`);
  }

  console.log('\n--> Submit Transaction: TransferAsset asset1, transfer to new owner of Tom');
  await contract.submitTransaction('TransferAsset', 'asset1', 'Tom');
  console.log('*** Result: committed');

  console.log('\n--> Evaluate Transaction: ReadAsset, function returns "asset1" attributes');
  result = await contract.evaluateTransaction('ReadAsset', 'asset1');
  console.log(`*** Result: ${prettyJSONString(result.toString())}`);
} finally {
  // Disconnect from the gateway when the application is closing
  // This will close all connections to the network
  gateway.disconnect();
}

 

I have only touched the surface. In the background, there are key providers, authentication managers and other infra running.

More on that later.

 

Related Blog
Blockchain - HyperLedger Fabric pt 1: post and search transactions on a distributed trusted ledger
Blockchain - Hyperledger Burrow: set up a distributed ledger
Blockchain - Get Some Crypto Currency on an Infineon Security 2Go Card
Blockchain - Debug the Infineon Demo App with Android Studio and Your Phone
Blockchain - Analyse the Infineon Android Demo App - part a: Detect Card
Blockchain - Analyse the Infineon Android Demo App - part b: Retrieve Ethereum Crypto Currency Balance
Blockchain - Analyse the Infineon Android Demo App - part c: Transaction, Move Crypto Currency to Another Account
Blockchain - Talk Directly to the Infineon 2Go Smart Cards API
Blockchain - Smart Contract Test
Road Test notepad: Infineon Blockchain Starter Kit
Infineon Blockchain Starter Kit - Review
Blockchain - HyperLedger Fabric pt 2: application using blockchain and smart contract