Skip to content

Commit

Permalink
Add interactive asset management demo
Browse files Browse the repository at this point in the history
This adds an expanded, interactive asset management demo that uses the
preexisting example chaincode "asset_management.go".

Rather than a single application which performs all of the asset
administration, assignments, and transfers, three applications now exist
which perform each of those operations. The third application offers a
command line interface so the user can actually invoke specific asset
transfers of his/her choosing.

A detailed description of these applications and their usage can be found
in the README.

A video demonstration of the applications running can be viewed here:
https://www.youtube.com/watch?v=PCZrFAKXlTE.
Note that this video link is only present in this description and was not
added to any of the committed files.

Change-Id: I4da4bcf99c4829c59bd4659954013c4d42d9930f
Signed-off-by: Mike Zaccardo <mike.zaccardo@cloudsoftcorp.com>
  • Loading branch information
Mike Zaccardo committed Dec 2, 2016
1 parent de00eaa commit eba912b
Show file tree
Hide file tree
Showing 11 changed files with 2,118 additions and 0 deletions.
169 changes: 169 additions & 0 deletions examples/chaincode/go/asset_management_interactive/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# Hyperledger Fabric - Interactive Asset Management App

## Overview

The *Interactive Asset Management App* consists of three separate applications which test the behavior of the standard *asset management* chaincode example. The apps each bootstrap a non-validating peer and construct fabric confidential transactions to deploy, invoke, and/or query the asset management chaincode as described below.

In particular, we consider a scenario in which we have the following parties:

1. *Alice* is the chaincode deployer, represented by `app1`
2. *Bob* is the chaincode administrator, represented by `app2`
3. *Charlie*, *Dave*, and *Edwina* are asset owners, each represented by a separate instance of `app3`

that interact in the following way:

1. *Alice* deploys and assigns the administrator role to *Bob*
2. *Bob* assigns the assets listed in [assets.txt](app2/assets.txt) to *Charlie*, *Dave*, and *Edwina*
3. *Charlie*, *Dave*, and *Edwina* can transfer the ownership of their assets between each other

In the following sections, we describe in more detail the interactions
described above that the asset management app exercises.

### Alice deploys and assigns the administrator role to Bob via `app1`

The following actions take place:

1. *Alice* obtains, via an out-of-band channel, the ECert of Bob, let us call these certificates *BobCert*
2. Alice constructs a deploy transaction, as described in *application-ACL.md*, setting the transaction metadata to *DER(BobCert)*
3. Alice submits the deploy transaction to the fabric network

*Bob* is now the administrator of the chaincode.

### Bob assigns ownership of all the assets via `app2`

1. *Bob* obtains, via out-of-band channels, the ECerts of *Charlie*, *Dave*, and *Edwina*; let us call these certificates *CharlieCert*, *DaveCert*, and *EdwinaCert*, respectively
2. *Bob* constructs an invoke transaction, as described in *application-ACL.md* using *BobCert* to gain access, to invoke the *assign* function passing as parameters *('ASSET_NAME_HERE', Base64(DER(CharlieCert)))*
3. *Bob* submits the transaction to the fabric network
4. *Bob* repeates the above steps for every asset listed in [assets.txt](app2/assets.txt), rotating between *Charlie*, *Dave*, and *Edwina* as the assigned owner

*Charlie*, *Dave*, and *Edwina* are now each the owners of 1/3 of the assets.

Notice that, to assign ownership of assets, *Bob* has to use *BobCert* to authenticate his invocations.

### Charlie, Dave, and Edwina transfer the ownership of their assets between each other via separate instances of `app3`

1. *Charlie*, *Dave*, and *Edwina* each obtain, via out-of-band channels, the ECerts of the other owners; let us call these certificates *CharlieCert*, *DaveCert*, and *EdwinaCert*, respectively
2. Owner *X* constructs an invoke transaction, as described in *application-ACL.md* using *XCert*, to invoke the *transfer* function passing as parameters *('ASSET_NAME_HERE', Base64(DER(YCert)))*.
3. *X* submits the transaction to the fabric network.
4. These steps can be repeated for any asset to be transferred between any two users *X* -> *Y*, if and only if *X* is the current owner of the asset

