aboutsummaryrefslogblamecommitdiffstats
path: root/core/vm/runtime/runtime.go
blob: 5656f661a472301f96e5e78195a202feb1fe227e (plain) (tree)
1
                                         

















                                                                                  
              


                  





                                                      

 
                                                                            

                    
                                       




                                  
                          

                            
                        
                             
 
                                




                                            
                                   
                                                      
                                                      






                                                     

         





                                                        

                                             











                                                            
                                                                                                               







                                                                               
                                                                                      





                                                                               
                             
                                                                                                  
         
             
                                                                   
                                     
                                                   
         
                                        
                                                                          
                                        
                                                      
                                  
                       
                                                          

                             


                          


                                  
                                                       
                                                                                





                                 
                                                                                                  

             
                                    
                                                  


                                                      
                                                        




                             
                                              

 




                                                                               
                                                                                      

                        
                            


                                                           
                                            



                             


                          
                                    
 
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package runtime

import (
    "math"
    "math/big"
    "time"

    "github.com/dexon-foundation/dexon/common"
    "github.com/dexon-foundation/dexon/core/state"
    "github.com/dexon-foundation/dexon/core/vm"
    "github.com/dexon-foundation/dexon/crypto"
    "github.com/dexon-foundation/dexon/ethdb"
    "github.com/dexon-foundation/dexon/params"
)

// Config is a basic type specifying certain configuration flags for running
// the EVM.
type Config struct {
    ChainConfig *params.ChainConfig
    Difficulty  *big.Int
    Origin      common.Address
    Coinbase    common.Address
    BlockNumber *big.Int
    Time        *big.Int
    GasLimit    uint64
    GasPrice    *big.Int
    Value       *big.Int
    Debug       bool
    EVMConfig   vm.Config

    State     *state.StateDB
    GetHashFn func(n uint64) common.Hash
}

// sets defaults on the config
func setDefaults(cfg *Config) {
    if cfg.ChainConfig == nil {
        cfg.ChainConfig = &params.ChainConfig{
            ChainID:        big.NewInt(1),
            HomesteadBlock: new(big.Int),
            DAOForkBlock:   new(big.Int),
            DAOForkSupport: false,
            EIP150Block:    new(big.Int),
            EIP155Block:    new(big.Int),
            EIP158Block:    new(big.Int),
        }
    }

    if cfg.Difficulty == nil {
        cfg.Difficulty = new(big.Int)
    }
    if cfg.Time == nil {
        cfg.Time = big.NewInt(time.Now().Unix())
    }
    if cfg.GasLimit == 0 {
        cfg.GasLimit = math.MaxUint64
    }
    if cfg.GasPrice == nil {
        cfg.GasPrice = new(big.Int)
    }
    if cfg.Value == nil {
        cfg.Value = new(big.Int)
    }
    if cfg.BlockNumber == nil {
        cfg.BlockNumber = new(big.Int)
    }
    if cfg.GetHashFn == nil {
        cfg.GetHashFn = func(n uint64) common.Hash {
            return common.BytesToHash(crypto.Keccak256([]byte(new(big.Int).SetUint64(n).String())))
        }
    }
}

// Execute executes the code using the input as call data during the execution.
// It returns the EVM's return value, the new state and an error if it failed.
//
// Executes sets up a in memory, temporarily, environment for the execution of
// the given code. It makes sure that it's restored to it's original state afterwards.
func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
    if cfg == nil {
        cfg = new(Config)
    }
    setDefaults(cfg)

    if cfg.State == nil {
        cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
    }
    var (
        address = common.BytesToAddress([]byte("contract"))
        vmenv   = NewEnv(cfg)
        sender  = vm.AccountRef(cfg.Origin)
    )
    cfg.State.CreateAccount(address)
    // set the receiver's (the executing contract) code for execution.
    cfg.State.SetCode(address, code)
    // Call the code with the given configuration.
    ret, _, err := vmenv.Call(
        sender,
        common.BytesToAddress([]byte("contract")),
        input,
        cfg.GasLimit,
        cfg.Value,
    )

    return ret, cfg.State, err
}

// Create executes the code using the EVM create method
func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
    if cfg == nil {
        cfg = new(Config)
    }
    setDefaults(cfg)

    if cfg.State == nil {
        cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
    }
    var (
        vmenv  = NewEnv(cfg)
        sender = vm.AccountRef(cfg.Origin)
    )

    // Call the code with the given configuration.
    code, address, leftOverGas, err := vmenv.Create(
        sender,
        input,
        cfg.GasLimit,
        cfg.Value,
    )
    return code, address, leftOverGas, err
}

// Call executes the code given by the contract's address. It will return the
// EVM's return value or an error if it failed.
//
// Call, unlike Execute, requires a config and also requires the State field to
// be set.
func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, error) {
    setDefaults(cfg)

    vmenv := NewEnv(cfg)

    sender := cfg.State.GetOrNewStateObject(cfg.Origin)
    // Call the code with the given configuration.
    ret, leftOverGas, err := vmenv.Call(
        sender,
        address,
        input,
        cfg.GasLimit,
        cfg.Value,
    )

    return ret, leftOverGas, err
}