OSDN Git Service

add api calculate-transaction-gas
authoroysheng <oysheng@bytom.io>
Mon, 16 Apr 2018 08:40:55 +0000 (16:40 +0800)
committeroysheng <oysheng@bytom.io>
Mon, 16 Apr 2018 08:40:55 +0000 (16:40 +0800)
api/api.go
api/transact.go
blockchain/txbuilder/finalize.go
cmd/bytomcli/commands/bytomcli.go
cmd/bytomcli/commands/transaction.go

index f43620e..0ccaad3 100644 (file)
@@ -191,6 +191,7 @@ func (a *API) buildHandler() {
                m.Handle("/build-transaction", jsonHandler(a.build))
                m.Handle("/sign-transaction", jsonHandler(a.pseudohsmSignTemplates))
                m.Handle("/submit-transaction", jsonHandler(a.submit))
+               m.Handle("/calculate-transaction-gas", jsonHandler(a.calculateGas))
                // TODO remove this api, separate sign and submit process
                m.Handle("/sign-submit-transaction", jsonHandler(a.signSubmit))
                m.Handle("/get-transaction", jsonHandler(a.getTransaction))
index 4a72dd4..c1b1ff8 100644 (file)
@@ -11,7 +11,9 @@ import (
 
        "github.com/bytom/blockchain/pseudohsm"
        "github.com/bytom/blockchain/txbuilder"
+       "github.com/bytom/consensus"
        "github.com/bytom/errors"
+       "github.com/bytom/math/checked"
        "github.com/bytom/net/http/reqid"
        "github.com/bytom/protocol/bc"
        "github.com/bytom/protocol/bc/types"
@@ -43,7 +45,7 @@ func (a *API) actionDecoder(action string) (func([]byte) (txbuilder.Action, erro
 }
 
 func mergeActions(req *BuildRequest) []map[string]interface{} {
-       actions := make([]map[string]interface{}, 0)
+       var actions []map[string]interface{}
        actionMap := make(map[string]map[string]interface{})
 
        for _, m := range req.Actions {
@@ -205,3 +207,38 @@ func (a *API) signSubmit(ctx context.Context, x struct {
        log.WithField("tx_id", txID["tx_id"]).Info("submit single tx")
        return NewSuccessResponse(txID)
 }
+
+type calculateTxGasResp struct {
+       LeftBTM     int64 `json:"left_btm"`
+       ConsumedBTM int64 `json:"consumed_btm"`
+       LeftGas     int64 `json:"left_gas"`
+       ConsumedGas int64 `json:"consumed_gas"`
+       StorageGas  int64 `json:"storage_gas"`
+       VMGas       int64 `json:"vm_gas"`
+}
+
+// POST /calculate-transaction-gas
+func (a *API) calculateGas(ctx context.Context, ins struct {
+       Tx types.Tx `json:"raw_transaction"`
+}) Response {
+       gasState, err := txbuilder.CalculateTxGas(a.chain, &ins.Tx)
+       if err != nil {
+               return NewErrorResponse(err)
+       }
+
+       btmLeft, ok := checked.MulInt64(gasState.GasLeft, consensus.VMGasRate)
+       if !ok {
+               return NewErrorResponse(errors.New("calculate btmleft got a math error"))
+       }
+
+       txGasResp := &calculateTxGasResp{
+               LeftBTM:     btmLeft,
+               ConsumedBTM: int64(gasState.BTMValue) - btmLeft,
+               LeftGas:     gasState.GasLeft,
+               ConsumedGas: gasState.GasUsed,
+               StorageGas:  gasState.StorageGas,
+               VMGas:       gasState.GasUsed - gasState.StorageGas,
+       }
+
+       return NewSuccessResponse(txGasResp)
+}
index 043954e..edb6fc0 100644 (file)
@@ -7,6 +7,7 @@ import (
        "github.com/bytom/errors"
        "github.com/bytom/protocol"
        "github.com/bytom/protocol/bc/types"
+       "github.com/bytom/protocol/validation"
        "github.com/bytom/protocol/vm"
 )
 
@@ -46,6 +47,27 @@ func FinalizeTx(ctx context.Context, c *protocol.Chain, tx *types.Tx) error {
        return errors.Wrap(err)
 }
 
+// CalculateTxGas calculate a transaction gas by validating a transaction
+func CalculateTxGas(c *protocol.Chain, tx *types.Tx) (*validation.GasState, error) {
+       // This part is use for prevent tx size  is 0
+       data, err := tx.TxData.MarshalText()
+       if err != nil {
+               return nil, err
+       }
+       tx.TxData.SerializedSize = uint64(len(data))
+       tx.Tx.SerializedSize = uint64(len(data))
+
+       bh := c.BestBlockHeader()
+       block := types.MapBlock(&types.Block{BlockHeader: *bh})
+
+       gasState, err := validation.ValidateTx(tx.Tx, block)
+       if err != nil {
+               return nil, err
+       }
+
+       return gasState, nil
+}
+
 var (
        // ErrNoTxSighashCommitment is returned when no input commits to the
        // complete transaction.
index e3584c0..b3b1582 100644 (file)
@@ -97,6 +97,7 @@ func AddCommands() {
        BytomcliCmd.AddCommand(buildTransactionCmd)
        BytomcliCmd.AddCommand(signTransactionCmd)
        BytomcliCmd.AddCommand(submitTransactionCmd)
+       BytomcliCmd.AddCommand(calculateTransactionGasCmd)
        BytomcliCmd.AddCommand(signSubTransactionCmd)
 
        BytomcliCmd.AddCommand(getBlockCountCmd)
index ac738a6..69fb5ed 100644 (file)
@@ -227,7 +227,7 @@ var signTransactionCmd = &cobra.Command{
 
 var submitTransactionCmd = &cobra.Command{
        Use:   "submit-transaction  <signed json raw_transaction>",
-       Short: "Submit signed transaction template",
+       Short: "Submit signed transaction",
        Args:  cobra.ExactArgs(1),
        Run: func(cmd *cobra.Command, args []string) {
                var ins = struct {
@@ -249,6 +249,30 @@ var submitTransactionCmd = &cobra.Command{
        },
 }
 
+var calculateTransactionGasCmd = &cobra.Command{
+       Use:   "calculate-transaction-gas  <signed json raw_transaction>",
+       Short: "calculate gas for signed transaction",
+       Args:  cobra.ExactArgs(1),
+       Run: func(cmd *cobra.Command, args []string) {
+               var ins = struct {
+                       Tx types.Tx `json:"raw_transaction"`
+               }{}
+
+               err := json.Unmarshal([]byte(args[0]), &ins)
+               if err != nil {
+                       jww.ERROR.Println(err)
+                       os.Exit(util.ErrLocalExe)
+               }
+
+               data, exitCode := util.ClientCall("/calculate-transaction-gas", &ins)
+               if exitCode != util.Success {
+                       os.Exit(exitCode)
+               }
+
+               printJSON(data)
+       },
+}
+
 var signSubTransactionCmd = &cobra.Command{
        Use:   "sign-submit-transaction  <json templates>",
        Short: "Sign and Submit transaction templates with account password",
@@ -266,7 +290,7 @@ var signSubTransactionCmd = &cobra.Command{
                }
 
                var req = struct {
-                       Password string           `json:"password"`
+                       Password string             `json:"password"`
                        Txs      txbuilder.Template `json:"transaction"`
                }{Password: password, Txs: template}