*Y* is now the owner of the asset.

Notice that, to transfer the ownership of a given asset, user *X* has to use *XCert* to authenticate his/her invocations.

## How To run the Interactive Asset Management App

In order to run the Interactive Asset Management App, the following steps are required.

### Setup the fabric network and create app's configuration file

Follow the [create](https://github.com/hyperledger/fabric/blob/master/examples/chaincode/go/asset_management/app/README.md#create-apps-configuration-file) and [setup](https://github.com/hyperledger/fabric/blob/master/examples/chaincode/go/asset_management/app/README.md#setup-the-fabric-network) steps from the original asset management demo instructions. Note that the `core.yaml` that is described should be placed in this directory on the CLI node.

### Build the apps

Follow the first two instructions of the [run step](https://github.com/hyperledger/fabric/blob/master/examples/chaincode/go/asset_management/app/README.md#run-the-app) from the original asset management demo instructions, but change into the following directory instead:

```
cd $GOPATH/src/github.com/hyperldger/fabric/examples/chaincode/go/asset_management_interactive
```

Then build all three applications by issuing the following command:

```
./build.sh
```

### Run `app1`

Run `app1` by issuing the following command:

```
cd app1
./app1
```

Wait for `app1` to complete, and note the output value of `ChaincodeName`, which needs to be supplied to the following applications. For the rest of these instructions, we will use `8bc69f84aa55195b9eba6aed6261a01ba528acd3413f37b34df580f96e0d8a525e0fe8d41f967b38f192f7a731d63596eedcbd08ee636afdadb96be02d5d150d` as the `ChaincodeName` value.

### Run `app2`

Run `app2` by issuing the following command:

```
cd ../app2
./app2 8bc69f84aa55195b9eba6aed6261a01ba528acd3413f37b34df580f96e0d8a525e0fe8d41f967b38f192f7a731d63596eedcbd08ee636afdadb96be02d5d150d
```

### Run `app3` for each owner

Run `app3` for each owner by issuing the following commands (note that a separate terminal window for each owner is recommended):

```
cd ../app3
```

Run as *Charlie*:

```
./app3 8bc69f84aa55195b9eba6aed6261a01ba528acd3413f37b34df580f96e0d8a525e0fe8d41f967b38f192f7a731d63596eedcbd08ee636afdadb96be02d5d150d charlie
```

Run as *Dave*:

```
./app3 8bc69f84aa55195b9eba6aed6261a01ba528acd3413f37b34df580f96e0d8a525e0fe8d41f967b38f192f7a731d63596eedcbd08ee636afdadb96be02d5d150d dave
```

Run as *Edwina*:

```
./app3 8bc69f84aa55195b9eba6aed6261a01ba528acd3413f37b34df580f96e0d8a525e0fe8d41f967b38f192f7a731d63596eedcbd08ee636afdadb96be02d5d150d edwina
```

Each app will then provide a simple console interface for perfoming one of two actions: listing owned assets and transferring an asset to another owner.

#### List Assets

List an owner's assets by issuing the `list` command. For example, this is the expected output of *Charlie's* first `list`:

```
charlie$ list
...
'charlie' owns the following 16 assets:
'Lot01: BERNARD LEACH VASE WITH 'LEAPING FISH' DESIGN'
'Lot04: PETER LANYON TREVALGAN'
'Lot07: DAVID BOMBERG MOORISH RONDA, ANDALUCIA'
'Lot10: HAROLD GILMAN INTERIOR (MRS MOUNTER)'
'Lot13: WILLIAM SCOTT, R.A. GIRL SEATED AT A TABLE'
'Lot16: JACK BUTLER YEATS, R.H.A. SLEEP SOUND'
'Lot19: SIR EDUARDO PAOLOZZI, R.A. WEDDING OF THE ROCK AND DYNAMO'
'Lot22: JEAN-MICHEL BASQUIAT AIR POWER'
'Lot25: KENNETH ARMITAGE, R.A. MODEL FOR DIARCHY (SMALL VERSION)'
'Lot28: FRANK AUERBACH E.O.W'S RECLINING HEAD'
'Lot31: SIR EDUARDO PAOLOZZI, R.A. FORMS ON A BOW NO. 2'
'Lot34: MARCEL DUCHAMP WITH HIDDEN NOISE (A BRUIT SECRET)'
'Lot37: FRANCIS PICABIA MENDICA'
'Lot40: DAVID BOMBERG PLAZUELA DE LA PAZ, RONDA'
'Lot43: PATRICK CAULFIELD, R.A., C.B.E. FOYER'
'Lot46: DAMIEN HIRST UNTITLED FISH FOR DAVID'
```

#### Transfer Assets

Transfer an asset to another owner by issuing the `transfer LotXX owner_here` command. For example, this is the command to transfer *Lot01* from *Charlie* to *Dave*.

```
charlie$ transfer Lot01 dave
...
'dave' is the new owner of 'Lot01: BERNARD LEACH VASE WITH 'LEAPING FISH' DESIGN'!
------------- Done!
```

## Compatibility

This demo application has been successfully tested against the
[v0.6.0-preview](https://github.com/hyperledger/fabric/releases/tag/v0.6.0-preview) and
[v0.6.1-preview](https://github.com/hyperledger/fabric/releases/tag/v0.6.1-preview) releases.

## Copyright Note

The new source code files retain `Copyright IBM Corp.` because they are closely adopted from a preexisting example that contains an IBM copyright.
103 changes: 103 additions & 0 deletions examples/chaincode/go/asset_management_interactive/app1/app1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"os"
"time"

"github.com/hyperledger/fabric/core/crypto"
pb "github.com/hyperledger/fabric/protos"
"github.com/op/go-logging"
"google.golang.org/grpc"
)

var (
// Logging
appLogger = logging.MustGetLogger("app")

// NVP related objects
peerClientConn *grpc.ClientConn
serverClient pb.PeerClient

// Alice is the deployer
alice crypto.Client

// Bob is the administrator
bob crypto.Client
bobCert crypto.CertificateHandler
)

func deploy() (err error) {
appLogger.Debug("------------- Alice wants to assign the administrator role to Bob;")
// Deploy:
// 1. Alice is the deployer of the chaincode;
// 2. Alice wants to assign the administrator role to Bob;
// 3. Alice obtains, via an out-of-band channel, the ECert of Bob, let us call this certificate *BobCert*;
// 4. Alice constructs a deploy transaction, as described in *application-ACL.md*, setting the transaction
// metadata to *DER(CharlieCert)*.
// 5. Alice submits th e transaction to the fabric network.

resp, err := deployInternal(alice, bobCert)
if err != nil {
appLogger.Errorf("Failed deploying [%s]", err)
return
}
appLogger.Debugf("Resp [%s]", resp.String())
appLogger.Debugf("Chaincode NAME: [%s]-[%s]", chaincodeName, string(resp.Msg))

appLogger.Debug("Wait 60 seconds")
time.Sleep(60 * time.Second)

appLogger.Debug("------------- Done!")
return
}

func testAssetManagementChaincode() (err error) {
// Deploy
err = deploy()
if err != nil {
appLogger.Errorf("Failed deploying [%s]", err)
return
}

appLogger.Debug("Deployed!")

closeCryptoClient(alice)
closeCryptoClient(bob)

return
}

func main() {
// Initialize a non-validating peer whose role is to submit
// transactions to the fabric network.
// A 'core.yaml' file is assumed to be available in the working directory.
if err := initNVP(); err != nil {
appLogger.Debugf("Failed initiliazing NVP [%s]", err)
os.Exit(-1)
}

// Enable fabric 'confidentiality'
confidentiality(true)

// Exercise the 'asset_management' chaincode
if err := testAssetManagementChaincode(); err != nil {
appLogger.Debugf("Failed testing asset management chaincode [%s]", err)
os.Exit(-2)
}
}
Loading

0 comments on commit eba912b

Please sign in to comment.