github.com/bencicandrej/quorum@v2.2.6-0.20190909091323-878cab86f711+incompatible/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  	if private {
    51  		signer = types.QuorumPrivateTxSigner{}
    52  	}
    53  
    54  	tx, err := types.SignTx(types.NewTransaction(cg.TxNonce(from), to, new(big.Int), 1000000, new(big.Int), input), signer, key)
    55  
    56  	if err != nil {
    57  		return err
    58  	}
    59  	defer func() { cg.nonces[from]++ }()
    60  	msg, err := tx.AsMessage(signer)
    61  	if err != nil {
    62  		return err
    63  	}
    64  
    65  	publicState, privateState := cg.PublicState, cg.PrivateState
    66  	if !private {
    67  		privateState = publicState
    68  	}
    69  	// TODO(joel): can we just pass nil instead of bc?
    70  	bc, _ := NewBlockChain(cg.db, nil, params.QuorumTestChainConfig, ethash.NewFaker(), vm.Config{}, nil)
    71  	context := NewEVMContext(msg, &cg.header, bc, &from)
    72  	vmenv := vm.NewEVM(context, publicState, privateState, params.QuorumTestChainConfig, vm.Config{})
    73  	sender := vm.AccountRef(msg.From())
    74  	vmenv.Call(sender, to, msg.Data(), 100000000, new(big.Int))
    75  	if err != nil {
    76  		return err
    77  	}
    78  	return nil
    79  }
    80  
    81  // MakeCallHelper returns a new callHelper
    82  func MakeCallHelper() *callHelper {
    83  	memdb := ethdb.NewMemDatabase()
    84  	db := state.NewDatabase(memdb)
    85  
    86  	publicState, err := state.New(common.Hash{}, db)
    87  	if err != nil {
    88  		panic(err)
    89  	}
    90  	privateState, err := state.New(common.Hash{}, db)
    91  	if err != nil {
    92  		panic(err)
    93  	}
    94  	cg := &callHelper{
    95  		db:           memdb,
    96  		nonces:       make(map[common.Address]uint64),
    97  		gp:           new(GasPool).AddGas(5000000),
    98  		PublicState:  publicState,
    99  		PrivateState: privateState,
   100  	}
   101  	return cg
   102  }