-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathutils.go
More file actions
138 lines (128 loc) · 3.61 KB
/
utils.go
File metadata and controls
138 lines (128 loc) · 3.61 KB
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
package api
import (
"encoding/hex"
"errors"
"fmt"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/rpc"
"github.com/onflow/flow-evm-gateway/metrics"
errs "github.com/onflow/flow-evm-gateway/models/errors"
"github.com/onflow/flow-evm-gateway/storage"
"github.com/rs/zerolog"
)
func resolveBlockTag(
blockNumberOrHash *rpc.BlockNumberOrHash,
blocksDB storage.BlockIndexer,
logger zerolog.Logger,
) (uint64, error) {
if blockNumberOrHash == nil {
return 0, fmt.Errorf(
"%w: neither block number nor hash specified",
errs.ErrInvalid,
)
}
if number, ok := blockNumberOrHash.Number(); ok {
height, err := resolveBlockNumber(number, blocksDB)
if err != nil {
return 0, err
}
return height, nil
}
if hash, ok := blockNumberOrHash.Hash(); ok {
height, err := blocksDB.GetHeightByID(hash)
if err != nil {
return 0, err
}
return height, nil
}
return 0, fmt.Errorf(
"%w: neither block number nor hash specified",
errs.ErrInvalid,
)
}
func resolveBlockNumber(
blockNumber rpc.BlockNumber,
blocksDB storage.BlockIndexer,
) (uint64, error) {
// if special values (latest) we return latest executed height
//
// all the special values are:
// EarliestBlockNumber = BlockNumber(-5)
// SafeBlockNumber = BlockNumber(-4)
// FinalizedBlockNumber = BlockNumber(-3)
// LatestBlockNumber = BlockNumber(-2)
// PendingBlockNumber = BlockNumber(-1)
switch blockNumber {
case rpc.EarliestBlockNumber:
// the earliest block is the genesis block, which has a block number of `0`
return 0, nil
case rpc.SafeBlockNumber,
rpc.FinalizedBlockNumber,
rpc.LatestBlockNumber,
rpc.PendingBlockNumber:
// EVM on Flow does not have these concepts,
// but the latest block is the closest fit
height, err := blocksDB.LatestEVMHeight()
if err != nil {
return 0, err
}
return height, nil
}
return uint64(blockNumber), nil
}
// decodeHash parses a hex-encoded 32-byte hash. The input may optionally
// be prefixed by 0x and can have a byte length up to 32.
func decodeHash(s string) (h common.Hash, err error) {
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
s = s[2:]
}
if (len(s) & 1) > 0 {
s = "0" + s
}
b, err := hex.DecodeString(s)
if err != nil {
return common.Hash{}, fmt.Errorf("invalid hex string: %s", s)
}
if len(b) > common.HashLength {
return common.Hash{}, fmt.Errorf(
"hex string too long, want at most 32 bytes, have %d bytes",
len(b),
)
}
return common.BytesToHash(b), nil
}
// handleError takes in an error and in case the error is of type ErrEntityNotFound
// it returns nil instead of an error since that is according to the API spec,
// if the error is not of type ErrEntityNotFound it will return the error and the generic
// empty type.
func handleError[T any](err error, log zerolog.Logger, collector metrics.Collector) (T, error) {
var (
zero T
revertedErr *errs.RevertError
)
switch {
// as per specification returning nil and nil for not found resources
case errors.Is(err, errs.ErrEntityNotFound):
return zero, nil
case errors.Is(err, errs.ErrInvalid):
return zero, err
case errors.Is(err, errs.ErrFailedTransaction):
return zero, err
case errors.As(err, &revertedErr):
return zero, revertedErr
case errors.Is(err, core.ErrNonceTooLow):
return zero, err
case errors.Is(err, core.ErrNonceTooHigh):
return zero, err
case errors.Is(err, core.ErrInsufficientFunds):
return zero, err
case errors.Is(err, errs.ErrRateLimit):
return zero, err
default:
collector.ApiErrorOccurred()
log.Error().Err(err).Msg("api error")
return zero, err
}
}