X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=api%2Ftransact.go;h=67d4429fc2a7f3387b6805636e3ebcf74a8f4785;hp=1c0f27411b6f847e35f1acd34d1ab91a0d944ac1;hb=31f8f7cf1ffbec5365ab6ebf217537809cf714e5;hpb=8964bcf0ffc12618f95c54f6677fcf45c7919534 diff --git a/api/transact.go b/api/transact.go index 1c0f2741..67d4429f 100644 --- a/api/transact.go +++ b/api/transact.go @@ -3,7 +3,6 @@ package api import ( "context" "encoding/json" - "math" "strings" "time" @@ -11,29 +10,27 @@ import ( "github.com/vapor/account" "github.com/vapor/blockchain/txbuilder" - "github.com/vapor/consensus" - "github.com/vapor/consensus/segwit" "github.com/vapor/errors" - "github.com/vapor/math/checked" - "github.com/vapor/net/http/reqid" "github.com/vapor/protocol/bc" "github.com/vapor/protocol/bc/types" ) var ( - defaultTxTTL = 5 * time.Minute + defaultTxTTL = 30 * time.Minute defaultBaseRate = float64(100000) - flexibleGas = int64(1800) ) func (a *API) actionDecoder(action string) (func([]byte) (txbuilder.Action, error), bool) { decoders := map[string]func([]byte) (txbuilder.Action, error){ "control_address": txbuilder.DecodeControlAddressAction, "control_program": txbuilder.DecodeControlProgramAction, - "issue": a.wallet.AssetReg.DecodeIssueAction, + "cross_chain_out": txbuilder.DecodeCrossOutAction, + "vote_output": txbuilder.DecodeVoteOutputAction, "retire": txbuilder.DecodeRetireAction, + "cross_chain_in": txbuilder.DecodeCrossInAction, "spend_account": a.wallet.AccountMgr.DecodeSpendAction, "spend_account_unspent_output": a.wallet.AccountMgr.DecodeSpendUTXOAction, + "veto": a.wallet.AccountMgr.DecodeVetoAction, } decoder, ok := decoders[action] return decoder, ok @@ -91,8 +88,7 @@ func (a *API) buildSingle(ctx context.Context, req *BuildRequest) (*txbuilder.Te // POST /build-transaction func (a *API) build(ctx context.Context, buildReqs *BuildRequest) Response { - subctx := reqid.NewSubContext(ctx, reqid.New()) - tmpl, err := a.buildSingle(subctx, buildReqs) + tmpl, err := a.buildSingle(ctx, buildReqs) if err != nil { return NewErrorResponse(err) } @@ -180,8 +176,7 @@ func (a *API) buildTxs(ctx context.Context, req *BuildRequest) ([]*txbuilder.Tem // POST /build-chain-transactions func (a *API) buildChainTxs(ctx context.Context, buildReqs *BuildRequest) Response { - subctx := reqid.NewSubContext(ctx, reqid.New()) - tmpls, err := a.buildTxs(subctx, buildReqs) + tmpls, err := a.buildTxs(ctx, buildReqs) if err != nil { return NewErrorResponse(err) } @@ -223,115 +218,11 @@ func (a *API) submitTxs(ctx context.Context, ins struct { return NewSuccessResponse(&submitTxsResp{TxID: txHashs}) } -// EstimateTxGasResp estimate transaction consumed gas -type EstimateTxGasResp struct { - TotalNeu int64 `json:"total_neu"` - StorageNeu int64 `json:"storage_neu"` - VMNeu int64 `json:"vm_neu"` -} - -// EstimateTxGas estimate consumed neu for transaction -func EstimateTxGas(template txbuilder.Template) (*EstimateTxGasResp, error) { - // base tx size and not include sign - data, err := template.Transaction.TxData.MarshalText() - if err != nil { - return nil, err - } - baseTxSize := int64(len(data)) - - // extra tx size for sign witness parts - signSize := estimateSignSize(template.SigningInstructions) - - // total gas for tx storage - totalTxSizeGas, ok := checked.MulInt64(baseTxSize+signSize, consensus.StorageGasRate) - if !ok { - return nil, errors.New("calculate txsize gas got a math error") - } - - // consume gas for run VM - totalP2WPKHGas := int64(0) - totalP2WSHGas := int64(0) - baseP2WPKHGas := int64(1419) - // flexible Gas is used for handle need extra utxo situation - - for pos, inpID := range template.Transaction.Tx.InputIDs { - sp, err := template.Transaction.Spend(inpID) - if err != nil { - continue - } - - resOut, err := template.Transaction.Output(*sp.SpentOutputId) - if err != nil { - continue - } - - if segwit.IsP2WPKHScript(resOut.ControlProgram.Code) { - totalP2WPKHGas += baseP2WPKHGas - } else if segwit.IsP2WSHScript(resOut.ControlProgram.Code) { - sigInst := template.SigningInstructions[pos] - totalP2WSHGas += estimateP2WSHGas(sigInst) - } - } - - // total estimate gas - totalGas := totalTxSizeGas + totalP2WPKHGas + totalP2WSHGas + flexibleGas - - // rounding totalNeu with base rate 100000 - totalNeu := float64(totalGas*consensus.VMGasRate) / defaultBaseRate - roundingNeu := math.Ceil(totalNeu) - estimateNeu := int64(roundingNeu) * int64(defaultBaseRate) - - // TODO add priority - - return &EstimateTxGasResp{ - TotalNeu: estimateNeu, - StorageNeu: totalTxSizeGas * consensus.VMGasRate, - VMNeu: (totalP2WPKHGas + totalP2WSHGas) * consensus.VMGasRate, - }, nil -} - -// estimate p2wsh gas. -// OP_CHECKMULTISIG consume (984 * a - 72 * b - 63) gas, -// where a represent the num of public keys, and b represent the num of quorum. -func estimateP2WSHGas(sigInst *txbuilder.SigningInstruction) int64 { - P2WSHGas := int64(0) - baseP2WSHGas := int64(738) - - for _, witness := range sigInst.WitnessComponents { - switch t := witness.(type) { - case *txbuilder.SignatureWitness: - P2WSHGas += baseP2WSHGas + (984*int64(len(t.Keys)) - 72*int64(t.Quorum) - 63) - case *txbuilder.RawTxSigWitness: - P2WSHGas += baseP2WSHGas + (984*int64(len(t.Keys)) - 72*int64(t.Quorum) - 63) - } - } - return P2WSHGas -} - -// estimate signature part size. -// if need multi-sign, calculate the size according to the length of keys. -func estimateSignSize(signingInstructions []*txbuilder.SigningInstruction) int64 { - signSize := int64(0) - baseWitnessSize := int64(300) - - for _, sigInst := range signingInstructions { - for _, witness := range sigInst.WitnessComponents { - switch t := witness.(type) { - case *txbuilder.SignatureWitness: - signSize += int64(t.Quorum) * baseWitnessSize - case *txbuilder.RawTxSigWitness: - signSize += int64(t.Quorum) * baseWitnessSize - } - } - } - return signSize -} - // 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) + txGasResp, err := txbuilder.EstimateTxGas(in.TxTemplate) if err != nil { return NewErrorResponse(err) }