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 }