OSDN Git Service

Merge build-transaction Actions (#265)
authoricodezjb <icodezjb@163.com>
Tue, 9 Jan 2018 07:46:09 +0000 (15:46 +0800)
committerGuanghua Guo <1536310027@qq.com>
Tue, 9 Jan 2018 07:46:09 +0000 (15:46 +0800)
* Merge build-transaction Actions

* Add TestMergeActions in transact_test.go

* Update MergeActions

* Update MergeActions

blockchain/transact.go
blockchain/transact_test.go [new file with mode: 0644]

index 354121f..5e55ebe 100644 (file)
@@ -3,6 +3,7 @@ package blockchain
 import (
        "context"
        "encoding/json"
+       "fmt"
        "time"
 
        log "github.com/sirupsen/logrus"
@@ -43,13 +44,41 @@ func (bcr *BlockchainReactor) actionDecoder(action string) (func([]byte) (txbuil
        return decoder, true
 }
 
+func MergeActions(req *BuildRequest) []map[string]interface{} {
+       actions := make([]map[string]interface{}, 0)
+       actionMap := make(map[string]map[string]interface{})
+
+       for _, m := range req.Actions {
+               if actionType := m["type"].(string); actionType != "spend_account" {
+                       actions = append(actions, m)
+                       continue
+               }
+
+               actionKey := m["asset_id"].(string) + m["account_id"].(string)
+               amountNumber := m["amount"].(json.Number)
+               amount, _ := amountNumber.Int64()
+
+               if tmpM, ok := actionMap[actionKey]; ok {
+                       tmpNumber, _ := tmpM["amount"].(json.Number)
+                       tmpAmount, _ := tmpNumber.Int64()
+                       tmpM["amount"] = json.Number(fmt.Sprintf("%v", tmpAmount+amount))
+               } else {
+                       actionMap[actionKey] = m
+                       actions = append(actions, m)
+               }
+       }
+
+       return actions
+}
+
 func (bcr *BlockchainReactor) buildSingle(ctx context.Context, req *BuildRequest) (*txbuilder.Template, error) {
        err := bcr.filterAliases(ctx, req)
        if err != nil {
                return nil, err
        }
-       actions := make([]txbuilder.Action, 0, len(req.Actions))
-       for i, act := range req.Actions {
+       reqActions := MergeActions(req)
+       actions := make([]txbuilder.Action, 0, len(reqActions))
+       for i, act := range reqActions {
                typ, ok := act["type"].(string)
                if !ok {
                        return nil, errors.WithDetailf(errBadActionType, "no action type provided on action %d", i)
diff --git a/blockchain/transact_test.go b/blockchain/transact_test.go
new file mode 100644 (file)
index 0000000..bfc745b
--- /dev/null
@@ -0,0 +1,100 @@
+package blockchain
+
+import (
+       "encoding/json"
+       "fmt"
+       "testing"
+)
+
+func TestMergeActions(t *testing.T) {
+       cases := []struct {
+               buildStr    string
+               actionCount int
+               wantBTM     int64
+               wantOther   int64
+       }{
+               {
+                       `{"actions": [
+                       {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount":100, "account_id": "123"},
+                               {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","amount": 200,"account_id": "123"},
+                               {"type": "control_receiver", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount": 200, "receiver":{"control_program": "program","expires_at":"2017"}}
+                       ]}`,
+                       2,
+                       300,
+                       0,
+               },
+               {
+                       `{"actions": [
+                       {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount":100, "account_id": "123"},
+                               {"type": "spend_account", "asset_id": "43c6946d092b2959c1a82e90b282c68fca63e66de289048f6acd6cea9383c79c","amount": 200,"account_id": "123"},
+                               {"type": "control_receiver", "asset_id": "43c6946d092b2959c1a82e90b282c68fca63e66de289048f6acd6cea9383c79c", "amount": 200, "receiver":{"control_program": "program","expires_at":"2017"}}
+                       ]}`,
+                       3,
+                       100,
+                       200,
+               }, {
+                       `{"actions": [
+                       {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount":100, "account_id": "123"},
+                               {"type": "spend_account", "asset_id": "43c6946d092b2959c1a82e90b282c68fca63e66de289048f6acd6cea9383c79c","amount": 200,"account_id": "123"},
+                               {"type": "spend_account", "asset_id": "43c6946d092b2959c1a82e90b282c68fca63e66de289048f6acd6cea9383c79c","amount": 300,"account_id": "123"},
+                               {"type": "control_receiver", "asset_id": "43c6946d092b2959c1a82e90b282c68fca63e66de289048f6acd6cea9383c79c", "amount": 500, "receiver":{"control_program": "program","expires_at":"2017"}}
+                       ]}`,
+                       3,
+                       100,
+                       500,
+               },
+               {
+                       `{"actions": [
+                       {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount":100, "account_id": "123"},
+                               {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","amount": 200,"account_id": "123"},
+                               {"type": "spend_account", "asset_id": "43c6946d092b2959c1a82e90b282c68fca63e66de289048f6acd6cea9383c79c","amount": 200,"account_id": "123"},
+                               {"type": "spend_account", "asset_id": "43c6946d092b2959c1a82e90b282c68fca63e66de289048f6acd6cea9383c79c","amount": 300,"account_id": "123"},
+                               {"type": "control_receiver", "asset_id": "43c6946d092b2959c1a82e90b282c68fca63e66de289048f6acd6cea9383c79c", "amount": 500, "receiver":{"control_program": "program","expires_at":"2017"}}
+                       ]}`,
+                       3,
+                       300,
+                       500,
+               },
+       }
+
+       for i, c := range cases {
+               BuildReq := &BuildRequest{}
+
+               if err := json.Unmarshal([]byte(c.buildStr), BuildReq); err != nil {
+                       t.Fatal(err)
+               }
+
+               for _, m := range BuildReq.Actions {
+                       amount := m["amount"].(float64)
+                       m["amount"] = json.Number(fmt.Sprintf("%v", amount))
+               }
+
+               actions := MergeActions(BuildReq)
+
+               if len(actions) != c.actionCount {
+                       t.Fatalf("got error count %d, want %d", len(actions), c.actionCount)
+               }
+
+               for _, a := range actions {
+                       actionType := a["type"].(string)
+                       assetID := a["asset_id"].(string)
+                       if actionType == "spend_account" {
+                               amountNumber := a["amount"].(json.Number)
+                               amount, _ := amountNumber.Int64()
+
+                               switch assetID {
+                               case "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":
+                                       if amount != c.wantBTM {
+                                               t.Fatalf("index %d, get error amount %v, want %d", i, amount, c.wantBTM)
+                                       }
+                               case "43c6946d092b2959c1a82e90b282c68fca63e66de289048f6acd6cea9383c79c":
+                                       if amount != c.wantOther {
+                                               t.Fatalf("index %d, get error amount %v, want %d", i, amount, c.wantOther)
+                                       }
+                               default:
+                                       t.Fatalf("no %s in test cases", assetID)
+                               }
+                       }
+               }
+       }
+}