github.com/igggame/nebulas-go@v2.1.0+incompatible/core/transaction_binary_payload.go (about)

     1  // Copyright (C) 2017 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // the go-nebulas library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU General Public License
    16  // along with the go-nebulas library.  If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  
    19  package core
    20  
    21  import (
    22  	"fmt"
    23  
    24  	"github.com/nebulasio/go-nebulas/util"
    25  	"github.com/nebulasio/go-nebulas/util/logging"
    26  	"github.com/sirupsen/logrus"
    27  )
    28  
    29  // BinaryPayload carry some data
    30  type BinaryPayload struct {
    31  	Data []byte
    32  }
    33  
    34  // LoadBinaryPayload from bytes
    35  func LoadBinaryPayload(bytes []byte) (*BinaryPayload, error) {
    36  	return NewBinaryPayload(bytes), nil
    37  }
    38  
    39  // NewBinaryPayload with data
    40  func NewBinaryPayload(data []byte) *BinaryPayload {
    41  	return &BinaryPayload{
    42  		Data: data,
    43  	}
    44  }
    45  
    46  // ToBytes serialize payload
    47  func (payload *BinaryPayload) ToBytes() ([]byte, error) {
    48  	return payload.Data, nil
    49  }
    50  
    51  // BaseGasCount returns base gas count
    52  func (payload *BinaryPayload) BaseGasCount() *util.Uint128 {
    53  	return util.NewUint128()
    54  }
    55  
    56  // Execute the payload in tx
    57  func (payload *BinaryPayload) Execute(limitedGas *util.Uint128, tx *Transaction, block *Block, ws WorldState) (*util.Uint128, string, error) {
    58  	if block == nil || tx == nil || tx.to == nil {
    59  		return util.NewUint128(), "", ErrNilArgument
    60  	}
    61  
    62  	// transfer to contract
    63  	if tx.to.Type() == ContractAddress && AcceptAvailableAtHeight(block.height) {
    64  		// payloadGasLimit <= 0, v8 engine not limit the execution instructions
    65  		if limitedGas.Cmp(util.NewUint128()) <= 0 {
    66  			return util.NewUint128(), "", ErrOutOfGasLimit
    67  		}
    68  
    69  		// contract address is tx.to.
    70  		contract, err := CheckContract(tx.to, ws)
    71  		if err != nil {
    72  			return util.NewUint128(), "", err
    73  		}
    74  
    75  		birthTx, err := GetTransaction(contract.BirthPlace(), ws)
    76  		if err != nil {
    77  			return util.NewUint128(), "", err
    78  		}
    79  		deploy, err := LoadDeployPayload(birthTx.data.Payload) // ToConfirm: move deploy payload in ctx.
    80  		if err != nil {
    81  			return util.NewUint128(), "", err
    82  		}
    83  
    84  		engine, err := block.nvm.CreateEngine(block, tx, contract, ws)
    85  		if err != nil {
    86  			return util.NewUint128(), "", err
    87  		}
    88  		defer engine.Dispose()
    89  
    90  		if err := engine.SetExecutionLimits(limitedGas.Uint64(), DefaultLimitsOfTotalMemorySize); err != nil {
    91  			return util.NewUint128(), "", err
    92  		}
    93  
    94  		result, exeErr := engine.Call(deploy.Source, deploy.SourceType, ContractAcceptFunc, "")
    95  		gasCount := engine.ExecutionInstructions()
    96  		instructions, err := util.NewUint128FromInt(int64(gasCount))
    97  		if err != nil || exeErr == ErrUnexpected {
    98  			logging.VLog().WithFields(logrus.Fields{
    99  				"err":      err,
   100  				"exeErr":   exeErr,
   101  				"gasCount": gasCount,
   102  			}).Error("Unexpected error when executing binary")
   103  			return util.NewUint128(), "", ErrUnexpected
   104  		}
   105  
   106  		if exeErr == ErrExecutionFailed && len(result) > 0 {
   107  			exeErr = fmt.Errorf("Binary: %s", result)
   108  		}
   109  		if exeErr != nil {
   110  			return instructions, "", exeErr
   111  		}
   112  	}
   113  
   114  	return util.NewUint128(), "", nil
   115  }