Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
d6da4342
Commit
d6da4342
authored
3 years ago
by
George Hotz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
further
parent
ffaa1784
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
656 additions
and
2 deletions
+656
-2
error.go
minigeth/core/error.go
+93
-0
evm.go
minigeth/core/evm.go
+119
-0
gaspool.go
minigeth/core/gaspool.go
+54
-0
state_processor.go
minigeth/core/state_processor.go
+4
-2
state_transition.go
minigeth/core/state_transition.go
+365
-0
interpreter.go
minigeth/core/vm/interpreter.go
+21
-0
No files found.
minigeth/core/error.go
0 → 100644
View file @
d6da4342
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
core
import
(
"errors"
"github.com/ethereum/go-ethereum/core/types"
)
var
(
// ErrKnownBlock is returned when a block to import is already known locally.
ErrKnownBlock
=
errors
.
New
(
"block already known"
)
// ErrBannedHash is returned if a block to import is on the banned list.
ErrBannedHash
=
errors
.
New
(
"banned hash"
)
// ErrNoGenesis is returned when there is no Genesis Block.
ErrNoGenesis
=
errors
.
New
(
"genesis not found in chain"
)
)
// List of evm-call-message pre-checking errors. All state transition messages will
// be pre-checked before execution. If any invalidation detected, the corresponding
// error should be returned which is defined here.
//
// - If the pre-checking happens in the miner, then the transaction won't be packed.
// - If the pre-checking happens in the block processing procedure, then a "BAD BLOCk"
// error should be emitted.
var
(
// ErrNonceTooLow is returned if the nonce of a transaction is lower than the
// one present in the local chain.
ErrNonceTooLow
=
errors
.
New
(
"nonce too low"
)
// ErrNonceTooHigh is returned if the nonce of a transaction is higher than the
// next one expected based on the local chain.
ErrNonceTooHigh
=
errors
.
New
(
"nonce too high"
)
// ErrGasLimitReached is returned by the gas pool if the amount of gas required
// by a transaction is higher than what's left in the block.
ErrGasLimitReached
=
errors
.
New
(
"gas limit reached"
)
// ErrInsufficientFundsForTransfer is returned if the transaction sender doesn't
// have enough funds for transfer(topmost call only).
ErrInsufficientFundsForTransfer
=
errors
.
New
(
"insufficient funds for transfer"
)
// ErrInsufficientFunds is returned if the total cost of executing a transaction
// is higher than the balance of the user's account.
ErrInsufficientFunds
=
errors
.
New
(
"insufficient funds for gas * price + value"
)
// ErrGasUintOverflow is returned when calculating gas usage.
ErrGasUintOverflow
=
errors
.
New
(
"gas uint64 overflow"
)
// ErrIntrinsicGas is returned if the transaction is specified to use less gas
// than required to start the invocation.
ErrIntrinsicGas
=
errors
.
New
(
"intrinsic gas too low"
)
// ErrTxTypeNotSupported is returned if a transaction is not supported in the
// current network configuration.
ErrTxTypeNotSupported
=
types
.
ErrTxTypeNotSupported
// ErrTipAboveFeeCap is a sanity error to ensure no one is able to specify a
// transaction with a tip higher than the total fee cap.
ErrTipAboveFeeCap
=
errors
.
New
(
"max priority fee per gas higher than max fee per gas"
)
// ErrTipVeryHigh is a sanity error to avoid extremely big numbers specified
// in the tip field.
ErrTipVeryHigh
=
errors
.
New
(
"max priority fee per gas higher than 2^256-1"
)
// ErrFeeCapVeryHigh is a sanity error to avoid extremely big numbers specified
// in the fee cap field.
ErrFeeCapVeryHigh
=
errors
.
New
(
"max fee per gas higher than 2^256-1"
)
// ErrFeeCapTooLow is returned if the transaction fee cap is less than the
// the base fee of the block.
ErrFeeCapTooLow
=
errors
.
New
(
"max fee per gas less than block base fee"
)
// ErrSenderNoEOA is returned if the sender of a transaction is a contract.
ErrSenderNoEOA
=
errors
.
New
(
"sender not an eoa"
)
)
This diff is collapsed.
Click to expand it.
minigeth/core/evm.go
0 → 100644
View file @
d6da4342
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
core
import
(
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
)
// ChainContext supports retrieving headers and consensus parameters from the
// current blockchain to be used during transaction processing.
type
ChainContext
interface
{
// Engine retrieves the chain's consensus engine.
Engine
()
consensus
.
Engine
// GetHeader returns the hash corresponding to their hash.
GetHeader
(
common
.
Hash
,
uint64
)
*
types
.
Header
}
// NewEVMBlockContext creates a new context for use in the EVM.
func
NewEVMBlockContext
(
header
*
types
.
Header
,
chain
ChainContext
,
author
*
common
.
Address
)
vm
.
BlockContext
{
var
(
beneficiary
common
.
Address
baseFee
*
big
.
Int
)
// If we don't have an explicit author (i.e. not mining), extract from the header
if
author
==
nil
{
beneficiary
,
_
=
chain
.
Engine
()
.
Author
(
header
)
// Ignore error, we're past header validation
}
else
{
beneficiary
=
*
author
}
if
header
.
BaseFee
!=
nil
{
baseFee
=
new
(
big
.
Int
)
.
Set
(
header
.
BaseFee
)
}
return
vm
.
BlockContext
{
CanTransfer
:
CanTransfer
,
Transfer
:
Transfer
,
GetHash
:
GetHashFn
(
header
,
chain
),
Coinbase
:
beneficiary
,
BlockNumber
:
new
(
big
.
Int
)
.
Set
(
header
.
Number
),
Time
:
new
(
big
.
Int
)
.
SetUint64
(
header
.
Time
),
Difficulty
:
new
(
big
.
Int
)
.
Set
(
header
.
Difficulty
),
BaseFee
:
baseFee
,
GasLimit
:
header
.
GasLimit
,
}
}
// NewEVMTxContext creates a new transaction context for a single transaction.
func
NewEVMTxContext
(
msg
Message
)
vm
.
TxContext
{
return
vm
.
TxContext
{
Origin
:
msg
.
From
(),
GasPrice
:
new
(
big
.
Int
)
.
Set
(
msg
.
GasPrice
()),
}
}
// GetHashFn returns a GetHashFunc which retrieves header hashes by number
func
GetHashFn
(
ref
*
types
.
Header
,
chain
ChainContext
)
func
(
n
uint64
)
common
.
Hash
{
// Cache will initially contain [refHash.parent],
// Then fill up with [refHash.p, refHash.pp, refHash.ppp, ...]
var
cache
[]
common
.
Hash
return
func
(
n
uint64
)
common
.
Hash
{
// If there's no hash cache yet, make one
if
len
(
cache
)
==
0
{
cache
=
append
(
cache
,
ref
.
ParentHash
)
}
if
idx
:=
ref
.
Number
.
Uint64
()
-
n
-
1
;
idx
<
uint64
(
len
(
cache
))
{
return
cache
[
idx
]
}
// No luck in the cache, but we can start iterating from the last element we already know
lastKnownHash
:=
cache
[
len
(
cache
)
-
1
]
lastKnownNumber
:=
ref
.
Number
.
Uint64
()
-
uint64
(
len
(
cache
))
for
{
header
:=
chain
.
GetHeader
(
lastKnownHash
,
lastKnownNumber
)
if
header
==
nil
{
break
}
cache
=
append
(
cache
,
header
.
ParentHash
)
lastKnownHash
=
header
.
ParentHash
lastKnownNumber
=
header
.
Number
.
Uint64
()
-
1
if
n
==
lastKnownNumber
{
return
lastKnownHash
}
}
return
common
.
Hash
{}
}
}
// CanTransfer checks whether there are enough funds in the address' account to make a transfer.
// This does not take the necessary gas in to account to make the transfer valid.
func
CanTransfer
(
db
vm
.
StateDB
,
addr
common
.
Address
,
amount
*
big
.
Int
)
bool
{
return
db
.
GetBalance
(
addr
)
.
Cmp
(
amount
)
>=
0
}
// Transfer subtracts amount from sender and adds amount to recipient using the given Db
func
Transfer
(
db
vm
.
StateDB
,
sender
,
recipient
common
.
Address
,
amount
*
big
.
Int
)
{
db
.
SubBalance
(
sender
,
amount
)
db
.
AddBalance
(
recipient
,
amount
)
}
This diff is collapsed.
Click to expand it.
minigeth/core/gaspool.go
0 → 100644
View file @
d6da4342
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
core
import
(
"fmt"
"math"
)
// GasPool tracks the amount of gas available during execution of the transactions
// in a block. The zero value is a pool with zero gas available.
type
GasPool
uint64
// AddGas makes gas available for execution.
func
(
gp
*
GasPool
)
AddGas
(
amount
uint64
)
*
GasPool
{
if
uint64
(
*
gp
)
>
math
.
MaxUint64
-
amount
{
panic
(
"gas pool pushed above uint64"
)
}
*
(
*
uint64
)(
gp
)
+=
amount
return
gp
}
// SubGas deducts the given amount from the pool if enough gas is
// available and returns an error otherwise.
func
(
gp
*
GasPool
)
SubGas
(
amount
uint64
)
error
{
if
uint64
(
*
gp
)
<
amount
{
return
ErrGasLimitReached
}
*
(
*
uint64
)(
gp
)
-=
amount
return
nil
}
// Gas returns the amount of gas remaining in the pool.
func
(
gp
*
GasPool
)
Gas
()
uint64
{
return
uint64
(
*
gp
)
}
func
(
gp
*
GasPool
)
String
()
string
{
return
fmt
.
Sprintf
(
"%d"
,
*
gp
)
}
This diff is collapsed.
Click to expand it.
minigeth/core/state_processor.go
View file @
d6da4342
...
@@ -18,11 +18,14 @@ package core
...
@@ -18,11 +18,14 @@ package core
import
(
import
(
"fmt"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params"
/*"fmt"
/*"fmt"
"math/big"
"math/big"
...
@@ -96,7 +99,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
...
@@ -96,7 +99,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
return
receipts
,
allLogs
,
*
usedGas
,
nil
return
receipts
,
allLogs
,
*
usedGas
,
nil
}
}
/*
func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) {
func
applyTransaction
(
msg
types
.
Message
,
config
*
params
.
ChainConfig
,
bc
ChainContext
,
author
*
common
.
Address
,
gp
*
GasPool
,
statedb
*
state
.
StateDB
,
blockNumber
*
big
.
Int
,
blockHash
common
.
Hash
,
tx
*
types
.
Transaction
,
usedGas
*
uint64
,
evm
*
vm
.
EVM
)
(
*
types
.
Receipt
,
error
)
{
// Create a new context to be used in the EVM environment.
// Create a new context to be used in the EVM environment.
txContext
:=
NewEVMTxContext
(
msg
)
txContext
:=
NewEVMTxContext
(
msg
)
evm
.
Reset
(
txContext
,
statedb
)
evm
.
Reset
(
txContext
,
statedb
)
...
@@ -155,4 +158,3 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
...
@@ -155,4 +158,3 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
vmenv
:=
vm
.
NewEVM
(
blockContext
,
vm
.
TxContext
{},
statedb
,
config
,
cfg
)
vmenv
:=
vm
.
NewEVM
(
blockContext
,
vm
.
TxContext
{},
statedb
,
config
,
cfg
)
return
applyTransaction
(
msg
,
config
,
bc
,
author
,
gp
,
statedb
,
header
.
Number
,
header
.
Hash
(),
tx
,
usedGas
,
vmenv
)
return
applyTransaction
(
msg
,
config
,
bc
,
author
,
gp
,
statedb
,
header
.
Number
,
header
.
Hash
(),
tx
,
usedGas
,
vmenv
)
}
}
*/
This diff is collapsed.
Click to expand it.
minigeth/core/state_transition.go
0 → 100644
View file @
d6da4342
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
core
import
(
"fmt"
"math"
"math/big"
"github.com/ethereum/go-ethereum/common"
cmath
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)
var
emptyCodeHash
=
crypto
.
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
4) Value transfer
== If contract creation ==
4a) Attempt to run transaction data
4b) If valid, use result as code for the new state object
== end ==
5) Run Script section
6) Derive new state root
*/
type
StateTransition
struct
{
gp
*
GasPool
msg
Message
gas
uint64
gasPrice
*
big
.
Int
gasFeeCap
*
big
.
Int
gasTipCap
*
big
.
Int
initialGas
uint64
value
*
big
.
Int
data
[]
byte
state
vm
.
StateDB
evm
*
vm
.
EVM
}
// Message represents a message sent to a contract.
type
Message
interface
{
From
()
common
.
Address
To
()
*
common
.
Address
GasPrice
()
*
big
.
Int
GasFeeCap
()
*
big
.
Int
GasTipCap
()
*
big
.
Int
Gas
()
uint64
Value
()
*
big
.
Int
Nonce
()
uint64
IsFake
()
bool
Data
()
[]
byte
AccessList
()
types
.
AccessList
}
// ExecutionResult includes all output after executing given evm
// message no matter the execution itself is successful or not.
type
ExecutionResult
struct
{
UsedGas
uint64
// Total used gas but include the refunded gas
Err
error
// Any error encountered during the execution(listed in core/vm/errors.go)
ReturnData
[]
byte
// Returned data from evm(function result or data supplied with revert opcode)
}
// Unwrap returns the internal evm error which allows us for further
// analysis outside.
func
(
result
*
ExecutionResult
)
Unwrap
()
error
{
return
result
.
Err
}
// Failed returns the indicator whether the execution is successful or not
func
(
result
*
ExecutionResult
)
Failed
()
bool
{
return
result
.
Err
!=
nil
}
// Return is a helper function to help caller distinguish between revert reason
// and function return. Return returns the data after execution if no error occurs.
func
(
result
*
ExecutionResult
)
Return
()
[]
byte
{
if
result
.
Err
!=
nil
{
return
nil
}
return
common
.
CopyBytes
(
result
.
ReturnData
)
}
// Revert returns the concrete revert reason if the execution is aborted by `REVERT`
// opcode. Note the reason can be nil if no data supplied with revert opcode.
func
(
result
*
ExecutionResult
)
Revert
()
[]
byte
{
if
result
.
Err
!=
vm
.
ErrExecutionReverted
{
return
nil
}
return
common
.
CopyBytes
(
result
.
ReturnData
)
}
// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
func
IntrinsicGas
(
data
[]
byte
,
accessList
types
.
AccessList
,
isContractCreation
bool
,
isHomestead
,
isEIP2028
bool
)
(
uint64
,
error
)
{
// Set the starting gas for the raw transaction
var
gas
uint64
if
isContractCreation
&&
isHomestead
{
gas
=
params
.
TxGasContractCreation
}
else
{
gas
=
params
.
TxGas
}
// Bump the required gas by the amount of transactional data
if
len
(
data
)
>
0
{
// Zero and non-zero bytes are priced differently
var
nz
uint64
for
_
,
byt
:=
range
data
{
if
byt
!=
0
{
nz
++
}
}
// Make sure we don't exceed uint64 for all data combinations
nonZeroGas
:=
params
.
TxDataNonZeroGasFrontier
if
isEIP2028
{
nonZeroGas
=
params
.
TxDataNonZeroGasEIP2028
}
if
(
math
.
MaxUint64
-
gas
)
/
nonZeroGas
<
nz
{
return
0
,
ErrGasUintOverflow
}
gas
+=
nz
*
nonZeroGas
z
:=
uint64
(
len
(
data
))
-
nz
if
(
math
.
MaxUint64
-
gas
)
/
params
.
TxDataZeroGas
<
z
{
return
0
,
ErrGasUintOverflow
}
gas
+=
z
*
params
.
TxDataZeroGas
}
if
accessList
!=
nil
{
gas
+=
uint64
(
len
(
accessList
))
*
params
.
TxAccessListAddressGas
gas
+=
uint64
(
accessList
.
StorageKeys
())
*
params
.
TxAccessListStorageKeyGas
}
return
gas
,
nil
}
// NewStateTransition initialises and returns a new state transition object.
func
NewStateTransition
(
evm
*
vm
.
EVM
,
msg
Message
,
gp
*
GasPool
)
*
StateTransition
{
return
&
StateTransition
{
gp
:
gp
,
evm
:
evm
,
msg
:
msg
,
gasPrice
:
msg
.
GasPrice
(),
gasFeeCap
:
msg
.
GasFeeCap
(),
gasTipCap
:
msg
.
GasTipCap
(),
value
:
msg
.
Value
(),
data
:
msg
.
Data
(),
state
:
evm
.
StateDB
,
}
}
// ApplyMessage computes the new state by applying the given message
// against the old state within the environment.
//
// ApplyMessage returns the bytes returned by any EVM execution (if it took place),
// the gas used (which includes gas refunds) and an error if it failed. An error always
// indicates a core error meaning that the message would always fail for that particular
// state and would never be accepted within a block.
func
ApplyMessage
(
evm
*
vm
.
EVM
,
msg
Message
,
gp
*
GasPool
)
(
*
ExecutionResult
,
error
)
{
return
NewStateTransition
(
evm
,
msg
,
gp
)
.
TransitionDb
()
}
// to returns the recipient of the message.
func
(
st
*
StateTransition
)
to
()
common
.
Address
{
if
st
.
msg
==
nil
||
st
.
msg
.
To
()
==
nil
/* contract creation */
{
return
common
.
Address
{}
}
return
*
st
.
msg
.
To
()
}
func
(
st
*
StateTransition
)
buyGas
()
error
{
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"
,
ErrInsufficientFunds
,
st
.
msg
.
From
()
.
Hex
(),
have
,
want
)
}
if
err
:=
st
.
gp
.
SubGas
(
st
.
msg
.
Gas
());
err
!=
nil
{
return
err
}
st
.
gas
+=
st
.
msg
.
Gas
()
st
.
initialGas
=
st
.
msg
.
Gas
()
st
.
state
.
SubBalance
(
st
.
msg
.
From
(),
mgval
)
return
nil
}
func
(
st
*
StateTransition
)
preCheck
()
error
{
// 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"
,
ErrNonceTooHigh
,
st
.
msg
.
From
()
.
Hex
(),
msgNonce
,
stNonce
)
}
else
if
stNonce
>
msgNonce
{
return
fmt
.
Errorf
(
"%w: address %v, tx: %d state: %d"
,
ErrNonceTooLow
,
st
.
msg
.
From
()
.
Hex
(),
msgNonce
,
stNonce
)
}
// Make sure the sender is an EOA
if
codeHash
:=
st
.
state
.
GetCodeHash
(
st
.
msg
.
From
());
codeHash
!=
emptyCodeHash
&&
codeHash
!=
(
common
.
Hash
{})
{
return
fmt
.
Errorf
(
"%w: address %v, codehash: %s"
,
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"
,
ErrFeeCapVeryHigh
,
st
.
msg
.
From
()
.
Hex
(),
l
)
}
if
l
:=
st
.
gasTipCap
.
BitLen
();
l
>
256
{
return
fmt
.
Errorf
(
"%w: address %v, maxPriorityFeePerGas bit length: %d"
,
ErrTipVeryHigh
,
st
.
msg
.
From
()
.
Hex
(),
l
)
}
if
st
.
gasFeeCap
.
Cmp
(
st
.
gasTipCap
)
<
0
{
return
fmt
.
Errorf
(
"%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s"
,
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"
,
ErrFeeCapTooLow
,
st
.
msg
.
From
()
.
Hex
(),
st
.
gasFeeCap
,
st
.
evm
.
Context
.
BaseFee
)
}
}
}
return
st
.
buyGas
()
}
// TransitionDb will transition the state by applying the current message and
// returning the evm execution result with following fields.
//
// - used gas:
// total gas used (including gas being refunded)
// - returndata:
// the returned data from evm
// - concrete execution error:
// various **EVM** error which aborts the execution,
// e.g. ErrOutOfGas, ErrExecutionReverted
//
// However if any consensus issue encountered, return the error directly with
// nil evm execution result.
func
(
st
*
StateTransition
)
TransitionDb
()
(
*
ExecutionResult
,
error
)
{
// First check this message satisfies all consensus rules before
// applying the message. The rules include these clauses
//
// 1. the nonce of the message caller is correct
// 2. caller has enough balance to cover transaction fee(gaslimit * gasprice)
// 3. the amount of gas required is available in the block
// 4. the purchased gas is enough to cover intrinsic usage
// 5. there is no overflow when calculating intrinsic gas
// 6. caller has enough balance to cover asset transfer for **topmost** call
// Check clauses 1-3, buy gas if everything is correct
if
err
:=
st
.
preCheck
();
err
!=
nil
{
return
nil
,
err
}
msg
:=
st
.
msg
sender
:=
vm
.
AccountRef
(
msg
.
From
())
homestead
:=
st
.
evm
.
ChainConfig
()
.
IsHomestead
(
st
.
evm
.
Context
.
BlockNumber
)
istanbul
:=
st
.
evm
.
ChainConfig
()
.
IsIstanbul
(
st
.
evm
.
Context
.
BlockNumber
)
london
:=
st
.
evm
.
ChainConfig
()
.
IsLondon
(
st
.
evm
.
Context
.
BlockNumber
)
contractCreation
:=
msg
.
To
()
==
nil
// Check clauses 4-5, subtract intrinsic gas if everything is correct
gas
,
err
:=
IntrinsicGas
(
st
.
data
,
st
.
msg
.
AccessList
(),
contractCreation
,
homestead
,
istanbul
)
if
err
!=
nil
{
return
nil
,
err
}
if
st
.
gas
<
gas
{
return
nil
,
fmt
.
Errorf
(
"%w: have %d, want %d"
,
ErrIntrinsicGas
,
st
.
gas
,
gas
)
}
st
.
gas
-=
gas
// Check clause 6
if
msg
.
Value
()
.
Sign
()
>
0
&&
!
st
.
evm
.
Context
.
CanTransfer
(
st
.
state
,
msg
.
From
(),
msg
.
Value
())
{
return
nil
,
fmt
.
Errorf
(
"%w: address %v"
,
ErrInsufficientFundsForTransfer
,
msg
.
From
()
.
Hex
())
}
// Set up the initial access list.
if
rules
:=
st
.
evm
.
ChainConfig
()
.
Rules
(
st
.
evm
.
Context
.
BlockNumber
);
rules
.
IsBerlin
{
st
.
state
.
PrepareAccessList
(
msg
.
From
(),
msg
.
To
(),
vm
.
ActivePrecompiles
(
rules
),
msg
.
AccessList
())
}
var
(
ret
[]
byte
vmerr
error
// vm errors do not effect consensus and are therefore not assigned to err
)
if
contractCreation
{
ret
,
_
,
st
.
gas
,
vmerr
=
st
.
evm
.
Create
(
sender
,
st
.
data
,
st
.
gas
,
st
.
value
)
}
else
{
// Increment the nonce for the next transaction
st
.
state
.
SetNonce
(
msg
.
From
(),
st
.
state
.
GetNonce
(
sender
.
Address
())
+
1
)
ret
,
st
.
gas
,
vmerr
=
st
.
evm
.
Call
(
sender
,
st
.
to
(),
st
.
data
,
st
.
gas
,
st
.
value
)
}
if
!
london
{
// Before EIP-3529: refunds were capped to gasUsed / 2
st
.
refundGas
(
params
.
RefundQuotient
)
}
else
{
// After EIP-3529: refunds are capped to gasUsed / 5
st
.
refundGas
(
params
.
RefundQuotientEIP3529
)
}
effectiveTip
:=
st
.
gasPrice
if
london
{
effectiveTip
=
cmath
.
BigMin
(
st
.
gasTipCap
,
new
(
big
.
Int
)
.
Sub
(
st
.
gasFeeCap
,
st
.
evm
.
Context
.
BaseFee
))
}
st
.
state
.
AddBalance
(
st
.
evm
.
Context
.
Coinbase
,
new
(
big
.
Int
)
.
Mul
(
new
(
big
.
Int
)
.
SetUint64
(
st
.
gasUsed
()),
effectiveTip
))
return
&
ExecutionResult
{
UsedGas
:
st
.
gasUsed
(),
Err
:
vmerr
,
ReturnData
:
ret
,
},
nil
}
func
(
st
*
StateTransition
)
refundGas
(
refundQuotient
uint64
)
{
// Apply refund counter, capped to a refund quotient
refund
:=
st
.
gasUsed
()
/
refundQuotient
if
refund
>
st
.
state
.
GetRefund
()
{
refund
=
st
.
state
.
GetRefund
()
}
st
.
gas
+=
refund
// Return ETH for remaining gas, exchanged at the original rate.
remaining
:=
new
(
big
.
Int
)
.
Mul
(
new
(
big
.
Int
)
.
SetUint64
(
st
.
gas
),
st
.
gasPrice
)
st
.
state
.
AddBalance
(
st
.
msg
.
From
(),
remaining
)
// Also return remaining gas to the block gas counter so it is
// available for the next transaction.
st
.
gp
.
AddGas
(
st
.
gas
)
}
// gasUsed returns the amount of gas used up by the state transition.
func
(
st
*
StateTransition
)
gasUsed
()
uint64
{
return
st
.
initialGas
-
st
.
gas
}
This diff is collapsed.
Click to expand it.
minigeth/core/vm/interpreter.go
View file @
d6da4342
...
@@ -18,13 +18,34 @@ package vm
...
@@ -18,13 +18,34 @@ package vm
import
(
import
(
"hash"
"hash"
"math/big"
"sync/atomic"
"sync/atomic"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/common/math"
//"github.com/ethereum/go-ethereum/log"
//"github.com/ethereum/go-ethereum/log"
)
)
// **** stub Tracer ****
type
Tracer
struct
{}
// CaptureStart implements the Tracer interface to initialize the tracing operation.
func
(
jst
*
Tracer
)
CaptureStart
(
env
*
EVM
,
from
common
.
Address
,
to
common
.
Address
,
create
bool
,
input
[]
byte
,
gas
uint64
,
value
*
big
.
Int
)
{
}
// CaptureState implements the Tracer interface to trace a single step of VM execution.
func
(
jst
*
Tracer
)
CaptureState
(
env
*
EVM
,
pc
uint64
,
op
OpCode
,
gas
,
cost
uint64
,
scope
*
ScopeContext
,
rData
[]
byte
,
depth
int
,
err
error
)
{
}
// CaptureFault implements the Tracer interface to trace an execution fault
func
(
jst
*
Tracer
)
CaptureFault
(
env
*
EVM
,
pc
uint64
,
op
OpCode
,
gas
,
cost
uint64
,
scope
*
ScopeContext
,
depth
int
,
err
error
)
{
}
// CaptureEnd is called after the call finishes to finalize the tracing.
func
(
jst
*
Tracer
)
CaptureEnd
(
output
[]
byte
,
gasUsed
uint64
,
t
time
.
Duration
,
err
error
)
{
}
// Config are the configuration options for the Interpreter
// Config are the configuration options for the Interpreter
type
Config
struct
{
type
Config
struct
{
Debug
bool
// Enables debugging
Debug
bool
// Enables debugging
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment