github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/core/call_helper.go (about) 1 package core 2 3 import ( 4 "crypto/ecdsa" 5 "math/big" 6 7 "github.com/kisexp/xdchain/common" 8 "github.com/kisexp/xdchain/consensus/ethash" 9 "github.com/kisexp/xdchain/core/rawdb" 10 "github.com/kisexp/xdchain/core/state" 11 "github.com/kisexp/xdchain/core/types" 12 "github.com/kisexp/xdchain/core/vm" 13 "github.com/kisexp/xdchain/crypto" 14 "github.com/kisexp/xdchain/ethdb" 15 "github.com/kisexp/xdchain/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, nil, nil) 72 txContext := NewEVMTxContext(msg) 73 evmContext := NewEVMBlockContext(&cg.header, bc, &from) 74 vmenv := vm.NewEVM(evmContext, txContext, publicState, privateState, params.QuorumTestChainConfig, vm.Config{}) 75 sender := vm.AccountRef(msg.From()) 76 vmenv.Call(sender, to, msg.Data(), 100000000, new(big.Int)) 77 return err 78 } 79 80 // MakeCallHelper returns a new callHelper 81 func MakeCallHelper() *callHelper { 82 memdb := rawdb.NewMemoryDatabase() 83 db := state.NewDatabase(memdb) 84 85 publicState, err := state.New(common.Hash{}, db, nil) 86 if err != nil { 87 panic(err) 88 } 89 privateState, err := state.New(common.Hash{}, db, nil) 90 if err != nil { 91 panic(err) 92 } 93 cg := &callHelper{ 94 db: memdb, 95 nonces: make(map[common.Address]uint64), 96 gp: new(GasPool).AddGas(5000000), 97 PublicState: publicState, 98 PrivateState: privateState, 99 } 100 return cg 101 }