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  }