Skip to content

Commit 69703be

Browse files
committed
all: implement eip-7702 set code tx 30078
1 parent 3af6290 commit 69703be

File tree

14 files changed

+468
-19
lines changed

14 files changed

+468
-19
lines changed

common/constants.all.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ type constant struct {
6464
tipEpochHalving *big.Int
6565
eip1559Block *big.Int
6666
cancunBlock *big.Int
67+
pragueBlock *big.Int
6768

6869
trc21IssuerSMC Address
6970
xdcxListingSMC Address
@@ -98,6 +99,7 @@ var (
9899
TIPXDCXReceiverDisable = MaintnetConstant.tipXDCXReceiverDisable
99100
Eip1559Block = MaintnetConstant.eip1559Block
100101
CancunBlock = MaintnetConstant.cancunBlock
102+
PragueBlock = MaintnetConstant.pragueBlock
101103
TIPUpgradeReward = MaintnetConstant.tipUpgradeReward
102104
TipUpgradePenalty = MaintnetConstant.tipUpgradePenalty
103105
TIPEpochHalving = MaintnetConstant.tipEpochHalving
@@ -160,6 +162,7 @@ func CopyConstants(chainID uint64) {
160162
TIPXDCXReceiverDisable = c.tipXDCXReceiverDisable
161163
Eip1559Block = c.eip1559Block
162164
CancunBlock = c.cancunBlock
165+
PragueBlock = c.pragueBlock
163166
TIPUpgradeReward = c.tipUpgradeReward
164167
TipUpgradePenalty = c.tipUpgradePenalty
165168
TIPEpochHalving = c.tipEpochHalving

common/constants.devnet.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ var DevnetConstant = constant{
2828
tipXDCXReceiverDisable: big.NewInt(0),
2929
eip1559Block: big.NewInt(32400),
3030
cancunBlock: big.NewInt(43200),
31+
pragueBlock: big.NewInt(9999999999),
3132
tipUpgradeReward: big.NewInt(9999999999),
3233
tipUpgradePenalty: big.NewInt(9999999999),
3334
tipEpochHalving: big.NewInt(9999999999),

common/constants.local.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ var localConstant = constant{
2828
tipXDCXReceiverDisable: big.NewInt(0),
2929
eip1559Block: big.NewInt(0),
3030
cancunBlock: big.NewInt(0),
31+
pragueBlock: big.NewInt(9999999999),
3132
tipUpgradeReward: big.NewInt(999999999),
3233
tipUpgradePenalty: big.NewInt(999999999),
3334
tipEpochHalving: big.NewInt(999999999),

common/constants.mainnet.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ var MaintnetConstant = constant{
2828
tipXDCXReceiverDisable: big.NewInt(80370900), // Target 2nd Oct 2024, safer to release after disable miner
2929
eip1559Block: big.NewInt(9999999999),
3030
cancunBlock: big.NewInt(9999999999),
31+
pragueBlock: big.NewInt(9999999999),
3132
tipUpgradeReward: big.NewInt(9999999999),
3233
tipUpgradePenalty: big.NewInt(9999999999),
3334
tipEpochHalving: big.NewInt(9999999999),

common/constants.testnet.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ var TestnetConstant = constant{
2828
tipXDCXReceiverDisable: big.NewInt(66825000), // Target 26 Aug 2024
2929
eip1559Block: big.NewInt(71550000), // Target 14th Feb 2025
3030
cancunBlock: big.NewInt(71551800),
31+
pragueBlock: big.NewInt(9999999999),
3132
tipUpgradeReward: big.NewInt(9999999999),
3233
tipUpgradePenalty: big.NewInt(9999999999),
3334
tipEpochHalving: big.NewInt(9999999999),

core/error.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,25 @@ var (
9999
// ErrSenderNoEOA is returned if the sender of a transaction is a contract.
100100
ErrSenderNoEOA = errors.New("sender not an eoa")
101101

102-
ErrNotXDPoS = errors.New("XDPoS not found in config")
103-
104-
ErrNotFoundM1 = errors.New("list M1 not found ")
102+
// -- XDPoS errors --
105103

104+
ErrNotXDPoS = errors.New("XDPoS not found in config")
105+
ErrNotFoundM1 = errors.New("list M1 not found ")
106106
ErrStopPreparingBlock = errors.New("stop calculating a block not verified by M2")
107+
108+
// -- EIP-7702 errors --
109+
110+
// Message validation errors:
111+
ErrEmptyAuthList = errors.New("EIP-7702 transaction with empty auth list")
112+
ErrSetCodeTxCreate = errors.New("EIP-7702 transaction cannot be used to create contract")
113+
)
114+
115+
// EIP-7702 state transition errors.
116+
// Note these are just informational, and do not cause tx execution abort.
117+
var (
118+
ErrAuthorizationWrongChainID = errors.New("EIP-7702 authorization chain ID mismatch")
119+
ErrAuthorizationNonceOverflow = errors.New("EIP-7702 authorization nonce > 64 bit")
120+
ErrAuthorizationInvalidSignature = errors.New("EIP-7702 authorization has invalid signature")
121+
ErrAuthorizationDestinationHasCode = errors.New("EIP-7702 authorization destination is a contract")
122+
ErrAuthorizationNonceMismatch = errors.New("EIP-7702 authorization nonce does not match current account nonce")
107123
)

core/types/transaction.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,11 @@ var (
5050

5151
// Transaction types.
5252
const (
53-
LegacyTxType = iota
54-
AccessListTxType
55-
DynamicFeeTxType
53+
LegacyTxType = 0x00
54+
AccessListTxType = 0x01
55+
DynamicFeeTxType = 0x02
56+
BlobTxType = 0x03
57+
SetCodeTxType = 0x04
5658
)
5759

5860
// Transaction is an Ethereum transaction.

core/types/tx_setcode.go

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
// Copyright 2024 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package types
18+
19+
import (
20+
"bytes"
21+
"crypto/ecdsa"
22+
"errors"
23+
"math/big"
24+
25+
"github.com/XinFinOrg/XDPoSChain/common"
26+
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
27+
"github.com/XinFinOrg/XDPoSChain/crypto"
28+
"github.com/XinFinOrg/XDPoSChain/rlp"
29+
"github.com/holiman/uint256"
30+
)
31+
32+
// DelegationPrefix is used by code to denote the account is delegating to
33+
// another account.
34+
var DelegationPrefix = []byte{0xef, 0x01, 0x00}
35+
36+
// ParseDelegation tries to parse the address from a delegation slice.
37+
func ParseDelegation(b []byte) (common.Address, bool) {
38+
if len(b) != 23 || !bytes.HasPrefix(b, DelegationPrefix) {
39+
return common.Address{}, false
40+
}
41+
return common.BytesToAddress(b[len(DelegationPrefix):]), true
42+
}
43+
44+
// AddressToDelegation adds the delegation prefix to the specified address.
45+
func AddressToDelegation(addr common.Address) []byte {
46+
return append(DelegationPrefix, addr.Bytes()...)
47+
}
48+
49+
// SetCodeTx implements the EIP-7702 transaction type which temporarily installs
50+
// the code at the signer's address.
51+
type SetCodeTx struct {
52+
ChainID uint64
53+
Nonce uint64
54+
GasTipCap *uint256.Int // a.k.a. maxPriorityFeePerGas
55+
GasFeeCap *uint256.Int // a.k.a. maxFeePerGas
56+
Gas uint64
57+
To common.Address
58+
Value *uint256.Int
59+
Data []byte
60+
AccessList AccessList
61+
AuthList []Authorization
62+
63+
// Signature values
64+
V *uint256.Int `json:"v" gencodec:"required"`
65+
R *uint256.Int `json:"r" gencodec:"required"`
66+
S *uint256.Int `json:"s" gencodec:"required"`
67+
}
68+
69+
//go:generate go run github.com/fjl/gencodec -type Authorization -field-override authorizationMarshaling -out gen_authorization.go
70+
71+
// Authorization is an authorization from an account to deploy code at its address.
72+
type Authorization struct {
73+
ChainID uint64 `json:"chainId" gencodec:"required"`
74+
Address common.Address `json:"address" gencodec:"required"`
75+
Nonce uint64 `json:"nonce" gencodec:"required"`
76+
V uint8 `json:"v" gencodec:"required"`
77+
R uint256.Int `json:"r" gencodec:"required"`
78+
S uint256.Int `json:"s" gencodec:"required"`
79+
}
80+
81+
// field type overrides for gencodec
82+
type authorizationMarshaling struct {
83+
ChainID hexutil.Uint64
84+
Nonce hexutil.Uint64
85+
V hexutil.Uint64
86+
}
87+
88+
// SignAuth signs the provided authorization.
89+
func SignAuth(auth Authorization, prv *ecdsa.PrivateKey) (Authorization, error) {
90+
sighash := auth.sigHash()
91+
sig, err := crypto.Sign(sighash[:], prv)
92+
if err != nil {
93+
return Authorization{}, err
94+
}
95+
return auth.withSignature(sig), nil
96+
}
97+
98+
// withSignature updates the signature of an Authorization to be equal the
99+
// decoded signature provided in sig.
100+
func (a *Authorization) withSignature(sig []byte) Authorization {
101+
r, s, _ := decodeSignature(sig)
102+
return Authorization{
103+
ChainID: a.ChainID,
104+
Address: a.Address,
105+
Nonce: a.Nonce,
106+
V: sig[64],
107+
R: *uint256.MustFromBig(r),
108+
S: *uint256.MustFromBig(s),
109+
}
110+
}
111+
112+
func (a *Authorization) sigHash() common.Hash {
113+
return prefixedRlpHash(0x05, []any{
114+
a.ChainID,
115+
a.Address,
116+
a.Nonce,
117+
})
118+
}
119+
120+
// Authority recovers the the authorizing account of an authorization.
121+
func (a *Authorization) Authority() (common.Address, error) {
122+
sighash := a.sigHash()
123+
if !crypto.ValidateSignatureValues(a.V, a.R.ToBig(), a.S.ToBig(), true) {
124+
return common.Address{}, ErrInvalidSig
125+
}
126+
// encode the signature in uncompressed format
127+
var sig [crypto.SignatureLength]byte
128+
a.R.WriteToSlice(sig[:32])
129+
a.S.WriteToSlice(sig[32:64])
130+
sig[64] = a.V
131+
// recover the public key from the signature
132+
pub, err := crypto.Ecrecover(sighash[:], sig[:])
133+
if err != nil {
134+
return common.Address{}, err
135+
}
136+
if len(pub) == 0 || pub[0] != 4 {
137+
return common.Address{}, errors.New("invalid public key")
138+
}
139+
var addr common.Address
140+
copy(addr[:], crypto.Keccak256(pub[1:])[12:])
141+
return addr, nil
142+
}
143+
144+
// copy creates a deep copy of the transaction data and initializes all fields.
145+
func (tx *SetCodeTx) copy() TxData {
146+
cpy := &SetCodeTx{
147+
Nonce: tx.Nonce,
148+
To: tx.To,
149+
Data: common.CopyBytes(tx.Data),
150+
Gas: tx.Gas,
151+
// These are copied below.
152+
AccessList: make(AccessList, len(tx.AccessList)),
153+
AuthList: make([]Authorization, len(tx.AuthList)),
154+
Value: new(uint256.Int),
155+
ChainID: tx.ChainID,
156+
GasTipCap: new(uint256.Int),
157+
GasFeeCap: new(uint256.Int),
158+
V: new(uint256.Int),
159+
R: new(uint256.Int),
160+
S: new(uint256.Int),
161+
}
162+
copy(cpy.AccessList, tx.AccessList)
163+
copy(cpy.AuthList, tx.AuthList)
164+
if tx.Value != nil {
165+
cpy.Value.Set(tx.Value)
166+
}
167+
if tx.GasTipCap != nil {
168+
cpy.GasTipCap.Set(tx.GasTipCap)
169+
}
170+
if tx.GasFeeCap != nil {
171+
cpy.GasFeeCap.Set(tx.GasFeeCap)
172+
}
173+
if tx.V != nil {
174+
cpy.V.Set(tx.V)
175+
}
176+
if tx.R != nil {
177+
cpy.R.Set(tx.R)
178+
}
179+
if tx.S != nil {
180+
cpy.S.Set(tx.S)
181+
}
182+
return cpy
183+
}
184+
185+
// accessors for innerTx.
186+
func (tx *SetCodeTx) txType() byte { return SetCodeTxType }
187+
func (tx *SetCodeTx) chainID() *big.Int { return big.NewInt(int64(tx.ChainID)) }
188+
func (tx *SetCodeTx) accessList() AccessList { return tx.AccessList }
189+
func (tx *SetCodeTx) data() []byte { return tx.Data }
190+
func (tx *SetCodeTx) gas() uint64 { return tx.Gas }
191+
func (tx *SetCodeTx) gasFeeCap() *big.Int { return tx.GasFeeCap.ToBig() }
192+
func (tx *SetCodeTx) gasTipCap() *big.Int { return tx.GasTipCap.ToBig() }
193+
func (tx *SetCodeTx) gasPrice() *big.Int { return tx.GasFeeCap.ToBig() }
194+
func (tx *SetCodeTx) value() *big.Int { return tx.Value.ToBig() }
195+
func (tx *SetCodeTx) nonce() uint64 { return tx.Nonce }
196+
func (tx *SetCodeTx) to() *common.Address { tmp := tx.To; return &tmp }
197+
198+
func (tx *SetCodeTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
199+
if baseFee == nil {
200+
return dst.Set(tx.GasFeeCap.ToBig())
201+
}
202+
tip := dst.Sub(tx.GasFeeCap.ToBig(), baseFee)
203+
if tip.Cmp(tx.GasTipCap.ToBig()) > 0 {
204+
tip.Set(tx.GasTipCap.ToBig())
205+
}
206+
return tip.Add(tip, baseFee)
207+
}
208+
209+
func (tx *SetCodeTx) rawSignatureValues() (v, r, s *big.Int) {
210+
return tx.V.ToBig(), tx.R.ToBig(), tx.S.ToBig()
211+
}
212+
213+
func (tx *SetCodeTx) setSignatureValues(chainID, v, r, s *big.Int) {
214+
tx.ChainID = chainID.Uint64()
215+
tx.V.SetFromBig(v)
216+
tx.R.SetFromBig(r)
217+
tx.S.SetFromBig(s)
218+
}
219+
220+
func (tx *SetCodeTx) encode(b *bytes.Buffer) error {
221+
return rlp.Encode(b, tx)
222+
}
223+
224+
func (tx *SetCodeTx) decode(input []byte) error {
225+
return rlp.DecodeBytes(input, tx)
226+
}

0 commit comments

Comments
 (0)