Hyperledger Fabric 1.0 Actual Combat Development Series The third lesson Chaincode development

Source: Internet
Author: User
Tags sprintf docker compose hyperledger fabric

The Chaincode is written in the go language and implements the defined interface. Other languages, such as Java, are also supported. The ledger state can be initialized and managed by application volume Transaction,chaincode.

A chaincode-created ledger state is independent and cannot be accessed directly by other chaincode. With the appropriate permission, Chaincode can invoke other Chaincode under the same network to access its ledger state.

Next, let's look at Chaincode from the perspective of Chaincode developers. Let's look at each method of the Chaincode Shim API in a Chaincode case.

1.Chaincode API

Each chaincode needs to implement the Chaincode interface, which is used to respond to received transaction. When Chaincode receives the instantiate or upgrade transaction, the Init method is invoked so that Chaincode can perform any necessary initialization, including application state initialization. Invokes the Invoke method when Chaincode receives the invoke transaction, which is used to process the transaction proposal.

The other interfaces in the "Shim" API are chaincodestubinterface for accessing and changing ledger, and for calling between Chaincode.

In this tutorial, we will demonstrate the use of these APIs by implementing simple Chaincode applications, which manage simple "assets".

2. Simple Asset Chaincode

Our application is a basic sample chaincode for creating assets on ledger (key-value pairs).

It is recommended to use Vscode for Go code writing,

Open the terminal and run the following command:

sudo add-apt-repository ppa:ubuntu-desktop/ubuntu-make
sudo apt-get update
sudo apt-get install Ubuntu-make
If it is already installed, run the following command:
Umake Web Visual-studio-code

Please note that during the installation process, you will be asked to give the path Insatllation package. After that, it asks to submit your permission to install the Visual Studio code. Please press ' to install (' to indicate acceptance terms and conditions ').


Set Gopath

Vscode when installing the Go plug-in prompts Gopath not set error, open Launch.json in env
Install Vscode go

Search the Vscode App Store for go, click Install.

2.1 Select the location of the code

The preferred need is to determine that the go environment is installed and properly configured.

For the sake of simplicity, we use the following command:

Mkdir-p $GOPATH/src/asset && cd $GOPATH/src/asset

Next, we create the source file

Touch Asset.go

2.2 Introduction Package

Each Chaincode implements the Chaincode interface

Package main

Import (
    "FMT"

    "Github.com/hyperledger/fabric/core/chaincode/shim" "
    github.com/ Hyperledger/fabric/protos/peer "
)

2.3 Initialization of Chaincode

Our class is called Simpleasset.

Type simpleasset struct {
}

Next, we have init functions beforehand

The Init is called during Chaincode instantiation to initialize any data.
Func (t *simpleasset) Init (stub shim. Chaincodestubinterface) Peer. Response {

}

Note: Chaincode upgrade also calls this function. When a chaincode is to be upgraded, make sure that the INIT function is properly modified. If there is nothing to migrate, or nothing to initialize at the time of the upgrade, the null init function needs to be provided.

Next, we call the Chaincodestubinterface.getstringargs method to get the parameters required in init and check the validity of the parameters. The parameter we expect to get is a key-value pair.

The Init is called during Chaincode instantiation to initialize any
//data.  Note that Chaincode upgrade also calls this function to reset
//or to migrate data, so is careful to avoid a scenario where you
//inadvertently clobber your ledger ' s data!
Func (t *simpleasset) Init (stub shim. Chaincodestubinterface) Peer. Response {
  //Get the args from the transaction proposal
  args: = Stub. Getstringargs ()
  If Len (args)!= 2 {return
    shim. Error ("Incorrect arguments. Expecting a key and a value ")
  }
}

Next, as our call is valid, we will store the initial state on the ledger. To implement state storage, we will call the Chaincodestubinterface.putstate method and enter the key value as a parameter. Assuming that everything is working properly, a peer is returned. Response object, surface initialization succeeded.

