DeleteState 和 PutState 函数不会改变分类帐状态

问题描述

我是智能合约开发的新手,并试图使其适用于处理资产。我的资产称为 GOcerts。

我已经使用token UTXO智能合约作为基础开始学习,并根据我的需要添加了变化和功能

添加一个名为 ClaimGO() 的附加函数,它应该删除资产并在分类帐中创建和存储两个新资产。但是函数 DeleteState 和 putState 似乎没有在账本上存储任何东西,因为当我调用函数查询账本时,就像没有改变账本状态一样。

ClaimGO 函数的实现如下:

 //ClaimGO claims an amount X of GOcert Y. This function is implemented following the UTXO model
    func (s *SmartContract) ClaimGO(ctx contractapi.TransactionContextInterface,goCertInputKey string,amount int) ([]GOCERT,error) {
        //1. Get ID of submitting client identity
        clientID,err := ctx.GetClientIdentity().GetID()
        if err != nil {
            return nil,fmt.Errorf("Failed to get client id: %v",err)
        }
    
        //2. Validate GOcert input
        goCertInputCompositeKey,err := ctx.GetStub().CreateCompositeKey("goCert",[]string{clientID,goCertInputKey})
        if err != nil {
            return nil,fmt.Errorf("Failed to create composite key: %v",err)
        }
    
        goCertInput := GOCERT{}
        //2.1 Validate that client has a GOcert matching the input key
        goCertAsBytes,err := ctx.GetStub().GetState(goCertInputCompositeKey)
        if err != nil {
            return nil,fmt.Errorf("Failed to read goCertInputCompositeKey %s from world state: %v",goCertInputCompositeKey,err)
        }
        errr := json.Unmarshal(goCertAsBytes,&goCertInput)
    
        if errr != nil {
            return nil,fmt.Errorf("goCertInput %s not found for client %s: %v\n,gocertInput: %#v\n gocerAsbytes: %v",goCertInputKey,clientID,errr,goCertInput,goCertAsBytes)
        }
    
        txID := ctx.GetStub().GetTxID()
        pbKey := goCertInput.ProdBatchKey
        expDate := goCertInput.ExpirationDate
    
        //erase prevIoUs GOcert
        err = ctx.GetStub().DelState(goCertInputCompositeKey)
        if err != nil {
            return nil,err
        }
        log.Printf("goCertInput deleted: %+v",goCertInput)
    
        var goCertOutputs []GOCERT
   //goCertOutput1 is the GO with the cancelled amount
        goCertOutput1 := GOCERT{}
        goCertOutput1.Amount = amount
        goCertOutput1.ExpirationDate = expDate
        goCertOutput1.Owner = clientID
        goCertOutput1.ProdBatchKey = pbKey
        goCertOutput1.State = "Cancelled"
        goCertOutput1.Key = fmt.Sprintf("%s.%d",txID,0)
        goCertOutputs = append(goCertOutputs,goCertOutput1)
    
        goCertAsBytes,_ := json.Marshal(goCertOutput1)
    
        goCertOutputCompositeKey,[]string{goCertOutput1.Owner,goCertOutput1.Key})
        err = ctx.GetStub().PutState(goCertOutputCompositeKey,goCertAsBytes)
        if err != nil {
            return nil,err
        }
        log.Printf("goCertOutput created: %+v",goCertOutput1)
    
        //goCertOutput 2 is the GO with the remaining amount that has not been claimed yet
        goCertOutput2 := GOCERT{}
        goCertOutput2.Amount = goCertInput.Amount - amount
        goCertOutput2.ExpirationDate = expDate
        goCertOutput2.Owner = clientID
        goCertOutput2.ProdBatchKey = pbKey
        goCertOutput2.State = "Issued"
        goCertOutput2.Key = fmt.Sprintf("%s.%d",1)
        goCertOutputs = append(goCertOutputs,goCertOutput2)
    
        goCertAsBytes2,_ := json.Marshal(goCertOutput2)
    
        goCertOutputCompositeKey2,[]string{goCertOutput2.Owner,goCertOutput2.Key})
        err = ctx.GetStub().PutState(goCertOutputCompositeKey2,goCertAsBytes2)
        if err != nil {
            return nil,goCertOutput2)
    
        return goCertOutputs,nil
    }

我正在尝试使用 Hyperledger Fabric 测试网络的智能合约。使用logspout工具,可以看到显示了两条日志信息,所以我知道代码正在正确执行。问题是,尽管它执行时没有错误DeleteState 和 PutState 函数实际上并没有改变分类帐上的任何内容

对于可能出现的问题的任何帮助将不胜感激。

非常感谢。

解决方法

在交易被背书、提交给排序者、提交到一个块中并分发给对等点以便他们可以更新其本地分类帐状态之后,分类帐实际上不会得到更新。如果不满足某些背书要求,交易发送给orderer后仍有可能无法提交成功。

如果您使用 peer chaincode query 命令进行调用,交易不会发送给排序者,因此不会发生分类帐更新。如果您使用 peer chaincode invoke 命令,则背书交易将发送给订购者并更新分类帐。

然而,在调用命令之后的查询命令不会看到由调用引起的账本更新,直到它们执行的对等方收到来自排序节点的提交块并更新其本地账本状态。要让 peer chaincode invoke 命令在退出之前等待交易在对等分类账中提交,请使用 --waitForEvent 命令行标志。

运行 peer chaincode invoke --help 以获取可用命令行标志的详细信息。