mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
all: implement eip-1559 (#22837)
This commit is contained in:
parent
6a3b818069
commit
e18553b855
37 changed files with 508 additions and 79 deletions
|
|
@ -525,6 +525,8 @@ func (m callMsg) Nonce() uint64 { return 0 }
|
|||
func (m callMsg) CheckNonce() bool { return false }
|
||||
func (m callMsg) To() *common.Address { return m.CallMsg.To }
|
||||
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
|
||||
func (m callMsg) FeeCap() *big.Int { return m.CallMsg.FeeCap }
|
||||
func (m callMsg) Tip() *big.Int { return m.CallMsg.Tip }
|
||||
func (m callMsg) Gas() uint64 { return m.CallMsg.Gas }
|
||||
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
|
||||
func (m callMsg) Data() []byte { return m.CallMsg.Data }
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import "math/big"
|
|||
|
||||
var MinGasPrice50x = big.NewInt(12500000000)
|
||||
var GasPrice50x = big.NewInt(12500000000)
|
||||
var BaseFee = big.NewInt(12500000000)
|
||||
|
||||
func GetGasFee(blockNumber, gas uint64) *big.Int {
|
||||
fee := new(big.Int).SetUint64(gas)
|
||||
|
|
|
|||
|
|
@ -241,6 +241,10 @@ func (x *XDPoS_v1) verifyCascadingFields(chain consensus.ChainReader, header *ty
|
|||
if parent.Time.Uint64()+x.config.Period > header.Time.Uint64() {
|
||||
return utils.ErrInvalidTimestamp
|
||||
}
|
||||
// Verify the header's EIP-1559 attributes.
|
||||
if err := misc.VerifyEip1559Header(chain.Config(), header); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if number%x.config.Epoch != 0 {
|
||||
return x.verifySeal(chain, header, parents, fullVerify)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto/sha3"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
|
|
@ -62,7 +61,7 @@ func getM1M2(masternodes []common.Address, validators []int64, currentHeader *ty
|
|||
func sigHash(header *types.Header) (hash common.Hash) {
|
||||
hasher := sha3.NewKeccak256()
|
||||
|
||||
err := rlp.Encode(hasher, []interface{}{
|
||||
enc := []interface{}{
|
||||
header.ParentHash,
|
||||
header.UncleHash,
|
||||
header.Coinbase,
|
||||
|
|
@ -78,10 +77,11 @@ func sigHash(header *types.Header) (hash common.Hash) {
|
|||
header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short
|
||||
header.MixDigest,
|
||||
header.Nonce,
|
||||
})
|
||||
if err != nil {
|
||||
log.Debug("Fail to encode", err)
|
||||
}
|
||||
if header.BaseFee != nil {
|
||||
enc = append(enc, header.BaseFee)
|
||||
}
|
||||
rlp.Encode(hasher, enc)
|
||||
hasher.Sum(hash[:0])
|
||||
return hash
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import (
|
|||
func sigHash(header *types.Header) (hash common.Hash) {
|
||||
hasher := sha3.NewKeccak256()
|
||||
|
||||
err := rlp.Encode(hasher, []interface{}{
|
||||
enc := []interface{}{
|
||||
header.ParentHash,
|
||||
header.UncleHash,
|
||||
header.Coinbase,
|
||||
|
|
@ -38,10 +38,11 @@ func sigHash(header *types.Header) (hash common.Hash) {
|
|||
header.Nonce,
|
||||
header.Validators,
|
||||
header.Penalties,
|
||||
})
|
||||
if err != nil {
|
||||
log.Debug("Fail to encode", err)
|
||||
}
|
||||
if header.BaseFee != nil {
|
||||
enc = append(enc, header.BaseFee)
|
||||
}
|
||||
rlp.Encode(hasher, enc)
|
||||
hasher.Sum(hash[:0])
|
||||
return hash
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,10 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
|
|||
if header.UncleHash != utils.UncleHash {
|
||||
return utils.ErrInvalidUncleHash
|
||||
}
|
||||
|
||||
// Verify the header's EIP-1559 attributes.
|
||||
if err := misc.VerifyEip1559Header(chain.Config(), header); err != nil {
|
||||
return err
|
||||
}
|
||||
if header.Difficulty.Cmp(big.NewInt(1)) != 0 {
|
||||
return utils.ErrInvalidDifficulty
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ type SignerFn func(accounts.Account, []byte) ([]byte, error)
|
|||
func sigHash(header *types.Header) (hash common.Hash) {
|
||||
hasher := sha3.NewKeccak256()
|
||||
|
||||
rlp.Encode(hasher, []interface{}{
|
||||
enc := []interface{}{
|
||||
header.ParentHash,
|
||||
header.UncleHash,
|
||||
header.Coinbase,
|
||||
|
|
@ -163,7 +163,11 @@ func sigHash(header *types.Header) (hash common.Hash) {
|
|||
header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short
|
||||
header.MixDigest,
|
||||
header.Nonce,
|
||||
})
|
||||
}
|
||||
if header.BaseFee != nil {
|
||||
enc = append(enc, header.BaseFee)
|
||||
}
|
||||
rlp.Encode(hasher, enc)
|
||||
hasher.Sum(hash[:0])
|
||||
return hash
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,6 +253,10 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *
|
|||
if header.GasUsed > header.GasLimit {
|
||||
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
|
||||
}
|
||||
// Verify the header's EIP-1559 attributes.
|
||||
if err := misc.VerifyEip1559Header(chain.Config(), header); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify that the gas limit remains within allowed bounds
|
||||
diff := int64(parent.GasLimit) - int64(header.GasLimit)
|
||||
|
|
|
|||
62
consensus/misc/eip1559.go
Normal file
62
consensus/misc/eip1559.go
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2021 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 misc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
// VerifyEip1559Header verifies some header attributes which were changed in EIP-1559,
|
||||
// - gas limit check
|
||||
// - basefee check
|
||||
func VerifyEip1559Header(config *params.ChainConfig, header *types.Header) error {
|
||||
if !config.IsEIP1559(header.Number) {
|
||||
if header.BaseFee != nil {
|
||||
return fmt.Errorf("invalid baseFee: have %s, want <nil>",
|
||||
header.BaseFee)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify the header is not malformed
|
||||
if header.BaseFee == nil {
|
||||
return fmt.Errorf("header is missing baseFee")
|
||||
}
|
||||
|
||||
// Verify the baseFee is correct based on the current header.
|
||||
expectedBaseFee := CalcBaseFee(config, header)
|
||||
if header.BaseFee.Cmp(expectedBaseFee) != 0 {
|
||||
return fmt.Errorf("invalid baseFee: have %s, want %s",
|
||||
header.BaseFee, expectedBaseFee)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CalcBaseFee calculates the basefee of the header.
|
||||
func CalcBaseFee(config *params.ChainConfig, header *types.Header) *big.Int {
|
||||
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
|
||||
if config.IsEIP1559(header.Number) {
|
||||
return new(big.Int).Set(common.BaseFee)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ package core
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"sync"
|
||||
|
|
@ -1431,7 +1432,7 @@ func TestEIP2718Transition(t *testing.T) {
|
|||
// A sender who makes transactions, has some funds
|
||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||
funds = big.NewInt(1000000000)
|
||||
funds = big.NewInt(math.MaxInt64)
|
||||
gspec = &Genesis{
|
||||
Config: ¶ms.ChainConfig{
|
||||
ChainId: new(big.Int).SetBytes([]byte("eip1559")),
|
||||
|
|
@ -1458,7 +1459,7 @@ func TestEIP2718Transition(t *testing.T) {
|
|||
byte(vm.SLOAD),
|
||||
},
|
||||
Nonce: 0,
|
||||
Balance: big.NewInt(0),
|
||||
Balance: big.NewInt(50000000000),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -1475,7 +1476,7 @@ func TestEIP2718Transition(t *testing.T) {
|
|||
Nonce: 0,
|
||||
To: &aa,
|
||||
Gas: 30000,
|
||||
GasPrice: big.NewInt(1),
|
||||
GasPrice: new(big.Int).Set(common.BaseFee),
|
||||
AccessList: types.AccessList{{
|
||||
Address: aa,
|
||||
StorageKeys: []common.Hash{{0}},
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
|
|||
time = new(big.Int).Add(parent.Time(), big.NewInt(10)) // block time is fixed at 10 seconds
|
||||
}
|
||||
|
||||
return &types.Header{
|
||||
header := &types.Header{
|
||||
Root: state.IntermediateRoot(chain.Config().IsEIP158(parent.Number())),
|
||||
ParentHash: parent.Hash(),
|
||||
Coinbase: parent.Coinbase(),
|
||||
|
|
@ -279,6 +279,10 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
|
|||
Number: new(big.Int).Add(parent.Number(), common.Big1),
|
||||
Time: time,
|
||||
}
|
||||
|
||||
header.BaseFee = misc.CalcBaseFee(chain.Config(), header)
|
||||
|
||||
return header
|
||||
}
|
||||
|
||||
// newCanonical creates a chain database, and injects a deterministic canonical
|
||||
|
|
|
|||
|
|
@ -53,4 +53,8 @@ var (
|
|||
|
||||
// ErrGasUintOverflow is returned when calculating gas usage.
|
||||
ErrGasUintOverflow = errors.New("gas uint64 overflow")
|
||||
|
||||
// ErrFeeCapTooLow is returned if the transaction fee cap is less than the
|
||||
// the base fee of the block.
|
||||
ErrFeeCapTooLow = errors.New("fee cap less than block base fee")
|
||||
)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ func NewEVMBlockContext(header *types.Header, chain consensus.ChainContext, auth
|
|||
// If we don't have an explicit author (i.e. not mining), extract from the header
|
||||
var (
|
||||
beneficiary common.Address
|
||||
baseFee *big.Int
|
||||
random common.Hash
|
||||
)
|
||||
if author == nil {
|
||||
|
|
@ -38,6 +39,9 @@ func NewEVMBlockContext(header *types.Header, chain consensus.ChainContext, auth
|
|||
} else {
|
||||
beneficiary = *author
|
||||
}
|
||||
if header.BaseFee != nil {
|
||||
baseFee = new(big.Int).Set(header.BaseFee)
|
||||
}
|
||||
// since xdpos chain do not use difficulty and mixdigest, we use hash of the block number as random
|
||||
random = crypto.Keccak256Hash(header.Number.Bytes())
|
||||
return vm.BlockContext{
|
||||
|
|
@ -48,6 +52,7 @@ func NewEVMBlockContext(header *types.Header, chain consensus.ChainContext, auth
|
|||
BlockNumber: new(big.Int).Set(header.Number),
|
||||
Time: new(big.Int).Set(header.Time),
|
||||
Difficulty: new(big.Int).Set(header.Difficulty),
|
||||
BaseFee: baseFee,
|
||||
GasLimit: header.GasLimit,
|
||||
Random: &random,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -264,6 +264,9 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
|
|||
if g.Difficulty == nil {
|
||||
head.Difficulty = params.GenesisDifficulty
|
||||
}
|
||||
if g.Config != nil && g.Config.IsEIP1559(common.Big0) {
|
||||
head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee)
|
||||
}
|
||||
statedb.Commit(false)
|
||||
statedb.Database().TrieDB().Commit(root, true)
|
||||
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
|
|||
}
|
||||
}
|
||||
statedb.Prepare(tx.Hash(), i)
|
||||
receipt, gas, err, tokenFeeUsed := applyTransaction(p.config, balanceFee, gp, statedb, coinbaseOwner, blockNumber, blockHash, tx, usedGas, vmenv)
|
||||
receipt, gas, err, tokenFeeUsed := applyTransaction(p.config, balanceFee, gp, statedb, coinbaseOwner, blockNumber, header.BaseFee, blockHash, tx, usedGas, vmenv)
|
||||
if err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
|
|
@ -198,7 +198,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
|
|||
}
|
||||
}
|
||||
statedb.Prepare(tx.Hash(), i)
|
||||
receipt, gas, err, tokenFeeUsed := applyTransaction(p.config, balanceFee, gp, statedb, coinbaseOwner, blockNumber, blockHash, tx, usedGas, vmenv)
|
||||
receipt, gas, err, tokenFeeUsed := applyTransaction(p.config, balanceFee, gp, statedb, coinbaseOwner, blockNumber, header.BaseFee, blockHash, tx, usedGas, vmenv)
|
||||
if err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
|
|
@ -220,7 +220,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
|
|||
return receipts, allLogs, *usedGas, nil
|
||||
}
|
||||
|
||||
func applyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*big.Int, gp *GasPool, statedb *state.StateDB, coinbaseOwner common.Address, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, uint64, error, bool) {
|
||||
func applyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*big.Int, gp *GasPool, statedb *state.StateDB, coinbaseOwner common.Address, blockNumber, baseFee *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, uint64, error, bool) {
|
||||
to := tx.To()
|
||||
if to != nil {
|
||||
if *to == common.BlockSignersBinary && config.IsTIPSigning(blockNumber) {
|
||||
|
|
@ -246,7 +246,8 @@ func applyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*
|
|||
balanceFee = value
|
||||
}
|
||||
}
|
||||
msg, err := tx.AsMessage(types.MakeSigner(config, blockNumber), balanceFee, blockNumber)
|
||||
// msg, err := tx.AsMessage(types.MakeSigner(config, blockNumber), balanceFee, blockNumber)
|
||||
msg, err := tx.AsMessage(types.MakeSigner(config, blockNumber), balanceFee, blockNumber, baseFee)
|
||||
if err != nil {
|
||||
return nil, 0, err, false
|
||||
}
|
||||
|
|
@ -465,7 +466,7 @@ func ApplyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*
|
|||
blockContext := NewEVMBlockContext(header, bc, author)
|
||||
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, XDCxState, config, cfg)
|
||||
coinbaseOwner := getCoinbaseOwner(bc, statedb, header, author)
|
||||
return applyTransaction(config, tokensFee, gp, statedb, coinbaseOwner, header.Number, header.Hash(), tx, usedGas, vmenv)
|
||||
return applyTransaction(config, tokensFee, gp, statedb, coinbaseOwner, header.Number, header.BaseFee, header.Hash(), tx, usedGas, vmenv)
|
||||
}
|
||||
|
||||
func ApplySignTransaction(config *params.ChainConfig, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64) (*types.Receipt, uint64, error, bool) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
cmath "github.com/XinFinOrg/XDPoSChain/common/math"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
|
|
@ -57,6 +58,8 @@ type StateTransition struct {
|
|||
msg Message
|
||||
gas uint64
|
||||
gasPrice *big.Int
|
||||
feeCap *big.Int
|
||||
tip *big.Int
|
||||
initialGas uint64
|
||||
value *big.Int
|
||||
data []byte
|
||||
|
|
@ -71,6 +74,8 @@ type Message interface {
|
|||
To() *common.Address
|
||||
|
||||
GasPrice() *big.Int
|
||||
FeeCap() *big.Int
|
||||
Tip() *big.Int
|
||||
Gas() uint64
|
||||
Value() *big.Int
|
||||
|
||||
|
|
@ -125,6 +130,8 @@ func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition
|
|||
evm: evm,
|
||||
msg: msg,
|
||||
gasPrice: msg.GasPrice(),
|
||||
feeCap: msg.FeeCap(),
|
||||
tip: msg.Tip(),
|
||||
value: msg.Value(),
|
||||
data: msg.Data(),
|
||||
state: evm.StateDB,
|
||||
|
|
@ -197,19 +204,28 @@ func (st *StateTransition) buyGas() error {
|
|||
}
|
||||
|
||||
func (st *StateTransition) preCheck() error {
|
||||
// Make sure this transaction's nonce is correct
|
||||
if st.msg.CheckNonce() {
|
||||
// Make sure this transaction's nonce is correct.
|
||||
stNonce := st.state.GetNonce(st.from().Address())
|
||||
if msgNonce := st.msg.Nonce(); stNonce < msgNonce {
|
||||
// Make sure this transaction's nonce is correct.
|
||||
msg := st.msg
|
||||
if msg.CheckNonce() {
|
||||
stNonce := st.state.GetNonce(msg.From())
|
||||
if msgNonce := msg.Nonce(); stNonce < msgNonce {
|
||||
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooHigh,
|
||||
st.msg.From().Hex(), msgNonce, stNonce)
|
||||
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)
|
||||
msg.From().Hex(), msgNonce, stNonce)
|
||||
} else if stNonce+1 < stNonce {
|
||||
return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax,
|
||||
st.msg.From().Hex(), stNonce)
|
||||
msg.From().Hex(), stNonce)
|
||||
}
|
||||
}
|
||||
// Make sure that transaction feeCap is greater than the baseFee (post london)
|
||||
if st.evm.ChainConfig().IsEIP1559(st.evm.Context.BlockNumber) {
|
||||
// This will panic if baseFee is nil, but basefee presence is verified
|
||||
// as part of header validation.
|
||||
if st.feeCap.Cmp(st.evm.Context.BaseFee) < 0 {
|
||||
return fmt.Errorf("%w: address %v, feeCap: %s baseFee: %s", ErrFeeCapTooLow,
|
||||
msg.From().Hex(), st.feeCap, st.evm.Context.BaseFee)
|
||||
}
|
||||
}
|
||||
return st.buyGas()
|
||||
|
|
@ -307,7 +323,11 @@ func (st *StateTransition) TransitionDb(owner common.Address) (ret []byte, usedG
|
|||
st.state.AddBalance(owner, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
|
||||
}
|
||||
} else {
|
||||
st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
|
||||
effectiveTip := st.gasPrice
|
||||
if st.evm.ChainConfig().IsEIP1559(st.evm.Context.BlockNumber) {
|
||||
effectiveTip = cmath.BigMin(st.tip, new(big.Int).Sub(st.feeCap, st.evm.Context.BaseFee))
|
||||
}
|
||||
st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip))
|
||||
}
|
||||
|
||||
return ret, st.gasUsed(), vmerr != nil, nil, vmerr
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ func (m callMsg) Nonce() uint64 { return 0 }
|
|||
func (m callMsg) CheckNonce() bool { return false }
|
||||
func (m callMsg) To() *common.Address { return m.CallMsg.To }
|
||||
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
|
||||
func (m callMsg) FeeCap() *big.Int { return m.CallMsg.FeeCap }
|
||||
func (m callMsg) Tip() *big.Int { return m.CallMsg.Tip }
|
||||
func (m callMsg) Gas() uint64 { return m.CallMsg.Gas }
|
||||
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
|
||||
func (m callMsg) Data() []byte { return m.CallMsg.Data }
|
||||
|
|
|
|||
|
|
@ -102,6 +102,8 @@ func (tx *AccessListTx) accessList() AccessList { return tx.AccessList }
|
|||
func (tx *AccessListTx) data() []byte { return tx.Data }
|
||||
func (tx *AccessListTx) gas() uint64 { return tx.Gas }
|
||||
func (tx *AccessListTx) gasPrice() *big.Int { return tx.GasPrice }
|
||||
func (tx *AccessListTx) tip() *big.Int { return tx.GasPrice }
|
||||
func (tx *AccessListTx) feeCap() *big.Int { return tx.GasPrice }
|
||||
func (tx *AccessListTx) value() *big.Int { return tx.Value }
|
||||
func (tx *AccessListTx) nonce() uint64 { return tx.Nonce }
|
||||
func (tx *AccessListTx) to() *common.Address { return tx.To }
|
||||
|
|
|
|||
|
|
@ -81,6 +81,9 @@ type Header struct {
|
|||
Validators []byte `json:"validators" gencodec:"required"`
|
||||
Validator []byte `json:"validator" gencodec:"required"`
|
||||
Penalties []byte `json:"penalties" gencodec:"required"`
|
||||
|
||||
// BaseFee was added by EIP-1559 and is ignored in legacy headers.
|
||||
BaseFee *big.Int `json:"baseFee" rlp:"optional"`
|
||||
}
|
||||
|
||||
// field type overrides for gencodec
|
||||
|
|
@ -91,6 +94,7 @@ type headerMarshaling struct {
|
|||
GasUsed hexutil.Uint64
|
||||
Time *hexutil.Big
|
||||
Extra hexutil.Bytes
|
||||
BaseFee *hexutil.Big
|
||||
Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON
|
||||
}
|
||||
|
||||
|
|
@ -264,6 +268,9 @@ func CopyHeader(h *Header) *Header {
|
|||
if cpy.Number = new(big.Int); h.Number != nil {
|
||||
cpy.Number.Set(h.Number)
|
||||
}
|
||||
if h.BaseFee != nil {
|
||||
cpy.BaseFee = new(big.Int).Set(h.BaseFee)
|
||||
}
|
||||
if len(h.Extra) > 0 {
|
||||
cpy.Extra = make([]byte, len(h.Extra))
|
||||
copy(cpy.Extra, h.Extra)
|
||||
|
|
@ -340,6 +347,13 @@ func (b *Block) Extra() []byte { return common.CopyBytes(b.header.Ext
|
|||
func (b *Block) Penalties() []byte { return common.CopyBytes(b.header.Penalties) }
|
||||
func (b *Block) Validator() []byte { return common.CopyBytes(b.header.Validator) }
|
||||
|
||||
func (b *Block) BaseFee() *big.Int {
|
||||
if b.header.BaseFee == nil {
|
||||
return nil
|
||||
}
|
||||
return new(big.Int).Set(b.header.BaseFee)
|
||||
}
|
||||
|
||||
func (b *Block) Header() *Header { return CopyHeader(b.header) }
|
||||
|
||||
// Body returns the non-header content of the block.
|
||||
|
|
|
|||
104
core/types/dynamic_fee_tx.go
Normal file
104
core/types/dynamic_fee_tx.go
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright 2021 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 types
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
)
|
||||
|
||||
type DynamicFeeTx struct {
|
||||
ChainID *big.Int
|
||||
Nonce uint64
|
||||
Tip *big.Int
|
||||
FeeCap *big.Int
|
||||
Gas uint64
|
||||
To *common.Address `rlp:"nil"` // nil means contract creation
|
||||
Value *big.Int
|
||||
Data []byte
|
||||
AccessList AccessList
|
||||
|
||||
// Signature values
|
||||
V *big.Int `json:"v" gencodec:"required"`
|
||||
R *big.Int `json:"r" gencodec:"required"`
|
||||
S *big.Int `json:"s" gencodec:"required"`
|
||||
}
|
||||
|
||||
// copy creates a deep copy of the transaction data and initializes all fields.
|
||||
func (tx *DynamicFeeTx) copy() TxData {
|
||||
cpy := &DynamicFeeTx{
|
||||
Nonce: tx.Nonce,
|
||||
To: tx.To, // TODO: copy pointed-to address
|
||||
Data: common.CopyBytes(tx.Data),
|
||||
Gas: tx.Gas,
|
||||
// These are copied below.
|
||||
AccessList: make(AccessList, len(tx.AccessList)),
|
||||
Value: new(big.Int),
|
||||
ChainID: new(big.Int),
|
||||
Tip: new(big.Int),
|
||||
FeeCap: new(big.Int),
|
||||
V: new(big.Int),
|
||||
R: new(big.Int),
|
||||
S: new(big.Int),
|
||||
}
|
||||
copy(cpy.AccessList, tx.AccessList)
|
||||
if tx.Value != nil {
|
||||
cpy.Value.Set(tx.Value)
|
||||
}
|
||||
if tx.ChainID != nil {
|
||||
cpy.ChainID.Set(tx.ChainID)
|
||||
}
|
||||
if tx.Tip != nil {
|
||||
cpy.Tip.Set(tx.Tip)
|
||||
}
|
||||
if tx.FeeCap != nil {
|
||||
cpy.FeeCap.Set(tx.FeeCap)
|
||||
}
|
||||
if tx.V != nil {
|
||||
cpy.V.Set(tx.V)
|
||||
}
|
||||
if tx.R != nil {
|
||||
cpy.R.Set(tx.R)
|
||||
}
|
||||
if tx.S != nil {
|
||||
cpy.S.Set(tx.S)
|
||||
}
|
||||
return cpy
|
||||
}
|
||||
|
||||
// accessors for innerTx.
|
||||
func (tx *DynamicFeeTx) txType() byte { return DynamicFeeTxType }
|
||||
func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID }
|
||||
func (tx *DynamicFeeTx) protected() bool { return true }
|
||||
func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList }
|
||||
func (tx *DynamicFeeTx) data() []byte { return tx.Data }
|
||||
func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas }
|
||||
func (tx *DynamicFeeTx) feeCap() *big.Int { return tx.FeeCap }
|
||||
func (tx *DynamicFeeTx) tip() *big.Int { return tx.Tip }
|
||||
func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.FeeCap }
|
||||
func (tx *DynamicFeeTx) value() *big.Int { return tx.Value }
|
||||
func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce }
|
||||
func (tx *DynamicFeeTx) to() *common.Address { return tx.To }
|
||||
|
||||
func (tx *DynamicFeeTx) rawSignatureValues() (v, r, s *big.Int) {
|
||||
return tx.V, tx.R, tx.S
|
||||
}
|
||||
|
||||
func (tx *DynamicFeeTx) setSignatureValues(chainID, v, r, s *big.Int) {
|
||||
tx.ChainID, tx.V, tx.R, tx.S = chainID, v, r, s
|
||||
}
|
||||
|
|
@ -98,6 +98,8 @@ func (tx *LegacyTx) accessList() AccessList { return nil }
|
|||
func (tx *LegacyTx) data() []byte { return tx.Data }
|
||||
func (tx *LegacyTx) gas() uint64 { return tx.Gas }
|
||||
func (tx *LegacyTx) gasPrice() *big.Int { return tx.GasPrice }
|
||||
func (tx *LegacyTx) tip() *big.Int { return tx.GasPrice }
|
||||
func (tx *LegacyTx) feeCap() *big.Int { return tx.GasPrice }
|
||||
func (tx *LegacyTx) value() *big.Int { return tx.Value }
|
||||
func (tx *LegacyTx) nonce() uint64 { return tx.Nonce }
|
||||
func (tx *LegacyTx) to() *common.Address { return tx.To }
|
||||
|
|
|
|||
|
|
@ -124,10 +124,6 @@ func (r *Receipt) EncodeRLP(w io.Writer) error {
|
|||
if r.Type == LegacyTxType {
|
||||
return rlp.Encode(w, data)
|
||||
}
|
||||
// It's an EIP-2718 typed TX receipt.
|
||||
if r.Type != AccessListTxType {
|
||||
return ErrTxTypeNotSupported
|
||||
}
|
||||
buf := encodeBufferPool.Get().(*bytes.Buffer)
|
||||
defer encodeBufferPool.Put(buf)
|
||||
buf.Reset()
|
||||
|
|
@ -163,7 +159,7 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
|
|||
return errEmptyTypedReceipt
|
||||
}
|
||||
r.Type = b[0]
|
||||
if r.Type == AccessListTxType {
|
||||
if r.Type == AccessListTxType || r.Type == DynamicFeeTxType {
|
||||
var dec receiptRLP
|
||||
if err := rlp.DecodeBytes(b[1:], &dec); err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/math"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
)
|
||||
|
|
@ -56,6 +57,7 @@ var (
|
|||
const (
|
||||
LegacyTxType = iota
|
||||
AccessListTxType
|
||||
DynamicFeeTxType
|
||||
)
|
||||
|
||||
// Transaction is an Ethereum transaction.
|
||||
|
|
@ -88,6 +90,8 @@ type TxData interface {
|
|||
data() []byte
|
||||
gas() uint64
|
||||
gasPrice() *big.Int
|
||||
tip() *big.Int
|
||||
feeCap() *big.Int
|
||||
value() *big.Int
|
||||
nonce() uint64
|
||||
to() *common.Address
|
||||
|
|
@ -191,6 +195,10 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
|
|||
var inner AccessListTx
|
||||
err := rlp.DecodeBytes(b[1:], &inner)
|
||||
return &inner, err
|
||||
case DynamicFeeTxType:
|
||||
var inner DynamicFeeTx
|
||||
err := rlp.DecodeBytes(b[1:], &inner)
|
||||
return &inner, err
|
||||
default:
|
||||
return nil, ErrTxTypeNotSupported
|
||||
}
|
||||
|
|
@ -274,6 +282,12 @@ func (tx *Transaction) Gas() uint64 { return tx.inner.gas() }
|
|||
// GasPrice returns the gas price of the transaction.
|
||||
func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.inner.gasPrice()) }
|
||||
|
||||
// Tip returns the tip per gas of the transaction.
|
||||
func (tx *Transaction) Tip() *big.Int { return new(big.Int).Set(tx.inner.tip()) }
|
||||
|
||||
// FeeCap returns the fee cap per gas of the transaction.
|
||||
func (tx *Transaction) FeeCap() *big.Int { return new(big.Int).Set(tx.inner.feeCap()) }
|
||||
|
||||
// Value returns the ether amount of the transaction.
|
||||
func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.inner.value()) }
|
||||
|
||||
|
|
@ -351,11 +365,13 @@ func (tx *Transaction) Size() common.StorageSize {
|
|||
}
|
||||
|
||||
// AsMessage returns the transaction as a core.Message.
|
||||
func (tx *Transaction) AsMessage(s Signer, balanceFee *big.Int, number *big.Int) (Message, error) {
|
||||
func (tx *Transaction) AsMessage(s Signer, balanceFee, blockNumber, baseFee *big.Int) (Message, error) {
|
||||
msg := Message{
|
||||
nonce: tx.Nonce(),
|
||||
gasLimit: tx.Gas(),
|
||||
gasPrice: new(big.Int).Set(tx.GasPrice()),
|
||||
feeCap: new(big.Int).Set(tx.FeeCap()),
|
||||
tip: new(big.Int).Set(tx.Tip()),
|
||||
to: tx.To(),
|
||||
amount: tx.Value(),
|
||||
data: tx.Data(),
|
||||
|
|
@ -364,17 +380,23 @@ func (tx *Transaction) AsMessage(s Signer, balanceFee *big.Int, number *big.Int)
|
|||
balanceTokenFee: balanceFee,
|
||||
}
|
||||
|
||||
if balanceFee != nil {
|
||||
if blockNumber != nil {
|
||||
if blockNumber.Cmp(common.BlockNumberGas50x) >= 0 {
|
||||
msg.gasPrice = common.GasPrice50x
|
||||
} else if blockNumber.Cmp(common.TIPTRC21Fee) > 0 {
|
||||
msg.gasPrice = common.TRC21GasPrice
|
||||
} else {
|
||||
msg.gasPrice = common.TRC21GasPriceBefore
|
||||
}
|
||||
}
|
||||
} else if baseFee != nil {
|
||||
// If baseFee provided, set gasPrice to effectiveGasPrice.
|
||||
msg.gasPrice = math.BigMin(msg.gasPrice.Add(msg.tip, baseFee), msg.feeCap)
|
||||
}
|
||||
|
||||
var err error
|
||||
msg.from, err = Sender(s, tx)
|
||||
if balanceFee != nil {
|
||||
if number.Cmp(common.BlockNumberGas50x) >= 0 {
|
||||
msg.gasPrice = common.GasPrice50x
|
||||
} else if number.Cmp(common.TIPTRC21Fee) > 0 {
|
||||
msg.gasPrice = common.TRC21GasPrice
|
||||
} else {
|
||||
msg.gasPrice = common.TRC21GasPriceBefore
|
||||
}
|
||||
}
|
||||
return msg, err
|
||||
}
|
||||
|
||||
|
|
@ -742,13 +764,15 @@ type Message struct {
|
|||
amount *big.Int
|
||||
gasLimit uint64
|
||||
gasPrice *big.Int
|
||||
feeCap *big.Int
|
||||
tip *big.Int
|
||||
data []byte
|
||||
accessList AccessList
|
||||
checkNonce bool
|
||||
balanceTokenFee *big.Int
|
||||
}
|
||||
|
||||
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, accessList AccessList, checkNonce bool, balanceTokenFee *big.Int, number *big.Int) Message {
|
||||
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice, feeCap, tip *big.Int, data []byte, accessList AccessList, checkNonce bool, balanceTokenFee *big.Int, number *big.Int) Message {
|
||||
if balanceTokenFee != nil {
|
||||
gasPrice = common.GetGasPrice(number)
|
||||
}
|
||||
|
|
@ -759,6 +783,8 @@ func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *b
|
|||
amount: amount,
|
||||
gasLimit: gasLimit,
|
||||
gasPrice: gasPrice,
|
||||
feeCap: feeCap,
|
||||
tip: tip,
|
||||
data: data,
|
||||
accessList: accessList,
|
||||
checkNonce: checkNonce,
|
||||
|
|
@ -770,6 +796,8 @@ func (m Message) From() common.Address { return m.from }
|
|||
func (m Message) BalanceTokenFee() *big.Int { return m.balanceTokenFee }
|
||||
func (m Message) To() *common.Address { return m.to }
|
||||
func (m Message) GasPrice() *big.Int { return m.gasPrice }
|
||||
func (m Message) FeeCap() *big.Int { return m.feeCap }
|
||||
func (m Message) Tip() *big.Int { return m.tip }
|
||||
func (m Message) Value() *big.Int { return m.amount }
|
||||
func (m Message) Gas() uint64 { return m.gasLimit }
|
||||
func (m Message) Nonce() uint64 { return m.nonce }
|
||||
|
|
|
|||
|
|
@ -14,15 +14,19 @@ type txJSON struct {
|
|||
Type hexutil.Uint64 `json:"type"`
|
||||
|
||||
// Common transaction fields:
|
||||
Nonce *hexutil.Uint64 `json:"nonce"`
|
||||
GasPrice *hexutil.Big `json:"gasPrice"`
|
||||
Gas *hexutil.Uint64 `json:"gas"`
|
||||
Value *hexutil.Big `json:"value"`
|
||||
Data *hexutil.Bytes `json:"input"`
|
||||
V *hexutil.Big `json:"v"`
|
||||
R *hexutil.Big `json:"r"`
|
||||
S *hexutil.Big `json:"s"`
|
||||
To *common.Address `json:"to"`
|
||||
Nonce *hexutil.Uint64 `json:"nonce"`
|
||||
GasPrice *hexutil.Big `json:"gasPrice"`
|
||||
FeeCap *hexutil.Big `json:"feeCap"`
|
||||
Tip *hexutil.Big `json:"tip"`
|
||||
MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"`
|
||||
MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"`
|
||||
Gas *hexutil.Uint64 `json:"gas"`
|
||||
Value *hexutil.Big `json:"value"`
|
||||
Data *hexutil.Bytes `json:"input"`
|
||||
V *hexutil.Big `json:"v"`
|
||||
R *hexutil.Big `json:"r"`
|
||||
S *hexutil.Big `json:"s"`
|
||||
To *common.Address `json:"to"`
|
||||
|
||||
// Access list transaction fields:
|
||||
ChainID *hexutil.Big `json:"chainId,omitempty"`
|
||||
|
|
@ -63,6 +67,19 @@ func (t *Transaction) MarshalJSON() ([]byte, error) {
|
|||
enc.V = (*hexutil.Big)(tx.V)
|
||||
enc.R = (*hexutil.Big)(tx.R)
|
||||
enc.S = (*hexutil.Big)(tx.S)
|
||||
case *DynamicFeeTx:
|
||||
enc.ChainID = (*hexutil.Big)(tx.ChainID)
|
||||
enc.AccessList = &tx.AccessList
|
||||
enc.Nonce = (*hexutil.Uint64)(&tx.Nonce)
|
||||
enc.Gas = (*hexutil.Uint64)(&tx.Gas)
|
||||
enc.FeeCap = (*hexutil.Big)(tx.FeeCap)
|
||||
enc.Tip = (*hexutil.Big)(tx.Tip)
|
||||
enc.Value = (*hexutil.Big)(tx.Value)
|
||||
enc.Data = (*hexutil.Bytes)(&tx.Data)
|
||||
enc.To = t.To()
|
||||
enc.V = (*hexutil.Big)(tx.V)
|
||||
enc.R = (*hexutil.Big)(tx.R)
|
||||
enc.S = (*hexutil.Big)(tx.S)
|
||||
}
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
|
@ -175,6 +192,75 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
|
|||
}
|
||||
}
|
||||
|
||||
case DynamicFeeTxType:
|
||||
var itx DynamicFeeTx
|
||||
inner = &itx
|
||||
// Access list is optional for now.
|
||||
if dec.AccessList != nil {
|
||||
itx.AccessList = *dec.AccessList
|
||||
}
|
||||
if dec.ChainID == nil {
|
||||
return errors.New("missing required field 'chainId' in transaction")
|
||||
}
|
||||
itx.ChainID = (*big.Int)(dec.ChainID)
|
||||
if dec.To != nil {
|
||||
itx.To = dec.To
|
||||
}
|
||||
if dec.Nonce == nil {
|
||||
return errors.New("missing required field 'nonce' in transaction")
|
||||
}
|
||||
itx.Nonce = uint64(*dec.Nonce)
|
||||
switch {
|
||||
case dec.Tip == nil && dec.MaxPriorityFeePerGas == nil:
|
||||
return errors.New("at least one of 'tip' or 'maxPriorityFeePerGas' must be defined")
|
||||
case dec.Tip != nil && dec.MaxPriorityFeePerGas != nil:
|
||||
return errors.New("only one of 'tip' or 'maxPriorityFeePerGas' may be defined")
|
||||
case dec.Tip != nil && dec.MaxPriorityFeePerGas == nil:
|
||||
itx.Tip = (*big.Int)(dec.Tip)
|
||||
case dec.Tip == nil && dec.MaxPriorityFeePerGas != nil:
|
||||
itx.Tip = (*big.Int)(dec.MaxPriorityFeePerGas)
|
||||
}
|
||||
switch {
|
||||
case dec.FeeCap == nil && dec.MaxFeePerGas == nil:
|
||||
return errors.New("at least one of 'feeCap' or 'maxFeePerGas' must be defined")
|
||||
case dec.FeeCap != nil && dec.MaxFeePerGas != nil:
|
||||
return errors.New("only one of 'feeCap' or 'maxFeePerGas' may be defined")
|
||||
case dec.FeeCap != nil && dec.MaxFeePerGas == nil:
|
||||
itx.FeeCap = (*big.Int)(dec.FeeCap)
|
||||
case dec.FeeCap == nil && dec.MaxFeePerGas != nil:
|
||||
itx.FeeCap = (*big.Int)(dec.MaxFeePerGas)
|
||||
}
|
||||
if dec.Gas == nil {
|
||||
return errors.New("missing required field 'gas' for txdata")
|
||||
}
|
||||
itx.Gas = uint64(*dec.Gas)
|
||||
if dec.Value == nil {
|
||||
return errors.New("missing required field 'value' in transaction")
|
||||
}
|
||||
itx.Value = (*big.Int)(dec.Value)
|
||||
if dec.Data == nil {
|
||||
return errors.New("missing required field 'input' in transaction")
|
||||
}
|
||||
itx.Data = *dec.Data
|
||||
if dec.V == nil {
|
||||
return errors.New("missing required field 'v' in transaction")
|
||||
}
|
||||
itx.V = (*big.Int)(dec.V)
|
||||
if dec.R == nil {
|
||||
return errors.New("missing required field 'r' in transaction")
|
||||
}
|
||||
itx.R = (*big.Int)(dec.R)
|
||||
if dec.S == nil {
|
||||
return errors.New("missing required field 's' in transaction")
|
||||
}
|
||||
itx.S = (*big.Int)(dec.S)
|
||||
withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
|
||||
if withSignature {
|
||||
if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return ErrTxTypeNotSupported
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
|
|||
var signer Signer
|
||||
switch {
|
||||
case config.IsEIP1559(blockNumber):
|
||||
signer = NewEIP2930Signer(config.ChainId)
|
||||
signer = NewLondonSigner(config.ChainId)
|
||||
case config.IsEIP155(blockNumber):
|
||||
signer = NewEIP155Signer(config.ChainId)
|
||||
case config.IsHomestead(blockNumber):
|
||||
|
|
@ -63,7 +63,7 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
|
|||
func LatestSigner(config *params.ChainConfig) Signer {
|
||||
if config.ChainId != nil {
|
||||
if common.Eip1559Block.Uint64() != 9999999999 || config.Eip1559Block != nil {
|
||||
return NewEIP2930Signer(config.ChainId)
|
||||
return NewLondonSigner(config.ChainId)
|
||||
}
|
||||
if config.EIP155Block != nil {
|
||||
return NewEIP155Signer(config.ChainId)
|
||||
|
|
@ -83,7 +83,7 @@ func LatestSignerForChainID(chainID *big.Int) Signer {
|
|||
if chainID == nil {
|
||||
return HomesteadSigner{}
|
||||
}
|
||||
return NewEIP2930Signer(chainID)
|
||||
return NewLondonSigner(chainID)
|
||||
}
|
||||
|
||||
// SignTx signs the transaction using the given signer and private key.
|
||||
|
|
@ -170,6 +170,72 @@ type Signer interface {
|
|||
Equal(Signer) bool
|
||||
}
|
||||
|
||||
type londonSigner struct{ eip2930Signer }
|
||||
|
||||
// NewLondonSigner returns a signer that accepts
|
||||
// - EIP-1559 dynamic fee transactions
|
||||
// - EIP-2930 access list transactions,
|
||||
// - EIP-155 replay protected transactions, and
|
||||
// - legacy Homestead transactions.
|
||||
func NewLondonSigner(chainId *big.Int) Signer {
|
||||
return londonSigner{eip2930Signer{NewEIP155Signer(chainId)}}
|
||||
}
|
||||
|
||||
func (s londonSigner) Sender(tx *Transaction) (common.Address, error) {
|
||||
if tx.Type() != DynamicFeeTxType {
|
||||
return s.eip2930Signer.Sender(tx)
|
||||
}
|
||||
V, R, S := tx.RawSignatureValues()
|
||||
// DynamicFee txs are defined to use 0 and 1 as their recovery
|
||||
// id, add 27 to become equivalent to unprotected Homestead signatures.
|
||||
V = new(big.Int).Add(V, big.NewInt(27))
|
||||
if tx.ChainId().Cmp(s.chainId) != 0 {
|
||||
return common.Address{}, ErrInvalidChainId
|
||||
}
|
||||
return recoverPlain(s.Hash(tx), R, S, V, true)
|
||||
}
|
||||
|
||||
func (s londonSigner) Equal(s2 Signer) bool {
|
||||
x, ok := s2.(londonSigner)
|
||||
return ok && x.chainId.Cmp(s.chainId) == 0
|
||||
}
|
||||
|
||||
func (s londonSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) {
|
||||
txdata, ok := tx.inner.(*DynamicFeeTx)
|
||||
if !ok {
|
||||
return s.eip2930Signer.SignatureValues(tx, sig)
|
||||
}
|
||||
// Check that chain ID of tx matches the signer. We also accept ID zero here,
|
||||
// because it indicates that the chain ID was not specified in the tx.
|
||||
if txdata.ChainID.Sign() != 0 && txdata.ChainID.Cmp(s.chainId) != 0 {
|
||||
return nil, nil, nil, ErrInvalidChainId
|
||||
}
|
||||
R, S, _ = decodeSignature(sig)
|
||||
V = big.NewInt(int64(sig[64]))
|
||||
return R, S, V, nil
|
||||
}
|
||||
|
||||
// Hash returns the hash to be signed by the sender.
|
||||
// It does not uniquely identify the transaction.
|
||||
func (s londonSigner) Hash(tx *Transaction) common.Hash {
|
||||
if tx.Type() != DynamicFeeTxType {
|
||||
return s.eip2930Signer.Hash(tx)
|
||||
}
|
||||
return prefixedRlpHash(
|
||||
tx.Type(),
|
||||
[]interface{}{
|
||||
s.chainId,
|
||||
tx.Nonce(),
|
||||
tx.Tip(),
|
||||
tx.FeeCap(),
|
||||
tx.Gas(),
|
||||
tx.To(),
|
||||
tx.Value(),
|
||||
tx.Data(),
|
||||
tx.AccessList(),
|
||||
})
|
||||
}
|
||||
|
||||
type eip2930Signer struct{ EIP155Signer }
|
||||
|
||||
// NewEIP2930Signer returns a signer that accepts EIP-2930 access list transactions,
|
||||
|
|
@ -193,8 +259,8 @@ func (s eip2930Signer) Sender(tx *Transaction) (common.Address, error) {
|
|||
case LegacyTxType:
|
||||
return s.EIP155Signer.Sender(tx)
|
||||
case AccessListTxType:
|
||||
// ACL txs are defined to use 0 and 1 as their recovery id, add
|
||||
// 27 to become equivalent to unprotected Homestead signatures.
|
||||
// AL txs are defined to use 0 and 1 as their recovery
|
||||
// id, add 27 to become equivalent to unprotected Homestead signatures.
|
||||
V = new(big.Int).Add(V, big.NewInt(27))
|
||||
default:
|
||||
return common.Address{}, ErrTxTypeNotSupported
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ func enable3198(jt *JumpTable) {
|
|||
|
||||
// opBaseFee implements BASEFEE opcode
|
||||
func opBaseFee(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) {
|
||||
baseFee, _ := uint256.FromBig(common.MinGasPrice50x)
|
||||
baseFee, _ := uint256.FromBig(common.BaseFee)
|
||||
callContext.Stack.push(baseFee)
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ type BlockContext struct {
|
|||
BlockNumber *big.Int // Provides information for NUMBER
|
||||
Time *big.Int // Provides information for TIME
|
||||
Difficulty *big.Int // Provides information for DIFFICULTY
|
||||
BaseFee *big.Int // Provides information for BASEFEE
|
||||
Random *common.Hash // Provides information for PREVRANDAO
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
|
|
@ -242,7 +241,8 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
|
|||
balance = value
|
||||
}
|
||||
}
|
||||
msg, _ := tx.AsMessage(signer, balance, task.block.Number())
|
||||
header := task.block.Header()
|
||||
msg, _ := tx.AsMessage(signer, balance, header.Number, header.BaseFee)
|
||||
txctx := &tracers.Context{
|
||||
BlockHash: task.block.Hash(),
|
||||
TxIndex: i,
|
||||
|
|
@ -486,7 +486,8 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
|
|||
balance = value
|
||||
}
|
||||
}
|
||||
msg, _ := txs[task.index].AsMessage(signer, balance, block.Number())
|
||||
header := block.Header()
|
||||
msg, _ := txs[task.index].AsMessage(signer, balance, header.Number, header.BaseFee)
|
||||
txctx := &tracers.Context{
|
||||
BlockHash: blockHash,
|
||||
TxIndex: task.index,
|
||||
|
|
@ -518,7 +519,8 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
|
|||
}
|
||||
}
|
||||
// Generate the next state snapshot fast without tracing
|
||||
msg, _ := tx.AsMessage(signer, balance, block.Number())
|
||||
header := block.Header()
|
||||
msg, _ := tx.AsMessage(signer, balance, header.Number, header.BaseFee)
|
||||
txContext := core.NewEVMTxContext(msg)
|
||||
statedb.Prepare(tx.Hash(), i)
|
||||
|
||||
|
|
@ -800,7 +802,8 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree
|
|||
balanceFee = value
|
||||
}
|
||||
}
|
||||
msg, err := tx.AsMessage(types.MakeSigner(api.config, block.Header().Number), balanceFee, block.Number())
|
||||
header := block.Header()
|
||||
msg, err := tx.AsMessage(types.MakeSigner(api.config, header.Number), balanceFee, header.Number, header.BaseFee)
|
||||
if err != nil {
|
||||
return nil, vm.BlockContext{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
|
|||
t.Fatalf("failed to create call tracer: %v", err)
|
||||
}
|
||||
evm := vm.NewEVM(context, txContext, statedb, nil, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer})
|
||||
msg, err := tx.AsMessage(signer, nil, nil)
|
||||
msg, err := tx.AsMessage(signer, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||
}
|
||||
|
|
@ -201,7 +201,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
|
|||
b.Fatalf("failed to parse testcase input: %v", err)
|
||||
}
|
||||
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)))
|
||||
msg, err := tx.AsMessage(signer, nil, nil)
|
||||
msg, err := tx.AsMessage(signer, nil, nil, nil)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ func TestZeroValueToNotExitCall(t *testing.T) {
|
|||
t.Fatalf("failed to create call tracer: %v", err)
|
||||
}
|
||||
evm := vm.NewEVM(context, txContext, statedb, nil, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
||||
msg, err := tx.AsMessage(signer, nil, nil)
|
||||
msg, err := tx.AsMessage(signer, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||
}
|
||||
|
|
@ -239,7 +239,7 @@ func TestPrestateTracerCreate2(t *testing.T) {
|
|||
}
|
||||
evm := vm.NewEVM(context, txContext, statedb, nil, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
||||
|
||||
msg, err := tx.AsMessage(signer, nil, nil)
|
||||
msg, err := tx.AsMessage(signer, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||
}
|
||||
|
|
@ -336,7 +336,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
|
|||
//EnableReturnData: false,
|
||||
})
|
||||
evm := vm.NewEVM(context, txContext, statedb, nil, params.AllEthashProtocolChanges, vm.Config{Debug: true, Tracer: tracer})
|
||||
msg, err := tx.AsMessage(signer, nil, nil)
|
||||
msg, err := tx.AsMessage(signer, nil, nil, nil)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,7 +120,11 @@ type CallMsg struct {
|
|||
Value *big.Int // amount of wei sent along with the call
|
||||
Data []byte // input data, usually an ABI-encoded contract method invocation
|
||||
BalanceTokenFee *big.Int
|
||||
AccessList types.AccessList // EIP-2930 access list.
|
||||
|
||||
FeeCap *big.Int // EIP-1559 fee cap per gas.
|
||||
Tip *big.Int // EIP-1559 tip per gas.
|
||||
|
||||
AccessList types.AccessList // EIP-2930 access list.
|
||||
}
|
||||
|
||||
// A ContractCaller provides contract calls, essentially transactions that are executed by
|
||||
|
|
|
|||
|
|
@ -1822,7 +1822,7 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
|
|||
result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
|
||||
result.TransactionIndex = (*hexutil.Uint64)(&index)
|
||||
}
|
||||
if tx.Type() == types.AccessListTxType {
|
||||
if tx.Type() != types.LegacyTxType {
|
||||
al := tx.AccessList()
|
||||
result.Accesses = &al
|
||||
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
||||
|
|
@ -1960,7 +1960,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
|||
if value, ok := feeCapacity[to]; ok {
|
||||
balanceTokenFee = value
|
||||
}
|
||||
msg := types.NewMessage(args.from(), args.To, uint64(*args.Nonce), args.Value.ToInt(), uint64(*args.Gas), args.GasPrice.ToInt(), args.data(), accessList, false, balanceTokenFee, header.Number)
|
||||
msg := types.NewMessage(args.from(), args.To, uint64(*args.Nonce), args.Value.ToInt(), uint64(*args.Gas), args.GasPrice.ToInt(), nil, nil, args.data(), accessList, false, balanceTokenFee, header.Number)
|
||||
|
||||
// Apply the transaction with the access list tracer
|
||||
tracer := vm.NewAccessListTracer(accessList, args.from(), to, precompiles)
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ func (args *TransactionArgs) ToMessage(b Backend, number *big.Int, globalGasCap
|
|||
}
|
||||
|
||||
// Create new call message
|
||||
msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, data, accessList, false, nil, number)
|
||||
msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, nil, nil, data, accessList, false, nil, number)
|
||||
return msg
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
|
|||
if value, ok := feeCapacity[testContractAddr]; ok {
|
||||
balanceTokenFee = value
|
||||
}
|
||||
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, nil, false, balanceTokenFee, header.Number)}
|
||||
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, new(big.Int), nil, nil, data, nil, false, balanceTokenFee, header.Number)}
|
||||
|
||||
context := core.NewEVMBlockContext(header, bc, nil)
|
||||
txContext := core.NewEVMTxContext(msg)
|
||||
|
|
@ -154,7 +154,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
|
|||
if value, ok := feeCapacity[testContractAddr]; ok {
|
||||
balanceTokenFee = value
|
||||
}
|
||||
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, nil, false, balanceTokenFee, header.Number)}
|
||||
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), nil, nil, data, nil, false, balanceTokenFee, header.Number)}
|
||||
context := core.NewEVMBlockContext(header, lc, nil)
|
||||
txContext := core.NewEVMTxContext(msg)
|
||||
vmenv := vm.NewEVM(context, txContext, statedb, nil, config, vm.Config{})
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
|
|||
if value, ok := feeCapacity[testContractAddr]; ok {
|
||||
balanceTokenFee = value
|
||||
}
|
||||
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, nil, false, balanceTokenFee, header.Number)}
|
||||
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), nil, nil, data, nil, false, balanceTokenFee, header.Number)}
|
||||
txContext := core.NewEVMTxContext(msg)
|
||||
context := core.NewEVMBlockContext(header, chain, nil)
|
||||
vmenv := vm.NewEVM(context, txContext, st, nil, config, vm.Config{})
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ const (
|
|||
|
||||
TxDataNonZeroGas uint64 = 68 // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
|
||||
|
||||
InitialBaseFee = 12500000000 // Initial base fee for EIP-1559 blocks.
|
||||
|
||||
MaxCodeSize = 24576 // Maximum bytecode to permit for a contract
|
||||
|
||||
// Precompiled contract gas prices
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ func (tx *stTransaction) toMessage(ps stPostState, number *big.Int) (core.Messag
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid tx data %q", dataHex)
|
||||
}
|
||||
msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, tx.GasPrice, data, nil, true, nil, number)
|
||||
msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, tx.GasPrice, nil, nil, data, nil, true, nil, number)
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue