-
Notifications
You must be signed in to change notification settings - Fork 7
/
utils.go
152 lines (131 loc) · 4.92 KB
/
utils.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
149
150
151
152
// Copyright 2021 Evmos Foundation
// This file is part of Evmos' Ethermint library.
//
// The Ethermint library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The Ethermint library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the Ethermint library. If not, see https://github.com/planq-network/planq/v2/blob/main/LICENSE
package types
import (
"fmt"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"math/big"
"github.com/gogo/protobuf/proto"
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
)
// DefaultPriorityReduction is the default amount of price values required for 1 unit of priority.
// Because priority is `int64` while price is `big.Int`, it's necessary to scale down the range to keep it more pratical.
// The default value is the same as the `sdk.DefaultPowerReduction`.
var DefaultPriorityReduction = sdk.DefaultPowerReduction
var EmptyCodeHash = crypto.Keccak256(nil)
// DecodeTxResponse decodes an protobuf-encoded byte slice into TxResponse
func DecodeTxResponse(in []byte) (*MsgEthereumTxResponse, error) {
var txMsgData sdk.TxMsgData
if err := proto.Unmarshal(in, &txMsgData); err != nil {
return nil, err
}
if len(txMsgData.MsgResponses) == 0 {
return &MsgEthereumTxResponse{}, nil
}
var res MsgEthereumTxResponse
if err := proto.Unmarshal(txMsgData.MsgResponses[0].Value, &res); err != nil {
return nil, errorsmod.Wrap(err, "failed to unmarshal tx response message data")
}
return &res, nil
}
// DecodeTxResponses decodes a protobuf-encoded byte slice into TxResponses
func DecodeTxResponses(in []byte) ([]*MsgEthereumTxResponse, error) {
var txMsgData sdk.TxMsgData
if err := proto.Unmarshal(in, &txMsgData); err != nil {
return nil, err
}
responses := make([]*MsgEthereumTxResponse, len(txMsgData.MsgResponses))
for i, res := range txMsgData.MsgResponses {
var response MsgEthereumTxResponse
if err := proto.Unmarshal(res.Value, &response); err != nil {
return nil, sdkerrors.Wrap(err, "failed to unmarshal tx response message data")
}
responses[i] = &response
}
return responses, nil
}
// DecodeTxLogsFromEvents decodes a protobuf-encoded byte slice into ethereum logs
func DecodeTxLogsFromEvents(in []byte) ([]*ethtypes.Log, error) {
txResponses, err := DecodeTxResponses(in)
if err != nil {
return nil, err
}
var txLogs []*Log
for _, response := range txResponses {
txLogs = append(txLogs, response.Logs...)
}
return LogsToEthereum(txLogs), nil
}
// EncodeTransactionLogs encodes TransactionLogs slice into a protobuf-encoded byte slice.
func EncodeTransactionLogs(res *TransactionLogs) ([]byte, error) {
return proto.Marshal(res)
}
// DecodeTransactionLogs decodes an protobuf-encoded byte slice into TransactionLogs
func DecodeTransactionLogs(data []byte) (TransactionLogs, error) {
var logs TransactionLogs
err := proto.Unmarshal(data, &logs)
if err != nil {
return TransactionLogs{}, err
}
return logs, nil
}
// UnwrapEthereumMsg extract MsgEthereumTx from wrapping sdk.Tx
func UnwrapEthereumMsg(tx *sdk.Tx, ethHash common.Hash) (*MsgEthereumTx, error) {
if tx == nil {
return nil, fmt.Errorf("invalid tx: nil")
}
for _, msg := range (*tx).GetMsgs() {
ethMsg, ok := msg.(*MsgEthereumTx)
if !ok {
return nil, fmt.Errorf("invalid tx type: %T", tx)
}
txHash := ethMsg.AsTransaction().Hash()
ethMsg.Hash = txHash.Hex()
if txHash == ethHash {
return ethMsg, nil
}
}
return nil, fmt.Errorf("eth tx not found: %s", ethHash)
}
// BinSearch execute the binary search and hone in on an executable gas limit
func BinSearch(lo, hi uint64, executable func(uint64) (bool, *MsgEthereumTxResponse, error)) (uint64, error) {
for lo+1 < hi {
mid := (hi + lo) / 2
failed, _, err := executable(mid)
// If the error is not nil(consensus error), it means the provided message
// call or transaction will never be accepted no matter how much gas it is
// assigned. Return the error directly, don't struggle any more.
if err != nil {
return 0, err
}
if failed {
lo = mid
} else {
hi = mid
}
}
return hi, nil
}
// EffectiveGasPrice compute the effective gas price based on eip-1159 rules
// `effectiveGasPrice = min(baseFee + tipCap, feeCap)`
func EffectiveGasPrice(baseFee *big.Int, feeCap *big.Int, tipCap *big.Int) *big.Int {
return math.BigMin(new(big.Int).Add(tipCap, baseFee), feeCap)
}