/
ante.go
148 lines (127 loc) · 4.33 KB
/
ante.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package ante
import (
"fmt"
"runtime/debug"
tmlog "github.com/tendermint/tendermint/libs/log"
errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
sdk "github.com/cosmos/cosmos-sdk/types"
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/xtelabs/xtechain/crypto/ethsecp256k1"
)
const (
secp256k1VerifyCost uint64 = 21000
)
// NewAnteHandler returns an ante handler responsible for attempting to route an
// Ethereum or SDK transaction to an internal ante handler for performing
// transaction-level processing (e.g. fee payment, signature verification) before
// being passed onto it's respective handler.
func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
if err := options.validate(); err != nil {
return nil, err
}
return func(
ctx sdk.Context, tx sdk.Tx, sim bool,
) (newCtx sdk.Context, err error) {
var anteHandler sdk.AnteHandler
defer Recover(ctx.Logger(), &err)
txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx)
if ok {
opts := txWithExtensions.GetExtensionOptions()
if len(opts) > 0 {
switch typeURL := opts[0].GetTypeUrl(); typeURL {
case "/xte.evm.v1.ExtensionOptionsEthereumTx":
// handle as *evmtypes.MsgEthereumTx
anteHandler = newEthAnteHandler(options)
case "/xte.types.v1.ExtensionOptionsWeb3Tx":
// Deprecated: Handle as normal Cosmos SDK tx, except signature is checked for Legacy EIP712 representation
anteHandler = NewLegacyCosmosAnteHandlerEip712(options)
case "/xte.types.v1.ExtensionOptionDynamicFeeTx":
// cosmos-sdk tx with dynamic fee extension
anteHandler = newCosmosAnteHandler(options)
default:
return ctx, errorsmod.Wrapf(
errortypes.ErrUnknownExtensionOptions,
"rejecting tx with unsupported extension option: %s", typeURL,
)
}
return anteHandler(ctx, tx, sim)
}
}
// handle as totally normal Cosmos SDK tx
switch tx.(type) {
case sdk.Tx:
anteHandler = newCosmosAnteHandler(options)
default:
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid transaction type: %T", tx)
}
return anteHandler(ctx, tx, sim)
}, nil
}
func Recover(logger tmlog.Logger, err *error) {
if r := recover(); r != nil {
*err = errorsmod.Wrapf(errortypes.ErrPanic, "%v", r)
if e, ok := r.(error); ok {
logger.Error(
"ante handler panicked",
"error", e,
"stack trace", string(debug.Stack()),
)
} else {
logger.Error(
"ante handler panicked",
"recover", fmt.Sprintf("%v", r),
)
}
}
}
var _ authante.SignatureVerificationGasConsumer = DefaultSigVerificationGasConsumer
// DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas
// for signature verification based upon the public key type. The cost is fetched from the given params and is matched
// by the concrete type.
func DefaultSigVerificationGasConsumer(
meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params,
) error {
pubkey := sig.PubKey
switch pubkey := pubkey.(type) {
case *ethsecp256k1.PubKey:
meter.ConsumeGas(secp256k1VerifyCost, "ante verify: eth_secp256k1")
return nil
case multisig.PubKey:
// Multisig keys
multisignature, ok := sig.Data.(*signing.MultiSignatureData)
if !ok {
return fmt.Errorf("expected %T, got, %T", &signing.MultiSignatureData{}, sig.Data)
}
return ConsumeMultisignatureVerificationGas(meter, multisignature, pubkey, params, sig.Sequence)
default:
return authante.DefaultSigVerificationGasConsumer(meter, sig, params)
}
}
// ConsumeMultisignatureVerificationGas consumes gas from a GasMeter for verifying a multisig pubkey signature
func ConsumeMultisignatureVerificationGas(
meter sdk.GasMeter, sig *signing.MultiSignatureData, pubkey multisig.PubKey,
params authtypes.Params, accSeq uint64,
) error {
size := sig.BitArray.Count()
sigIndex := 0
for i := 0; i < size; i++ {
if !sig.BitArray.GetIndex(i) {
continue
}
sigV2 := signing.SignatureV2{
PubKey: pubkey.GetPubKeys()[i],
Data: sig.Signatures[sigIndex],
Sequence: accSeq,
}
err := DefaultSigVerificationGasConsumer(meter, sigV2, params)
if err != nil {
return err
}
sigIndex++
}
return nil
}