更新时间:2021-12-30 GMT+08:00
分享

修改跨链资产数值(putStateWithLock)

在跨链资产交换涉及的智能合约方法中,所有对跨链资产的修改都必须与资产上锁同时进行。可将上述逻辑封装至一个方法中,便于后续在其他智能合约方法(主要是preCommitSend与preCommitRecv)中调用:

 /*
  * putStateWithLock will update the account balance and lock the account
  * @Param account: The name of the account that whose balance is going to be updated with lock
  * @Param balance: The amount of units that will be put to the account
  * @Param txID: The id of this transaction that transfer units of one account to another account
  */
func putStateWithLock(stub shim.ChaincodeStubInterface, txID string, account string, balance []byte) error {
    accountBytes, err := stub.GetState(account)
    if err != nil {
        return fmt.Errorf("failed to get account state: %v", err)
    }
    if accountBytes == nil {
        accountBytes = []byte("")
    }
    accountLockKey := account + lockSuffix
    accountLockBytes, err := stub.GetState(accountLockKey)
    if err != nil {
        return fmt.Errorf("failed to get accountLock state: %v", err)
    }
    accountLock := AccountLock{}

    /*
     * Detect the account lock's status
     * if account is not locked:
     * 1. put lock to the blockchain ledger with current account balance
     * 2. update the account balance
     * If account is locked:
     * 1. is locked by the same txID, then return success
     * 2. is not locked by this txID,then not allowed to update account balance
     */
    if accountLockBytes == nil {
        accountLock = AccountLock{
            PreValue: string(accountBytes),
            CrossTXID: txID,
       }
       accountLockBytes, err = json.Marshal(accountLock)
       if err != nil {
            return fmt.Errorf("failed to marshal accountLockBytes: %v", err)
       }
       err = stub.PutState(accountLockKey, accountLockBytes)
       if err != nil {
            return fmt.Errorf("failed to put accountLock state: %v", err)
       }
       err = stub.PutState(account, balance)
       if err != nil {
            return fmt.Errorf("failed to put account state: %v", err)
       }
       return nil
    } else {
       err = json.Unmarshal(accountLockBytes, &accountLock)
       if err != nil {
            return fmt.Errorf("failed to unmarshal accountLockBytes: %v", err)
       }
       if accountLock.CrossTXID == txID {
            return nil
       }
       return fmt.Errorf("account %s locked", account)
    }
 }

相关文档