1. 程式人生 > >hyperledger fabric鏈碼開發(Chaincode for Developers)

hyperledger fabric鏈碼開發(Chaincode for Developers)

What is Chaincode(什麼是鏈碼)?

                鏈碼(ChainCode)是一個用GO語言編寫的實現了規定介面的程式。事實上,它也支援其他語言,比如JAVA。鏈碼(ChainCode)執行在一個安全的Docker容器中,該容器與其他的程式相隔離。鏈碼(ChainCode)通過應用程式提交的事務來初始化和管理賬本狀態(the ledger state).

                鏈碼(chainCode)通常處理網路成員同意的業務邏輯,所以它類似於“智慧合約”(smart contract)。由鏈碼(ChainCode)建立的分類狀態僅限於該鏈碼,不能由其他鏈碼(ChainCode)直接訪問。考慮到適當的許可,一個鏈碼(ChainCode)可以呼叫另一個鏈碼(ChainCode)來訪問其在相同網路中的狀態。

                 在下面的章節中,我們將以程式開發人員的眼光來探索鏈碼(ChainCode)。我們將簡單的介紹一個鏈碼(ChainCode)的應用程式示例,並介紹鏈碼(ChainCode)Shim API的每種方法的用途。                 

Chaincode API(鏈碼API)

                 每一個鏈碼(ChainCode)程式都必須實現鏈碼(ChainCode)介面,其方法被呼叫以響應接收到的事務。當鏈碼(ChainCode)接收到一個instantiate或者upgrade事務時執行Init方法進行必要的初始化,包括初始化應用程式的狀態。呼叫Invoke方法來處理處理應用程式提交的事務。

                   鏈碼(ChainCode)的shim API中的另一個介面是ChaincodeStubInterface, 用於訪問和修改分類賬本和進行鏈碼之間的呼叫。

                   在本教程中,我們將通過實現一個簡單的“資產”管理的鏈碼來演示如何使用這些API。

Simple Asset Chaincode(簡單資產鏈碼)

                    我們的程式是一個簡單的在賬本中建立資產(鍵值對)。

Choosing a Location for the Code(選擇程式碼的位置)

                    如果你還未使用過Go語言進行編碼,你也許需要去確定你是否安裝了Go程式語言並且你的系統做過正確的配置

                    現在你需要在你的$GOPATH/src/下建立一個子目錄去儲存你的鏈碼程式。

                    為了是事情簡單,我們提供了一句簡單的指令:

mkdir -p $GOPATH/src/sacc && cd $GOPATH/src/sacc

                    我們建立一個原始檔:

touch sacc.go

Housekeeping(編碼)

                    首先讓我們準備編碼。像每一個鏈碼一樣,它實現了鏈碼的Init和Invoke函式。所以讓我們使用go import語句匯入鏈碼的必要依賴庫,我們將匯入鏈碼的shim 包和peer protobuf 包。接下來讓我們新增一個結構 SimpleAsset作為鏈碼 shim 函式的接受器。

package main

import (
    "fmt"

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

// SimpleAsset implements a simple chaincode to manage an asset
type SimpleAsset struct {
}

Initializing the Chaincode(初始化鏈碼)

            下一步我們實現Init函式。

// Init is called during chaincode instantiation to initialize any data.
func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {

}

            請注意! 鏈碼升級時也會呼叫Init函式,在編寫將升級現有鏈碼的鏈碼時,請適當的修改Init函式。特別是如果沒有遷移或者沒有任何內容作為升級的一部分進行初始化,請提供一個空的Init方法。

            接下來我們將使用ChaincodeStubInterface.GetStringArgs函式檢索Init呼叫的引數並檢查其有效性,我們的例子中應當接受到的是一個鍵值對。

// 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 be 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")
  }
}

            下一步我們確定呼叫合法,我們將儲存初始化狀態到賬本中。要做到這一點我們將呼叫ChaincodeStubInterface.PutState 並將鍵和值作為引數傳入。假設一切順利,返回一個初始化成功的peer.Response物件。

// 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 be 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 here 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)
}

Invoking the Chaincode(呼叫鏈碼)

            首先我們新增Invoke函式的簽名。

// Invoke is called per transaction on the chaincode. Each transaction is
// either a 'get' or a 'set' on the asset created by Init function. The 'set'
// method may create a new asset by specifying a new key-value pair.
func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response {

}

            與上面的Init函式一樣,我們需要從ChaincodeStubInterface中提取引數。Invoke函式的引數將會是要呼叫的chaincode應用程式的函式的名稱。在我們的例子中,我們的應用程式只有兩個引數: set和get, 它們允許設定資產的值或檢索當前狀態。我們首先呼叫ChaincodeStubInterface.GetFunctionAndParameters來提取鏈碼應用函式的函式名稱和引數。

