-
Notifications
You must be signed in to change notification settings - Fork 74
/
tx_verify.go
115 lines (95 loc) · 3.81 KB
/
tx_verify.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
package keeper
import (
"errors"
"math/big"
"github.com/artela-network/artela/ethereum/utils"
"github.com/ethereum/go-ethereum/params"
errorsmod "cosmossdk.io/errors"
artelatype "github.com/artela-network/artela/x/evm/artela/types"
"github.com/artela-network/artela/x/evm/states"
"github.com/artela-network/aspect-core/djpm"
cosmos "github.com/cosmos/cosmos-sdk/types"
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/ethereum/go-ethereum/common"
ethereum "github.com/ethereum/go-ethereum/core/types"
)
func (k *Keeper) VerifySig(ctx cosmos.Context, tx *ethereum.Transaction) (common.Address, []byte, error) {
// tx without signature
txConfig := k.TxConfig(ctx, tx.Hash(), tx.Type())
stateDB := states.New(ctx, k, txConfig)
// calling a contract without signature, verify with aspect
// this verification method is only allowed in call contract,
// transactions that transfer value or creating contract must be signed
if k.isCustomizedVerification(tx) && (stateDB.GetCodeHash(*tx.To()) != common.Hash{}) {
return k.tryAspectVerifier(ctx, tx)
}
// tx with valid ec sig
chainID := k.ChainID()
evmParams := k.GetParams(ctx)
chainCfg := evmParams.GetChainConfig()
ethCfg := chainCfg.EthereumConfig(chainID)
blockNum := big.NewInt(ctx.BlockHeight())
signer := ethereum.MakeSigner(ethCfg, blockNum, uint64(ctx.BlockTime().Unix()))
allowUnprotectedTxs := evmParams.GetAllowUnprotectedTxs()
if !allowUnprotectedTxs && !tx.Protected() {
return common.Address{}, nil, errorsmod.Wrapf(
errortypes.ErrNotSupported,
"rejected unprotected Ethereum transaction. Please EIP155 sign your transaction to protect it against replay-attacks")
}
sender, err := signer.Sender(tx)
if err != nil {
return common.Address{}, nil, errorsmod.Wrapf(
errortypes.ErrorInvalidSigner,
"couldn't retrieve sender address from the ethereum transaction: %s",
err.Error(),
)
}
return sender, nil, nil
}
func (k *Keeper) tryAspectVerifier(ctx cosmos.Context, tx *ethereum.Transaction) (common.Address, []byte, error) {
// retrieve aspectCtx from sdk.Context
aspectCtx, ok := ctx.Value(artelatype.AspectContextKey).(*artelatype.AspectRuntimeContext)
if !ok {
return common.Address{}, []byte{}, errors.New("ApplyMessageWithConfig: wrap *artelatype.AspectRuntimeContext failed")
}
return djpm.AspectInstance().GetSenderAndCallData(aspectCtx, aspectCtx.EthBlockContext().BlockHeader().Number.Int64(), tx)
}
func (k *Keeper) MakeSigner(ctx cosmos.Context, tx *ethereum.Transaction, config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) ethereum.Signer {
txConfig := k.TxConfig(ctx, tx.Hash(), tx.Type())
stateDB := states.New(ctx, k, txConfig)
if k.isCustomizedVerification(tx) && (stateDB.GetCodeHash(*tx.To()) != common.Hash{}) {
return &aspectSigner{k, ctx}
}
return ethereum.MakeSigner(config, blockNumber, blockTime)
}
func (k *Keeper) isCustomizedVerification(tx *ethereum.Transaction) bool {
return utils.IsCustomizedVerification(tx)
}
func (k *Keeper) processMsgData(tx *ethereum.Transaction) ([]byte, error) {
if k.isCustomizedVerification(tx) {
_, callData, err := djpm.DecodeValidationAndCallData(tx.Data())
return callData, err
}
return tx.Data(), nil
}
type aspectSigner struct {
keeper *Keeper
ctx cosmos.Context
}
func (a *aspectSigner) Sender(tx *ethereum.Transaction) (common.Address, error) {
sender, _, err := a.keeper.VerifySig(a.ctx, tx)
return sender, err
}
func (a *aspectSigner) SignatureValues(tx *ethereum.Transaction, sig []byte) (r, s, v *big.Int, err error) {
return nil, nil, nil, errors.New("not supported")
}
func (a *aspectSigner) ChainID() *big.Int {
return a.keeper.ChainID()
}
func (a *aspectSigner) Hash(tx *ethereum.Transaction) common.Hash {
return tx.Hash()
}
func (a *aspectSigner) Equal(signer ethereum.Signer) bool {
_, ok := signer.(*aspectSigner)
return ok
}