mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
wip
This commit is contained in:
parent
d4d88f9bce
commit
ef06b2955d
5 changed files with 137 additions and 4 deletions
|
|
@ -139,6 +139,7 @@ type Message struct {
|
|||
AccessList types.AccessList
|
||||
BlobGasFeeCap *big.Int
|
||||
BlobHashes []common.Hash
|
||||
Delegate bool
|
||||
|
||||
// When SkipAccountChecks is true, the message nonce is not checked against the
|
||||
// account nonce in state. It also disables checking that the sender is an EOA.
|
||||
|
|
@ -161,6 +162,7 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
|
|||
SkipAccountChecks: false,
|
||||
BlobHashes: tx.BlobHashes(),
|
||||
BlobGasFeeCap: tx.BlobGasFeeCap(),
|
||||
Delegate: tx.Delegate(),
|
||||
}
|
||||
// If baseFee provided, set gasPrice to effectiveGasPrice.
|
||||
if baseFee != nil {
|
||||
|
|
@ -416,7 +418,12 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||
} else {
|
||||
// Increment the nonce for the next transaction
|
||||
st.state.SetNonce(msg.From, st.state.GetNonce(sender.Address())+1)
|
||||
ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, msg.Value)
|
||||
if !msg.Delegate {
|
||||
ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, msg.Value)
|
||||
} else {
|
||||
var contract = vm.NewContract(sender, sender, nil, st.gasRemaining)
|
||||
ret, st.gasRemaining, vmerr = st.evm.DelegateCall(contract, st.to(), msg.Data, st.gasRemaining)
|
||||
}
|
||||
}
|
||||
|
||||
if !rules.IsLondon {
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ func ValidateTransaction(tx *types.Transaction, blobs []kzg4844.Blob, commits []
|
|||
if !opts.Config.IsCancun(head.Number, head.Time) && tx.Type() == types.BlobTxType {
|
||||
return fmt.Errorf("%w: type %d rejected, pool not yet in Cancun", core.ErrTxTypeNotSupported, tx.Type())
|
||||
}
|
||||
if !opts.Config.IsPrague(head.Number, head.Time) && tx.Type() == types.DelegateTxType {
|
||||
return fmt.Errorf("%w: type %d rejected, pool not yet in Prague", core.ErrTxTypeNotSupported, tx.Type())
|
||||
}
|
||||
// Check whether the init code size has been exceeded
|
||||
if opts.Config.IsShanghai(head.Number, head.Time) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize {
|
||||
return fmt.Errorf("%w: code size %v, limit %v", core.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize)
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ func (r *Receipt) decodeTyped(b []byte) error {
|
|||
return errShortTypedReceipt
|
||||
}
|
||||
switch b[0] {
|
||||
case DynamicFeeTxType, AccessListTxType, BlobTxType:
|
||||
case DynamicFeeTxType, AccessListTxType, BlobTxType, DelegateTxType:
|
||||
var data receiptRLP
|
||||
err := rlp.DecodeBytes(b[1:], &data)
|
||||
if err != nil {
|
||||
|
|
@ -302,7 +302,7 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) {
|
|||
}
|
||||
w.WriteByte(r.Type)
|
||||
switch r.Type {
|
||||
case AccessListTxType, DynamicFeeTxType, BlobTxType:
|
||||
case AccessListTxType, DynamicFeeTxType, BlobTxType, DelegateTxType:
|
||||
rlp.Encode(w, data)
|
||||
default:
|
||||
// For unsupported types, write nothing. Since this is for
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ const (
|
|||
AccessListTxType = 0x01
|
||||
DynamicFeeTxType = 0x02
|
||||
BlobTxType = 0x03
|
||||
DelegateTxType = 0x04
|
||||
)
|
||||
|
||||
// Transaction is an Ethereum transaction.
|
||||
|
|
@ -68,7 +69,7 @@ func NewTx(inner TxData) *Transaction {
|
|||
|
||||
// TxData is the underlying data of a transaction.
|
||||
//
|
||||
// This is implemented by DynamicFeeTx, LegacyTx and AccessListTx.
|
||||
// This is implemented by DynamicFeeTx, LegacyTx, AccessListTx and DelegateTx.
|
||||
type TxData interface {
|
||||
txType() byte // returns the type ID
|
||||
copy() TxData // creates a deep copy and initializes all fields
|
||||
|
|
@ -200,6 +201,10 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
|
|||
var inner BlobTx
|
||||
err := rlp.DecodeBytes(b[1:], &inner)
|
||||
return &inner, err
|
||||
case DelegateTxType:
|
||||
var inner DelegateTx
|
||||
err := rlp.DecodeBytes(b[1:], &inner)
|
||||
return &inner, err
|
||||
default:
|
||||
return nil, ErrTxTypeNotSupported
|
||||
}
|
||||
|
|
@ -264,6 +269,11 @@ func (tx *Transaction) Type() uint8 {
|
|||
return tx.inner.txType()
|
||||
}
|
||||
|
||||
// Delegate returns wether the transaction type corresponds to a delegate operation or not. (see EIP-5806)
|
||||
func (tx *Transaction) Delegate() bool {
|
||||
return tx.inner.txType() == DelegateTxType
|
||||
}
|
||||
|
||||
// ChainId returns the EIP155 chain ID of the transaction. The return value will always be
|
||||
// non-nil. For legacy transactions which are not replay-protected, the return value is
|
||||
// zero.
|
||||
|
|
|
|||
113
core/types/tx_delegate.go
Normal file
113
core/types/tx_delegate.go
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
// 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/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// DelegateTx represents an EIP-5806 transaction.
|
||||
type DelegateTx struct {
|
||||
ChainID *big.Int
|
||||
Nonce uint64
|
||||
GasTipCap *big.Int // a.k.a. maxPriorityFeePerGas
|
||||
GasFeeCap *big.Int // a.k.a. maxFeePerGas
|
||||
Gas uint64
|
||||
To *common.Address `rlp:"nil"` // nil means contract creation
|
||||
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 *DelegateTx) copy() TxData {
|
||||
cpy := &DelegateTx{
|
||||
Nonce: tx.Nonce,
|
||||
To: copyAddressPtr(tx.To),
|
||||
Data: common.CopyBytes(tx.Data),
|
||||
Gas: tx.Gas,
|
||||
// These are copied below.
|
||||
AccessList: make(AccessList, len(tx.AccessList)),
|
||||
ChainID: new(big.Int),
|
||||
GasTipCap: new(big.Int),
|
||||
GasFeeCap: new(big.Int),
|
||||
V: new(big.Int),
|
||||
R: new(big.Int),
|
||||
S: new(big.Int),
|
||||
}
|
||||
copy(cpy.AccessList, tx.AccessList)
|
||||
if tx.ChainID != nil {
|
||||
cpy.ChainID.Set(tx.ChainID)
|
||||
}
|
||||
if tx.GasTipCap != nil {
|
||||
cpy.GasTipCap.Set(tx.GasTipCap)
|
||||
}
|
||||
if tx.GasFeeCap != nil {
|
||||
cpy.GasFeeCap.Set(tx.GasFeeCap)
|
||||
}
|
||||
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 *DelegateTx) txType() byte { return DelegateTxType }
|
||||
func (tx *DelegateTx) chainID() *big.Int { return tx.ChainID }
|
||||
func (tx *DelegateTx) accessList() AccessList { return tx.AccessList }
|
||||
func (tx *DelegateTx) data() []byte { return tx.Data }
|
||||
func (tx *DelegateTx) gas() uint64 { return tx.Gas }
|
||||
func (tx *DelegateTx) gasFeeCap() *big.Int { return tx.GasFeeCap }
|
||||
func (tx *DelegateTx) gasTipCap() *big.Int { return tx.GasTipCap }
|
||||
func (tx *DelegateTx) gasPrice() *big.Int { return tx.GasFeeCap }
|
||||
func (tx *DelegateTx) value() *big.Int { return big.NewInt(0) }
|
||||
func (tx *DelegateTx) nonce() uint64 { return tx.Nonce }
|
||||
func (tx *DelegateTx) to() *common.Address { return tx.To }
|
||||
func (tx *DelegateTx) blobGas() uint64 { return 0 }
|
||||
func (tx *DelegateTx) blobGasFeeCap() *big.Int { return nil }
|
||||
func (tx *DelegateTx) blobHashes() []common.Hash { return nil }
|
||||
|
||||
func (tx *DelegateTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
|
||||
if baseFee == nil {
|
||||
return dst.Set(tx.GasFeeCap)
|
||||
}
|
||||
tip := dst.Sub(tx.GasFeeCap, baseFee)
|
||||
if tip.Cmp(tx.GasTipCap) > 0 {
|
||||
tip.Set(tx.GasTipCap)
|
||||
}
|
||||
return tip.Add(tip, baseFee)
|
||||
}
|
||||
|
||||
func (tx *DelegateTx) rawSignatureValues() (v, r, s *big.Int) {
|
||||
return tx.V, tx.R, tx.S
|
||||
}
|
||||
|
||||
func (tx *DelegateTx) setSignatureValues(chainID, v, r, s *big.Int) {
|
||||
tx.ChainID, tx.V, tx.R, tx.S = chainID, v, r, s
|
||||
}
|
||||
Loading…
Reference in a new issue