The Init is called during Chaincode instantiation to initialize any
//data.  Note that Chaincode upgrade also calls this function to reset
//or to migrate data, so is careful to avoid a scenario where you
//inadvertently clobber your ledger ' s data!
Func (t *simpleasset) Init (stub shim. Chaincodestubinterface) Peer. Response {
  //Get the args from the transaction proposal
  args: = Stub. Getstringargs ()
  If Len (args)!= 2 {return
    shim. Error ("Incorrect arguments. Expecting a key and a value ")
  }

  //Set up any variables or assets this by calling stub. Putstate ()

  //We store the key and the value on the ledger
  err: = Stub. Putstate (Args[0], []byte (Args[1]))
  If Err!= nil {return
    shim. Error (FMT. Sprintf (' Failed to create asset:%s ', args[0])
  } return
  shim. Success (nil)
}

2.4 Call Chaincode

First, add the Invoke function signature

The Invoke is called/transaction on the Chaincode. Each transaction are
//either a ' get ' or a ' set ' on the asset created by Init function. The ' Set '
//may create a new asset by specifying a new Key-value pair.
Func (t *simpleasset) Invoke (stub shim. Chaincodestubinterface) Peer. Response {

}

Just like the init function above, we need to get the parameters through Chaincodestubinterface. The arguments to the invoke function are the names that need to invoke the Chaincode application. In our example, our application has two simple functions set and get, allowing asset values to be set, while allowing for the current state to be obtained. We first call chaincodestubinterface.getfunctionandparameters to get the function name and parameters for the Chaincode application.

The Invoke is called/transaction on the Chaincode. Each transaction are
//either a ' get ' or a ' set ' on the asset created by Init function. The Set
//May create a new asset by specifying a new Key-value pair.
Func (t *simpleasset) Invoke (stub shim. Chaincodestubinterface) Peer. Response {
    //Extract the function and args from the transaction proposal
    FN, args: = Stub. Getfunctionandparameters ()

}

We then set the set and get function names and call these Chaincode application functions to return an appropriate response via shim. The error function will serialize a response to a GRPC protobuf message.

The Invoke is called/transaction on the Chaincode. Each transaction are
//either a ' get ' or a ' set ' on the asset created by Init function. The Set
//May create a new asset by specifying a new Key-value pair.
Func (t *simpleasset) Invoke (stub shim. Chaincodestubinterface) Peer. Response {
    //Extract the function and args from the transaction proposal
    FN, args: = Stub. Getfunctionandparameters ()

    var result string
    var err error
    If fn = ' Set ' {result
            , err = set (stub, args) c9/>} else {result
            , err = get (stub, args)
    }
    If err!= nil {return
            shim. Error (Err. Error ())
    }//Return of result as

    Success payload return
    Shim. Success ([]byte (Result)
}

2.5 Implement Chaincode Application

Our Chaincode application implements two functions that can be invoked through invoke. Next, implement these functions. As we mentioned above, I use the chaincodestubinterface.putstate and chaincodestubinterface.getstate of the Chaincode Shim API to access the state of access.

Set stores the asset (both key and value) on the ledger. If the key exists,//It'll override the value with the new one Func set (stub shim. Chaincodestubinterface, args []string) (string, error) {if Len (args)!= 2 {return "", FMT. Errorf ("incorrect arguments.") Expecting a key and a value "} Err: = Stub. Putstate (Args[0], []byte (Args[1])) If Err!= nil {return "", FMT. Errorf ("Failed to set Asset:%s", Args[0])} return args[1], nil}//Get returns the value of the specified Asse T key func get (stub shim. Chaincodestubinterface, args []string) (string, error) {if Len (args)!= 1 {return "", FMT. Errorf ("incorrect arguments.") Expecting a key ")} value, Err: = Stub. GetState (Args[0]) If Err!= nil {return "", FMT. Errorf ("Failed to get asset:%s with Error:%s", Args[0], err)} if value = = Nil {return "", FMT. Errorf (' Asset not found:%s ', args[0])} return string (value), nil} 

2.6 Merging the above code

Package main import ("FMT" "Github.com/hyperledger/fabric/core/chaincode/shim" "Github.com/hyperledger/fabr  Ic/protos/peer ")//Simpleasset implements a simple chaincode to manage an asset type simpleasset struct {}//Init is Called during Chaincode instantiation to initialize any//data.
Note that Chaincode upgrade also calls the This function to reset//to migrate data. Func (t *simpleasset) Init (stub shim. Chaincodestubinterface) Peer. Response {//Get the args from the transaction proposal args: = Stub. Getstringargs () If Len (args)!= 2 {return shim. Error ("Incorrect arguments. Expecting a key and a value ")}//Set up any variables or assets this by calling stub. Putstate ()//We store the key and the value on the ledger err: = Stub. Putstate (Args[0], []byte (Args[1])) If Err!= nil {return shim. Error (FMT. Sprintf (' Failed to create asset:%s ', args[0])} return shim. Success (NIL)}//Invoke is Called/Transaction on the Chaincode. Each transaction are//either a ' get ' or a ' set ' on the asset created by Init function.
The Set//may create a new asset by specifying a new Key-value pair. Func (t *simpleasset) Invoke (stub shim. Chaincodestubinterface) Peer. Response {//Extract the function and args from the transaction proposal FN, args: = Stub. Getfunctionandparameters () var result string var err error if fn = ' Set ' {result, err = set (stu b, args)} else {//assume ' get ' even if FN be nil result, err = get (stub, args)} If Err!= nil {return shim. Error (Err. Error ())}//Return of result as success payload return shim. Success ([]byte)}//Set stores the asset (both key and value) on the ledger. If the key exists,//It'll override the value with the new one Func set (stub shim. Chaincodestubinterface, args []string) (string, error) {if Len (args)!= 2 {return "",Fmt. Errorf ("incorrect arguments.") Expecting a key and a value "} Err: = Stub. Putstate (Args[0], []byte (Args[1])) If Err!= nil {return "", FMT. Errorf ("Failed to set Asset:%s", Args[0])} return args[1], nil}//Get returns the value of the specified Asse T key func get (stub shim. Chaincodestubinterface, args []string) (string, error) {if Len (args)!= 1 {return "", FMT. Errorf ("incorrect arguments.") Expecting a key ")} value, Err: = Stub. GetState (Args[0]) If Err!= nil {return "", FMT. Errorf ("Failed to get asset:%s with Error:%s", Args[0], err)} if value = = Nil {return "", FMT. Errorf (' Asset not found:%s ', args[0])} return string (value), nil}//main function starts up the Chaincode in The container during instantiate func main () {if err: = shim. Start (New (Simpleasset)); Err!= Nil {fmt. Printf ("Error starting Simpleasset Chaincode:%s", err)}}

2.7 Build Chaincode

Compiling Chaincode

Go get-u--tags nopkcs11 github.com/hyperledger/fabric/core/chaincode/shim go build
--tags NOPKCS11

Next Test Chaincode

2.8 Using DEV Mode test

Generally speaking, peer starts and holds chaincode. In development mode, however, Chaincode is created and started by the user. This pattern is useful in the development phase of the chain code during the fast Code/build/Run/debug cycle turnaround period.

We start a "development model" of a simple development network by leveraging the pre generated order and channel artifacts. As a result, users can immediately compile chaincode and call functions.

3. Installation of Hyberledger Fabric sample

Please install the Hyberledger Fabric sample first.

Enter Fabric-samples and Chaincode-docker-devmode directory

CD Chaincode-docker-devmode

4. Download Docker image

We need four Docker mirrors for development mode to allow Docker compose Script, if you have already installed the Fabric-samples warehouse clone and follow the instructions to download the platform-specific-binaries, then you should follow Docker mirroring locally. Enter the docker images command to display the Docker image. Should be able to see the following:

Docker images REPOSITORY TAG IMAGE ID CREATED SIZE Hyperledger/fabric-tools latest e09f38f8928d 4 hours ago 1.32 GB H Yperledger/fabric-tools x86_64-1.0.0-rc1-snapshot-f20846c6 e09f38f8928d 4 hours ago 1.32 GB Hyperle Dger/fabric-orderer latest 0df93ba35a25 4 hours ago 179 MB HYPERLEDGER/FA Bric-orderer x86_64-1.0.0-rc1-snapshot-f20846c6 0df93ba35a25 4 hours ago 179 MB Hyperledger/fabric-pe        ER latest 533aec3f5a01 4 hours ago MB hyperledger/fabric-peer X86_64-1.0.0-rc1-snapshot-f20846c6 533aec3f5a01 4 hours ago MB hyperledger/fabric-ccenv late St 4b70698a71d3 4 hours ago 1.29 GB Hyperledger/fabric-ccenv x86_64-1.0 .0-rc1-snapshot-f20846c6   4b70698a71d3 4 hours ago 1.29 GB 

5. Start Network

Docker-compose-f Docker-compose-simple.yaml up

The above code starts the network that includes Singlesamplemspsolo Orderer profile, and initiates the development mode of peer. This launches the other two containers, one is the chaincode environment and the CLI interacting with the Chaincode. Create and join channel commands in the CLI container, so we can start Chaincode calls.

6.build and Boot Chaincode

Docker exec-it Chaincode Bash

Into the container,

root@d2629980e76b:/opt/gopath/src/chaincode#

Next, compile the Chaincode

CD Asset Go Build

Run Chaincode Now:

core_peer_address=peer:7051 core_chaincode_id_name=mycc:0. /asset

Peer started the Chaincode, and Chaincode logs indicate that peer successfully registered Chaincode. This stage Chaincode does not have any association with any channel. This is done in subsequent steps that use the instantiation command.

7. Use of Chaincode

Even now in--peer-chaincodedev mode, you still need to install chaincode so that the lifecycle Chaincode can be checked properly.

We use the CLI container to invoke these methods

Docker exec-it CLI Bash
Peer Chaincode install-p chaincodedev/chaincode/asset-n mycc-v 0 Peer Chaincode instantiate-n mycc-v 0-c
' {' Args ": [" a "," Ten "]} '-C MYC

Next, change the value of a to 20.

Peer Chaincode invoke-n mycc-c ' {Args ': [' Set ', ' a ', ' ']} '-C MYC

Last Query

Peer Chaincode query-n mycc-c ' {Args ': [' query ', ' a ']}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.