github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/cmd/wasm/runner.go (about)

     1  package main
     2  
     3  import (
     4  	"github.com/PlatONnetwork/PlatON-Go/cmd/utils"
     5  	"github.com/PlatONnetwork/PlatON-Go/common"
     6  	"github.com/PlatONnetwork/PlatON-Go/core"
     7  	"github.com/PlatONnetwork/PlatON-Go/core/state"
     8  	"github.com/PlatONnetwork/PlatON-Go/core/vm"
     9  	"github.com/PlatONnetwork/PlatON-Go/ethdb"
    10  	"github.com/PlatONnetwork/PlatON-Go/life/runtime"
    11  	"github.com/PlatONnetwork/PlatON-Go/log"
    12  	"github.com/PlatONnetwork/PlatON-Go/params"
    13  	"github.com/PlatONnetwork/PlatON-Go/rlp"
    14  	"bytes"
    15  	"encoding/json"
    16  	"fmt"
    17  	"gopkg.in/urfave/cli.v1"
    18  	"io/ioutil"
    19  	"math/big"
    20  	"os"
    21  	"time"
    22  
    23  	covert "github.com/PlatONnetwork/PlatON-Go/life/utils"
    24  	goruntime "runtime"
    25  )
    26  
    27  var runCommond = cli.Command{
    28  	Action:      runCmd,
    29  	Name:        "run",
    30  	Usage:       "run arbitrary wasm binary",
    31  	ArgsUsage:   "<code>",
    32  	Description: "The run command runs arbitrary WASM code",
    33  }
    34  
    35  // readGenesis will read the given JSON format genesis file and
    36  // return the initialized Genesis structure
    37  func readGenesis(genesisPath string) *core.Genesis {
    38  	if len(genesisPath) == 0 {
    39  		utils.Fatalf("Must supply path to genesis JSON file")
    40  	}
    41  	file, err := os.Open(genesisPath)
    42  	if err != nil {
    43  		utils.Fatalf("Failed to read genesis file : %v", err)
    44  	}
    45  	defer file.Close()
    46  
    47  	genesis := new(core.Genesis)
    48  	if err := json.NewDecoder(file).Decode(genesis); err != nil {
    49  		utils.Fatalf("invalid genesis file : %v", err)
    50  	}
    51  	return genesis
    52  }
    53  
    54  func runCmd(ctx *cli.Context) error {
    55  	glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
    56  	glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name)))
    57  	log.Root().SetHandler(glogger)
    58  	logconfig := &vm.LogConfig{
    59  		DisableMemory: false,
    60  		DisableStack:  false,
    61  		Debug:         ctx.GlobalBool(DebugFlag.Name),
    62  	}
    63  
    64  	var (
    65  		tracer			vm.Tracer
    66  		debugLogger		*vm.StructLogger
    67  		statedb			*state.StateDB
    68  		chainConfig		*params.ChainConfig
    69  		sender			= common.BytesToAddress([]byte("sender"))
    70  		receiver		= common.BytesToAddress([]byte("receiver"))
    71  		genesisConfig	*core.Genesis
    72  	)
    73  	if ctx.GlobalBool(MachineFlag.Name) {
    74  		tracer = NewJSONLogger(logconfig, os.Stdout)
    75  	} else if ctx.GlobalBool(DebugFlag.Name) {
    76  		debugLogger = vm.NewStructLogger(logconfig)
    77  		tracer = debugLogger
    78  	} else {
    79  		debugLogger = vm.NewStructLogger(logconfig)
    80  	}
    81  	if ctx.GlobalString(GenesisFlag.Name) != "" {
    82  		gen := readGenesis(ctx.GlobalString(GenesisFlag.Name))
    83  		genesisConfig = gen
    84  		db := ethdb.NewMemDatabase()
    85  		genesis := gen.ToBlock(db)
    86  		statedb, _ = state.New(genesis.Root(), state.NewDatabase(db), genesis.Number(), genesis.Hash())
    87  		chainConfig = gen.Config
    88  	} else {
    89  		statedb, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()), big.NewInt(0), common.Hash{})
    90  		genesisConfig = new(core.Genesis)
    91  	}
    92  	if ctx.GlobalString(SenderFlag.Name) != "" {
    93  		sender = common.HexToAddress(ctx.GlobalString(SenderFlag.Name))
    94  	}
    95  	statedb.CreateAccount(sender)
    96  	if ctx.GlobalString(ReceiverFlag.Name) != "" {
    97  		receiver = common.HexToAddress(ctx.GlobalString(ReceiverFlag.Name))
    98  	}
    99  
   100  	var (
   101  		code 	[]byte
   102  		abi		[]byte
   103  		ret		[]byte
   104  		err 	error
   105  	)
   106  
   107  	// The '--code' or '--codefile' flag overrides code in state
   108  	if ctx.GlobalString(CodeFileFlag.Name) != "" {
   109  		var hexcode []byte
   110  		var err error
   111  		if ctx.GlobalString(CodeFileFlag.Name) == "-" {
   112  			// try reading from stdin
   113  			if hexcode, err = ioutil.ReadAll(os.Stdin); err != nil {
   114  				utils.Fatalf("Could not load code from stdin : %v", err)
   115  			}
   116  		} else {
   117  			// codefile with hex assembly
   118  			if hexcode, err = ioutil.ReadFile(ctx.GlobalString(CodeFileFlag.Name)); err != nil {
   119  				utils.Fatalf("Could not load code from file: %v", err)
   120  			}
   121  		}
   122  		// Eliminate line breaks
   123  		code = common.Hex2Bytes(string(bytes.TrimRight(hexcode,"\n")))
   124  	} else if ctx.GlobalString(CodeFlag.Name) != "" {
   125  		code = common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name))
   126  	}
   127  
   128  	// The '--abi' or '--abifile' flag overrides abi in state
   129  	if ctx.GlobalString(AbiFileFlag.Name) != "" {
   130  		var strabi []byte
   131  		var err error
   132  		if ctx.GlobalString(AbiFileFlag.Name) == "-" {
   133  			// try reading from stdin
   134  			if strabi, err = ioutil.ReadAll(os.Stdin); err != nil {
   135  				utils.Fatalf("Could not load abi from stdin : %v", err)
   136  			}
   137  		} else {
   138  			// codefile with hex assembly
   139  			if strabi, err = ioutil.ReadFile(ctx.GlobalString(AbiFileFlag.Name)); err != nil {
   140  				utils.Fatalf("Could not load abi from file: %v", err)
   141  			}
   142  		}
   143  		hexabi := common.Bytes2Hex(bytes.TrimRight(strabi,"\n"))
   144  		abi = common.Hex2Bytes(hexabi)
   145  	} else if ctx.GlobalString(AbiFlag.Name) != "" {
   146  		abi = []byte(ctx.GlobalString(AbiFlag.Name))
   147  	}
   148  
   149  	initialGas := ctx.GlobalUint64(GasFlag.Name)
   150  	if genesisConfig.GasLimit != 0 {
   151  		initialGas = genesisConfig.GasLimit
   152  	}
   153  	runtimeConfig := runtime.Config{
   154  		Origin:      sender,
   155  		State:       statedb,
   156  		GasLimit:    initialGas,
   157  		GasPrice:    utils.GlobalBig(ctx, GasPriceFlag.Name),
   158  		Value:       utils.GlobalBig(ctx, ValueFlag.Name),
   159  		Time:        new(big.Int).SetUint64(genesisConfig.Timestamp),
   160  		Coinbase:    genesisConfig.Coinbase,
   161  		BlockNumber: new(big.Int).SetUint64(genesisConfig.Number),
   162  		EVMConfig: vm.Config{
   163  			Tracer: tracer,
   164  			Debug:  ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name),
   165  		},
   166  	}
   167  
   168  	if chainConfig != nil {
   169  		runtimeConfig.ChainConfig = chainConfig
   170  	}
   171  
   172  	txType := ctx.GlobalInt64(TxTypeFlag.Name)
   173  
   174  	tstart := time.Now()
   175  	var leftOverGas uint64
   176  	if ctx.GlobalBool(CreateFlag.Name) {
   177  		// Contract creation logic,Input is an external input, possibly a parameter。Need to be encoded in wasm to complete
   178  		rlpData := make([][]byte,0)
   179  		rlpData = append(rlpData, covert.Int64ToBytes(txType), abi, code)
   180  
   181  		buffer := new(bytes.Buffer)
   182  		err := rlp.Encode(buffer, rlpData)
   183  		if err != nil {
   184  			utils.Fatalf("rlp parse fail: %v", err)
   185  		}
   186  		ret, _, leftOverGas, err = runtime.Create(buffer.Bytes(), &runtimeConfig)
   187  	} else {
   188  		if len(code) > 0 {
   189  			statedb.SetCode(receiver, code)
   190  		}
   191  		if len(abi) > 0 {
   192  			statedb.SetAbi(receiver, abi)
   193  		}
   194  		// input : rlp.encoded format.
   195  		input := common.Hex2Bytes(ctx.GlobalString(InputFlag.Name))
   196  		ret, leftOverGas, err = runtime.Call(receiver, input, &runtimeConfig)
   197  	}
   198  	execTime := time.Since(tstart)
   199  
   200  	statedb.IntermediateRoot(true)
   201  	fmt.Println(string(statedb.Dump()))
   202  
   203  	if ctx.GlobalBool(StatDumpFlag.Name) {
   204  		var mem goruntime.MemStats
   205  		goruntime.ReadMemStats(&mem)
   206  		fmt.Fprintf(os.Stderr, `evm execution time: %v
   207  heap objects:       %d
   208  allocations:        %d
   209  total allocations:  %d
   210  GC calls:           %d
   211  Gas used:           %d
   212  
   213  `, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas)
   214  	}
   215  
   216  	if tracer == nil {
   217  		fmt.Printf("0x%x\n", ret)
   218  		if err != nil {
   219  			fmt.Printf(" error: %v\n", err)
   220  		}
   221  	}
   222  
   223  	return nil
   224  }