// Invoke is called per transaction on the chaincode. Each transaction is
// either a 'get' or a 'set' on the asset created by Init function. The Set
// method 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()

}

            接下來, 我們將驗證函式名稱為set或get,並呼叫這些chaincode的應用函式。通過shim返回適當的響應, shim.Success或shim.Error函式將響應序列化到gRPC protobuf訊息。

// Invoke is called per transaction on the chaincode. Each transaction is
// either a 'get' or a 'set' on the asset created by Init function. The Set
// method 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)
    } else {
            result, err = get(stub, args)
    }
    if err != nil {
            return shim.Error(err.Error())
    }

    // Return the result as success payload
    return shim.Success([]byte(result))
}

Implementing the Chaincode Application(實現鏈碼程式)

            如上所述,我們的鏈碼應用程式實現了兩個可以通過Invoke函式呼叫的函式。現在我們實現這些功能。請注意,正如我們上面提到的,為了訪問賬本的狀態,我們將利用鏈碼的shim API的ChaincodeStubInterface.PutState和ChaincodeStubInterface.GetState函式。

// Set stores the asset (both key and value) on the ledger. If the key exists,
// it will 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 asset 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
}

Pulling it All Together(集合程式碼)

            最後,我們需要新增主函式,它將呼叫shim.Start函式。這是整個Chaincode程式的完整程式碼。

package main

