-
Notifications
You must be signed in to change notification settings - Fork 510
/
txsigner.go
117 lines (91 loc) · 2.71 KB
/
txsigner.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
package crypto
import (
"crypto/ecdsa"
"fmt"
"math/big"
"github.com/0xPolygon/polygon-edge/chain"
"github.com/0xPolygon/polygon-edge/helper/keccak"
"github.com/0xPolygon/polygon-edge/types"
)
// Magic numbers from Ethereum, used in v calculation
var (
big27 = big.NewInt(27)
big35 = big.NewInt(35)
)
// TxSigner is a utility interface used to recover data from a transaction
type TxSigner interface {
// Hash returns the hash of the transaction
Hash(tx *types.Transaction) types.Hash
// Sender returns the sender of the transaction
Sender(tx *types.Transaction) (types.Address, error)
// SignTx signs a transaction
SignTx(tx *types.Transaction, priv *ecdsa.PrivateKey) (*types.Transaction, error)
}
// NewSigner creates a new signer object (EIP155 or FrontierSigner)
func NewSigner(forks chain.ForksInTime, chainID uint64) TxSigner {
var signer TxSigner
if forks.EIP155 {
signer = NewEIP155Signer(chainID, forks.Homestead)
} else {
signer = NewFrontierSigner(forks.Homestead)
}
// London signer requires a fallback signer that is defined above.
// This is the reason why the london signer check is separated.
if forks.London {
return NewLondonSigner(chainID, forks.Homestead, signer)
}
return signer
}
// encodeSignature generates a signature value based on the R, S and V value
func encodeSignature(R, S, V *big.Int, isHomestead bool) ([]byte, error) {
if !ValidateSignatureValues(V, R, S, isHomestead) {
return nil, fmt.Errorf("invalid txn signature")
}
sig := make([]byte, 65)
copy(sig[32-len(R.Bytes()):32], R.Bytes())
copy(sig[64-len(S.Bytes()):64], S.Bytes())
sig[64] = byte(V.Int64()) // here is safe to convert it since ValidateSignatureValues will validate the v value
return sig, nil
}
// calcTxHash calculates the transaction hash (keccak256 hash of the RLP value)
func calcTxHash(tx *types.Transaction, chainID uint64) types.Hash {
a := signerPool.Get()
isDynamicFeeTx := tx.Type == types.DynamicFeeTx
v := a.NewArray()
if isDynamicFeeTx {
v.Set(a.NewUint(chainID))
}
v.Set(a.NewUint(tx.Nonce))
if isDynamicFeeTx {
v.Set(a.NewBigInt(tx.GasTipCap))
v.Set(a.NewBigInt(tx.GasFeeCap))
} else {
v.Set(a.NewBigInt(tx.GasPrice))
}
v.Set(a.NewUint(tx.Gas))
if tx.To == nil {
v.Set(a.NewNull())
} else {
v.Set(a.NewCopyBytes((*tx.To).Bytes()))
}
v.Set(a.NewBigInt(tx.Value))
v.Set(a.NewCopyBytes(tx.Input))
if isDynamicFeeTx {
v.Set(a.NewArray())
} else {
// EIP155
if chainID != 0 {
v.Set(a.NewUint(chainID))
v.Set(a.NewUint(0))
v.Set(a.NewUint(0))
}
}
var hash []byte
if isDynamicFeeTx {
hash = keccak.PrefixedKeccak256Rlp([]byte{byte(tx.Type)}, nil, v)
} else {
hash = keccak.Keccak256Rlp(nil, v)
}
signerPool.Put(a)
return types.BytesToHash(hash)
}