Skip to content

Commit

Permalink
Add v0.18.5
Browse files Browse the repository at this point in the history
  • Loading branch information
m-bo-one committed Aug 30, 2021
1 parent bd67c2b commit d9c6d35
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 57 deletions.
30 changes: 24 additions & 6 deletions action/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,27 @@ func AbciHeaderToTendermint(header *abci.Header) tmtypes.Header {
}
}

// GetHashFn implements vm.GetHashFunc for protocol.
func GetHashFn(s *CommitStateDB) ethvm.GetHashFunc {
return func(height uint64) ethcmn.Hash {
return s.GetHeightHash(height)
// GetHashFn implements vm.GetHashFunc for OneLedger protocol. It handles 3 cases:
// 1. The requested height matches the current height (and thus same epoch number, could take from cache)
// 2. The requested height is from an previous height from the same chain epoch
// 3. The requested height is from a height greater than the latest one
func GetHashFn(s *CommitStateDB, header *abci.Header) ethvm.GetHashFunc {
return func(height uint64) common.Hash {
switch {
case header.GetHeight() == int64(height):
// Case 1: The requested height matches the one from the CommitStateDB so we can retrieve the block
// hash directly from the CommitStateDB.
return s.bhash

case header.GetHeight() > int64(height):
// Case 2: if the chain is not the current height we need to retrieve the hash from the store for the
// current chain epoch. This only applies if the current height is greater than the requested height.
return s.GetHeightHash(height)

default:
// Case 3: heights greater than the current one returns an empty hash.
return common.Hash{}
}
}
}

Expand Down Expand Up @@ -132,7 +149,7 @@ func (etx *EVMTransaction) NewEVM() *ethvm.EVM {
blockCtx := ethvm.BlockContext{
CanTransfer: ethcore.CanTransfer,
Transfer: ethcore.Transfer,
GetHash: GetHashFn(etx.stateDB),
GetHash: GetHashFn(etx.stateDB, etx.header),
Coinbase: ethcmn.Address{}, // there's no beneficiary since we're not mining
GasLimit: etx.ecfg.gasLimit,
BlockNumber: big.NewInt(etx.header.GetHeight()),
Expand All @@ -141,6 +158,7 @@ func (etx *EVMTransaction) NewEVM() *ethvm.EVM {
}

vmConfig := ethvm.Config{
NoBaseFee: true,
ExtraEips: etx.ecfg.extraEIPs,
}

Expand Down Expand Up @@ -170,7 +188,7 @@ func (etx *EVMTransaction) To() *ethcmn.Address {
}

func (etx *EVMTransaction) Apply(vmenv *ethvm.EVM, tx RawTx) (*ExecutionResult, error) {
msg := ethtypes.NewMessage(etx.From(), etx.To(), etx.nonce, etx.value, uint64(tx.Fee.Gas), etx.ecfg.gasPrice, nil, nil, etx.data, make(ethtypes.AccessList, 0), true)
msg := ethtypes.NewMessage(etx.From(), etx.To(), etx.nonce, etx.value, uint64(tx.Fee.Gas), etx.ecfg.gasPrice, big.NewInt(0), big.NewInt(0), etx.data, make(ethtypes.AccessList, 0), true)

txHash := etx.stateDB.GetCurrentTxHash()

Expand Down
4 changes: 2 additions & 2 deletions action/nexus/nexus.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,14 @@ func runNexus(ctx *action.Context, tx action.RawTx) (bool, action.Response) {
vmenv := evmTx.NewEVM()
execResult, err := evmTx.Apply(vmenv, tx)
if err != nil {
// must revert the snapshot in case of error
ctx.StateDB.RevertToSnapshot(snap)
ctx.Logger.Debugf("Execution apply VM got err: %s\n", err.Error())
tags = append(tags, action.UintTag("tx.status", ethtypes.ReceiptStatusFailed))
tags = append(tags, kv.Pair{
Key: []byte("tx.error"),
Value: []byte(err.Error()),
})
// must revert the snapshot in case of error
ctx.StateDB.RevertToSnapshot(snap)
return helpers.LogAndReturnFalse(ctx.Logger, status_codes.ProtocolError{
Msg: err.Error(),
Code: status_codes.TxErrVMExecution,
Expand Down
74 changes: 58 additions & 16 deletions action/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ import (
"math/big"

"github.com/Oneledger/protocol/data/keys"
"github.com/Oneledger/protocol/storage"
ethcmn "github.com/ethereum/go-ethereum/common"
ethcore "github.com/ethereum/go-ethereum/core"
ethtypes "github.com/ethereum/go-ethereum/core/types"
ethvm "github.com/ethereum/go-ethereum/core/vm"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
ethparams "github.com/ethereum/go-ethereum/params"
)

var emptyHash = ethcrypto.Keccak256Hash(nil)

/*
The State Transitioning Model
A state transition is a change made when a transaction is applied to the current world state
The state transitioning model does all the necessary work to work out a valid new state root.
1) Nonce handling
2) Pre pay gas
3) Create a new state object if the recipient is \0*32
Expand All @@ -36,12 +36,13 @@ type StateTransition struct {
msg Message
gas uint64
gasPrice *big.Int
gasFeeCap *big.Int
gasTipCap *big.Int
initialGas uint64
value *big.Int
data []byte
state ethvm.StateDB
evm *ethvm.EVM
gs *storage.State
}

// Message represents a message sent to a contract.
Expand All @@ -50,11 +51,13 @@ type Message interface {
To() *ethcmn.Address

GasPrice() *big.Int
GasFeeCap() *big.Int
GasTipCap() *big.Int
Gas() uint64
Value() *big.Int

Nonce() uint64
CheckNonce() bool
IsFake() bool
Data() []byte
AccessList() ethtypes.AccessList
}
Expand Down Expand Up @@ -139,13 +142,15 @@ func IntrinsicGas(data []byte, accessList ethtypes.AccessList, isContractCreatio
// NewStateTransition initialises and returns a new state transition object.
func NewStateTransition(evm *ethvm.EVM, msg Message, gp *ethcore.GasPool) *StateTransition {
return &StateTransition{
gp: gp,
evm: evm,
msg: msg,
gasPrice: msg.GasPrice(),
value: msg.Value(),
data: msg.Data(),
state: evm.StateDB,
gp: gp,
evm: evm,
msg: msg,
gasPrice: msg.GasPrice(),
gasFeeCap: msg.GasFeeCap(),
gasTipCap: msg.GasTipCap(),
value: msg.Value(),
data: msg.Data(),
state: evm.StateDB,
}
}

Expand All @@ -169,8 +174,15 @@ func (st *StateTransition) to() ethcmn.Address {
}

func (st *StateTransition) buyGas() error {
mgval := new(big.Int).Mul(new(big.Int).SetUint64(st.msg.Gas()), st.gasPrice)
if have, want := st.state.GetBalance(st.msg.From()), mgval; have.Cmp(want) < 0 {
mgval := new(big.Int).SetUint64(st.msg.Gas())
mgval = mgval.Mul(mgval, st.gasPrice)
balanceCheck := mgval
if st.gasFeeCap != nil {
balanceCheck = new(big.Int).SetUint64(st.msg.Gas())
balanceCheck = balanceCheck.Mul(balanceCheck, st.gasFeeCap)
balanceCheck.Add(balanceCheck, st.value)
}
if have, want := st.state.GetBalance(st.msg.From()), balanceCheck; have.Cmp(want) < 0 {
return fmt.Errorf("%w: address %v have %v want %v", ethcore.ErrInsufficientFunds, st.msg.From().Hex(), have, want)
}
if err := st.gp.SubGas(st.msg.Gas()); err != nil {
Expand All @@ -184,8 +196,9 @@ func (st *StateTransition) buyGas() error {
}

func (st *StateTransition) preCheck() error {
// Make sure this transaction's nonce is correct.
if st.msg.CheckNonce() {
// Only check transactions that are not fake
if !st.msg.IsFake() {
// Make sure this transaction's nonce is correct.
stNonce := st.state.GetNonce(st.msg.From())
if msgNonce := st.msg.Nonce(); stNonce < msgNonce {
return fmt.Errorf("%w: address %v, tx: %d state: %d", ethcore.ErrNonceTooHigh,
Expand All @@ -194,6 +207,35 @@ func (st *StateTransition) preCheck() error {
return fmt.Errorf("%w: address %v, tx: %d state: %d", ethcore.ErrNonceTooLow,
st.msg.From().Hex(), msgNonce, stNonce)
}
// Make sure the sender is an EOA
if codeHash := st.state.GetCodeHash(st.msg.From()); codeHash != emptyHash && codeHash != (ethcmn.Hash{}) {
return fmt.Errorf("%w: address %v, codehash: %s", ethcore.ErrSenderNoEOA,
st.msg.From().Hex(), codeHash)
}
}
// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call)
if !st.evm.Config.NoBaseFee || st.gasFeeCap.BitLen() > 0 || st.gasTipCap.BitLen() > 0 {
if l := st.gasFeeCap.BitLen(); l > 256 {
return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ethcore.ErrFeeCapVeryHigh,
st.msg.From().Hex(), l)
}
if l := st.gasTipCap.BitLen(); l > 256 {
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas bit length: %d", ethcore.ErrTipVeryHigh,
st.msg.From().Hex(), l)
}
if st.gasFeeCap.Cmp(st.gasTipCap) < 0 {
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s", ethcore.ErrTipAboveFeeCap,
st.msg.From().Hex(), st.gasTipCap, st.gasFeeCap)
}
// This will panic if baseFee is nil, but basefee presence is verified
// as part of header validation.
if st.gasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 {
return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ethcore.ErrFeeCapTooLow,
st.msg.From().Hex(), st.gasFeeCap, st.evm.Context.BaseFee)
}
}
}
return st.buyGas()
}
Expand Down
5 changes: 2 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@ require (
github.com/cespare/cp v1.1.1 // indirect
github.com/davecgh/go-spew v1.1.1
github.com/deckarep/golang-set v1.7.1 // indirect
github.com/ethereum/go-ethereum v1.10.7
github.com/ethereum/go-ethereum v1.10.8
github.com/go-kit/kit v0.10.0
github.com/google/go-cmp v0.5.4
github.com/google/uuid v1.1.5
github.com/kr/text v0.2.0 // indirect
github.com/magiconair/properties v1.8.1
github.com/mattn/go-colorable v0.1.7 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pkg/errors v0.9.1
github.com/powerman/rpc-codec v1.1.2
Expand All @@ -32,7 +31,7 @@ require (
github.com/tyler-smith/go-bip39 v1.0.2 // indirect
github.com/vmihailenco/msgpack v4.0.4+incompatible
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
)

Expand Down
Loading

0 comments on commit d9c6d35

Please sign in to comment.