package core import ( "crypto/ecdsa" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" ) // callHelper makes it easier to do proper calls and use the state transition object. // It also manages the nonces of the caller and keeps private and public state, which // can be freely modified outside of the helper. type callHelper struct { db ethdb.Database nonces map[common.Address]uint64 header types.Header gp *GasPool PrivateState, PublicState *state.StateDB } // TxNonce returns the pending nonce func (cg *callHelper) TxNonce(addr common.Address) uint64 { return cg.nonces[addr] } // MakeCall makes does a call to the recipient using the given input. It can switch between private and public // by setting the private boolean flag. It returns an error if the call failed. func (cg *callHelper) MakeCall(private bool, key *ecdsa.PrivateKey, to common.Address, input []byte) error { var ( from = crypto.PubkeyToAddress(key.PublicKey) err error ) tx, err := types.NewTransaction(cg.TxNonce(from), to, new(big.Int), big.NewInt(1000000), new(big.Int), input).SignECDSA(key) if err != nil { return err } defer func() { cg.nonces[from]++ }() publicState, privateState := cg.PublicState, cg.PrivateState if !private { privateState = publicState } else { tx.SetPrivate() } cg.header.Number = new(big.Int) _, _, err = ApplyMessage(NewEnv(publicState, privateState, &ChainConfig{}, nil, tx, &cg.header, vm.Config{}), tx, cg.gp) if err != nil { return err } return nil } // MakeCallHelper returns a new callHelper func MakeCallHelper() *callHelper { db, _ := ethdb.NewMemDatabase() publicState, err := state.New(common.Hash{}, db) if err != nil { panic(err) } privateState, err := state.New(common.Hash{}, db) if err != nil { panic(err) } cg := &callHelper{ nonces: make(map[common.Address]uint64), gp: new(GasPool).AddGas(big.NewInt(5000000)), PublicState: publicState, PrivateState: privateState, } return cg }