import (
    "fmt"

    "github.com/hyperledger/fabric/core/chaincode/shim"
    "github.com/hyperledger/fabric/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 this function to reset
// or 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 here 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 per transaction on the chaincode. Each transaction is
// either a 'get' or a 'set' on the asset created by Init function. The Set
// method may create a new asset by specifying a new key-value pair.
func (t *SimpleAsset) Invoke(
            
           

相關推薦

hyperledger fabric開發Chaincode for Developers

What is Chaincode(什麼是鏈碼)?                鏈碼(ChainCode)是一個用GO語言編寫的實現了規定介面的程式。事實上,它也支援其他語言,比如JAVA。鏈碼(ChainCode)執行在一個安全的Docker容器中,該容器與其他的程式相隔

HyperLedger Fabric開發及測試

1.鏈碼開發 先設計一個簡單的應用場景,假設有這樣的業務需求: 可以新增學校,資訊包括學校名稱、學校ID; 新增該學校的學生,資訊包括姓名,使用者ID,所在學校ID,所在班級名稱; 更新學生資訊; 根據學生ID查詢學生資訊; 根據學生ID刪除學生資訊; 根

HyperLeger Fabric開發——HyperLeger Fabric開發測試

HyperLeger Fabric開發(八)——HyperLeger Fabric鏈碼開發測試 一、鏈碼例項 SACC專案鏈碼例項如下: package main import ( "fmt" "github.com/hyperledger/fabric/core/chaincode/s

HyperLeger Fabric開發——HyperLeger Fabric開發

HyperLeger Fabric開發(七)——HyperLeger Fabric鏈碼開發 一、鏈碼開發模式 1、鏈碼開發模式簡介 Fabric的鏈碼開發除錯比較繁瑣。在不使用鏈碼開發模式的情況下,鏈碼不能在本地測試,必須部署到docker,install和instantiate後,Peer節點會在新的

Hyperledger Fabric 開發環境

title: Hyperledger Fabric 鏈碼的開發 tags: Hyperledger, fabric ,區塊鏈,chaincode 前面介紹過Hyperledger Fabric環境搭建和網路部署,現在我們開始鏈碼開發。 Fabric的fabric-sa

Hyperledger fabric 篇GO

# Hyperledger fabric 鏈碼篇GO(四) fabric中的鏈碼也就是我們區塊鏈所認知的智慧合約,fabric中可由nodejs,java,go編寫,本篇只針對GO語言編寫鏈碼。將詳細介紹鏈碼編寫所必須的函式以及相關功能函式。 ## 1、常識 - 鏈碼的包名指定 ```go /

Fabric實戰公民身份資訊

title: Fabric鏈碼實戰(二)公民身份資訊 tags: Hyperledger, fabric ,區塊鏈,chaincode 功能簡述 使用鏈碼可以新增和查詢公民資訊 功能實現 1.匯入包 package main import ( "git

Fabric實戰貸款還款

title: Fabric鏈碼實戰(一)貸款還款 tags: Hyperledger, fabric ,區塊鏈,chaincode 功能簡述 假設需要用鏈碼開發簡單的貸款還款,要實現以下簡單的幾個業務需求: 1.通過賬戶身份證號,銀行名字進行貸款 2.過賬戶身份證號,

2.07 hyperledger fabric案例

1.鏈碼入門 hello.go 安裝鏈碼 例項化鏈碼 呼叫鏈碼 2.賬戶相關鏈碼 payment.go 安裝鏈碼 例項化鏈碼 查詢賬戶 轉賬 查詢賬戶 存款 查詢賬戶

Fabric開發【Nodejs

Hyperledger Fabric是一種聯盟區塊鏈,Fabric區塊鏈也支援智慧合約,被稱為鏈碼(Chaincode)。Fabric鏈碼就是一個標準的(執行在docker容器中的)作業系統程序,通過gRPC協議與Fabric節點通訊。因此理論上可以使用任何語言開發Fabric鏈碼。目前

Hyperledger Fabric聯盟區塊 Node.js開發【秒懂】

Hyperledger Fabric是一種聯盟區塊鏈,Fabric區塊鏈也支援智慧合約,被稱為鏈碼(Chaincode)。Fabric鏈碼就是一個標準的(執行在docker容器中的)作業系統程序,通過gRPC協議與Fabric節點通訊。因此理論上可以使用任何語言開發Fabric鏈碼。目前官方

區塊開源實現hyperledger fabric架構詳解轉載

hyperledger fabric是區塊鏈中聯盟鏈的優秀實現,主要程式碼由IBM、Intel、各大銀行等貢獻,目前v1.1版的kafka共識方式可達到1000/s次的吞吐量。本文中我們依次討論:區塊鏈的共通特性、fabric核心概念、fabric的交易執行流程。本文來源於筆

【我的區塊之路】- Hyperledger fabric的簡單入門fabric主要配置檔案細講

fabric的各個配置檔案做講解 Peer 配置剖析         本例子是拿fabric-samples 來說的,【如果是 fabric 的話,在 fabric/的根目錄下有一個 core.yaml 】在 fabric-samples/config 目錄下有

用maven來創建scala和java項目代環境圖文詳解Intellij IDEAUltimate版本、Intellij IDEACommunity版本和Scala IDEA for Eclipse皆適用博主推薦

搭建 ava XML .com 自動 ado ima 強烈 mapred 為什麽要寫這篇博客?   首先,對於spark項目,強烈建議搭建,用Intellij IDEA(Ultimate版本),如果你還有另所愛好嘗試Scala IDEA for Eclipse,有時間自己去

CentOS6.5下如何正確下載、安裝Intellij IDEA、Scala、Scala-intellij-bin插件、Scala IDE for Eclipse助推大數據開發圖文詳解

scala 建議 strong 安裝jdk rgs 默認 tell launcher eclipse 第二步:安裝Intellij IDEA   若是3節點如,master、slave1、slave2,則建議將其安裝在master節點上   到https:/

ASP.NET Aries 高級開發教程:Excel導入之代編寫番外篇

chan 導入 設置 jna 配置 決定 ptc UNC 番外篇 前言: 以許框架提供的導入配置功能,已經能解決95%以上的導入情況,但有些情況總歸還是得代碼來解決。 本篇介紹與導入相關的代碼。 1、前端追加導入時Post的參數: var grid = new

分成確定性錢包開發的代實現HD錢包服務

label pbkdf2 err 發的 生成 enc 非對稱加密 ans 祖先 HD Wallets的全稱是Hierachical Deterministic Wallets, 對應中文是 分層確定性錢包。 這種錢包能夠使用一組助記詞來管理所有的賬戶的所有幣種,在比特幣的B

Fabric--的概念與使用

鏈碼的概念與使用 概念: Chaincode: 鏈上程式碼, 簡稱鏈碼, 一般是指使用者編寫的應用程式碼 鏈碼被部署在Fabric網路節點上, ​ Peer 節點 ​ – 背書節點 ​ – commit節點 ​

從位元組看Java中for-each迴圈增強for迴圈實現原理

下面是的兩個很簡單的類,可以看出它們的功能是一樣的。Java環境使用的是jdk1.8_111。 package iter; public class TestArray { public static void main(String[] args) { //String[] a

HTTP狀態大全轉自wiki

成對 節點 而是 沒有 redirect port multiple 許可 sta 1xx消息 這一類型的狀態碼,代表請求已被接受,需要繼續處理。這類響應是臨時響應,只包含狀態行和某些可選的響應頭信息,並以空行結束。由於HTTP/1.0協議中沒有定義任何1xx狀態碼,所以除