注册监听事件文档

如何使用事件监听方法

探寻SDK包

在寻找能接收event的SDK中的方法时,我们寻找到了很多可能解,也排除了很多情况。

我们曾经探究过能否使用event包下的RegisterTxStatusEvent,RegisterBlockEvent等方法,而由于我们需要的是执行智能合约时进行使用,而TxStatus只能查询一笔交易的情况,RegisterTxStatusEvent方法被排除了。而对于RegisterBlockEvent方法,由于并不是只有提交模型的信息被作为block上传,其中会包含有很多冗余信息需要处理,因此也遭到了排除。

最终我们选择了RegisterChaincodeEvent()方法。这个方法可以通过传入的eventFilter参数(一个字符串,传入的是正则表达式)来挑选符合条件的setevent释放出的信息。

问题解决

最终,我们的解决方式如下:
以官方示例的Release2.2中的fabcar为例,进行监听信息的模拟

首先在智能合约的CreateCar函数进行如下修改:

func (s *SmartContract) CreateCar(ctx contractapi.TransactionContextInterface, carNumber string, make string, model string, colour string, owner string) (string, error) {
    car := Car{
        Make:   make,
        Model:  model,
        Colour: colour,
        Owner:  owner,
    }

    carAsBytes, _ := json.Marshal(car)
    err := ctx.GetStub().PutState(carNumber, carAsBytes)
    if err != nil {
        return "", err
    }
    successResult := "Set the event successfully"
    err = ctx.GetStub().SetEvent("CreateCar", []byte(successResult))
    if err != nil {
        return "", err
    }
    return successResult, nil
}

此次修改加入了SetEvent方法,方便等下在SDK中进行监听

然后进入fabcar文件,运行脚本./startFabric.sh

等待运行结束后,进入go文件夹,修改fabcar.go文件,修改为如下内容:

/*
Copyright 2020 IBM All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package main

import (
    "errors"
    "fmt"
    "github.com/hyperledger/fabric-sdk-go/pkg/client/event"
    "github.com/hyperledger/fabric-sdk-go/pkg/core/config"
    "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
    "github.com/hyperledger/fabric-sdk-go/pkg/gateway"
    "io/ioutil"
    "os"
    "path/filepath"
    "time"
)

func main() {
    os.Setenv("DISCOVERY_AS_LOCALHOST", "true")
    wallet, err := gateway.NewFileSystemWallet("wallet")
    if err != nil {
        fmt.Printf("Failed to create wallet: %s\n", err)
        os.Exit(1)
    }

    if !wallet.Exists("appUser") {
        err = populateWallet(wallet)
        if err != nil {
            fmt.Printf("Failed to populate wallet contents: %s\n", err)
            os.Exit(1)
        }
    }

    ccpPath := filepath.Join(
        "..",
        "..",
        "test-network",
        "organizations",
        "peerOrganizations",
        "org1.example.com",
        "connection-org1.yaml",
    )

    gw, err := gateway.Connect(
        gateway.WithConfig(config.FromFile(filepath.Clean(ccpPath))),
        gateway.WithIdentity(wallet, "appUser"),
    )
    if err != nil {
        fmt.Printf("Failed to connect to gateway: %s\n", err)
        os.Exit(1)
    }
    defer gw.Close()

    network, err := gw.GetNetwork("mychannel")
    if err != nil {
        fmt.Printf("Failed to get network: %s\n", err)
        os.Exit(1)
    }

    contract := network.GetContract("fabcar")
    //sdk, err := fabsdk.New(config.FromFile(filepath.Clean(ccpPath)))
    //if err != nil {
    //    panic(err)
    //} else {
    //    fmt.Printf("sdk initialized successfully!\n")
    //}
    //failed to create identity manager provider: failed to initialize identity manager
    //for organization: org1: Either a cryptopath or an embedded list of users is required
    //need to add a cryptopath in config.yaml, all the errors can be fixed through make the
    //yaml file detail.
    //ccp := sdk.ChannelContext("mychannel", fabsdk.WithUser("Admin"))
    //if err != nil {
    //    panic(err)
    //}
    //cc, err := event.New(ccp)
    reg, channel, err := contract.RegisterEvent(".*")
    if err != nil {
    	panic(err)
    }
    reg, channel, err := contract.RegisterEvent("fabcar", ".*")
    if err != nil {
        panic(err)
    } else {
        fmt.Printf("channel initialized successfully!\n")
    }
    defer contract.Unregister(reg)
    go func() {
        select {
        case value := <-channel:
            {
                fmt.Printf("Get something from the channel, %v", value)
            }
        case <-time.After(20 * time.Second):
            fmt.Printf("timeout while waiting for chaincode event\n")
        }
    }()

    result, err := contract.EvaluateTransaction("queryAllCars")
    if err != nil {
        fmt.Printf("Failed to evaluate transaction: %s\n", err)
        os.Exit(1)
    }
    fmt.Println(string(result))

    result, err = contract.SubmitTransaction("createCar", "CAR10", "VW", "Polo", "Grey", "Mary")
    if err != nil {
        fmt.Printf("Failed to submit transaction: %s\n", err)
        os.Exit(1)
    }
    fmt.Println(string(result))

    result, err = contract.EvaluateTransaction("queryCar", "CAR10")
    if err != nil {
        fmt.Printf("Failed to evaluate transaction: %s\n", err)
        os.Exit(1)
    }
    fmt.Println(string(result))

    _, err = contract.SubmitTransaction("changeCarOwner", "CAR10", "Archie")
    if err != nil {
        fmt.Printf("Failed to submit transaction: %s\n", err)
        os.Exit(1)
    }

    result, err = contract.EvaluateTransaction("queryCar", "CAR10")
    if err != nil {
        fmt.Printf("Failed to evaluate transaction: %s\n", err)
        os.Exit(1)
    }
    fmt.Println(string(result))
}

func populateWallet(wallet *gateway.Wallet) error {
    credPath := filepath.Join(
        "..",
        "..",
        "test-network",
        "organizations",
        "peerOrganizations",
        "org1.example.com",
        "users",
        "User1@org1.example.com",
        "msp",
    )

    certPath := filepath.Join(credPath, "signcerts", "cert.pem")
    // read the certificate pem
    cert, err := ioutil.ReadFile(filepath.Clean(certPath))
    if err != nil {
        return err
    }

    keyDir := filepath.Join(credPath, "keystore")
    // there's a single file in this dir containing the private key
    files, err := ioutil.ReadDir(keyDir)
    if err != nil {
        return err
    }
    if len(files) != 1 {
        return errors.New("keystore folder should have contain one file")
    }
    keyPath := filepath.Join(keyDir, files[0].Name())
    key, err := ioutil.ReadFile(filepath.Clean(keyPath))
    if err != nil {
        return err
    }

    identity := gateway.NewX509Identity("Org1MSP", string(cert), string(key))

    err = wallet.Put("appUser", identity)
    if err != nil {
        return err
    }
    return nil
}

注:其中sdk注释内容是event包下的方法,此时则需要修改对应的配置文件才可使用。如若只想进行体验则直接使用未注释的contract包下的RegisterEvent即可。

posted @ 2023-05-01 20:13  MakeTheFoxRush  阅读(33)  评论(0)    收藏  举报