OSDN Git Service

fix review reward_util
authormars <mars@bytom.io>
Tue, 23 Jul 2019 03:25:46 +0000 (11:25 +0800)
committermars <mars@bytom.io>
Tue, 23 Jul 2019 03:25:46 +0000 (11:25 +0800)
toolbar/api_node/block.go [new file with mode: 0644]
toolbar/api_node/node.go [new file with mode: 0644]
toolbar/api_node/node_test.go [new file with mode: 0644]
toolbar/api_node/transaction.go [new file with mode: 0644]
toolbar/vote_reward/synchron/block_keeper.go

diff --git a/toolbar/api_node/block.go b/toolbar/api_node/block.go
new file mode 100644 (file)
index 0000000..a9789a2
--- /dev/null
@@ -0,0 +1,33 @@
+package apinode
+
+import (
+       "encoding/json"
+
+       "github.com/vapor/api"
+       "github.com/vapor/errors"
+       "github.com/vapor/protocol/bc/types"
+)
+
+func (n *Node) GetBlockByHash(hash string) (*types.Block, error) {
+       return n.getRawBlock(&getRawBlockReq{BlockHash: hash})
+}
+
+func (n *Node) GetBlockByHeight(height uint64) (*types.Block, error) {
+       return n.getRawBlock(&getRawBlockReq{BlockHeight: height})
+}
+
+type getRawBlockReq struct {
+       BlockHeight uint64 `json:"block_height"`
+       BlockHash   string `json:"block_hash"`
+}
+
+func (n *Node) getRawBlock(req *getRawBlockReq) (*types.Block, error) {
+       url := "/get-raw-block"
+       payload, err := json.Marshal(req)
+       if err != nil {
+               return nil, errors.Wrap(err, "json marshal")
+       }
+
+       resp := &api.GetRawBlockResp{}
+       return resp.RawBlock, n.request(url, payload, resp)
+}
diff --git a/toolbar/api_node/node.go b/toolbar/api_node/node.go
new file mode 100644 (file)
index 0000000..a056723
--- /dev/null
@@ -0,0 +1,37 @@
+package apinode
+
+import (
+       "encoding/json"
+
+       "github.com/vapor/errors"
+       "github.com/vapor/toolbar/common"
+)
+
+// Node can invoke the api which provide by the full node server
+type Node struct {
+       hostPort string
+}
+
+// NewNode create a api client with target server
+func NewNode(hostPort string) *Node {
+       return &Node{hostPort: hostPort}
+}
+
+type response struct {
+       Status    string          `json:"status"`
+       Data      json.RawMessage `json:"data"`
+       ErrDetail string          `json:"error_detail"`
+}
+
+func (n *Node) request(path string, payload []byte, respData interface{}) error {
+       resp := &response{}
+       if err := common.Post(n.hostPort+path, payload, resp); err != nil {
+               return err
+       }
+
+       if resp.Status != "success" {
+               return errors.New(resp.ErrDetail)
+       }
+
+       return json.Unmarshal(resp.Data, respData)
+}
diff --git a/toolbar/api_node/node_test.go b/toolbar/api_node/node_test.go
new file mode 100644 (file)
index 0000000..681bf02
--- /dev/null
@@ -0,0 +1,70 @@
+package apinode
+
+import (
+       "encoding/json"
+       "testing"
+
+       "github.com/vapor/consensus"
+       "github.com/vapor/errors"
+       "github.com/vapor/protocol/bc"
+)
+
+func buildTxRequest(accountID string, outputs map[string]uint64) ([]byte, error) {
+       totalBTM := uint64(10000000)
+       actions := []interface{}{}
+       for address, amount := range outputs {
+               actions = append(actions, &ControlAddressAction{
+                       Address:     address,
+                       AssetAmount: &bc.AssetAmount{AssetId: consensus.BTMAssetID, Amount: amount},
+               })
+               totalBTM += amount
+       }
+
+       actions = append(actions, &SpendAccountAction{
+               AccountID:   accountID,
+               AssetAmount: &bc.AssetAmount{AssetId: consensus.BTMAssetID, Amount: totalBTM},
+       })
+       payload, err := json.Marshal(&buildTxReq{Actions: actions})
+       if err != nil {
+               return nil, errors.Wrap(err, "Marshal spend request")
+       }
+
+       return payload, nil
+}
+
+type args struct {
+       accountID string
+       outputs   map[string]uint64
+}
+
+func TestBuildTxRequest(t *testing.T) {
+       cases := []struct {
+               args args
+               want string
+       }{
+               {
+                       args: args{
+                               accountID: "9bb77612-350e-4d53-81e2-525b28247ba5",
+                               outputs:   map[string]uint64{"sp1qlryy65a5apylphqp6axvhx7nd6y2zlexuvn7gf": 100},
+                       },
+                       want: `{"actions":[{"type":"control_address","address":"sp1qlryy65a5apylphqp6axvhx7nd6y2zlexuvn7gf","asset_id":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","amount":100},{"type":"spend_account","account_id":"9bb77612-350e-4d53-81e2-525b28247ba5","asset_id":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","amount":10000100}]}`,
+               },
+               {
+                       args: args{
+                               accountID: "9bb77612-350e-4d53-81e2-525b28247ba5",
+                               outputs:   map[string]uint64{"sp1qlryy65a5apylphqp6axvhx7nd6y2zlexuvn7gf": 100, "sp1qcgtxkhfzytul4lfttwex3skfqhm0tg6ms9da28": 200},
+                       },
+                       want: `{"actions":[{"type":"control_address","address":"sp1qlryy65a5apylphqp6axvhx7nd6y2zlexuvn7gf","asset_id":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","amount":100},{"type":"control_address","address":"sp1qcgtxkhfzytul4lfttwex3skfqhm0tg6ms9da28","asset_id":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","amount":200},{"type":"spend_account","account_id":"9bb77612-350e-4d53-81e2-525b28247ba5","asset_id":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","amount":10000300}]}`,
+               },
+       }
+
+       for i, c := range cases {
+               tx, err := buildTxRequest(c.args.accountID, c.args.outputs)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               if string(tx) != string(c.want) {
+                       t.Fatal(i, string(tx))
+               }
+       }
+}
diff --git a/toolbar/api_node/transaction.go b/toolbar/api_node/transaction.go
new file mode 100644 (file)
index 0000000..82ff3c9
--- /dev/null
@@ -0,0 +1,138 @@
+package apinode
+
+import (
+       "encoding/json"
+
+       "github.com/vapor/blockchain/txbuilder"
+       "github.com/vapor/consensus"
+       "github.com/vapor/errors"
+       "github.com/vapor/protocol/bc"
+       "github.com/vapor/protocol/bc/types"
+)
+
+type SpendAccountAction struct {
+       AccountID string `json:"account_id"`
+       *bc.AssetAmount
+}
+
+func (s *SpendAccountAction) MarshalJSON() ([]byte, error) {
+       return json.Marshal(&struct {
+               Type      string `json:"type"`
+               AccountID string `json:"account_id"`
+               *bc.AssetAmount
+       }{
+               Type:        "spend_account",
+               AccountID:   s.AccountID,
+               AssetAmount: s.AssetAmount,
+       })
+}
+
+type ControlAddressAction struct {
+       Address string `json:"address"`
+       *bc.AssetAmount
+}
+
+func (c *ControlAddressAction) MarshalJSON() ([]byte, error) {
+       return json.Marshal(&struct {
+               Type    string `json:"type"`
+               Address string `json:"address"`
+               *bc.AssetAmount
+       }{
+               Type:        "control_address",
+               Address:     c.Address,
+               AssetAmount: c.AssetAmount,
+       })
+}
+
+func (n *Node) BatchSendBTM(accountID, password string, outputs map[string]uint64) error {
+       totalBTM := uint64(10000000)
+       actions := []interface{}{}
+       for address, amount := range outputs {
+               actions = append(actions, &ControlAddressAction{
+                       Address:     address,
+                       AssetAmount: &bc.AssetAmount{AssetId: consensus.BTMAssetID, Amount: amount},
+               })
+               totalBTM += amount
+       }
+
+       actions = append(actions, &SpendAccountAction{
+               AccountID:   accountID,
+               AssetAmount: &bc.AssetAmount{AssetId: consensus.BTMAssetID, Amount: totalBTM},
+       })
+
+       tpl, err := n.buildTx(actions)
+       if err != nil {
+               return err
+       }
+
+       tpl, err = n.signTx(tpl, password)
+       if err != nil {
+               return err
+       }
+
+       _, err = n.SubmitTx(tpl.Transaction)
+       return err
+}
+
+type buildTxReq struct {
+       Actions []interface{} `json:"actions"`
+}
+
+func (n *Node) buildTx(actions []interface{}) (*txbuilder.Template, error) {
+       url := "/build-transaction"
+       payload, err := json.Marshal(&buildTxReq{Actions: actions})
+       if err != nil {
+               return nil, errors.Wrap(err, "Marshal spend request")
+       }
+
+       result := &txbuilder.Template{}
+       return result, n.request(url, payload, result)
+}
+
+type signTxReq struct {
+       Tx       *txbuilder.Template `json:"transaction"`
+       Password string              `json:"password"`
+}
+
+type signTxResp struct {
+       Tx           *txbuilder.Template `json:"transaction"`
+       SignComplete bool                `json:"sign_complete"`
+}
+
+func (n *Node) signTx(tpl *txbuilder.Template, password string) (*txbuilder.Template, error) {
+       url := "/sign-transaction"
+       payload, err := json.Marshal(&signTxReq{Tx: tpl, Password: password})
+       if err != nil {
+               return nil, errors.Wrap(err, "json marshal")
+       }
+
+       resp := &signTxResp{}
+       if err := n.request(url, payload, resp); err != nil {
+               return nil, err
+       }
+
+       if !resp.SignComplete {
+               return nil, errors.New("sign fail")
+       }
+
+       return resp.Tx, nil
+}
+
+type submitTxReq struct {
+       Tx *types.Tx `json:"raw_transaction"`
+}
+
+type submitTxResp struct {
+       TxID string `json:"tx_id"`
+}
+
+func (n *Node) SubmitTx(tx *types.Tx) (string, error) {
+       url := "/submit-transaction"
+       payload, err := json.Marshal(submitTxReq{Tx: tx})
+       if err != nil {
+               return "", errors.Wrap(err, "json marshal")
+       }
+
+       res := &submitTxResp{}
+       return res.TxID, n.request(url, payload, res)
+}
index 9903480..2b78a66 100644 (file)
@@ -8,7 +8,7 @@ import (
 
        "github.com/vapor/errors"
        "github.com/vapor/protocol/bc/types"
-       "github.com/vapor/toolbar/apinode"
+       apinode "github.com/vapor/toolbar/api_node"
        "github.com/vapor/toolbar/common"
        "github.com/vapor/toolbar/vote_reward/config"
        "github.com/vapor/toolbar/vote_reward/database/orm"