100 lines
2.6 KiB
Go
100 lines
2.6 KiB
Go
package types
|
|
|
|
import (
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/gogo/protobuf/proto"
|
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/crypto"
|
|
)
|
|
|
|
const maxBitLen = 256
|
|
|
|
var EmptyCodeHash = crypto.Keccak256(nil)
|
|
|
|
// DecodeTxResponse decodes an protobuf-encoded byte slice into TxResponse
|
|
func DecodeTxResponse(in []byte, cdc codec.Codec) (*MsgEthereumTxResponse, error) {
|
|
var txMsgData sdk.TxMsgData
|
|
if err := txMsgData.Unmarshal(in); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
responses := txMsgData.GetMsgResponses()
|
|
if len(responses) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
if err := cdc.UnpackAny(responses[0], new(TxResponse)); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal tx response message: %w", err)
|
|
}
|
|
|
|
msgval := responses[0].GetCachedValue()
|
|
res, ok := msgval.(*MsgEthereumTxResponse)
|
|
if !ok {
|
|
return nil, fmt.Errorf("tx response message has invalid type: %T", msgval)
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
// EncodeTransactionLogs encodes TransactionLogs slice into a protobuf-encoded byte slice.
|
|
func EncodeTransactionLogs(res *TransactionLogs) ([]byte, error) {
|
|
return proto.Marshal(res)
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
if ethMsg.AsTransaction().Hash() == 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
|
|
}
|
|
|
|
// SafeNewIntFromBigInt constructs Int from big.Int, return error if more than 256bits
|
|
func SafeNewIntFromBigInt(i *big.Int) (sdk.Int, error) {
|
|
if !IsValidInt256(i) {
|
|
return sdk.NewInt(0), fmt.Errorf("big int out of bound: %s", i)
|
|
}
|
|
return sdk.NewIntFromBigInt(i), nil
|
|
}
|
|
|
|
// IsValidInt256 check the bound of 256 bit number
|
|
func IsValidInt256(i *big.Int) bool {
|
|
return i == nil || i.BitLen() <= maxBitLen
|
|
}
|