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 }