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