github.com/zjj1991/quorum@v0.0.0-20190524123704-ae4b0a1e1a19/core/call_helper.go (about)

     1  package core
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"math/big"
     6  
     7  	"github.com/ethereum/go-ethereum/common"
     8  	"github.com/ethereum/go-ethereum/consensus/ethash"
     9  	"github.com/ethereum/go-ethereum/core/state"
    10  	"github.com/ethereum/go-ethereum/core/types"
    11  	"github.com/ethereum/go-ethereum/core/vm"
    12  	"github.com/ethereum/go-ethereum/crypto"
    13  	"github.com/ethereum/go-ethereum/ethdb"
    14  	"github.com/ethereum/go-ethereum/params"
    15  )
    16  
    17  // callHelper makes it easier to do proper calls and use the state transition object.
    18  // It also manages the nonces of the caller and keeps private and public state, which
    19  // can be freely modified outside of the helper.
    20  type callHelper struct {
    21  	db ethdb.Database
    22  
    23  	nonces map[common.Address]uint64
    24  	header types.Header
    25  	gp     *GasPool
    26  
    27  	PrivateState, PublicState *state.StateDB
    28  }
    29  
    30  // TxNonce returns the pending nonce
    31  func (cg *callHelper) TxNonce(addr common.Address) uint64 {
    32  	return cg.nonces[addr]
    33  }
    34  
    35  // MakeCall makes does a call to the recipient using the given input. It can switch between private and public
    36  // by setting the private boolean flag. It returns an error if the call failed.
    37  func (cg *callHelper) MakeCall(private bool, key *ecdsa.PrivateKey, to common.Address, input []byte) error {
    38  	var (
    39  		from = crypto.PubkeyToAddress(key.PublicKey)
    40  		err  error
    41  	)
    42  
    43  	// TODO(joel): these are just stubbed to the same values as in dual_state_test.go
    44  	cg.header.Number = new(big.Int)
    45  	cg.header.Time = new(big.Int).SetUint64(43)
    46  	cg.header.Difficulty = new(big.Int).SetUint64(1000488)
    47  	cg.header.GasLimit = 4700000
    48  
    49  	signer := types.MakeSigner(params.QuorumTestChainConfig, cg.header.Number)
    50  	tx, err := types.SignTx(types.NewTransaction(cg.TxNonce(from), to, new(big.Int), 1000000, new(big.Int), input), signer, key)
    51  	if err != nil {
    52  		return err
    53  	}
    54  	defer func() { cg.nonces[from]++ }()
    55  	msg, err := tx.AsMessage(signer)
    56  	if err != nil {
    57  		return err
    58  	}
    59  
    60  	publicState, privateState := cg.PublicState, cg.PrivateState
    61  	if !private {
    62  		privateState = publicState
    63  	} else {
    64  		tx.SetPrivate()
    65  	}
    66  
    67  	// TODO(joel): can we just pass nil instead of bc?
    68  	bc, _ := NewBlockChain(cg.db, nil, params.QuorumTestChainConfig, ethash.NewFaker(), vm.Config{}, nil)
    69  	context := NewEVMContext(msg, &cg.header, bc, &from)
    70  	vmenv := vm.NewEVM(context, publicState, privateState, params.QuorumTestChainConfig, vm.Config{})
    71  	_, _, _, err = ApplyMessage(vmenv, msg, cg.gp)
    72  	if err != nil {
    73  		return err
    74  	}
    75  	return nil
    76  }
    77  
    78  // MakeCallHelper returns a new callHelper
    79  func MakeCallHelper() *callHelper {
    80  	memdb := ethdb.NewMemDatabase()
    81  	db := state.NewDatabase(memdb)
    82  
    83  	publicState, err := state.New(common.Hash{}, db)
    84  	if err != nil {
    85  		panic(err)
    86  	}
    87  	privateState, err := state.New(common.Hash{}, db)
    88  	if err != nil {
    89  		panic(err)
    90  	}
    91  	cg := &callHelper{
    92  		db:           memdb,
    93  		nonces:       make(map[common.Address]uint64),
    94  		gp:           new(GasPool).AddGas(5000000),
    95  		PublicState:  publicState,
    96  		PrivateState: privateState,
    97  	}
    98  	return cg
    99  }