mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 15:35:09 +00:00
Fix transferFrom function so that we only delete token balances after we've verified the funds are available first - not before
Signed-off-by: Rob Evans <robevansuk@noreply.users.github.io>
This commit is contained in:
parent
7671bdd7c6
commit
074c5dc237
1 changed files with 48 additions and 28 deletions
|
|
@ -9,6 +9,7 @@ package chaincode
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -949,6 +950,8 @@ func removeBalance(ctx contractapi.TransactionContextInterface, sender string, i
|
|||
}
|
||||
defer balanceIterator.Close()
|
||||
|
||||
var deferredDeletions = []func() error{}
|
||||
|
||||
// Iterate over keys that store balances and add them to partialBalance until
|
||||
// either the necessary amount is reached or the keys ended
|
||||
for balanceIterator.HasNext() && partialBalance < neededAmount {
|
||||
|
|
@ -972,16 +975,22 @@ func removeBalance(ctx contractapi.TransactionContextInterface, sender string, i
|
|||
selfRecipientKeyNeedsToBeRemoved = true
|
||||
selfRecipientKey = queryResponse.Key
|
||||
} else {
|
||||
err = ctx.GetStub().DelState(queryResponse.Key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete the state of %v: %v", queryResponse.Key, err)
|
||||
}
|
||||
deferredDeletions = append(deferredDeletions, deferredDelete(ctx, queryResponse))
|
||||
}
|
||||
}
|
||||
|
||||
if partialBalance < neededAmount {
|
||||
return fmt.Errorf("sender has insufficient funds for token %v, needed funds: %v, available fund: %v", tokenId, neededAmount, partialBalance)
|
||||
} else if partialBalance > neededAmount {
|
||||
} else {
|
||||
// enough token funds have been found to perform the update
|
||||
// now we can delete the token entries to supply updated token balances
|
||||
for _, deleteFn := range deferredDeletions {
|
||||
err := deleteFn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if partialBalance > neededAmount {
|
||||
// Send the remainder back to the sender
|
||||
remainder, err := sub(partialBalance, neededAmount)
|
||||
if err != nil {
|
||||
|
|
@ -1009,10 +1018,21 @@ func removeBalance(ctx contractapi.TransactionContextInterface, sender string, i
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deferredDelete(ctx contractapi.TransactionContextInterface, queryResponse *queryresult.KV) func() error {
|
||||
return func() error {
|
||||
err := ctx.GetStub().DelState(queryResponse.Key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete the state of %v: %v", queryResponse.Key, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func emitTransferSingle(ctx contractapi.TransactionContextInterface, transferSingleEvent TransferSingle) error {
|
||||
transferSingleEventJSON, err := json.Marshal(transferSingleEvent)
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Reference in a new issue