-
Notifications
You must be signed in to change notification settings - Fork 22
/
tx_data.go
134 lines (114 loc) · 3.16 KB
/
tx_data.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package types
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)
var (
_ TxData = &LegacyTx{}
_ TxData = &AccessListTx{}
_ TxData = &DynamicFeeTx{}
)
const (
// txSlotSize is used to calculate how many data slots a single transaction
// takes up based on its size. The slots are used as DoS protection, ensuring
// that validating a new transaction remains a constant operation (in reality
// O(maxslots), where max slots are 4 currently).
TxSlotSize = 32 * 1024
// txMaxSize is the maximum size a single transaction can have. This field has
// non-trivial consequences: larger transactions are significantly harder and
// more expensive to propagate; larger transactions also take more resources
// to validate whether they fit into the pool or not.
TxMaxSize = 4 * TxSlotSize // 128KB
)
// TxData implements the Ethereum transaction tx structure. It is used
// solely as intended in Ethereum abiding by the protocol.
type TxData interface {
// TODO: embed ethtypes.TxData. See https://github.com/ethereum/go-ethereum/issues/23154
TxType() byte
Copy() TxData
GetChainID() *big.Int
GetAccessList() ethtypes.AccessList
GetData() []byte
GetNonce() uint64
GetGas() uint64
GetGasPrice() *big.Int
GetGasTipCap() *big.Int
GetGasFeeCap() *big.Int
GetValue() *big.Int
GetTo() *common.Address
GetRawSignatureValues() (v, r, s *big.Int)
SetSignatureValues(chainID, v, r, s *big.Int)
AsEthereumData() ethtypes.TxData
Validate() error
// static fee
Fee() *big.Int
Cost() *big.Int
// effective fee according to current base fee
EffectiveFee(baseFee *big.Int) *big.Int
EffectiveCost(baseFee *big.Int) *big.Int
}
func NewTxDataFromTx(tx *ethtypes.Transaction) (TxData, error) {
var txData TxData
var err error
switch tx.Type() {
case ethtypes.DynamicFeeTxType:
txData, err = newDynamicFeeTx(tx)
case ethtypes.AccessListTxType:
txData, err = newAccessListTx(tx)
default:
txData, err = newLegacyTx(tx)
}
if err != nil {
return nil, err
}
return txData, nil
}
// DeriveChainID derives the chain id from the given v parameter.
//
// CONTRACT: v value is either:
//
// - {0,1} + CHAIN_ID * 2 + 35, if EIP155 is used
// - {0,1} + 27, otherwise
//
// Ref: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
func DeriveChainID(v *big.Int) *big.Int {
if v == nil || v.Sign() < 1 {
return nil
}
if v.BitLen() <= 64 {
v := v.Uint64()
if v == 27 || v == 28 {
return new(big.Int)
}
if v < 35 {
return nil
}
// V MUST be of the form {0,1} + CHAIN_ID * 2 + 35
return new(big.Int).SetUint64((v - 35) / 2)
}
v = new(big.Int).Sub(v, big.NewInt(35))
return v.Div(v, big.NewInt(2))
}
func rawSignatureValues(vBz, rBz, sBz []byte) (v, r, s *big.Int) {
if len(vBz) > 0 {
v = new(big.Int).SetBytes(vBz)
}
if len(rBz) > 0 {
r = new(big.Int).SetBytes(rBz)
}
if len(sBz) > 0 {
s = new(big.Int).SetBytes(sBz)
}
return v, r, s
}
func fee(gasPrice *big.Int, gas uint64) *big.Int {
gasLimit := new(big.Int).SetUint64(gas)
return new(big.Int).Mul(gasPrice, gasLimit)
}
func cost(fee, value *big.Int) *big.Int {
if value != nil {
return new(big.Int).Add(fee, value)
}
return fee
}