diff --git a/README.md b/README.md index 5d79f614c..26454ecb2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +# NOTICE + +This repository is deprecated. It only teaches you how to write chaincode for Hyperledger Fabric v0.6. For information +on how to write chaincode for the latest Fabric releases, see the [Hyperledger documentation](http://hyperledger-fabric.readthedocs.io/en/latest/chaincode.html). + # Learn Chaincode A tutorial to get you started with writing smart contracts for Hyperledger. @@ -16,6 +21,7 @@ In order to support multiple versions of the Hyperledger fabric, this repository - [v2.0](https://github.com/ibm-blockchain/learn-chaincode/tree/v2.0) - Hyperledger fabric v0.6-developer-preview + - IBM Bluemix Blockchain Service v1.0.0 If you'd like to just deploy the sample code without completing the tutorial, then use the following URLs for the path parameter when deploying via the fabric REST API. Choose the URL that corresponds to the branch you are using above. @@ -250,7 +256,7 @@ If you're stuck or confused at any point, just go check out the `chaincode_finis # Interacting with Your First Chaincode -The fastest way to test your chaincode is to use the REST interface on your peers. If you're using the blockchain service on Bluemix, you should follow the steps described [here](https://new-console.ng.bluemix.net/docs/services/blockchain/ibmblockchain_tutorials.html). Otherwise, we recommend using a tool like Postman, as described in the [environment setup documentation](docs/setup.md). There are two REST endpoints we will be interacting with: `/chaincode` and `/registrar`. +The fastest way to test your chaincode is to use the REST interface on your peers. If you're using the blockchain service on Bluemix, you should follow the steps described [here](https://console.ng.bluemix.net/docs/services/blockchain/ibmblockchain_tutorials.html). Otherwise, we recommend using a tool like Postman, as described in the [environment setup documentation](docs/setup.md). There are two REST endpoints we will be interacting with: `/chaincode` and `/registrar`. - `/chaincode` is the endpoint used for deploying, invoking, and querying chaincode. Which operation you perform is controlled by the body of the request that you send. - `/registrar` allows you to enroll users. Why does this matter? Read on! @@ -259,7 +265,7 @@ The fastest way to test your chaincode is to use the REST interface on your peer Calls to the `/chaincode` endpoint of the REST interface require a secure context ID to be included in the body of the request. This means that you must first enroll a user from the user list in the membership service for your network. -- Find an available user to enroll on one of your peers. This will most likely require you to grab a user from the [membersrvc.yaml](https://github.com/hyperledger/fabric/blob/v0.6/membersrvc/membersrvc.yaml#L199) file for your network. Look for the section that has a list of users like this: +- Find an available user to enroll on one of your peers. This will most likely require you to grab a user from the [membersrvc.yaml](https://github.com/hyperledger/fabric/blob/v0.6/membersrvc/membersrvc.yaml#L199) file for your network. That link points to an example file from the fabric repository. Unless you are running on Bluemix, it is most likely that you will have the same users in your membership service as the ones listed in that file. Look for the section that has a list of users like this: ``` ... @@ -268,18 +274,39 @@ Calls to the `/chaincode` endpoint of the REST interface require a secure contex test_user2: 1 zMflqOKezFiA bank_c 00008 ... ``` +- All we care about are the usernames and secrets for these users. Open up a notepad and copy one set of credentials. You will use them to enroll the user. For the example list above, `test_user0` is a username and `MS9qrN8hFjlE` is a secret. -- Open up a notepad and copy one set of credentials. You will need them later. +- If you are using a network from Bluemix, you can find your list of users from either the API tab of the service dashboard, or your service credentials. + Example users from the service credentials: ``` - test_user0 MS9qrN8hFjlE + ... + { + "enrollId": "user_type1_1", + "enrollSecret": "56244fa98b", + "affiliation": "group1", + "username": "user_type1_1", + "secret": "56244fa98b" + }, + { + "enrollId": "user_type1_2", + "enrollSecret": "9853b2de7e", + "affiliation": "group1", + "username": "user_type1_2", + "secret": "9853b2de7e" + }, + ... ``` + + Example users from the API tab on the dashboard: + + ![/users from api tab](imgs/api_users.PNG) -- Create a POST request like the example below. +- Create an enrollment POST request in Postman like the example below. ![/registrar POST](imgs/registrar_post.png) - The url indicates that the REST port for one of my Bluemix peers is accessible at `b88037dd5b6d423caf5258c6b7b15f5a-vp3.dev.blockchain.ibm.com:443`. This is the api URL for vp3\. You would find this information on the **Service Credentials** tab of the Blockchain dashboard or the **Network** tab of your Bluemix console. This specific registration is being sent to vp3, but it could be directed at any network peer. +- You can see that we sent the username and secret to the `/registrar` endpoint of a peer. If you're wondering where the rest of that url came from, it came from my blockchain Bluemix service credentials. You can find this information yourself on the **Service Credentials** tab of the blockchain service on your Bluemix dashboard or the **Network** tab of your blockchain service dashboard. - The body for the request: @@ -290,7 +317,7 @@ Calls to the `/chaincode` endpoint of the REST interface require a secure contex } ``` -- Send the request. If everything goes smoothly, you will see a response like the one below +- Send the request. If everything goes smoothly, you will see a response like the one below: ![/registrar response](imgs/registrar_post_response.png) @@ -327,7 +354,7 @@ In order to deploy chaincode through the REST interface, you will need to have t "params": { "type": 1, "chaincodeID": { - "path": "https://github.com//learn-chaincode/finished" + "path": "http://gopkg.in//learn-chaincode.v2/start" }, "ctorMsg": { "function": "init", @@ -341,7 +368,9 @@ In order to deploy chaincode through the REST interface, you will need to have t } ``` -- The `"path":` is the path to your fork of the repository on Github, going one more directory down into `/finished`, where your `chaincode_finished.go` file lives. +- The `"path":` is the path to your fork of the repository on Github, going one more directory down into `/start`, where your `chaincode_start.go` file lives. The `v.2` portion of the URL indicates that the peer should checkout the code from the `v2.0` branch of your fork. + +- You may be wondering why we didn't use a URL like `http://github.com//learn-chaincode/start`. Well, this URL would work, but this would cause the peer to deploy the chaincode from the `master` branch of your repository, as opposed to the `v2.0` or `v1.0` branches. If you've been following this guide to the letter, then you have been committing changes and pushing to these branches in your fork, not the `master` branch. - Send the request. If everything goes smoothly, you will see a response like the one below diff --git a/README_zh-cn.md b/README_zh-cn.md index be364779e..2cc14da10 100644 --- a/README_zh-cn.md +++ b/README_zh-cn.md @@ -1,423 +1,427 @@ -# 学习链码 - -本教程可以指导你着手为 Hyperledger 编写智能合约。 - -# 部署 - -为了实现对 Hyperledger fabric 多个版本的支持,本仓库使用了与 gopkg.in URLs 结合的分支。对于初学者这意味着什么呢?随便选择下面的一个分支,使用分支中的指导说明就可以完成本教程。 - -## 支持的平台和版本 - -- [v1.0](https://github.com/ibm-blockchain/learn-chaincode/tree/v1.0) - - Hyperledger fabric v0.5-developer-preview - - IBM Bluemix Blockchain Service v0.4.2 -- [v2.0](https://github.com/ibm-blockchain/learn-chaincode/tree/v2.0) - - Hyperledger fabric v0.6-developer-preview - -如果你不想完整地学习本教程只打算部署这里的示例代码,你可以在使用 fabric REST API 部署链码的时候把 `path` 参数设置为下面的 URLs。URL 的选择对应于你上面选择的分支。 - -``` -http://gopkg.in/ibm-blockchain/learn-chaincode.v1/finished -OR -http://gopkg.in/ibm-blockchain/learn-chaincode.v2/finished -``` - -# 如何编写链码 - -本教程演示了构建 [Hyperledger fabric](https://gerrit.hyperledger.org/r/#/admin/projects/fabric) 链码应用程序所需的基本构建块和函数。你将逐步创建一个可以用于通用资产的链码。然后,你可以使用网络 API 与链码交互。阅读并完成本教程后,你应该能够明确回答以下问题: - -- 什么是链码? -- 如何实现链码? -- 实现链码需要什么依赖关系? -- 链码的主要功能是什么? -- 如何编译我的链码? -- 如何传递不同的值到我的参数? -- 如何安全地在我的网络上注册用户? -- 如何使用 REST API 与我的链码交互? - -## 什么是链码? - -链码是一段代码,它被部署到 [Hyperledger fabric](https://gerrit.hyperledger.org/r/#/admin/projects/fabric) 节点的网络中,实现与该网络的共享总账的交互。 - --------------------------------------------------------------------------------- - -# 实现你的第一个链码 - -## 配置你的开发环境 - -在你开始之前,你应该访问 [这里](docs/setup.md) 构建你的链码开发环境。 当你再次回到这里的时候,你将拥有完成本教程所需的所有工具。 - -## 设置你的开发管道(Pipeline) - -以下任务带你完成构建管道的过程,这能够让你有效地构建链码。 简而言之,用于链码迭代的管道包括以下步骤: - - - 更改本地上给定的链码,并检查代码是否能够编译。 - - 把你的更新推送到 Github。 - - 使用 fabric REST API 把更新的链码部署到本地 Hyperledger 网络中。 - - 使用 fabric REST API 测试你的链码。 - - 重复该过程。 - -1. 创建本仓库的分支到你的 Github 账户中。该操作可以通过点击本仓库顶部的 __Fork__ 按钮快速完成。 - - ![Fork Button Screenshot](imgs/fork.png) - - 对本仓库“创建分支”(Forking)意味着在你的 Github 账户中创建了一份本仓库的副本。请注意,Fork 操作将创建包括所有分支的整个仓库。切换左侧的 __Branch__ 按钮查看可用的分支。 - - ![Branch Button Screenshot](imgs/branch.png) - -2. 克隆你的分支到 $GOPATH 目录中。 - - ```bash - cd $GOPATH - mkdir -p src/github.com// - cd src/github.com// - git clone -b v1.0 https://github.com//learn-chaincode.git - OR - git clone -b v2.0 https://github.com//learn-chaincode.git - ``` - - 现在,你的电脑中已经有了你的分支的一个副本。你需要通过对这些本地文件的修改去开发你的链码,然后把它们推送到你的 Github 分支中,之后在你的一个节点上通过 REST API 把这些代码部署到你的区块链网络中。 - -3. 请注意,在本教程中,我们提供了两个不同版本的链码:[Start](start/chaincode_start.go) - 你将要在此基础上进行开发的框架链码,[Finished](finished/chaincode_finished.go) - 已完成的链码。 - -4. 确保它能够在你的本地环境中编译: - - - 打开终端或命令提示符 - - ```bash - cd $GOPATH/src/github.com//learn-chaincode/start - go build ./ - ``` - - - 编译的时候应该不会出现错误或文本。如果出现问题,请确保你已按照 [开发环境配置说明](docs/setup.md) 正确安装了 Go。 - -5. 把这些改变推送到你的 Github 分支中。 - - ```bash - cd $GOPATH/src/github.com//learn-chaincode/ - # 查看本地那些文件修改了。你应该能看到 chaincode_start.go - git status - # 暂存本地仓库中的所有更改以便进行提交 - git add --all - # 提交所有暂存的更改。在 -m 参数后插入简短的描述 - git commit -m "Compiled my code" - # 把本地的提交推送到 https://github.com//learn-chaincode/ - git push - ``` - -为了把一段 Go 代码转换为链码,你所需要做的就是实现链码的 shim 接口。你必须实现的三个函数分别是 **Init**、**Invoke** 和 **Query**。这三个函数都具有相同的原型;他们接受一个 `stub` ——用来读取和写入总账,一个函数名和一个字符串数组。这几个函数的主要区别在于它们何时被调用。本教程中,你将构建一个链码用来创建通用资产。 - -### 依赖 - -`import` 语句列出了成功构建链码的一些依赖关系。 -- `fmt` - 包含用于调试/日志记录的 `Println`。 -- `errors` - 标准 go 错误格式。 -- `github.com/hyperledger/fabric/core/chaincode/shim` - 包含了链码接口和链码 stub 的定义,它们用来与总账进行交互。 - -### Init() - -Init 在首次部署你的链码时被调用。顾名思义,此函数用于链码所需的所有初始化工作。在我们的示例中,我们使用 Init 函数设置总账一个键值对的初始状态。 - -在你的 `chaincode_start.go` 文件中,修改 `Init` 函数,以便将 `args` 参数中的第一个元素存储到键 “hello_world” 中。 - -```go -func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { - if len(args) != 1 { - return nil, errors.New("Incorrect number of arguments. Expecting 1") - } - - err := stub.PutState("hello_world", []byte(args[0])) - if err != nil { - return nil, err - } - - return nil, nil -} -``` - -这是通过 stub 的 `stub.PutState` 函数完成的。该函数将部署请求中发送的第一个参数解释为要存储在分类帐中的键 “hello_world” 下的值。 这个参数是从哪里来的,什么是部署请求?我们将在实现接口后再解释。如果发生错误,例如传入的参数数量错误,或者写入总账时发生错误,则此函数将返回错误。否则,它将完全退出,什么都不返回。 - -### Invoke() - -当你想调用链码函数来做真正的工作时,`Invoke` 就会被调用。这些调用会被当做交易被分组到链上的区块中。当你需要更新总账时,就会通过调用你的链码去完成。`Invoke` 的结构很简单。它接收一个 `function` 以及一个数组参数,基于调用请求中传递的 `function` 参数所指的函数,`Invoke` 将调用这个辅助函数或者返回错误。 - -在你的 `chaincode_start.go` 文件中,修改 `Invoke` 函数,让它调用一个普通的 `write` 函数。 - -```go -func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { - fmt.Println("invoke is running " + function) - - // 处理不同的函数 - if function == "init" { - return t.Init(stub, "init", args) - } else if function == "write" { - return t.write(stub, args) - } - fmt.Println("invoke did not find func: " + function) - - return nil, errors.New("Received unknown function invocation: " + function) -} -``` - -现在,它正在寻找 `write` 函数,让我们把这个函数写入你的 `chaincode_start.go` 文件。 - -```go -func (t *SimpleChaincode) write(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { - var key, value string - var err error - fmt.Println("running write()") - - if len(args) != 2 { - return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the key and value to set") - } - - key = args[0] //rename for fun - value = args[1] - err = stub.PutState(key, []byte(value)) //把变量写入链码状态中 - if err != nil { - return nil, err - } - return nil, nil -} -``` - -你可能会认为这个 `write` 函数看起来类似 `Init`。 它们确实很像。 这两个函数检查一定数量的参数,然后将一个键/值对写入总账。然而,你会注意到,`write` 函数使用两个参数,允许你同时传递给调用的 `PutState` 键和值。基本上,该函数允许你向区块链总账上存储任意你想要的键值对。 - -### Query() - -顾名思义,无论何时查询链码状态,`Query` 都会被调用。查询操作不会导致区块被添加到链中。你不能在 `Query` 中使用类似 `PutState` 的函数,也不能使用它调用的任何辅助函数。你将使用 `Query` 读取链码状态中键/值对的值。 - -在你的 `chaincode_start.go` 文件中,修改 `Query` 函数,让它调用一个普通的 `read` 函数,类似你对 `Invoke` 函数的修改。 - -```go -func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { - fmt.Println("query is running " + function) - - // 处理不同的函数 - if function == "read" { //读取变量 - return t.read(stub, args) - } - fmt.Println("query did not find func: " + function) - - return nil, errors.New("Received unknown function query: " + function) -} -``` - -现在,它正在寻找 `read` 函数,让我们在 `chaincode_start.go` 文件中创建该函数。 - -```go -func (t *SimpleChaincode) read(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { - var key, jsonResp string - var err error - - if len(args) != 1 { - return nil, errors.New("Incorrect number of arguments. Expecting name of the key to query") - } - - key = args[0] - valAsbytes, err := stub.GetState(key) - if err != nil { - jsonResp = "{\"Error\":\"Failed to get state for " + key + "\"}" - return nil, errors.New(jsonResp) - } - - return valAsbytes, nil -} -``` - -这个 `read` 函数使用了与 `PutState` 作用相反的 `GetState`。 `PutState` 允许你对一个键/值对赋值,`GetState`允许你读取之前赋值的键的值。你可以看到,该函数使用的唯一参数被作为应该检索的值的键。接下来,此函数将字符数组返回到 `Query`,然后将它返回给 REST 句柄。 - -### Main() - -最后,你需要创建一个简短的 `main` 函数,它在每个节点部署链码实例的时候执行。它仅仅调用了 `shim.Start()`,该函数会在链码与部署链码的节点之间建立通信。你不需要为该函数添加任何代码。`chaincode_start.go` 和 `chaincode_finished.go` 都有一个 `main` 函数,它位于文件的顶部。该函数如下所示: - -```go -func main() { - err := shim.Start(new(SimpleChaincode)) - if err != nil { - fmt.Printf("Error starting Simple chaincode: %s", err) - } -} -``` - -### 需要帮助? - -如果你在任何时候被卡住或有什么困惑,只需去查看 `chaincode_finished.go` 文件。使用该文件检查您正在编写的 `chaincode_start.go` 代码段是否正确。 - -# 与你的第一个链码交互 - -测试你的链码的最快方法是使用节点上的 REST 接口。如果你使用的是 Bluemix 上的块链服务,你应该依照 [这里](https://new-console.ng.bluemix.net/docs/services/blockchain/ibmblockchain_tutorials.html) 描述的步骤(否则,我们建议使用 [环境配置文档](docs/setup.md) 中所述类似 Postman 的工具)。我们需要与两个 REST 端点交互:`/chaincode` 和 `/registrar`。 - - - `/chaincode` 是用于部署、调用和查询链码的端点。执行哪种操作由发送的请求 Body 内容来控制。 - - `/registrar` 允许你注册用户。为什么这么重要?请继续阅读! - -### 安全注册 - -调用 REST 接口的 `/chaincode` 端点需要在请求的 Body 中包含一个安全上下文 ID。这意味着你必须先在网络成员服务的用户列表中注册一个用户。在你的节点中查找一个可用的用户去注册。这很可能需要为你的网络从 [membersrvc.yaml](fabric/membersrvc/membersrvc.yaml) 文件中抓取一个用户。找到包含以下用户列表的部分: - - ``` - ... - test_user0: 1 MS9qrN8hFjlE bank_a 00001 - test_user1: 1 jGlNl6ImkuDo institution_a 00007 - test_user2: 1 zMflqOKezFiA bank_c 00008 - ... - ``` - -- 打开记事本并复制一组凭证,接下来会用到它们。 - - ``` - test_user0 MS9qrN8hFjlE - ``` - -- 如下所示,创建一个 POST 请求。 - - ![/registrar POST](imgs/registrar_post.png) - - 该 URL 表示 Bluemix 某个节点的 REST 端口可以通过 `b88037dd5b6d423caf5258c6b7b15f5a-vp3.dev.blockchain.ibm.com:443` 访问。这是 vp3 节点的 api URL。你可以在区块链仪表盘 **服务凭据(Service Credentials)** 选项卡上找到该信息,或者在 Bluemix 控制台的 __网络__ 选项卡中。这个特定的注册会被发送到 vp3 节点,不过,它能够被转发到所有的网络节点上。 - -- 该请求的 Body 内容为: - - ```json - { - "enrollId": "", - "enrollSecret": "" - } - ``` - -- 发送这个请求。如果一切顺利,你会看到类似下面的响应: - - ![/registrar response](imgs/registrar_post_response.png) - - 如果你没有收到“登录成功”的响应,请返回并确保你已正确复制了注册 ID 和密码。现在,你有了一个 ID,它用于后续步骤中链码的部署、调用和查询。 - -### 部署链码 - -为了通过 REST 接口部署链码,你需要将链码存储在公共的 git 仓库中。当你向节点发送部署请求时,请求中包括你的链码仓库 URL 以及初始化链码所需的参数。 - -**在部署链码之前**,确保它能在本地构建! - -- 打开终端或命令提示符 - -- 进入包含 `chaincode_start.go` 的文件夹,编译你的链码: - - ```bash - cd $GOPATH/src/github.com//learn-chaincode/start - go build ./ - ``` - -- 如果没有出现错误/文本,这意味着你的链码已经编译成功了。这是个好兆头。 - -- 如下所示,创建一个 POST 请求。 - - ![/chaincode deploy example](imgs/deploy_example.PNG) - -- **注意**:确保你部署到的节点与用户注册到的节点是相同的。在这里我们使用的是 vp3 节点。 - -- 该请求的 Body 内容为: - - ```json - { - "jsonrpc": "2.0", - "method": "deploy", - "params": { - "type": 1, - "chaincodeID": { - "path": "https://github.com//learn-chaincode/finished" - }, - "ctorMsg": { - "function": "init", - "args": [ - "hi there" - ] - }, - "secureContext": "" - }, - "id": 1 - } - ``` - -- `"path"`:你创建的 Github 仓库分支的路径,`chaincode_finished.go` 文件在它的下一级目录 `/finished` 中。 - -- 发送该请求。如果一切顺利,你会看到类似下面的响应: - - ![/chaincode deploy response](imgs/deploy_response.PNG) - -部署响应的一长串字符串中包含了一个与链码相关的 ID。这个 ID 是一个由 128 个字母数字组成的哈希。可以在记事本上复制该 ID。现在,你应该有一组 enrollID 凭据和标识你的链码的加密哈希了。这就是在接下来调用或查询交易中如何引用链码的方式。 - -### 查询 - -接下来,让我们查询链码中 `hello_world` 键的值,之前我们使用了 `Init` 函数为它设置了初始值。 - -- 如下所示,创建一个 POST 请求。 - - ![/chaincode query example](imgs/query_example.PNG) - -- 该请求的 Body 内容为: - - ```json - { - "jsonrpc": "2.0", - "method": "query", - "params": { - "type": 1, - "chaincodeID": { - "name": "" - }, - "ctorMsg": { - "function": "read", - "args": [ - "hello_world" - ] - }, - "secureContext": "" - }, - "id": 2 - } - ``` - -- 发送该请求。如果一切顺利,你会看到类似下面的响应: - - ![/chaincode query response](imgs/query_response.PNG) - -该值是由之前部署请求的 Body 设置的。 - -### 调用 - -接下来,通过调用在链码中编写的普通 `write` 函数,将 “hello_world” 的值改为 “go away”。 - -- 如下所示,创建一个 POST 请求。 - - ![/chaincode invoke example](imgs/invoke_example.PNG) - -- 该请求的 Body 内容为: - - ```json - { - "jsonrpc": "2.0", - "method": "invoke", - "params": { - "type": 1, - "chaincodeID": { - "name": "" - }, - "ctorMsg": { - "function": "write", - "args": [ - "hello_world", "go away" - ] - }, - "secureContext": "" - }, - "id": 3 - } - ``` - -- 发送该请求。如果一切顺利,你会看到类似下面的响应: - - ![/chaincode invoke response](imgs/invoke_response.PNG) - -- 可以通过发送一个类似之前的查询操作,测试我们的更改是否成功。 - - ![/chaincode query2 response](imgs/query2_response.PNG) - +# 注意 + +该仓库已经过时了。这里只指导你如何编写 Hyperledger Fabric v0.6 的链码。对于如何编写最新 Fabric 版本的链码信息,请参阅 [Hyperledger 文档](http://hyperledger-fabric.readthedocs.io/en/latest/chaincode.html)。 + +# 学习链码 + +本教程可以指导你着手为 Hyperledger 编写智能合约。 + +# 部署 + +为了实现对 Hyperledger fabric 多个版本的支持,本仓库使用了与 gopkg.in URLs 结合的分支。对于初学者这意味着什么呢?随便选择下面的一个分支,使用分支中的指导说明就可以完成本教程。 + +## 支持的平台和版本 + +- [v1.0](https://github.com/ibm-blockchain/learn-chaincode/tree/v1.0) + - Hyperledger fabric v0.5-developer-preview + - IBM Bluemix Blockchain Service v0.4.2 +- [v2.0](https://github.com/ibm-blockchain/learn-chaincode/tree/v2.0) + - Hyperledger fabric v0.6-developer-preview + +如果你不想完整地学习本教程只打算部署这里的示例代码,你可以在使用 fabric REST API 部署链码的时候把 `path` 参数设置为下面的 URLs。URL 的选择对应于你上面选择的分支。 + +``` +http://gopkg.in/ibm-blockchain/learn-chaincode.v1/finished +OR +http://gopkg.in/ibm-blockchain/learn-chaincode.v2/finished +``` + +# 如何编写链码 + +本教程演示了构建 [Hyperledger fabric](https://gerrit.hyperledger.org/r/#/admin/projects/fabric) 链码应用程序所需的基本构建块和函数。你将逐步创建一个可以用于通用资产的链码。然后,你可以使用网络 API 与链码交互。阅读并完成本教程后,你应该能够明确回答以下问题: + +- 什么是链码? +- 如何实现链码? +- 实现链码需要什么依赖关系? +- 链码的主要功能是什么? +- 如何编译我的链码? +- 如何传递不同的值到我的参数? +- 如何安全地在我的网络上注册用户? +- 如何使用 REST API 与我的链码交互? + +## 什么是链码? + +链码是一段代码,它被部署到 [Hyperledger fabric](https://gerrit.hyperledger.org/r/#/admin/projects/fabric) 节点的网络中,实现与该网络的共享总账的交互。 + +-------------------------------------------------------------------------------- + +# 实现你的第一个链码 + +## 配置你的开发环境 + +在你开始之前,你应该访问 [这里](docs/setup.md) 构建你的链码开发环境。 当你再次回到这里的时候,你将拥有完成本教程所需的所有工具。 + +## 设置你的开发管道(Pipeline) + +以下任务带你完成构建管道的过程,这能够让你有效地构建链码。 简而言之,用于链码迭代的管道包括以下步骤: + + - 更改本地上给定的链码,并检查代码是否能够编译。 + - 把你的更新推送到 Github。 + - 使用 fabric REST API 把更新的链码部署到本地 Hyperledger 网络中。 + - 使用 fabric REST API 测试你的链码。 + - 重复该过程。 + +1. 创建本仓库的分支到你的 Github 账户中。该操作可以通过点击本仓库顶部的 __Fork__ 按钮快速完成。 + + ![Fork Button Screenshot](imgs/fork.png) + + 对本仓库“创建分支”(Forking)意味着在你的 Github 账户中创建了一份本仓库的副本。请注意,Fork 操作将创建包括所有分支的整个仓库。切换左侧的 __Branch__ 按钮查看可用的分支。 + + ![Branch Button Screenshot](imgs/branch.png) + +2. 克隆你的分支到 $GOPATH 目录中。 + + ```bash + cd $GOPATH + mkdir -p src/github.com// + cd src/github.com// + git clone -b v1.0 https://github.com//learn-chaincode.git + OR + git clone -b v2.0 https://github.com//learn-chaincode.git + ``` + + 现在,你的电脑中已经有了你的分支的一个副本。你需要通过对这些本地文件的修改去开发你的链码,然后把它们推送到你的 Github 分支中,之后在你的一个节点上通过 REST API 把这些代码部署到你的区块链网络中。 + +3. 请注意,在本教程中,我们提供了两个不同版本的链码:[Start](start/chaincode_start.go) - 你将要在此基础上进行开发的框架链码,[Finished](finished/chaincode_finished.go) - 已完成的链码。 + +4. 确保它能够在你的本地环境中编译: + + - 打开终端或命令提示符 + + ```bash + cd $GOPATH/src/github.com//learn-chaincode/start + go build ./ + ``` + + - 编译的时候应该不会出现错误或文本。如果出现问题,请确保你已按照 [开发环境配置说明](docs/setup.md) 正确安装了 Go。 + +5. 把这些改变推送到你的 Github 分支中。 + + ```bash + cd $GOPATH/src/github.com//learn-chaincode/ + # 查看本地那些文件修改了。你应该能看到 chaincode_start.go + git status + # 暂存本地仓库中的所有更改以便进行提交 + git add --all + # 提交所有暂存的更改。在 -m 参数后插入简短的描述 + git commit -m "Compiled my code" + # 把本地的提交推送到 https://github.com//learn-chaincode/ + git push + ``` + +为了把一段 Go 代码转换为链码,你所需要做的就是实现链码的 shim 接口。你必须实现的三个函数分别是 **Init**、**Invoke** 和 **Query**。这三个函数都具有相同的原型;他们接受一个 `stub` ——用来读取和写入总账,一个函数名和一个字符串数组。这几个函数的主要区别在于它们何时被调用。本教程中,你将构建一个链码用来创建通用资产。 + +### 依赖 + +`import` 语句列出了成功构建链码的一些依赖关系。 +- `fmt` - 包含用于调试/日志记录的 `Println`。 +- `errors` - 标准 go 错误格式。 +- `github.com/hyperledger/fabric/core/chaincode/shim` - 包含了链码接口和链码 stub 的定义,它们用来与总账进行交互。 + +### Init() + +Init 在首次部署你的链码时被调用。顾名思义,此函数用于链码所需的所有初始化工作。在我们的示例中,我们使用 Init 函数设置总账一个键值对的初始状态。 + +在你的 `chaincode_start.go` 文件中,修改 `Init` 函数,以便将 `args` 参数中的第一个元素存储到键 “hello_world” 中。 + +```go +func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { + if len(args) != 1 { + return nil, errors.New("Incorrect number of arguments. Expecting 1") + } + + err := stub.PutState("hello_world", []byte(args[0])) + if err != nil { + return nil, err + } + + return nil, nil +} +``` + +这是通过 stub 的 `stub.PutState` 函数完成的。该函数将部署请求中发送的第一个参数解释为要存储在分类帐中的键 “hello_world” 下的值。 这个参数是从哪里来的,什么是部署请求?我们将在实现接口后再解释。如果发生错误,例如传入的参数数量错误,或者写入总账时发生错误,则此函数将返回错误。否则,它将完全退出,什么都不返回。 + +### Invoke() + +当你想调用链码函数来做真正的工作时,`Invoke` 就会被调用。这些调用会被当做交易被分组到链上的区块中。当你需要更新总账时,就会通过调用你的链码去完成。`Invoke` 的结构很简单。它接收一个 `function` 以及一个数组参数,基于调用请求中传递的 `function` 参数所指的函数,`Invoke` 将调用这个辅助函数或者返回错误。 + +在你的 `chaincode_start.go` 文件中,修改 `Invoke` 函数,让它调用一个普通的 `write` 函数。 + +```go +func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { + fmt.Println("invoke is running " + function) + + // 处理不同的函数 + if function == "init" { + return t.Init(stub, "init", args) + } else if function == "write" { + return t.write(stub, args) + } + fmt.Println("invoke did not find func: " + function) + + return nil, errors.New("Received unknown function invocation: " + function) +} +``` + +现在,它正在寻找 `write` 函数,让我们把这个函数写入你的 `chaincode_start.go` 文件。 + +```go +func (t *SimpleChaincode) write(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { + var key, value string + var err error + fmt.Println("running write()") + + if len(args) != 2 { + return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the key and value to set") + } + + key = args[0] //rename for fun + value = args[1] + err = stub.PutState(key, []byte(value)) //把变量写入链码状态中 + if err != nil { + return nil, err + } + return nil, nil +} +``` + +你可能会认为这个 `write` 函数看起来类似 `Init`。 它们确实很像。 这两个函数检查一定数量的参数,然后将一个键/值对写入总账。然而,你会注意到,`write` 函数使用两个参数,允许你同时传递给调用的 `PutState` 键和值。基本上,该函数允许你向区块链总账上存储任意你想要的键值对。 + +### Query() + +顾名思义,无论何时查询链码状态,`Query` 都会被调用。查询操作不会导致区块被添加到链中。你不能在 `Query` 中使用类似 `PutState` 的函数,也不能使用它调用的任何辅助函数。你将使用 `Query` 读取链码状态中键/值对的值。 + +在你的 `chaincode_start.go` 文件中,修改 `Query` 函数,让它调用一个普通的 `read` 函数,类似你对 `Invoke` 函数的修改。 + +```go +func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { + fmt.Println("query is running " + function) + + // 处理不同的函数 + if function == "read" { //读取变量 + return t.read(stub, args) + } + fmt.Println("query did not find func: " + function) + + return nil, errors.New("Received unknown function query: " + function) +} +``` + +现在,它正在寻找 `read` 函数,让我们在 `chaincode_start.go` 文件中创建该函数。 + +```go +func (t *SimpleChaincode) read(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { + var key, jsonResp string + var err error + + if len(args) != 1 { + return nil, errors.New("Incorrect number of arguments. Expecting name of the key to query") + } + + key = args[0] + valAsbytes, err := stub.GetState(key) + if err != nil { + jsonResp = "{\"Error\":\"Failed to get state for " + key + "\"}" + return nil, errors.New(jsonResp) + } + + return valAsbytes, nil +} +``` + +这个 `read` 函数使用了与 `PutState` 作用相反的 `GetState`。 `PutState` 允许你对一个键/值对赋值,`GetState`允许你读取之前赋值的键的值。你可以看到,该函数使用的唯一参数被作为应该检索的值的键。接下来,此函数将字符数组返回到 `Query`,然后将它返回给 REST 句柄。 + +### Main() + +最后,你需要创建一个简短的 `main` 函数,它在每个节点部署链码实例的时候执行。它仅仅调用了 `shim.Start()`,该函数会在链码与部署链码的节点之间建立通信。你不需要为该函数添加任何代码。`chaincode_start.go` 和 `chaincode_finished.go` 都有一个 `main` 函数,它位于文件的顶部。该函数如下所示: + +```go +func main() { + err := shim.Start(new(SimpleChaincode)) + if err != nil { + fmt.Printf("Error starting Simple chaincode: %s", err) + } +} +``` + +### 需要帮助? + +如果你在任何时候被卡住或有什么困惑,只需去查看 `chaincode_finished.go` 文件。使用该文件检查您正在编写的 `chaincode_start.go` 代码段是否正确。 + +# 与你的第一个链码交互 + +测试你的链码的最快方法是使用节点上的 REST 接口。如果你使用的是 Bluemix 上的块链服务,你应该依照 [这里](https://new-console.ng.bluemix.net/docs/services/blockchain/ibmblockchain_tutorials.html) 描述的步骤(否则,我们建议使用 [环境配置文档](docs/setup.md) 中所述类似 Postman 的工具)。我们需要与两个 REST 端点交互:`/chaincode` 和 `/registrar`。 + + - `/chaincode` 是用于部署、调用和查询链码的端点。执行哪种操作由发送的请求 Body 内容来控制。 + - `/registrar` 允许你注册用户。为什么这么重要?请继续阅读! + +### 安全注册 + +调用 REST 接口的 `/chaincode` 端点需要在请求的 Body 中包含一个安全上下文 ID。这意味着你必须先在网络成员服务的用户列表中注册一个用户。在你的节点中查找一个可用的用户去注册。这很可能需要为你的网络从 [membersrvc.yaml](fabric/membersrvc/membersrvc.yaml) 文件中抓取一个用户。找到包含以下用户列表的部分: + + ``` + ... + test_user0: 1 MS9qrN8hFjlE bank_a 00001 + test_user1: 1 jGlNl6ImkuDo institution_a 00007 + test_user2: 1 zMflqOKezFiA bank_c 00008 + ... + ``` + +- 打开记事本并复制一组凭证,接下来会用到它们。 + + ``` + test_user0 MS9qrN8hFjlE + ``` + +- 如下所示,创建一个 POST 请求。 + + ![/registrar POST](imgs/registrar_post.png) + + 该 URL 表示 Bluemix 某个节点的 REST 端口可以通过 `b88037dd5b6d423caf5258c6b7b15f5a-vp3.dev.blockchain.ibm.com:443` 访问。这是 vp3 节点的 api URL。你可以在区块链仪表盘 **服务凭据(Service Credentials)** 选项卡上找到该信息,或者在 Bluemix 控制台的 __网络__ 选项卡中。这个特定的注册会被发送到 vp3 节点,不过,它能够被转发到所有的网络节点上。 + +- 该请求的 Body 内容为: + + ```json + { + "enrollId": "", + "enrollSecret": "" + } + ``` + +- 发送这个请求。如果一切顺利,你会看到类似下面的响应: + + ![/registrar response](imgs/registrar_post_response.png) + + 如果你没有收到“登录成功”的响应,请返回并确保你已正确复制了注册 ID 和密码。现在,你有了一个 ID,它用于后续步骤中链码的部署、调用和查询。 + +### 部署链码 + +为了通过 REST 接口部署链码,你需要将链码存储在公共的 git 仓库中。当你向节点发送部署请求时,请求中包括你的链码仓库 URL 以及初始化链码所需的参数。 + +**在部署链码之前**,确保它能在本地构建! + +- 打开终端或命令提示符 + +- 进入包含 `chaincode_start.go` 的文件夹,编译你的链码: + + ```bash + cd $GOPATH/src/github.com//learn-chaincode/start + go build ./ + ``` + +- 如果没有出现错误/文本,这意味着你的链码已经编译成功了。这是个好兆头。 + +- 如下所示,创建一个 POST 请求。 + + ![/chaincode deploy example](imgs/deploy_example.PNG) + +- **注意**:确保你部署到的节点与用户注册到的节点是相同的。在这里我们使用的是 vp3 节点。 + +- 该请求的 Body 内容为: + + ```json + { + "jsonrpc": "2.0", + "method": "deploy", + "params": { + "type": 1, + "chaincodeID": { + "path": "http://gopkg.in//learn-chaincode.v2/start" + }, + "ctorMsg": { + "function": "init", + "args": [ + "hi there" + ] + }, + "secureContext": "" + }, + "id": 1 + } + ``` + +- `"path"`:你创建的 Github 仓库分支的路径,`chaincode_start.go` 文件在它的下一级目录 `/start` 中。 + +- 发送该请求。如果一切顺利,你会看到类似下面的响应: + + ![/chaincode deploy response](imgs/deploy_response.PNG) + +部署响应的一长串字符串中包含了一个与链码相关的 ID。这个 ID 是一个由 128 个字母数字组成的哈希。可以在记事本上复制该 ID。现在,你应该有一组 enrollID 凭据和标识你的链码的加密哈希了。这就是在接下来调用或查询交易中如何引用链码的方式。 + +### 查询 + +接下来,让我们查询链码中 `hello_world` 键的值,之前我们使用了 `Init` 函数为它设置了初始值。 + +- 如下所示,创建一个 POST 请求。 + + ![/chaincode query example](imgs/query_example.PNG) + +- 该请求的 Body 内容为: + + ```json + { + "jsonrpc": "2.0", + "method": "query", + "params": { + "type": 1, + "chaincodeID": { + "name": "" + }, + "ctorMsg": { + "function": "read", + "args": [ + "hello_world" + ] + }, + "secureContext": "" + }, + "id": 2 + } + ``` + +- 发送该请求。如果一切顺利,你会看到类似下面的响应: + + ![/chaincode query response](imgs/query_response.PNG) + +该值是由之前部署请求的 Body 设置的。 + +### 调用 + +接下来,通过调用在链码中编写的普通 `write` 函数,将 “hello_world” 的值改为 “go away”。 + +- 如下所示,创建一个 POST 请求。 + + ![/chaincode invoke example](imgs/invoke_example.PNG) + +- 该请求的 Body 内容为: + + ```json + { + "jsonrpc": "2.0", + "method": "invoke", + "params": { + "type": 1, + "chaincodeID": { + "name": "" + }, + "ctorMsg": { + "function": "write", + "args": [ + "hello_world", "go away" + ] + }, + "secureContext": "" + }, + "id": 3 + } + ``` + +- 发送该请求。如果一切顺利,你会看到类似下面的响应: + + ![/chaincode invoke response](imgs/invoke_response.PNG) + +- 可以通过发送一个类似之前的查询操作,测试我们的更改是否成功。 + + ![/chaincode query2 response](imgs/query2_response.PNG) + 这就是编写基本链码所需要的全部内容。 \ No newline at end of file diff --git a/docs/setup.md b/docs/setup.md index 5eafe3ae4..021bb04a9 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -1,130 +1,130 @@ -# Chaincode Development Environment - -The following is a list of dependencies and recommended tools that you should install in order to develop chaincode. - -## Git - -- [Git download page](https://git-scm.com/downloads) -- [Pro Git ebook](https://git-scm.com/book/en/v2) -- [Git Desktop (for those uncomfortable with git's CLI)](https://desktop.github.com/) - -Git is a great version control tool to familiarize yourself with, both for chaincode development and software development in general. Also, git bash, which is installed with git on Windows, is an excellent alternative to the the Windows command prompt. - -### Instructions - -After following the installation instructions above, you can verify that git is installed using the following command: - -``` -$ git version -git version 2.9.0.windows.1 -``` - -Once you have git installed, go create an account for yourself on [GitHub](https://github.com/). The IBM Blockchain service on Bluemix currently requires that chaincode be in a GitHub repository in order to be deployed through the REST API. - -## Go - -- [Go 1.6 install](https://golang.org/dl/#go1.6.3) -- [Go installation instructions](https://golang.org/doc/install) -- [Go documentation and tutorials](https://golang.org/doc/) - -Currently, Go is the only supported language for writing chaincode. The Go installation installs a set of Go CLI tools which are very useful when writing chaincode. For example, the `go build` command allows you to check that your chaincode actually compiles before you attempt to deploy it to a network. You should install Go 1.6, so that you have the same version of the language that the fabric is written against. - -### Instructions - -Follow the installation instructions linked above. You can verify that Go is installed properly by running the following commands. Of course, the output of `go version` may change depending on your operating system. - -``` -$ go version -go version go1.6.3 windows/amd64 - -$ echo $GOPATH -C:\gopath -``` - -Your `GOPATH` does not need to match the one above. It only matters that you have this variable set to a valid directory on your filesystem. The installation instructions linked above will take you through the setup of this environment variable. Why is this variable important? When you run `go build` to test that your chaincode compiles, Go is going to look in the `$GOPATH/src` directory for the non-standard dependencies that you list in the `import` block of your chaincode. - -## Hyperledger fabric - -- [v0.5-developer-preview Hyperledger fabric](https://github.com/hyperledger-archives/fabric/tree/v0.5-developer-preview) -- [v0.6-preview Hyperledger fabric](https://gerrit.hyperledger.org/r/gitweb?p=fabric.git;a=shortlog;h=refs/heads/v0.6) -- [master branch of the Hyperledger fabric](https://gerrit.hyperledger.org/r/gitweb?p=fabric.git;a=summary) - -Any piece of chaincode that you write will need to import the chaincode shim from Hyperledger fabric in order to be able to read and write data to/from the ledger. In order to compile chaincode locally, which you will be doing a lot, you will need to have the fabric code present in your `GOPATH`. - -### Instructions - -Three different releases of the fabric are linked above. The release you choose needs to match the Hyperledger network you are deploying your chaincode onto. You will need to make sure that the fabric release you choose is stored under `$GOPATH/hyperledger/fabric`. - -The instructions below should take you through the process of properly installing the v0.5 release on your `GOPATH`. - -``` - -# Create the parent directories on your GOPATH -mkdir -p $GOPATH/src/github.com/hyperledger -cd $GOPATH/src/github.com/hyperledger - -# Clone the appropriate release codebase into $GOPATH/src/github.com/hyperledger/fabric -# Note that the v0.5 release is a branch of the repository. It is defined below after the -b argument -git clone -b v0.5-developer-preview https://github.com/hyperledger-archives/fabric.git -``` - -If you are installing the v0.6 release, use this for your `git clone` command: - -``` -# The v0.6 release exists as a branch inside the Gerrit fabric repository -git clone -b v0.6 http://gerrit.hyperledger.org/r/fabric -``` - -If the fabric is not installed properly on your `GOPATH`, you will see errors like the one below when building your chaincode: -``` -$ go build . -chaincode_example02.go:27:2: cannot find package "github.com/hyperledger/fabric/core/chaincode/shim" in any of: - C:\Go\src\github.com\hyperledger\fabric\core\chaincode\shim (from $GOROOT) - C:\gopath\src\github.com\hyperledger\fabric\core\chaincode\shim (from $GOPATH) -``` - -A list of known specific releases is included below: - -- [Blockchain service on Bluemix](https://new-console.ng.bluemix.net/catalog/services/blockchain/) - use the v0.5-developer-preview release - -## Postman - -- [Home page](https://www.getpostman.com/) - -Postman is a REST API testing tool. Though it is deprecated, we still use the REST API in the fabric for this tutorial because it allows you to deploy and test your chaincode without needing to use the fabric SDK. You'll learn more about the fabric SDK in our other examples. - -### Instructions - -Download the [Postman tool](https://www.getpostman.com/). Depending on your operating system, you may also need to install Chrome to use Postman. Once you have the tool running, import the [request collection](../LearnChaincodeREST.postman_collection.json) included in this repository. This collection contains requests for enrolling a user on a peer, as well as deploying, invoking, and querying chaincode. The collection repository contains all the REST calls need to complete this tutorial. - -## Node.js - -- [Download links](https://nodejs.org/en/download/) - -Node.js is NOT necessary to develop chaincode, but most of our demos are built on Node.js, so it might be handy to go ahead and install it now. Also, you'll need it when you start using the fabric SDK. - -### Instructions - -Download the appropriate installation package and make sure the following commands work on your machine: - -``` -$ node -v -v4.4.7 - -$ npm -v -3.10.5 -``` - -## IDE Suggestions - -### Visual Studio Code - -- [Download links](https://code.visualstudio.com/#alt-downloads) - -Visual Studio Code is a free IDE that supports both Node.js and Go through plugins. All of our demos and examples use either one or both of these languages. It also has tab support, git integration, and debugging support. - -### Atom - -- [Home page](https://atom.io/) - -Like VS Code, Atom has plugins to support any of the languages needed to develop chaincode or modify our examples. +# Chaincode Development Environment + +The following is a list of dependencies and recommended tools that you should install in order to develop chaincode. + +## Git + +- [Git download page](https://git-scm.com/downloads) +- [Pro Git ebook](https://git-scm.com/book/en/v2) +- [Git Desktop (for those uncomfortable with git's CLI)](https://desktop.github.com/) + +Git is a great version control tool to familiarize yourself with, both for chaincode development and software development in general. Also, git bash, which is installed with git on Windows, is an excellent alternative to the the Windows command prompt. + +### Instructions + +After following the installation instructions above, you can verify that git is installed using the following command: + +``` +$ git --version +git version 2.11.1.windows.1 +``` + +Once you have git installed, go create an account for yourself on [GitHub](https://github.com/). The IBM Blockchain service on Bluemix currently requires that chaincode be in a GitHub repository in order to be deployed through the REST API. + +## Go + +- [Go download page](https://golang.org/dl) +- [Go installation instructions](https://golang.org/doc/install) +- [Go documentation and tutorials](https://golang.org/doc/) + +Currently, Go is the only supported language for writing chaincode. The Go installation installs a set of Go CLI tools which are very useful when writing chaincode. For example, the `go build` command allows you to check that your chaincode actually compiles before you attempt to deploy it to a network. At time of writing, this chaincode is known to build successfully with version 1.7.5. + +### Instructions + +Follow the installation instructions linked above. You can verify that Go is installed properly by running the following commands. Of course, the output of `go version` may change depending on your operating system. + +``` +$ go version +go version go1.7.5 windows/amd64 + +$ echo $GOPATH +C:\gopath +``` + +Your `GOPATH` does not need to match the one above. It only matters that you have this variable set to a valid directory on your filesystem. The installation instructions linked above will take you through the setup of this environment variable. Why is this variable important? When you run `go build` to test that your chaincode compiles, Go is going to look in the `$GOPATH/src` directory for the non-standard dependencies that you list in the `import` block of your chaincode. + +## Hyperledger fabric + +- [v0.5-developer-preview Hyperledger fabric](https://github.com/hyperledger-archives/fabric/tree/v0.5-developer-preview) +- [v0.6-preview Hyperledger fabric](https://gerrit.hyperledger.org/r/gitweb?p=fabric.git;a=shortlog;h=refs/heads/v0.6) +- [master branch of the Hyperledger fabric](https://gerrit.hyperledger.org/r/gitweb?p=fabric.git;a=summary) + +Any piece of chaincode that you write will need to import the chaincode shim from Hyperledger fabric in order to be able to read and write data to/from the ledger. In order to compile chaincode locally, which you will be doing a lot, you will need to have the fabric code present in your `GOPATH`. + +### Instructions + +Three different releases of the fabric are linked above. The release you choose needs to match the Hyperledger network you are deploying your chaincode onto. You will need to make sure that the fabric release you choose is stored under `$GOPATH/src/hyperledger/fabric`. + +The instructions below should take you through the process of properly installing the v0.5 release on your `GOPATH`. + +``` + +# Create the parent directories on your GOPATH +mkdir -p $GOPATH/src/github.com/hyperledger +cd $GOPATH/src/github.com/hyperledger + +# Clone the appropriate release codebase into $GOPATH/src/github.com/hyperledger/fabric +# Note that the v0.5 release is a branch of the repository. It is defined below after the -b argument +git clone -b v0.5-developer-preview https://github.com/hyperledger-archives/fabric.git +``` + +If you are installing the v0.6 release, use this for your `git clone` command: + +``` +# The v0.6 release exists as a branch inside the Gerrit fabric repository +git clone -b v0.6 http://gerrit.hyperledger.org/r/fabric +``` + +If the fabric is not installed properly on your `GOPATH`, you will see errors like the one below when building your chaincode: +``` +$ go build . +chaincode_example02.go:27:2: cannot find package "github.com/hyperledger/fabric/core/chaincode/shim" in any of: + C:\Go\src\github.com\hyperledger\fabric\core\chaincode\shim (from $GOROOT) + C:\gopath\src\github.com\hyperledger\fabric\core\chaincode\shim (from $GOPATH) +``` + +A list of known specific releases is included below: + +- [Blockchain service on Bluemix](https://new-console.ng.bluemix.net/catalog/services/blockchain/) - use the v0.6 release + +## Postman + +- [Home page](https://www.getpostman.com/) + +Postman is a REST API testing tool. Though it is deprecated, we still use the REST API in the fabric for this tutorial because it allows you to deploy and test your chaincode without needing to use the fabric SDK. You'll learn more about the fabric SDK in our other examples. + +### Instructions + +Download the [Postman tool](https://www.getpostman.com/). Depending on your operating system, you may also need to install Chrome to use Postman. Once you have the tool running, import the [request collection](../LearnChaincodeREST.postman_collection.json) included in this repository. This collection contains requests for enrolling a user on a peer, as well as deploying, invoking, and querying chaincode. The collection repository contains all the REST calls need to complete this tutorial. + +## Node.js + +- [Download links](https://nodejs.org/en/download/) + +Node.js is NOT necessary to develop chaincode, but most of our demos are built on Node.js, so it might be handy to go ahead and install it now. Also, you'll need it when you start using the fabric SDK. + +### Instructions + +Download the latest Node.js LTS installation package and make sure the following commands work on your machine: + +``` +$ node -v +v6.10.1 + +$ npm -v +3.10.10 +``` + +## IDE Suggestions + +### Visual Studio Code + +- [Download links](https://code.visualstudio.com/#alt-downloads) + +Visual Studio Code is a free IDE that supports both Node.js and Go through plugins. All of our demos and examples use either one or both of these languages. It also has tab support, git integration, and debugging support. + +### Atom + +- [Home page](https://atom.io/) + +Like VS Code, Atom has plugins to support any of the languages needed to develop chaincode or modify our examples. diff --git a/imgs/api_users.PNG b/imgs/api_users.PNG new file mode 100644 index 000000000..1dc692e5f Binary files /dev/null and b/imgs/api_users.PNG differ diff --git a/imgs/deploy_example.PNG b/imgs/deploy_example.PNG index a96e11738..fa06f4581 100644 Binary files a/imgs/deploy_example.PNG and b/imgs/deploy_example.PNG differ