import (
"context"
"encoding/json"
- "math"
"strings"
"time"
log "github.com/sirupsen/logrus"
- "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"
+ "github.com/bytom/vapor/account"
+ "github.com/bytom/vapor/blockchain/txbuilder"
+ "github.com/bytom/vapor/errors"
+ "github.com/bytom/vapor/protocol/bc"
+ "github.com/bytom/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,
- "dpos_address": a.wallet.AccountMgr.DecodeDposAction,
- "ipfs_data": txbuilder.DecodeIpfsDataAction,
+ "veto": a.wallet.AccountMgr.DecodeVetoAction,
}
decoder, ok := decoders[action]
return decoder, ok
if !ok {
return false, errors.WithDetailf(ErrBadActionType, "no action type provided on action %d", i)
}
- if strings.HasPrefix(actionType, "dpos_address") {
- return false, nil
- }
+
if strings.HasPrefix(actionType, "spend") || actionType == "issue" {
count++
}
// 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)
}
// 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)
}
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)
}