m.Handle("/build-transaction", jsonHandler(a.build))
m.Handle("/sign-transaction", jsonHandler(a.pseudohsmSignTemplates))
m.Handle("/submit-transaction", jsonHandler(a.submit))
+ m.Handle("/calculate-transaction-gas", jsonHandler(a.calculateGas))
// TODO remove this api, separate sign and submit process
m.Handle("/sign-submit-transaction", jsonHandler(a.signSubmit))
m.Handle("/get-transaction", jsonHandler(a.getTransaction))
"github.com/bytom/blockchain/pseudohsm"
"github.com/bytom/blockchain/txbuilder"
+ "github.com/bytom/consensus"
"github.com/bytom/errors"
+ "github.com/bytom/math/checked"
"github.com/bytom/net/http/reqid"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/types"
}
func mergeActions(req *BuildRequest) []map[string]interface{} {
- actions := make([]map[string]interface{}, 0)
+ var actions []map[string]interface{}
actionMap := make(map[string]map[string]interface{})
for _, m := range req.Actions {
log.WithField("tx_id", txID["tx_id"]).Info("submit single tx")
return NewSuccessResponse(txID)
}
+
+type calculateTxGasResp 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"`
+}
+
+// POST /calculate-transaction-gas
+func (a *API) calculateGas(ctx context.Context, ins struct {
+ Tx types.Tx `json:"raw_transaction"`
+}) Response {
+ gasState, err := txbuilder.CalculateTxGas(a.chain, &ins.Tx)
+ if err != nil {
+ return NewErrorResponse(err)
+ }
+
+ btmLeft, ok := checked.MulInt64(gasState.GasLeft, consensus.VMGasRate)
+ if !ok {
+ return NewErrorResponse(errors.New("calculate btmleft got a math error"))
+ }
+
+ txGasResp := &calculateTxGasResp{
+ LeftBTM: btmLeft,
+ ConsumedBTM: int64(gasState.BTMValue) - btmLeft,
+ LeftGas: gasState.GasLeft,
+ ConsumedGas: gasState.GasUsed,
+ StorageGas: gasState.StorageGas,
+ VMGas: gasState.GasUsed - gasState.StorageGas,
+ }
+
+ return NewSuccessResponse(txGasResp)
+}
"github.com/bytom/errors"
"github.com/bytom/protocol"
"github.com/bytom/protocol/bc/types"
+ "github.com/bytom/protocol/validation"
"github.com/bytom/protocol/vm"
)
return errors.Wrap(err)
}
+// CalculateTxGas calculate a transaction gas by validating a transaction
+func CalculateTxGas(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.
BytomcliCmd.AddCommand(buildTransactionCmd)
BytomcliCmd.AddCommand(signTransactionCmd)
BytomcliCmd.AddCommand(submitTransactionCmd)
+ BytomcliCmd.AddCommand(calculateTransactionGasCmd)
BytomcliCmd.AddCommand(signSubTransactionCmd)
BytomcliCmd.AddCommand(getBlockCountCmd)
var submitTransactionCmd = &cobra.Command{
Use: "submit-transaction <signed json raw_transaction>",
- Short: "Submit signed transaction template",
+ Short: "Submit signed transaction",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
var ins = struct {
},
}
+var calculateTransactionGasCmd = &cobra.Command{
+ Use: "calculate-transaction-gas <signed json raw_transaction>",
+ Short: "calculate gas for signed transaction",
+ Args: cobra.ExactArgs(1),
+ Run: func(cmd *cobra.Command, args []string) {
+ var ins = struct {
+ Tx types.Tx `json:"raw_transaction"`
+ }{}
+
+ err := json.Unmarshal([]byte(args[0]), &ins)
+ if err != nil {
+ jww.ERROR.Println(err)
+ os.Exit(util.ErrLocalExe)
+ }
+
+ data, exitCode := util.ClientCall("/calculate-transaction-gas", &ins)
+ if exitCode != util.Success {
+ os.Exit(exitCode)
+ }
+
+ printJSON(data)
+ },
+}
+
var signSubTransactionCmd = &cobra.Command{
Use: "sign-submit-transaction <json templates>",
Short: "Sign and Submit transaction templates with account password",
}
var req = struct {
- Password string `json:"password"`
+ Password string `json:"password"`
Txs txbuilder.Template `json:"transaction"`
}{Password: password, Txs: template}