OSDN Git Service

Merge pull request #887 from Bytom/dev-estimate
authorPaladz <yzhu101@uottawa.ca>
Wed, 2 May 2018 14:55:55 +0000 (22:55 +0800)
committerGitHub <noreply@github.com>
Wed, 2 May 2018 14:55:55 +0000 (22:55 +0800)
rounding estimateNeu with ceil

api/api_test.go
api/transact.go

index 5906f0f..2ad63ce 100644 (file)
@@ -2,6 +2,8 @@ package api
 
 import (
        "context"
+       "encoding/json"
+       "math"
        "net/http/httptest"
        "os"
        "testing"
@@ -10,6 +12,7 @@ import (
 
        "github.com/bytom/accesstoken"
        "github.com/bytom/blockchain/rpc"
+       "github.com/bytom/blockchain/txbuilder"
        "github.com/bytom/testutil"
 )
 
@@ -33,9 +36,9 @@ func TestAPIHandler(t *testing.T) {
        }
 
        cases := []struct {
-               path        string
-               request     interface{}
-               respWant    *Response
+               path     string
+               request  interface{}
+               respWant *Response
        }{
                {
                        path: "/create-key",
@@ -96,3 +99,26 @@ func TestAPIHandler(t *testing.T) {
                }
        }
 }
+
+func TestEstimateTxGas(t *testing.T) {
+       tmplStr := `{"allow_additional_actions":false,"raw_transaction":"070100010161015ffe8a1209937a6a8b22e8c01f056fd5f1730734ba8964d6b79de4a639032cecddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8099c4d59901000116001485eb6eee8023332da85df60157dc9b16cc553fb2010002013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80afa08b4f011600142b4fd033bc76b4ddf5cb00f625362c4bc7b10efa00013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8090dfc04a011600146eea1ce6cfa5b718ae8094376be9bc1a87c9c82700","signing_instructions":[{"position":0,"witness_components":[{"keys":[{"derivation_path":["010100000000000000","0100000000000000"],"xpub":"cb4e5932d808ee060df9552963d87f60edac42360b11d4ad89558ef2acea4d4aaf4818f2ebf5a599382b8dfce0a0c798c7e44ec2667b3a1d34c61ba57609de55"}],"quorum":1,"signatures":null,"type":"raw_tx_signature"},{"type":"data","value":"1c9b5c1db7f4afe31fd1b7e0495a8bb042a271d8d7924d4fc1ff7cf1bff15813"}]}]}`
+       template := txbuilder.Template{}
+       err := json.Unmarshal([]byte(tmplStr), &template)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       estimateResult, err := EstimateTxGas(template)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       baseRate := float64(100000)
+       totalNeu := float64(estimateResult.StorageNeu+estimateResult.VMNeu) / baseRate
+       roundingNeu := math.Ceil(totalNeu)
+       estimateNeu := int64(roundingNeu) * int64(baseRate)
+
+       if estimateResult.TotalNeu != estimateNeu {
+               t.Errorf(`got=%#v; want=%#v`, estimateResult.TotalNeu, estimateNeu)
+       }
+}
index 56ec838..9bb72fd 100644 (file)
@@ -4,6 +4,7 @@ import (
        "context"
        "encoding/json"
        "fmt"
+       "math"
        "strings"
        "time"
 
@@ -19,7 +20,10 @@ import (
        "github.com/bytom/protocol/bc/types"
 )
 
-var defaultTxTTL = 5 * time.Minute
+var (
+       defaultTxTTL    = 5 * time.Minute
+       defaultBaseRate = float64(100000)
+)
 
 func (a *API) actionDecoder(action string) (func([]byte) (txbuilder.Action, error), bool) {
        var decoder func([]byte) (txbuilder.Action, error)
@@ -198,26 +202,24 @@ type EstimateTxGasResp struct {
        VMNeu      int64 `json:"vm_neu"`
 }
 
-// POST /estimate-transaction-gas
-func (a *API) estimateTxGas(ctx context.Context, in struct {
-       TxTemplate txbuilder.Template `json:"transaction_template"`
-}) Response {
+// EstimateTxGas estimate consumed neu for transaction
+func EstimateTxGas(template txbuilder.Template) (*EstimateTxGasResp, error) {
        // base tx size and not include sign
-       data, err := in.TxTemplate.Transaction.TxData.MarshalText()
+       data, err := template.Transaction.TxData.MarshalText()
        if err != nil {
-               return NewErrorResponse(err)
+               return nil, err
        }
        baseTxSize := int64(len(data))
 
        // extra tx size for sign witness parts
        baseWitnessSize := int64(300)
-       lenSignInst := int64(len(in.TxTemplate.SigningInstructions))
+       lenSignInst := int64(len(template.SigningInstructions))
        signSize := baseWitnessSize * lenSignInst
 
        // total gas for tx storage
        totalTxSizeGas, ok := checked.MulInt64(baseTxSize+signSize, consensus.StorageGasRate)
        if !ok {
-               return NewErrorResponse(errors.New("calculate txsize gas got a math error"))
+               return nil, errors.New("calculate txsize gas got a math error")
        }
 
        // consume gas for run VM
@@ -226,13 +228,13 @@ func (a *API) estimateTxGas(ctx context.Context, in struct {
        baseP2WPKHGas := int64(1419)
        baseP2WSHGas := int64(2499)
 
-       for _, inpID := range in.TxTemplate.Transaction.Tx.InputIDs {
-               sp, err := in.TxTemplate.Transaction.Spend(inpID)
+       for _, inpID := range template.Transaction.Tx.InputIDs {
+               sp, err := template.Transaction.Spend(inpID)
                if err != nil {
                        continue
                }
 
-               resOut, err := in.TxTemplate.Transaction.Output(*sp.SpentOutputId)
+               resOut, err := template.Transaction.Output(*sp.SpentOutputId)
                if err != nil {
                        continue
                }
@@ -247,11 +249,25 @@ func (a *API) estimateTxGas(ctx context.Context, in struct {
        // total estimate gas
        totalGas := totalTxSizeGas + totalP2WPKHGas + totalP2WSHGas
 
-       txGasResp := &EstimateTxGasResp{
-               TotalNeu:   totalGas * consensus.VMGasRate,
+       // rounding totalNeu with base rate 100000
+       totalNeu := float64(totalGas*consensus.VMGasRate) / defaultBaseRate
+       roundingNeu := math.Ceil(totalNeu)
+       estimateNeu := int64(roundingNeu) * int64(defaultBaseRate)
+
+       return &EstimateTxGasResp{
+               TotalNeu:   estimateNeu,
                StorageNeu: totalTxSizeGas * consensus.VMGasRate,
                VMNeu:      (totalP2WPKHGas + totalP2WSHGas) * consensus.VMGasRate,
-       }
+       }, nil
+}
 
+// POST /estimate-transaction-gas
+func (a *API) estimateTxGas(ctx context.Context, in struct {
+       TxTemplate txbuilder.Template `json:"transaction_template"`
+}) Response {
+       txGasResp, err := EstimateTxGas(in.TxTemplate)
+       if err != nil {
+               return NewErrorResponse(err)
+       }
        return NewSuccessResponse(txGasResp)
 }