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 }