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