@@ -9,6 +9,7 @@ package chaincode
9
9
import (
10
10
"encoding/json"
11
11
"fmt"
12
+ "github.com/hyperledger/fabric-protos-go/ledger/queryresult"
12
13
"sort"
13
14
"strconv"
14
15
"strings"
@@ -949,6 +950,8 @@ func removeBalance(ctx contractapi.TransactionContextInterface, sender string, i
949
950
}
950
951
defer balanceIterator .Close ()
951
952
953
+ var deferredDeletions = []func () error {}
954
+
952
955
// Iterate over keys that store balances and add them to partialBalance until
953
956
// either the necessary amount is reached or the keys ended
954
957
for balanceIterator .HasNext () && partialBalance < neededAmount {
@@ -972,47 +975,64 @@ func removeBalance(ctx contractapi.TransactionContextInterface, sender string, i
972
975
selfRecipientKeyNeedsToBeRemoved = true
973
976
selfRecipientKey = queryResponse .Key
974
977
} else {
975
- err = ctx .GetStub ().DelState (queryResponse .Key )
976
- if err != nil {
977
- return fmt .Errorf ("failed to delete the state of %v: %v" , queryResponse .Key , err )
978
- }
978
+ deferredDeletions = append (deferredDeletions , deferredDelete (ctx , queryResponse ))
979
979
}
980
980
}
981
981
982
982
if partialBalance < neededAmount {
983
983
return fmt .Errorf ("sender has insufficient funds for token %v, needed funds: %v, available fund: %v" , tokenId , neededAmount , partialBalance )
984
- } else if partialBalance > neededAmount {
985
- // Send the remainder back to the sender
986
- remainder , err := sub (partialBalance , neededAmount )
987
- if err != nil {
988
- return err
989
- }
990
-
991
- if selfRecipientKeyNeedsToBeRemoved {
992
- // Set balance for the key that has the same address for sender and recipient
993
- err = setBalance (ctx , sender , sender , tokenId , remainder )
984
+ } else {
985
+ // enough token funds have been found to perform the update
986
+ // now we can delete the token entries to supply updated token balances
987
+ for _ , deleteFn := range deferredDeletions {
988
+ err := deleteFn ()
994
989
if err != nil {
995
990
return err
996
991
}
997
- } else {
998
- err = addBalance (ctx , sender , sender , tokenId , remainder )
992
+ }
993
+ if partialBalance > neededAmount {
994
+ // Send the remainder back to the sender
995
+ remainder , err := sub (partialBalance , neededAmount )
999
996
if err != nil {
1000
997
return err
1001
998
}
1002
- }
1003
999
1004
- } else {
1005
- // Delete self recipient key
1006
- err = ctx .GetStub ().DelState (selfRecipientKey )
1007
- if err != nil {
1008
- return fmt .Errorf ("failed to delete the state of %v: %v" , selfRecipientKey , err )
1000
+ if selfRecipientKeyNeedsToBeRemoved {
1001
+ // Set balance for the key that has the same address for sender and recipient
1002
+ err = setBalance (ctx , sender , sender , tokenId , remainder )
1003
+ if err != nil {
1004
+ return err
1005
+ }
1006
+ } else {
1007
+ err = addBalance (ctx , sender , sender , tokenId , remainder )
1008
+ if err != nil {
1009
+ return err
1010
+ }
1011
+ }
1012
+
1013
+ } else {
1014
+ // Delete self recipient key
1015
+ err = ctx .GetStub ().DelState (selfRecipientKey )
1016
+ if err != nil {
1017
+ return fmt .Errorf ("failed to delete the state of %v: %v" , selfRecipientKey , err )
1018
+ }
1009
1019
}
1010
1020
}
1011
1021
}
1012
1022
1013
1023
return nil
1014
1024
}
1015
1025
1026
+ func deferredDelete (ctx contractapi.TransactionContextInterface , queryResponse * queryresult.KV ) func () error {
1027
+ return func () error {
1028
+ err := ctx .GetStub ().DelState (queryResponse .Key )
1029
+ if err != nil {
1030
+ return fmt .Errorf ("failed to delete the state of %v: %v" , queryResponse .Key , err )
1031
+ }
1032
+ return nil
1033
+ }
1034
+ }
1035
+
1016
1036
func emitTransferSingle (ctx contractapi.TransactionContextInterface , transferSingleEvent TransferSingle ) error {
1017
1037
transferSingleEventJSON , err := json .Marshal (transferSingleEvent )
1018
1038
if err != nil {
0 commit comments