OSDN Git Service

modify estimate-transaction-gas
authoroysheng <oysheng@bytom.io>
Thu, 19 Apr 2018 13:20:07 +0000 (21:20 +0800)
committeroysheng <oysheng@bytom.io>
Thu, 19 Apr 2018 13:20:07 +0000 (21:20 +0800)
api/transact.go
blockchain/txbuilder/finalize.go
cmd/bytomcli/commands/transaction.go

index 1cab954..e933b7e 100644 (file)
@@ -11,6 +11,7 @@ import (
 
        "github.com/bytom/blockchain/txbuilder"
        "github.com/bytom/consensus"
+       "github.com/bytom/consensus/segwit"
        "github.com/bytom/errors"
        "github.com/bytom/math/checked"
        "github.com/bytom/net/http/reqid"
@@ -170,36 +171,66 @@ func (a *API) submit(ctx context.Context, ins struct {
        return NewSuccessResponse(&submitTxResp{TxID: &ins.Tx.ID})
 }
 
+// EstimateTxGasResp estimate transaction consumed gas
 type EstimateTxGasResp 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"`
+       TotalGas   int64 `json:"total_gas"`
+       StorageGas int64 `json:"storage_gas"`
+       VMGas      int64 `json:"vm_gas"`
 }
 
 // POST /estimate-transaction-gas
-func (a *API) estimateTxGas(ctx context.Context, ins struct {
-       Tx types.Tx `json:"raw_transaction"`
+func (a *API) estimateTxGas(ctx context.Context, in struct {
+       TxTemplate txbuilder.Template `json:"transaction_template"`
 }) Response {
-       gasState, err := txbuilder.EstimateTxGas(a.chain, &ins.Tx)
+       // base tx size and not include sign
+       data, err := in.TxTemplate.Transaction.TxData.MarshalText()
        if err != nil {
                return NewErrorResponse(err)
        }
+       baseTxSize := int64(len(data))
+
+       // extra tx size for sign witness parts
+       baseWitnessSize := int64(300)
+       lenSignInst := int64(len(in.TxTemplate.SigningInstructions))
+       signSize := baseWitnessSize * lenSignInst
 
-       btmLeft, ok := checked.MulInt64(gasState.GasLeft, consensus.VMGasRate)
+       // total gas for tx storage
+       totalTxSizeGas, ok := checked.MulInt64(baseTxSize+signSize, consensus.StorageGasRate)
        if !ok {
-               return NewErrorResponse(errors.New("calculate btmleft got a math error"))
+               return NewErrorResponse(errors.New("calculate txsize gas got a math error"))
        }
 
+       // consume gas for run VM
+       totalP2WPKHGas := int64(0)
+       totalP2WSHGas := int64(0)
+       baseP2WPKHGas := int64(1419)
+       baseP2WSHGas := int64(2499)
+
+       for _, inpID := range in.TxTemplate.Transaction.Tx.InputIDs {
+               sp, err := in.TxTemplate.Transaction.Spend(inpID)
+               if err != nil {
+                       continue
+               }
+
+               resOut, ok := in.TxTemplate.Transaction.Entries[*sp.SpentOutputId].(*bc.Output)
+               if !ok {
+                       continue
+               }
+
+               if segwit.IsP2WPKHScript(resOut.ControlProgram.Code) {
+                       totalP2WPKHGas += baseP2WPKHGas
+               } else if segwit.IsP2WPKHScript(resOut.ControlProgram.Code) {
+                       totalP2WSHGas += baseP2WSHGas
+               }
+       }
+
+       // total estimate gas
+       totalGas := totalTxSizeGas + totalP2WPKHGas + totalP2WSHGas
+
        txGasResp := &EstimateTxGasResp{
-               LeftBTM:     btmLeft,
-               ConsumedBTM: int64(gasState.BTMValue) - btmLeft,
-               LeftGas:     gasState.GasLeft,
-               ConsumedGas: gasState.GasUsed,
-               StorageGas:  gasState.StorageGas,
-               VMGas:       gasState.GasUsed - gasState.StorageGas,
+               TotalGas:   totalGas,
+               StorageGas: totalTxSizeGas,
+               VMGas:      totalP2WPKHGas + totalP2WSHGas,
        }
 
        return NewSuccessResponse(txGasResp)
index 5222d22..043954e 100644 (file)
@@ -7,7 +7,6 @@ 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"
 )
 
@@ -47,27 +46,6 @@ func FinalizeTx(ctx context.Context, c *protocol.Chain, tx *types.Tx) error {
        return errors.Wrap(err)
 }
 
-// EstimateTxGas estimate a transaction gas by validating a transaction
-func EstimateTxGas(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 ddc8329..93e7ab1 100644 (file)
@@ -250,21 +250,23 @@ var submitTransactionCmd = &cobra.Command{
 }
 
 var estimateTransactionGasCmd = &cobra.Command{
-       Use:   "estimate-transaction-gas  <signed json raw_transaction>",
-       Short: "estimate gas for signed transaction",
+       Use:   "estimate-transaction-gas  <json templates>",
+       Short: "estimate gas for build transaction",
        Args:  cobra.ExactArgs(1),
        Run: func(cmd *cobra.Command, args []string) {
-               var ins = struct {
-                       Tx types.Tx `json:"raw_transaction"`
-               }{}
+               template := txbuilder.Template{}
 
-               err := json.Unmarshal([]byte(args[0]), &ins)
+               err := json.Unmarshal([]byte(args[0]), &template)
                if err != nil {
                        jww.ERROR.Println(err)
                        os.Exit(util.ErrLocalExe)
                }
 
-               data, exitCode := util.ClientCall("/estimate-transaction-gas", &ins)
+               var req = struct {
+                       TxTemplate txbuilder.Template `json:"transaction_template"`
+               }{TxTemplate: template}
+
+               data, exitCode := util.ClientCall("/estimate-transaction-gas", &req)
                if exitCode != util.Success {
                        os.Exit(exitCode)
                }