From: icodezjb Date: Tue, 9 Jan 2018 07:46:09 +0000 (+0800) Subject: Merge build-transaction Actions (#265) X-Git-Tag: v1.0.5-alpha~565 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=f2717d0a7adb730464414596b3c04c9dc8f1a8ba;p=bytom%2Fbytom-spv.git Merge build-transaction Actions (#265) * Merge build-transaction Actions * Add TestMergeActions in transact_test.go * Update MergeActions * Update MergeActions --- diff --git a/blockchain/transact.go b/blockchain/transact.go index 354121f8..5e55ebea 100644 --- a/blockchain/transact.go +++ b/blockchain/transact.go @@ -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 index 00000000..bfc745bf --- /dev/null +++ b/blockchain/transact_test.go @@ -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) + } + } + } + } +}