import (
"context"
+ "encoding/json"
+ "math"
"net/http/httptest"
"os"
"testing"
"github.com/bytom/accesstoken"
"github.com/bytom/blockchain/rpc"
+ "github.com/bytom/blockchain/txbuilder"
"github.com/bytom/testutil"
)
}
cases := []struct {
- path string
- request interface{}
- respWant *Response
+ path string
+ request interface{}
+ respWant *Response
}{
{
path: "/create-key",
}
}
}
+
+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)
+ }
+
+ totalNeu := float64(estimateResult.StorageNeu+estimateResult.VMNeu) / float64(100000)
+ roundingNeu := math.Ceil(totalNeu)
+ estimateNeu := int64(roundingNeu) * int64(100000)
+
+ if estimateResult.TotalNeu != estimateNeu {
+ t.Errorf(`got=%#v; want=%#v`, estimateResult.TotalNeu, estimateNeu)
+ }
+}
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
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
}
roundingNeu := math.Ceil(totalNeu)
estimateNeu := int64(roundingNeu) * int64(100000)
- txGasResp := &EstimateTxGasResp{
+ 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)
}