mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 10:50:44 +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) CheckNonce() bool { return false }
|
||||||
func (m callMsg) To() *common.Address { return m.CallMsg.To }
|
func (m callMsg) To() *common.Address { return m.CallMsg.To }
|
||||||
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
|
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) Gas() uint64 { return m.CallMsg.Gas }
|
||||||
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
|
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
|
||||||
func (m callMsg) Data() []byte { return m.CallMsg.Data }
|
func (m callMsg) Data() []byte { return m.CallMsg.Data }
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import "math/big"
|
||||||
|
|
||||||
var MinGasPrice50x = big.NewInt(12500000000)
|
var MinGasPrice50x = big.NewInt(12500000000)
|
||||||
var GasPrice50x = big.NewInt(12500000000)
|
var GasPrice50x = big.NewInt(12500000000)
|
||||||
|
var BaseFee = big.NewInt(12500000000)
|
||||||
|
|
||||||
func GetGasFee(blockNumber, gas uint64) *big.Int {
|
func GetGasFee(blockNumber, gas uint64) *big.Int {
|
||||||
fee := new(big.Int).SetUint64(gas)
|
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() {
|
if parent.Time.Uint64()+x.config.Period > header.Time.Uint64() {
|
||||||
return utils.ErrInvalidTimestamp
|
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 {
|
if number%x.config.Epoch != 0 {
|
||||||
return x.verifySeal(chain, header, parents, fullVerify)
|
return x.verifySeal(chain, header, parents, fullVerify)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto/sha3"
|
"github.com/XinFinOrg/XDPoSChain/crypto/sha3"
|
||||||
"github.com/XinFinOrg/XDPoSChain/log"
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/params"
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||||
lru "github.com/hashicorp/golang-lru"
|
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) {
|
func sigHash(header *types.Header) (hash common.Hash) {
|
||||||
hasher := sha3.NewKeccak256()
|
hasher := sha3.NewKeccak256()
|
||||||
|
|
||||||
err := rlp.Encode(hasher, []interface{}{
|
enc := []interface{}{
|
||||||
header.ParentHash,
|
header.ParentHash,
|
||||||
header.UncleHash,
|
header.UncleHash,
|
||||||
header.Coinbase,
|
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.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short
|
||||||
header.MixDigest,
|
header.MixDigest,
|
||||||
header.Nonce,
|
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])
|
hasher.Sum(hash[:0])
|
||||||
return hash
|
return hash
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import (
|
||||||
func sigHash(header *types.Header) (hash common.Hash) {
|
func sigHash(header *types.Header) (hash common.Hash) {
|
||||||
hasher := sha3.NewKeccak256()
|
hasher := sha3.NewKeccak256()
|
||||||
|
|
||||||
err := rlp.Encode(hasher, []interface{}{
|
enc := []interface{}{
|
||||||
header.ParentHash,
|
header.ParentHash,
|
||||||
header.UncleHash,
|
header.UncleHash,
|
||||||
header.Coinbase,
|
header.Coinbase,
|
||||||
|
|
@ -38,10 +38,11 @@ func sigHash(header *types.Header) (hash common.Hash) {
|
||||||
header.Nonce,
|
header.Nonce,
|
||||||
header.Validators,
|
header.Validators,
|
||||||
header.Penalties,
|
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])
|
hasher.Sum(hash[:0])
|
||||||
return hash
|
return hash
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,10 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
|
||||||
if header.UncleHash != utils.UncleHash {
|
if header.UncleHash != utils.UncleHash {
|
||||||
return utils.ErrInvalidUncleHash
|
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 {
|
if header.Difficulty.Cmp(big.NewInt(1)) != 0 {
|
||||||
return utils.ErrInvalidDifficulty
|
return utils.ErrInvalidDifficulty
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ type SignerFn func(accounts.Account, []byte) ([]byte, error)
|
||||||
func sigHash(header *types.Header) (hash common.Hash) {
|
func sigHash(header *types.Header) (hash common.Hash) {
|
||||||
hasher := sha3.NewKeccak256()
|
hasher := sha3.NewKeccak256()
|
||||||
|
|
||||||
rlp.Encode(hasher, []interface{}{
|
enc := []interface{}{
|
||||||
header.ParentHash,
|
header.ParentHash,
|
||||||
header.UncleHash,
|
header.UncleHash,
|
||||||
header.Coinbase,
|
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.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short
|
||||||
header.MixDigest,
|
header.MixDigest,
|
||||||
header.Nonce,
|
header.Nonce,
|
||||||
})
|
}
|
||||||
|
if header.BaseFee != nil {
|
||||||
|
enc = append(enc, header.BaseFee)
|
||||||
|
}
|
||||||
|
rlp.Encode(hasher, enc)
|
||||||
hasher.Sum(hash[:0])
|
hasher.Sum(hash[:0])
|
||||||
return hash
|
return hash
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -253,6 +253,10 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *
|
||||||
if header.GasUsed > header.GasLimit {
|
if header.GasUsed > header.GasLimit {
|
||||||
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", 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
|
// Verify that the gas limit remains within allowed bounds
|
||||||
diff := int64(parent.GasLimit) - int64(header.GasLimit)
|
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -1431,7 +1432,7 @@ func TestEIP2718Transition(t *testing.T) {
|
||||||
// A sender who makes transactions, has some funds
|
// A sender who makes transactions, has some funds
|
||||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
funds = big.NewInt(1000000000)
|
funds = big.NewInt(math.MaxInt64)
|
||||||
gspec = &Genesis{
|
gspec = &Genesis{
|
||||||
Config: ¶ms.ChainConfig{
|
Config: ¶ms.ChainConfig{
|
||||||
ChainId: new(big.Int).SetBytes([]byte("eip1559")),
|
ChainId: new(big.Int).SetBytes([]byte("eip1559")),
|
||||||
|
|
@ -1458,7 +1459,7 @@ func TestEIP2718Transition(t *testing.T) {
|
||||||
byte(vm.SLOAD),
|
byte(vm.SLOAD),
|
||||||
},
|
},
|
||||||
Nonce: 0,
|
Nonce: 0,
|
||||||
Balance: big.NewInt(0),
|
Balance: big.NewInt(50000000000),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -1475,7 +1476,7 @@ func TestEIP2718Transition(t *testing.T) {
|
||||||
Nonce: 0,
|
Nonce: 0,
|
||||||
To: &aa,
|
To: &aa,
|
||||||
Gas: 30000,
|
Gas: 30000,
|
||||||
GasPrice: big.NewInt(1),
|
GasPrice: new(big.Int).Set(common.BaseFee),
|
||||||
AccessList: types.AccessList{{
|
AccessList: types.AccessList{{
|
||||||
Address: aa,
|
Address: aa,
|
||||||
StorageKeys: []common.Hash{{0}},
|
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
|
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())),
|
Root: state.IntermediateRoot(chain.Config().IsEIP158(parent.Number())),
|
||||||
ParentHash: parent.Hash(),
|
ParentHash: parent.Hash(),
|
||||||
Coinbase: parent.Coinbase(),
|
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),
|
Number: new(big.Int).Add(parent.Number(), common.Big1),
|
||||||
Time: time,
|
Time: time,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header.BaseFee = misc.CalcBaseFee(chain.Config(), header)
|
||||||
|
|
||||||
|
return header
|
||||||
}
|
}
|
||||||
|
|
||||||
// newCanonical creates a chain database, and injects a deterministic canonical
|
// newCanonical creates a chain database, and injects a deterministic canonical
|
||||||
|
|
|
||||||
|
|
@ -53,4 +53,8 @@ var (
|
||||||
|
|
||||||
// ErrGasUintOverflow is returned when calculating gas usage.
|
// ErrGasUintOverflow is returned when calculating gas usage.
|
||||||
ErrGasUintOverflow = errors.New("gas uint64 overflow")
|
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
|
// If we don't have an explicit author (i.e. not mining), extract from the header
|
||||||
var (
|
var (
|
||||||
beneficiary common.Address
|
beneficiary common.Address
|
||||||
|
baseFee *big.Int
|
||||||
random common.Hash
|
random common.Hash
|
||||||
)
|
)
|
||||||
if author == nil {
|
if author == nil {
|
||||||
|
|
@ -38,6 +39,9 @@ func NewEVMBlockContext(header *types.Header, chain consensus.ChainContext, auth
|
||||||
} else {
|
} else {
|
||||||
beneficiary = *author
|
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
|
// since xdpos chain do not use difficulty and mixdigest, we use hash of the block number as random
|
||||||
random = crypto.Keccak256Hash(header.Number.Bytes())
|
random = crypto.Keccak256Hash(header.Number.Bytes())
|
||||||
return vm.BlockContext{
|
return vm.BlockContext{
|
||||||
|
|
@ -48,6 +52,7 @@ func NewEVMBlockContext(header *types.Header, chain consensus.ChainContext, auth
|
||||||
BlockNumber: new(big.Int).Set(header.Number),
|
BlockNumber: new(big.Int).Set(header.Number),
|
||||||
Time: new(big.Int).Set(header.Time),
|
Time: new(big.Int).Set(header.Time),
|
||||||
Difficulty: new(big.Int).Set(header.Difficulty),
|
Difficulty: new(big.Int).Set(header.Difficulty),
|
||||||
|
BaseFee: baseFee,
|
||||||
GasLimit: header.GasLimit,
|
GasLimit: header.GasLimit,
|
||||||
Random: &random,
|
Random: &random,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,9 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
|
||||||
if g.Difficulty == nil {
|
if g.Difficulty == nil {
|
||||||
head.Difficulty = params.GenesisDifficulty
|
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.Commit(false)
|
||||||
statedb.Database().TrieDB().Commit(root, true)
|
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)
|
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 {
|
if err != nil {
|
||||||
return nil, nil, 0, err
|
return nil, nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -198,7 +198,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
statedb.Prepare(tx.Hash(), i)
|
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 {
|
if err != nil {
|
||||||
return nil, nil, 0, err
|
return nil, nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -220,7 +220,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
|
||||||
return receipts, allLogs, *usedGas, nil
|
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()
|
to := tx.To()
|
||||||
if to != nil {
|
if to != nil {
|
||||||
if *to == common.BlockSignersBinary && config.IsTIPSigning(blockNumber) {
|
if *to == common.BlockSignersBinary && config.IsTIPSigning(blockNumber) {
|
||||||
|
|
@ -246,7 +246,8 @@ func applyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*
|
||||||
balanceFee = value
|
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 {
|
if err != nil {
|
||||||
return nil, 0, err, false
|
return nil, 0, err, false
|
||||||
}
|
}
|
||||||
|
|
@ -465,7 +466,7 @@ func ApplyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*
|
||||||
blockContext := NewEVMBlockContext(header, bc, author)
|
blockContext := NewEVMBlockContext(header, bc, author)
|
||||||
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, XDCxState, config, cfg)
|
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, XDCxState, config, cfg)
|
||||||
coinbaseOwner := getCoinbaseOwner(bc, statedb, header, author)
|
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) {
|
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"
|
"math/big"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
cmath "github.com/XinFinOrg/XDPoSChain/common/math"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/log"
|
"github.com/XinFinOrg/XDPoSChain/log"
|
||||||
|
|
@ -57,6 +58,8 @@ type StateTransition struct {
|
||||||
msg Message
|
msg Message
|
||||||
gas uint64
|
gas uint64
|
||||||
gasPrice *big.Int
|
gasPrice *big.Int
|
||||||
|
feeCap *big.Int
|
||||||
|
tip *big.Int
|
||||||
initialGas uint64
|
initialGas uint64
|
||||||
value *big.Int
|
value *big.Int
|
||||||
data []byte
|
data []byte
|
||||||
|
|
@ -71,6 +74,8 @@ type Message interface {
|
||||||
To() *common.Address
|
To() *common.Address
|
||||||
|
|
||||||
GasPrice() *big.Int
|
GasPrice() *big.Int
|
||||||
|
FeeCap() *big.Int
|
||||||
|
Tip() *big.Int
|
||||||
Gas() uint64
|
Gas() uint64
|
||||||
Value() *big.Int
|
Value() *big.Int
|
||||||
|
|
||||||
|
|
@ -125,6 +130,8 @@ func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition
|
||||||
evm: evm,
|
evm: evm,
|
||||||
msg: msg,
|
msg: msg,
|
||||||
gasPrice: msg.GasPrice(),
|
gasPrice: msg.GasPrice(),
|
||||||
|
feeCap: msg.FeeCap(),
|
||||||
|
tip: msg.Tip(),
|
||||||
value: msg.Value(),
|
value: msg.Value(),
|
||||||
data: msg.Data(),
|
data: msg.Data(),
|
||||||
state: evm.StateDB,
|
state: evm.StateDB,
|
||||||
|
|
@ -197,19 +204,28 @@ func (st *StateTransition) buyGas() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *StateTransition) preCheck() error {
|
func (st *StateTransition) preCheck() error {
|
||||||
// Make sure this transaction's nonce is correct
|
// Make sure this transaction's nonce is correct.
|
||||||
if st.msg.CheckNonce() {
|
msg := st.msg
|
||||||
// Make sure this transaction's nonce is correct.
|
if msg.CheckNonce() {
|
||||||
stNonce := st.state.GetNonce(st.from().Address())
|
stNonce := st.state.GetNonce(msg.From())
|
||||||
if msgNonce := st.msg.Nonce(); stNonce < msgNonce {
|
if msgNonce := msg.Nonce(); stNonce < msgNonce {
|
||||||
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooHigh,
|
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 {
|
} else if stNonce > msgNonce {
|
||||||
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow,
|
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 {
|
} else if stNonce+1 < stNonce {
|
||||||
return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax,
|
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()
|
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))
|
st.state.AddBalance(owner, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
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) CheckNonce() bool { return false }
|
||||||
func (m callMsg) To() *common.Address { return m.CallMsg.To }
|
func (m callMsg) To() *common.Address { return m.CallMsg.To }
|
||||||
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
|
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) Gas() uint64 { return m.CallMsg.Gas }
|
||||||
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
|
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
|
||||||
func (m callMsg) Data() []byte { return m.CallMsg.Data }
|
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) data() []byte { return tx.Data }
|
||||||
func (tx *AccessListTx) gas() uint64 { return tx.Gas }
|
func (tx *AccessListTx) gas() uint64 { return tx.Gas }
|
||||||
func (tx *AccessListTx) gasPrice() *big.Int { return tx.GasPrice }
|
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) value() *big.Int { return tx.Value }
|
||||||
func (tx *AccessListTx) nonce() uint64 { return tx.Nonce }
|
func (tx *AccessListTx) nonce() uint64 { return tx.Nonce }
|
||||||
func (tx *AccessListTx) to() *common.Address { return tx.To }
|
func (tx *AccessListTx) to() *common.Address { return tx.To }
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,9 @@ type Header struct {
|
||||||
Validators []byte `json:"validators" gencodec:"required"`
|
Validators []byte `json:"validators" gencodec:"required"`
|
||||||
Validator []byte `json:"validator" gencodec:"required"`
|
Validator []byte `json:"validator" gencodec:"required"`
|
||||||
Penalties []byte `json:"penalties" 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
|
// field type overrides for gencodec
|
||||||
|
|
@ -91,6 +94,7 @@ type headerMarshaling struct {
|
||||||
GasUsed hexutil.Uint64
|
GasUsed hexutil.Uint64
|
||||||
Time *hexutil.Big
|
Time *hexutil.Big
|
||||||
Extra hexutil.Bytes
|
Extra hexutil.Bytes
|
||||||
|
BaseFee *hexutil.Big
|
||||||
Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON
|
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 {
|
if cpy.Number = new(big.Int); h.Number != nil {
|
||||||
cpy.Number.Set(h.Number)
|
cpy.Number.Set(h.Number)
|
||||||
}
|
}
|
||||||
|
if h.BaseFee != nil {
|
||||||
|
cpy.BaseFee = new(big.Int).Set(h.BaseFee)
|
||||||
|
}
|
||||||
if len(h.Extra) > 0 {
|
if len(h.Extra) > 0 {
|
||||||
cpy.Extra = make([]byte, len(h.Extra))
|
cpy.Extra = make([]byte, len(h.Extra))
|
||||||
copy(cpy.Extra, 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) Penalties() []byte { return common.CopyBytes(b.header.Penalties) }
|
||||||
func (b *Block) Validator() []byte { return common.CopyBytes(b.header.Validator) }
|
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) }
|
func (b *Block) Header() *Header { return CopyHeader(b.header) }
|
||||||
|
|
||||||
// Body returns the non-header content of the block.
|
// 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) data() []byte { return tx.Data }
|
||||||
func (tx *LegacyTx) gas() uint64 { return tx.Gas }
|
func (tx *LegacyTx) gas() uint64 { return tx.Gas }
|
||||||
func (tx *LegacyTx) gasPrice() *big.Int { return tx.GasPrice }
|
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) value() *big.Int { return tx.Value }
|
||||||
func (tx *LegacyTx) nonce() uint64 { return tx.Nonce }
|
func (tx *LegacyTx) nonce() uint64 { return tx.Nonce }
|
||||||
func (tx *LegacyTx) to() *common.Address { return tx.To }
|
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 {
|
if r.Type == LegacyTxType {
|
||||||
return rlp.Encode(w, data)
|
return rlp.Encode(w, data)
|
||||||
}
|
}
|
||||||
// It's an EIP-2718 typed TX receipt.
|
|
||||||
if r.Type != AccessListTxType {
|
|
||||||
return ErrTxTypeNotSupported
|
|
||||||
}
|
|
||||||
buf := encodeBufferPool.Get().(*bytes.Buffer)
|
buf := encodeBufferPool.Get().(*bytes.Buffer)
|
||||||
defer encodeBufferPool.Put(buf)
|
defer encodeBufferPool.Put(buf)
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
|
|
@ -163,7 +159,7 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
|
||||||
return errEmptyTypedReceipt
|
return errEmptyTypedReceipt
|
||||||
}
|
}
|
||||||
r.Type = b[0]
|
r.Type = b[0]
|
||||||
if r.Type == AccessListTxType {
|
if r.Type == AccessListTxType || r.Type == DynamicFeeTxType {
|
||||||
var dec receiptRLP
|
var dec receiptRLP
|
||||||
if err := rlp.DecodeBytes(b[1:], &dec); err != nil {
|
if err := rlp.DecodeBytes(b[1:], &dec); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/common/math"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||||
)
|
)
|
||||||
|
|
@ -56,6 +57,7 @@ var (
|
||||||
const (
|
const (
|
||||||
LegacyTxType = iota
|
LegacyTxType = iota
|
||||||
AccessListTxType
|
AccessListTxType
|
||||||
|
DynamicFeeTxType
|
||||||
)
|
)
|
||||||
|
|
||||||
// Transaction is an Ethereum transaction.
|
// Transaction is an Ethereum transaction.
|
||||||
|
|
@ -88,6 +90,8 @@ type TxData interface {
|
||||||
data() []byte
|
data() []byte
|
||||||
gas() uint64
|
gas() uint64
|
||||||
gasPrice() *big.Int
|
gasPrice() *big.Int
|
||||||
|
tip() *big.Int
|
||||||
|
feeCap() *big.Int
|
||||||
value() *big.Int
|
value() *big.Int
|
||||||
nonce() uint64
|
nonce() uint64
|
||||||
to() *common.Address
|
to() *common.Address
|
||||||
|
|
@ -191,6 +195,10 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
|
||||||
var inner AccessListTx
|
var inner AccessListTx
|
||||||
err := rlp.DecodeBytes(b[1:], &inner)
|
err := rlp.DecodeBytes(b[1:], &inner)
|
||||||
return &inner, err
|
return &inner, err
|
||||||
|
case DynamicFeeTxType:
|
||||||
|
var inner DynamicFeeTx
|
||||||
|
err := rlp.DecodeBytes(b[1:], &inner)
|
||||||
|
return &inner, err
|
||||||
default:
|
default:
|
||||||
return nil, ErrTxTypeNotSupported
|
return nil, ErrTxTypeNotSupported
|
||||||
}
|
}
|
||||||
|
|
@ -274,6 +282,12 @@ func (tx *Transaction) Gas() uint64 { return tx.inner.gas() }
|
||||||
// GasPrice returns the gas price of the transaction.
|
// GasPrice returns the gas price of the transaction.
|
||||||
func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.inner.gasPrice()) }
|
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.
|
// Value returns the ether amount of the transaction.
|
||||||
func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.inner.value()) }
|
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.
|
// 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{
|
msg := Message{
|
||||||
nonce: tx.Nonce(),
|
nonce: tx.Nonce(),
|
||||||
gasLimit: tx.Gas(),
|
gasLimit: tx.Gas(),
|
||||||
gasPrice: new(big.Int).Set(tx.GasPrice()),
|
gasPrice: new(big.Int).Set(tx.GasPrice()),
|
||||||
|
feeCap: new(big.Int).Set(tx.FeeCap()),
|
||||||
|
tip: new(big.Int).Set(tx.Tip()),
|
||||||
to: tx.To(),
|
to: tx.To(),
|
||||||
amount: tx.Value(),
|
amount: tx.Value(),
|
||||||
data: tx.Data(),
|
data: tx.Data(),
|
||||||
|
|
@ -364,17 +380,23 @@ func (tx *Transaction) AsMessage(s Signer, balanceFee *big.Int, number *big.Int)
|
||||||
balanceTokenFee: balanceFee,
|
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
|
var err error
|
||||||
msg.from, err = Sender(s, tx)
|
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
|
return msg, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -742,13 +764,15 @@ type Message struct {
|
||||||
amount *big.Int
|
amount *big.Int
|
||||||
gasLimit uint64
|
gasLimit uint64
|
||||||
gasPrice *big.Int
|
gasPrice *big.Int
|
||||||
|
feeCap *big.Int
|
||||||
|
tip *big.Int
|
||||||
data []byte
|
data []byte
|
||||||
accessList AccessList
|
accessList AccessList
|
||||||
checkNonce bool
|
checkNonce bool
|
||||||
balanceTokenFee *big.Int
|
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 {
|
if balanceTokenFee != nil {
|
||||||
gasPrice = common.GetGasPrice(number)
|
gasPrice = common.GetGasPrice(number)
|
||||||
}
|
}
|
||||||
|
|
@ -759,6 +783,8 @@ func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *b
|
||||||
amount: amount,
|
amount: amount,
|
||||||
gasLimit: gasLimit,
|
gasLimit: gasLimit,
|
||||||
gasPrice: gasPrice,
|
gasPrice: gasPrice,
|
||||||
|
feeCap: feeCap,
|
||||||
|
tip: tip,
|
||||||
data: data,
|
data: data,
|
||||||
accessList: accessList,
|
accessList: accessList,
|
||||||
checkNonce: checkNonce,
|
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) BalanceTokenFee() *big.Int { return m.balanceTokenFee }
|
||||||
func (m Message) To() *common.Address { return m.to }
|
func (m Message) To() *common.Address { return m.to }
|
||||||
func (m Message) GasPrice() *big.Int { return m.gasPrice }
|
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) Value() *big.Int { return m.amount }
|
||||||
func (m Message) Gas() uint64 { return m.gasLimit }
|
func (m Message) Gas() uint64 { return m.gasLimit }
|
||||||
func (m Message) Nonce() uint64 { return m.nonce }
|
func (m Message) Nonce() uint64 { return m.nonce }
|
||||||
|
|
|
||||||
|
|
@ -14,15 +14,19 @@ type txJSON struct {
|
||||||
Type hexutil.Uint64 `json:"type"`
|
Type hexutil.Uint64 `json:"type"`
|
||||||
|
|
||||||
// Common transaction fields:
|
// Common transaction fields:
|
||||||
Nonce *hexutil.Uint64 `json:"nonce"`
|
Nonce *hexutil.Uint64 `json:"nonce"`
|
||||||
GasPrice *hexutil.Big `json:"gasPrice"`
|
GasPrice *hexutil.Big `json:"gasPrice"`
|
||||||
Gas *hexutil.Uint64 `json:"gas"`
|
FeeCap *hexutil.Big `json:"feeCap"`
|
||||||
Value *hexutil.Big `json:"value"`
|
Tip *hexutil.Big `json:"tip"`
|
||||||
Data *hexutil.Bytes `json:"input"`
|
MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"`
|
||||||
V *hexutil.Big `json:"v"`
|
MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"`
|
||||||
R *hexutil.Big `json:"r"`
|
Gas *hexutil.Uint64 `json:"gas"`
|
||||||
S *hexutil.Big `json:"s"`
|
Value *hexutil.Big `json:"value"`
|
||||||
To *common.Address `json:"to"`
|
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:
|
// Access list transaction fields:
|
||||||
ChainID *hexutil.Big `json:"chainId,omitempty"`
|
ChainID *hexutil.Big `json:"chainId,omitempty"`
|
||||||
|
|
@ -63,6 +67,19 @@ func (t *Transaction) MarshalJSON() ([]byte, error) {
|
||||||
enc.V = (*hexutil.Big)(tx.V)
|
enc.V = (*hexutil.Big)(tx.V)
|
||||||
enc.R = (*hexutil.Big)(tx.R)
|
enc.R = (*hexutil.Big)(tx.R)
|
||||||
enc.S = (*hexutil.Big)(tx.S)
|
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)
|
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:
|
default:
|
||||||
return ErrTxTypeNotSupported
|
return ErrTxTypeNotSupported
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
|
||||||
var signer Signer
|
var signer Signer
|
||||||
switch {
|
switch {
|
||||||
case config.IsEIP1559(blockNumber):
|
case config.IsEIP1559(blockNumber):
|
||||||
signer = NewEIP2930Signer(config.ChainId)
|
signer = NewLondonSigner(config.ChainId)
|
||||||
case config.IsEIP155(blockNumber):
|
case config.IsEIP155(blockNumber):
|
||||||
signer = NewEIP155Signer(config.ChainId)
|
signer = NewEIP155Signer(config.ChainId)
|
||||||
case config.IsHomestead(blockNumber):
|
case config.IsHomestead(blockNumber):
|
||||||
|
|
@ -63,7 +63,7 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
|
||||||
func LatestSigner(config *params.ChainConfig) Signer {
|
func LatestSigner(config *params.ChainConfig) Signer {
|
||||||
if config.ChainId != nil {
|
if config.ChainId != nil {
|
||||||
if common.Eip1559Block.Uint64() != 9999999999 || config.Eip1559Block != nil {
|
if common.Eip1559Block.Uint64() != 9999999999 || config.Eip1559Block != nil {
|
||||||
return NewEIP2930Signer(config.ChainId)
|
return NewLondonSigner(config.ChainId)
|
||||||
}
|
}
|
||||||
if config.EIP155Block != nil {
|
if config.EIP155Block != nil {
|
||||||
return NewEIP155Signer(config.ChainId)
|
return NewEIP155Signer(config.ChainId)
|
||||||
|
|
@ -83,7 +83,7 @@ func LatestSignerForChainID(chainID *big.Int) Signer {
|
||||||
if chainID == nil {
|
if chainID == nil {
|
||||||
return HomesteadSigner{}
|
return HomesteadSigner{}
|
||||||
}
|
}
|
||||||
return NewEIP2930Signer(chainID)
|
return NewLondonSigner(chainID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignTx signs the transaction using the given signer and private key.
|
// SignTx signs the transaction using the given signer and private key.
|
||||||
|
|
@ -170,6 +170,72 @@ type Signer interface {
|
||||||
Equal(Signer) bool
|
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 }
|
type eip2930Signer struct{ EIP155Signer }
|
||||||
|
|
||||||
// NewEIP2930Signer returns a signer that accepts EIP-2930 access list transactions,
|
// 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:
|
case LegacyTxType:
|
||||||
return s.EIP155Signer.Sender(tx)
|
return s.EIP155Signer.Sender(tx)
|
||||||
case AccessListTxType:
|
case AccessListTxType:
|
||||||
// ACL txs are defined to use 0 and 1 as their recovery id, add
|
// AL txs are defined to use 0 and 1 as their recovery
|
||||||
// 27 to become equivalent to unprotected Homestead signatures.
|
// id, add 27 to become equivalent to unprotected Homestead signatures.
|
||||||
V = new(big.Int).Add(V, big.NewInt(27))
|
V = new(big.Int).Add(V, big.NewInt(27))
|
||||||
default:
|
default:
|
||||||
return common.Address{}, ErrTxTypeNotSupported
|
return common.Address{}, ErrTxTypeNotSupported
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ func enable3198(jt *JumpTable) {
|
||||||
|
|
||||||
// opBaseFee implements BASEFEE opcode
|
// opBaseFee implements BASEFEE opcode
|
||||||
func opBaseFee(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) {
|
func opBaseFee(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) {
|
||||||
baseFee, _ := uint256.FromBig(common.MinGasPrice50x)
|
baseFee, _ := uint256.FromBig(common.BaseFee)
|
||||||
callContext.Stack.push(baseFee)
|
callContext.Stack.push(baseFee)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ type BlockContext struct {
|
||||||
BlockNumber *big.Int // Provides information for NUMBER
|
BlockNumber *big.Int // Provides information for NUMBER
|
||||||
Time *big.Int // Provides information for TIME
|
Time *big.Int // Provides information for TIME
|
||||||
Difficulty *big.Int // Provides information for DIFFICULTY
|
Difficulty *big.Int // Provides information for DIFFICULTY
|
||||||
|
BaseFee *big.Int // Provides information for BASEFEE
|
||||||
Random *common.Hash // Provides information for PREVRANDAO
|
Random *common.Hash // Provides information for PREVRANDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
|
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core"
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
|
|
@ -242,7 +241,8 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
|
||||||
balance = value
|
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{
|
txctx := &tracers.Context{
|
||||||
BlockHash: task.block.Hash(),
|
BlockHash: task.block.Hash(),
|
||||||
TxIndex: i,
|
TxIndex: i,
|
||||||
|
|
@ -486,7 +486,8 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
|
||||||
balance = value
|
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{
|
txctx := &tracers.Context{
|
||||||
BlockHash: blockHash,
|
BlockHash: blockHash,
|
||||||
TxIndex: task.index,
|
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
|
// 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)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
statedb.Prepare(tx.Hash(), i)
|
statedb.Prepare(tx.Hash(), i)
|
||||||
|
|
||||||
|
|
@ -800,7 +802,8 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree
|
||||||
balanceFee = value
|
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 {
|
if err != nil {
|
||||||
return nil, vm.BlockContext{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
|
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)
|
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})
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
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)
|
b.Fatalf("failed to parse testcase input: %v", err)
|
||||||
}
|
}
|
||||||
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)))
|
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 {
|
if err != nil {
|
||||||
b.Fatalf("failed to prepare transaction for tracing: %v", err)
|
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)
|
t.Fatalf("failed to create call tracer: %v", err)
|
||||||
}
|
}
|
||||||
evm := vm.NewEVM(context, txContext, statedb, nil, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
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})
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -336,7 +336,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
|
||||||
//EnableReturnData: false,
|
//EnableReturnData: false,
|
||||||
})
|
})
|
||||||
evm := vm.NewEVM(context, txContext, statedb, nil, params.AllEthashProtocolChanges, vm.Config{Debug: true, Tracer: tracer})
|
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 {
|
if err != nil {
|
||||||
b.Fatalf("failed to prepare transaction for tracing: %v", err)
|
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
|
Value *big.Int // amount of wei sent along with the call
|
||||||
Data []byte // input data, usually an ABI-encoded contract method invocation
|
Data []byte // input data, usually an ABI-encoded contract method invocation
|
||||||
BalanceTokenFee *big.Int
|
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
|
// 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.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
|
||||||
result.TransactionIndex = (*hexutil.Uint64)(&index)
|
result.TransactionIndex = (*hexutil.Uint64)(&index)
|
||||||
}
|
}
|
||||||
if tx.Type() == types.AccessListTxType {
|
if tx.Type() != types.LegacyTxType {
|
||||||
al := tx.AccessList()
|
al := tx.AccessList()
|
||||||
result.Accesses = &al
|
result.Accesses = &al
|
||||||
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
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 {
|
if value, ok := feeCapacity[to]; ok {
|
||||||
balanceTokenFee = value
|
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
|
// Apply the transaction with the access list tracer
|
||||||
tracer := vm.NewAccessListTracer(accessList, args.from(), to, precompiles)
|
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
|
// 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
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
|
||||||
if value, ok := feeCapacity[testContractAddr]; ok {
|
if value, ok := feeCapacity[testContractAddr]; ok {
|
||||||
balanceTokenFee = value
|
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)
|
context := core.NewEVMBlockContext(header, bc, nil)
|
||||||
txContext := core.NewEVMTxContext(msg)
|
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 {
|
if value, ok := feeCapacity[testContractAddr]; ok {
|
||||||
balanceTokenFee = value
|
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)
|
context := core.NewEVMBlockContext(header, lc, nil)
|
||||||
txContext := core.NewEVMTxContext(msg)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
vmenv := vm.NewEVM(context, txContext, statedb, nil, config, vm.Config{})
|
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 {
|
if value, ok := feeCapacity[testContractAddr]; ok {
|
||||||
balanceTokenFee = value
|
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)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
context := core.NewEVMBlockContext(header, chain, nil)
|
context := core.NewEVMBlockContext(header, chain, nil)
|
||||||
vmenv := vm.NewEVM(context, txContext, st, nil, config, vm.Config{})
|
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.
|
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
|
MaxCodeSize = 24576 // Maximum bytecode to permit for a contract
|
||||||
|
|
||||||
// Precompiled contract gas prices
|
// Precompiled contract gas prices
|
||||||
|
|
|
||||||
|
|
@ -241,7 +241,7 @@ func (tx *stTransaction) toMessage(ps stPostState, number *big.Int) (core.Messag
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid tx data %q", dataHex)
|
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
|
return msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue