DeleteState and PutState functions not changing ledger state

Viewed 233

I'm new to smart contract developing, and trying to make it work for handling assets. My assets are called GOcerts.

I have used the token UTXO smart contract as a basis to start learning, and added changes and functions depending on my needs.

I have added an aditional function called ClaimGO(), which is supposed to delete the asset and create and store two new assets in the ledger. But function DeleteState and putState do not seem to be storing anything on the ledger, because when I query the ledger after calling the function, is like if nothing had changed the ledger state.

The implementation of the ClaimGO function is as follows:

 //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, err := ctx.GetStub().CreateCompositeKey("goCert", []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", txID, 1)
        goCertOutputs = append(goCertOutputs, goCertOutput2)
    
        goCertAsBytes2, _ := json.Marshal(goCertOutput2)
    
        goCertOutputCompositeKey2, err := ctx.GetStub().CreateCompositeKey("goCert", []string{goCertOutput2.Owner, goCertOutput2.Key})
        err = ctx.GetStub().PutState(goCertOutputCompositeKey2, goCertAsBytes2)
        if err != nil {
            return nil, err
        }
        log.Printf("goCertOutput created: %+v", goCertOutput2)
    
        return goCertOutputs, nil
    }

I'm trying the smart contract with the Hyperledger Fabric test-network. Using the logspout tool, I can see that the two log messages are displayed, so I know that the code is being executed correctly. The issue is that, eve though it executes with no errors, the functions DeleteState and PutState are not actually changing anything on the ledger.

Any help on what could be the issue will be highly appreciated.

Thank you very much.

1 Answers

The ledger doesn't actually get updated until after a transaction is endorsed, submitted to the orderer, committed in a block, and distributed to peers so they can update their local ledger state. It is still possible for the transaction to fail to commit successfully after sending to the orderer if some endorsement requirements have not been met.

If you are using the peer chaincode query command to do your invocation, the transaction is not sent to the orderer so no ledger update occurs. If you are using the peer chaincode invoke command then the endorsed transaction will be sent to the orderer and update the ledger.

However, query commands following an invoke command will not see the ledger update caused by the invoke until the peer they execute on has received the committed block from the orderer and updated its local ledger state. To have the peer chaincode invoke command wait for transactions to be committed in peer ledgers before exiting, use the --waitForEvent command-line flag.

Run peer chaincode invoke --help for details of the available command-line flags.

Related