• 【区块链技术与应用】(六)


    在这里插入图片描述

    引言

    本次任务相对顺利,因为是已经打包的案例。不过二三案例中不像案例一中有go的chaincode,执行需要花时间debug
    在这里插入图片描述

    案例链接:

    https://pkg.go.dev/github.com/hyperledger/fabric-gateway/pkg/client#section-readme

    案例一:资产转移基本示例

    代码分析

    资产转移基本示例演示:

    • 将客户端应用程序连接到 Fabric 区块链网络。
    • 提交智能合约交易以更新账本状态。
    • 评估智能合约交易以查询账本状态。
    • 处理事务调用中的错误。

    https://blog.csdn.net/ling1998/article/details/127202209

    链码启动

    项目地址:

    https://github.com/hyperledger/fabric-samples/blob/main/asset-transfer-basic/chaincode-go/assetTransfer.go

    /*
    SPDX-License-Identifier: Apache-2.0
    */
    
    package main
    
    import (
    	"log"
    
    	"github.com/hyperledger/fabric-contract-api-go/contractapi"
    	"github.com/hyperledger/fabric-samples/asset-transfer-basic/chaincode-go/chaincode"
    )
    
    func main() {
    	assetChaincode, err := contractapi.NewChaincode(&chaincode.SmartContract{})
    	if err != nil {
    		log.Panicf("Error creating asset-transfer-basic chaincode: %v", err)
    	}
    
    	if err := assetChaincode.Start(); err != nil {
    		log.Panicf("Error starting asset-transfer-basic chaincode: %v", err)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    链码结构

    asset-transfer-basic/chaincode-go/chaincode/smartcontract.go

    type SmartContract struct {
    	contractapi.Contract
    }
    
    • 1
    • 2
    • 3

    完整代码

    package chaincode
    
    import (
    	"encoding/json"
    	"fmt"
    
    	"github.com/hyperledger/fabric-contract-api-go/contractapi"
    )
    
    // SmartContract provides functions for managing an Asset
    type SmartContract struct {
    	contractapi.Contract
    }
    
    // Asset describes basic details of what makes up a simple asset
    //Insert struct field in alphabetic order => to achieve determinism across languages
    // golang keeps the order when marshal to json but doesn't order automatically
    type Asset struct {
    	AppraisedValue int    `json:"AppraisedValue"`
    	Color          string `json:"Color"`
    	ID             string `json:"ID"`
    	Owner          string `json:"Owner"`
    	Size           int    `json:"Size"`
    }
    
    // InitLedger adds a base set of assets to the ledger
    func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {
    	assets := []Asset{
    		{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},
    	}
    
    	for _, asset := range assets {
    		assetJSON, err := json.Marshal(asset)
    		if err != nil {
    			return err
    		}
    
    		err = ctx.GetStub().PutState(asset.ID, assetJSON)
    		if err != nil {
    			return fmt.Errorf("failed to put to world state. %v", err)
    		}
    	}
    
    	return nil
    }
    
    // CreateAsset issues a new asset to the world state with given details.
    func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, id string, color string, size int, owner string, appraisedValue int) error {
    	exists, err := s.AssetExists(ctx, id)
    	if err != nil {
    		return err
    	}
    	if exists {
    		return fmt.Errorf("the asset %s already exists", id)
    	}
    
    	asset := Asset{
    		ID:             id,
    		Color:          color,
    		Size:           size,
    		Owner:          owner,
    		AppraisedValue: appraisedValue,
    	}
    	assetJSON, err := json.Marshal(asset)
    	if err != nil {
    		return err
    	}
    
    	return ctx.GetStub().PutState(id, assetJSON)
    }
    
    // ReadAsset returns the asset stored in the world state with given id.
    func (s *SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface, id string) (*Asset, error) {
    	assetJSON, err := ctx.GetStub().GetState(id)
    	if err != nil {
    		return nil, fmt.Errorf("failed to read from world state: %v", err)
    	}
    	if assetJSON == nil {
    		return nil, fmt.Errorf("the asset %s does not exist", id)
    	}
    
    	var asset Asset
    	err = json.Unmarshal(assetJSON, &asset)
    	if err != nil {
    		return nil, err
    	}
    
    	return &asset, nil
    }
    
    // UpdateAsset updates an existing asset in the world state with provided parameters.
    func (s *SmartContract) UpdateAsset(ctx contractapi.TransactionContextInterface, id string, color string, size int, owner string, appraisedValue int) error {
    	exists, err := s.AssetExists(ctx, id)
    	if err != nil {
    		return err
    	}
    	if !exists {
    		return fmt.Errorf("the asset %s does not exist", id)
    	}
    
    	// overwriting original asset with new asset
    	asset := Asset{
    		ID:             id,
    		Color:          color,
    		Size:           size,
    		Owner:          owner,
    		AppraisedValue: appraisedValue,
    	}
    	assetJSON, err := json.Marshal(asset)
    	if err != nil {
    		return err
    	}
    
    	return ctx.GetStub().PutState(id, assetJSON)
    }
    
    // DeleteAsset deletes an given asset from the world state.
    func (s *SmartContract) DeleteAsset(ctx contractapi.TransactionContextInterface, id string) error {
    	exists, err := s.AssetExists(ctx, id)
    	if err != nil {
    		return err
    	}
    	if !exists {
    		return fmt.Errorf("the asset %s does not exist", id)
    	}
    
    	return ctx.GetStub().DelState(id)
    }
    
    // AssetExists returns true when asset with given ID exists in world state
    func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) {
    	assetJSON, err := ctx.GetStub().GetState(id)
    	if err != nil {
    		return false, fmt.Errorf("failed to read from world state: %v", err)
    	}
    
    	return assetJSON != nil, nil
    }
    
    // TransferAsset updates the owner field of asset with given id in world state, and returns the old owner.
    func (s *SmartContract) TransferAsset(ctx contractapi.TransactionContextInterface, id string, newOwner string) (string, error) {
    	asset, err := s.ReadAsset(ctx, id)
    	if err != nil {
    		return "", err
    	}
    
    	oldOwner := asset.Owner
    	asset.Owner = newOwner
    
    	assetJSON, err := json.Marshal(asset)
    	if err != nil {
    		return "", err
    	}
    
    	err = ctx.GetStub().PutState(id, assetJSON)
    	if err != nil {
    		return "", err
    	}
    
    	return oldOwner, nil
    }
    
    // GetAllAssets returns all assets found in world state
    func (s *SmartContract) GetAllAssets(ctx contractapi.TransactionContextInterface) ([]*Asset, error) {
    	// range query with empty string for startKey and endKey does an
    	// open-ended query of all assets in the chaincode namespace.
    	resultsIterator, err := ctx.GetStub().GetStateByRange("", "")
    	if err != nil {
    		return nil, err
    	}
    	defer resultsIterator.Close()
    
    	var assets []*Asset
    	for resultsIterator.HasNext() {
    		queryResponse, err := resultsIterator.Next()
    		if err != nil {
    			return nil, err
    		}
    
    		var asset Asset
    		err = json.Unmarshal(queryResponse.Value, &asset)
    		if err != nil {
    			return nil, err
    		}
    		assets = append(assets, &asset)
    	}
    
    	return assets, nil
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194

    运行

    创建测试网络和通道
    ./network.sh up createChannel -c mychannel -ca
    
    • 1

    在这里插入图片描述
    请添加图片描述

    部署实现其中一个智能合约
    # To deploy the TypeScript chaincode implementation
    ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-typescript/ -ccl typescript
    
    # To deploy the Go chaincode implementation
    ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go/ -ccl go
    
    # To deploy the Java chaincode implementation
    ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-java/ -ccl java
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

    运行应用程序
    # To run the Typescript sample application
    cd application-gateway-typescript
    npm install
    npm start
    
    # To run the Go sample application
    cd application-gateway-go
    go run .
    
    # To run the Java sample application
    cd application-gateway-java
    ./gradlew run
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述
    在这里插入图片描述

    结束

    ./network.sh down
    
    • 1

    案例二:资产转移事件示例

    资产转移事件示例演示:

    从智能合约交易函数发出链码事件。
    在客户端应用程序中接收链码事件。
    在客户端应用程序中重放以前的链码事件。

    运行

    创建测试网络和通道
    ./network.sh up createChannel -c mychannel -ca
    
    • 1

    在这里插入图片描述

    部署实现其中一个智能合约
    # To deploy the JavaScript chaincode implementation
    ./network.sh deployCC -ccn events -ccp ../asset-transfer-events/chaincode-javascript/ -ccl javascript -ccep "OR('Org1MSP.peer','Org2MSP.peer')"
    
    # To deploy the Java chaincode implementation
    ./network.sh deployCC -ccn events -ccp ../asset-transfer-events/chaincode-java/ -ccl java -ccep "OR('Org1MSP.peer','Org2MSP.peer')"
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    在这里插入图片描述

    运行应用程序

    (从文件夹)asset-transfer-events

    # To run the Go sample application
    cd application-gateway-go
    go run .
    
    # To run the Typescript sample application
    cd application-gateway-typescript
    npm install
    npm start
    
    # To run the Java sample application
    cd application-gateway-java
    ./gradlew run
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    结束

    回到test-network

    ./network.sh down
    
    • 1

    案例三:链下数据存储示例

    链下数据存储示例演示:

    • 在客户端应用程序中接收块事件。
    • 使用检查指针在发生故障或应用程序重新启动后恢复事件侦听。
    • 从区块事件中提取账本更新,以构建链下数据存储。

    运行

    创建测试网络和通道
    ./network.sh up createChannel -c mychannel -ca
    
    • 1

    在这里插入图片描述
    在这里插入图片描述

    部署资产转移基本智能合约实现之一
    # To deploy the TypeScript chaincode implementation
    ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-typescript/ -ccl typescript
    
    # To deploy the Go chaincode implementation
    ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go/ -ccl go
    
    # To deploy the Java chaincode implementation
    ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-java/ -ccl java
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    用一些资产填充账本,并使用事件来捕获账本更新

    从文件夹)。off_chain_data

    # To run the TypeScript sample application
    cd application-typescript
    npm install
    npm start transact listen
    
    # To run the Java sample application
    cd application-java
    ./gradlew run --quiet --args='transact listen'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    使用Control-C 中断侦听器进程
    查看区块链的当前世界状态

    off_chain_datastore.log

    # To run the TypeScript sample application
    cd application-typescript
    npm --silent start getAllAssets
    
    # To run the Java sample application
    cd application-java
    ./gradlew run --quiet --args=getAllAssets
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    进行更多账本更新,然后观察侦听器恢复功能
    # To run the TypeScript sample application
    cd application-typescript
    npm start transact
    SIMULATED_FAILURE_COUNT=5 npm start listen
    npm start listen
    
    # To run the Java sample application
    cd application-java
    ./gradlew run --quiet --args=transact
    SIMULATED_FAILURE_COUNT=5 ./gradlew run --quiet --args=listen
    ./gradlew run --quiet --args=listen
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    请添加图片描述
    在这里插入图片描述

    总结

    本周主要进行了三个案例的实战,跑代码很顺利所以心情也很好。
    需要注意的一点是,案例中同时给出了java和go的代码,第一次把两个都跑了,事实上只需要选择一个就可。
    建议还是用go。
    在这里插入图片描述
    第一部分的资产转移案例还有拓展内容,可以作为参考

    https://blog.csdn.net/ling1998/article/details/127202209
    在这里插入图片描述

  • 相关阅读:
    SpringBoot整合JSR-303表单校验
    Android 开发一个动画
    CH34X-MPHSI高速Master扩展应用—SPI设备调试
    PHP7 +nginx Docker 部署
    iconfont 的symbol字体如何修改颜色 / svg如何修改颜色?
    MYSQL高可用架构之MHA实战(真实可用)
    Android OpenCV 身份证识别实战
    使用学校的服务器跑深度学习
    在scroll-view中使用u-charts,滚动图表
    IDEA下载安装
  • 原文地址:https://blog.csdn.net/Algernon98/article/details/127780171