forked from cerc-io/laconicd-deprecated
Finish and clean up module queries and txs (#152)
* Basic transactions set up (to be separated) * Change transaction command to not include create operation (to include other command in next commit) * set up create command and made minor changes * wip implements module queries * Added tests for query address decoding * Added ambiguous encoding of to address in transaction and added tests * Fix linting issue * Move registering key types to application level to allow module usage to ignore * Move genaccounts code to be reused * Switches nonce increase to always happen in ante handler * change SetNonce from keeper to point to actual nonce operation * Remove no op nonce switch (not needed with clearing cache) * Changes to update all accounts pre state transition and clear cache at end of block * Update accounts before end of block commit (edge case where necessary) * Fix nonce of sender going into evm in case it's checked, and let evm set contract starting nonce
This commit is contained in:
@@ -10,7 +10,6 @@ var ModuleCdc = codec.New()
|
||||
func init() {
|
||||
cdc := codec.New()
|
||||
|
||||
RegisterCodec(cdc)
|
||||
codec.RegisterCrypto(cdc)
|
||||
|
||||
ModuleCdc = cdc.Seal()
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ package types
|
||||
|
||||
const (
|
||||
// ModuleName string name of module
|
||||
ModuleName = "ethermint"
|
||||
ModuleName = "evm"
|
||||
|
||||
// EvmStoreKey key for ethereum storage data
|
||||
EvmStoreKey = "evmstore"
|
||||
|
||||
@@ -30,11 +30,8 @@ type StateTransition struct {
|
||||
|
||||
// TransitionCSDB performs an evm state transition from a transaction
|
||||
func (st StateTransition) TransitionCSDB(ctx sdk.Context) (*big.Int, sdk.Result) {
|
||||
contractCreation := st.Recipient == nil
|
||||
|
||||
if res := st.checkNonce(); !res.IsOK() {
|
||||
return nil, res
|
||||
}
|
||||
contractCreation := st.Recipient == nil
|
||||
|
||||
cost, err := core.IntrinsicGas(st.Payload, contractCreation, true)
|
||||
if err != nil {
|
||||
@@ -44,7 +41,7 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) (*big.Int, sdk.Result)
|
||||
// This gas limit the the transaction gas limit with intrinsic gas subtracted
|
||||
gasLimit := st.GasLimit - ctx.GasMeter().GasConsumed()
|
||||
|
||||
csdb := st.Csdb
|
||||
csdb := st.Csdb.WithContext(ctx)
|
||||
if st.Simulate {
|
||||
// gasLimit is set here because stdTxs incur gaskv charges in the ante handler, but for eth_call
|
||||
// the cost needs to be the same as an Ethereum transaction sent through the web3 API
|
||||
@@ -59,6 +56,9 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) (*big.Int, sdk.Result)
|
||||
csdb = st.Csdb.Copy()
|
||||
}
|
||||
|
||||
// Clear cache of accounts to handle changes outside of the EVM
|
||||
csdb.UpdateAccounts()
|
||||
|
||||
// Create context for evm
|
||||
context := vm.Context{
|
||||
CanTransfer: core.CanTransfer,
|
||||
@@ -88,14 +88,23 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) (*big.Int, sdk.Result)
|
||||
senderRef = vm.AccountRef(st.Sender)
|
||||
)
|
||||
|
||||
// Get nonce of account outside of the EVM
|
||||
currentNonce := st.Csdb.GetNonce(st.Sender)
|
||||
// Set nonce of sender account before evm state transition for usage in generating Create address
|
||||
st.Csdb.SetNonce(st.Sender, st.AccountNonce)
|
||||
|
||||
if contractCreation {
|
||||
ret, addr, leftOverGas, vmerr = vmenv.Create(senderRef, st.Payload, gasLimit, st.Amount)
|
||||
} else {
|
||||
// Increment the nonce for the next transaction
|
||||
// Increment the nonce for the next transaction (just for evm state transition)
|
||||
csdb.SetNonce(st.Sender, csdb.GetNonce(st.Sender)+1)
|
||||
|
||||
ret, leftOverGas, vmerr = vmenv.Call(senderRef, *st.Recipient, st.Payload, gasLimit, st.Amount)
|
||||
}
|
||||
|
||||
// Resets nonce to value pre state transition
|
||||
st.Csdb.SetNonce(st.Sender, currentNonce)
|
||||
|
||||
// Generate bloom filter to be saved in tx receipt data
|
||||
bloomInt := big.NewInt(0)
|
||||
var bloomFilter ethtypes.Bloom
|
||||
@@ -132,18 +141,3 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) (*big.Int, sdk.Result)
|
||||
|
||||
return bloomInt, sdk.Result{Data: returnData, GasUsed: st.GasLimit - leftOverGas}
|
||||
}
|
||||
|
||||
func (st *StateTransition) checkNonce() sdk.Result {
|
||||
// If simulated transaction, don't verify nonce
|
||||
if !st.Simulate {
|
||||
// Make sure this transaction's nonce is correct.
|
||||
nonce := st.Csdb.GetNonce(st.Sender)
|
||||
if nonce < st.AccountNonce {
|
||||
return emint.ErrInvalidNonce("nonce too high").Result()
|
||||
} else if nonce > st.AccountNonce {
|
||||
return emint.ErrInvalidNonce("nonce too low").Result()
|
||||
}
|
||||
}
|
||||
|
||||
return sdk.Result{}
|
||||
}
|
||||
|
||||
+24
-1
@@ -9,6 +9,8 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
|
||||
emint "github.com/cosmos/ethermint/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethstate "github.com/ethereum/go-ethereum/core/state"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
@@ -523,7 +525,7 @@ func (csdb *CommitStateDB) Suicide(addr ethcmn.Address) bool {
|
||||
// Reset clears out all ephemeral state objects from the state db, but keeps
|
||||
// the underlying account mapper and store keys to avoid reloading data for the
|
||||
// next operations.
|
||||
func (csdb *CommitStateDB) Reset(root ethcmn.Hash) error {
|
||||
func (csdb *CommitStateDB) Reset(_ ethcmn.Hash) error {
|
||||
csdb.stateObjects = make(map[ethcmn.Address]*stateObject)
|
||||
csdb.stateObjectsDirty = make(map[ethcmn.Address]struct{})
|
||||
csdb.thash = ethcmn.Hash{}
|
||||
@@ -537,6 +539,27 @@ func (csdb *CommitStateDB) Reset(root ethcmn.Hash) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateAccounts updates the nonce and coin balances of accounts
|
||||
func (csdb *CommitStateDB) UpdateAccounts() {
|
||||
for addr, so := range csdb.stateObjects {
|
||||
currAcc := csdb.ak.GetAccount(csdb.ctx, sdk.AccAddress(addr.Bytes()))
|
||||
emintAcc, ok := currAcc.(*emint.Account)
|
||||
if ok {
|
||||
if (so.Balance() != emintAcc.Balance().BigInt()) || (so.Nonce() != emintAcc.GetSequence()) {
|
||||
// If queried account's balance or nonce are invalid, update the account pointer
|
||||
so.account = emintAcc
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ClearStateObjects clears cache of state objects to handle account changes outside of the EVM
|
||||
func (csdb *CommitStateDB) ClearStateObjects() {
|
||||
csdb.stateObjects = make(map[ethcmn.Address]*stateObject)
|
||||
csdb.stateObjectsDirty = make(map[ethcmn.Address]struct{})
|
||||
}
|
||||
|
||||
func (csdb *CommitStateDB) clearJournalAndRefund() {
|
||||
csdb.journal = newJournal()
|
||||
csdb.validRevisions = csdb.validRevisions[:0]
|
||||
|
||||
Reference in New Issue
Block a user