Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
2b34a1ee
Commit
2b34a1ee
authored
Jan 21, 2022
by
inphi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
removed eth_call sync code; cache mod latest blocks
parent
1cf8b15d
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
377 additions
and
376 deletions
+377
-376
backend.go
go/proxyd/backend.go
+6
-37
cache.go
go/proxyd/cache.go
+32
-21
cache_test.go
go/proxyd/cache_test.go
+143
-109
config.go
go/proxyd/config.go
+3
-2
lvc.go
go/proxyd/lvc.go
+19
-17
methods.go
go/proxyd/methods.go
+101
-139
metrics.go
go/proxyd/metrics.go
+18
-2
proxyd.go
go/proxyd/proxyd.go
+52
-44
server.go
go/proxyd/server.go
+3
-5
No files found.
go/proxyd/backend.go
View file @
2b34a1ee
...
@@ -16,9 +16,7 @@ import (
...
@@ -16,9 +16,7 @@ import (
"strings"
"strings"
"time"
"time"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
"github.com/gorilla/websocket"
"github.com/gorilla/websocket"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus"
)
)
...
@@ -86,7 +84,6 @@ type Backend struct {
...
@@ -86,7 +84,6 @@ type Backend struct {
authPassword
string
authPassword
string
rateLimiter
RateLimiter
rateLimiter
RateLimiter
client
*
http
.
Client
client
*
http
.
Client
blockNumberLVC
*
EthLastValueCache
dialer
*
websocket
.
Dialer
dialer
*
websocket
.
Dialer
maxRetries
int
maxRetries
int
maxResponseSize
int64
maxResponseSize
int64
...
@@ -169,7 +166,7 @@ func NewBackend(
...
@@ -169,7 +166,7 @@ func NewBackend(
wsURL
string
,
wsURL
string
,
rateLimiter
RateLimiter
,
rateLimiter
RateLimiter
,
opts
...
BackendOpt
,
opts
...
BackendOpt
,
)
(
*
Backend
,
error
)
{
)
*
Backend
{
backend
:=
&
Backend
{
backend
:=
&
Backend
{
Name
:
name
,
Name
:
name
,
rpcURL
:
rpcURL
,
rpcURL
:
rpcURL
,
...
@@ -186,28 +183,11 @@ func NewBackend(
...
@@ -186,28 +183,11 @@ func NewBackend(
opt
(
backend
)
opt
(
backend
)
}
}
rpcClient
,
err
:=
rpc
.
DialHTTPWithClient
(
rpcURL
,
backend
.
client
)
if
err
!=
nil
{
return
nil
,
err
}
backend
.
blockNumberLVC
=
newLVC
(
ethclient
.
NewClient
(
rpcClient
),
func
(
ctx
context
.
Context
,
client
*
ethclient
.
Client
)
(
interface
{},
error
)
{
blockNumber
,
err
:=
client
.
BlockNumber
(
ctx
)
return
blockNumber
,
err
})
if
!
backend
.
stripTrailingXFF
&&
backend
.
proxydIP
==
""
{
if
!
backend
.
stripTrailingXFF
&&
backend
.
proxydIP
==
""
{
log
.
Warn
(
"proxied requests' XFF header will not contain the proxyd ip address"
)
log
.
Warn
(
"proxied requests' XFF header will not contain the proxyd ip address"
)
}
}
return
backend
,
nil
return
backend
}
func
(
b
*
Backend
)
Start
()
{
b
.
blockNumberLVC
.
Start
()
}
func
(
b
*
Backend
)
Stop
()
{
b
.
blockNumberLVC
.
Stop
()
}
}
func
(
b
*
Backend
)
Forward
(
ctx
context
.
Context
,
req
*
RPCReq
)
(
*
RPCRes
,
error
)
{
func
(
b
*
Backend
)
Forward
(
ctx
context
.
Context
,
req
*
RPCReq
)
(
*
RPCRes
,
error
)
{
...
@@ -288,14 +268,6 @@ func (b *Backend) ProxyWS(clientConn *websocket.Conn, methodWhitelist *StringSet
...
@@ -288,14 +268,6 @@ func (b *Backend) ProxyWS(clientConn *websocket.Conn, methodWhitelist *StringSet
return
NewWSProxier
(
b
,
clientConn
,
backendConn
,
methodWhitelist
),
nil
return
NewWSProxier
(
b
,
clientConn
,
backendConn
,
methodWhitelist
),
nil
}
}
func
(
b
*
Backend
)
BlockNumber
()
uint64
{
var
blockNum
uint64
if
val
:=
b
.
blockNumberLVC
.
Read
();
val
!=
nil
{
blockNum
=
val
.
(
uint64
)
}
return
blockNum
}
func
(
b
*
Backend
)
Online
()
bool
{
func
(
b
*
Backend
)
Online
()
bool
{
online
,
err
:=
b
.
rateLimiter
.
IsBackendOnline
(
b
.
Name
)
online
,
err
:=
b
.
rateLimiter
.
IsBackendOnline
(
b
.
Name
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -423,16 +395,13 @@ type BackendGroup struct {
...
@@ -423,16 +395,13 @@ type BackendGroup struct {
Backends
[]
*
Backend
Backends
[]
*
Backend
}
}
func
(
b
*
BackendGroup
)
Forward
(
ctx
context
.
Context
,
rpcReq
*
RPCReq
)
(
*
RPCRes
,
uint64
,
error
)
{
func
(
b
*
BackendGroup
)
Forward
(
ctx
context
.
Context
,
rpcReq
*
RPCReq
)
(
*
RPCRes
,
error
)
{
rpcRequestsTotal
.
Inc
()
rpcRequestsTotal
.
Inc
()
for
_
,
back
:=
range
b
.
Backends
{
for
_
,
back
:=
range
b
.
Backends
{
// The blockNum must precede the forwarded RPC to establish a synchronization point
blockNum
:=
back
.
BlockNumber
()
res
,
err
:=
back
.
Forward
(
ctx
,
rpcReq
)
res
,
err
:=
back
.
Forward
(
ctx
,
rpcReq
)
if
errors
.
Is
(
err
,
ErrMethodNotWhitelisted
)
{
if
errors
.
Is
(
err
,
ErrMethodNotWhitelisted
)
{
return
nil
,
0
,
err
return
nil
,
err
}
}
if
errors
.
Is
(
err
,
ErrBackendOffline
)
{
if
errors
.
Is
(
err
,
ErrBackendOffline
)
{
log
.
Warn
(
log
.
Warn
(
...
@@ -462,11 +431,11 @@ func (b *BackendGroup) Forward(ctx context.Context, rpcReq *RPCReq) (*RPCRes, ui
...
@@ -462,11 +431,11 @@ func (b *BackendGroup) Forward(ctx context.Context, rpcReq *RPCReq) (*RPCRes, ui
)
)
continue
continue
}
}
return
res
,
blockNum
,
nil
return
res
,
nil
}
}
RecordUnserviceableRequest
(
ctx
,
RPCRequestSourceHTTP
)
RecordUnserviceableRequest
(
ctx
,
RPCRequestSourceHTTP
)
return
nil
,
0
,
ErrNoBackends
return
nil
,
ErrNoBackends
}
}
func
(
b
*
BackendGroup
)
ProxyWS
(
ctx
context
.
Context
,
clientConn
*
websocket
.
Conn
,
methodWhitelist
*
StringSet
)
(
*
WSProxier
,
error
)
{
func
(
b
*
BackendGroup
)
ProxyWS
(
ctx
context
.
Context
,
clientConn
*
websocket
.
Conn
,
methodWhitelist
*
StringSet
)
(
*
WSProxier
,
error
)
{
...
...
go/proxyd/cache.go
View file @
2b34a1ee
...
@@ -4,13 +4,13 @@ import (
...
@@ -4,13 +4,13 @@ import (
"context"
"context"
"github.com/go-redis/redis/v8"
"github.com/go-redis/redis/v8"
"github.com/golang/snappy"
lru
"github.com/hashicorp/golang-lru"
lru
"github.com/hashicorp/golang-lru"
)
)
type
Cache
interface
{
type
Cache
interface
{
Get
(
ctx
context
.
Context
,
key
string
)
(
string
,
error
)
Get
(
ctx
context
.
Context
,
key
string
)
(
string
,
error
)
Put
(
ctx
context
.
Context
,
key
string
,
value
string
)
error
Put
(
ctx
context
.
Context
,
key
string
,
value
string
)
error
Remove
(
ctx
context
.
Context
,
key
string
)
error
}
}
const
(
const
(
...
@@ -39,11 +39,6 @@ func (c *cache) Put(ctx context.Context, key string, value string) error {
...
@@ -39,11 +39,6 @@ func (c *cache) Put(ctx context.Context, key string, value string) error {
return
nil
return
nil
}
}
func
(
c
*
cache
)
Remove
(
ctx
context
.
Context
,
key
string
)
error
{
c
.
lru
.
Remove
(
key
)
return
nil
}
type
redisCache
struct
{
type
redisCache
struct
{
rdb
*
redis
.
Client
rdb
*
redis
.
Client
}
}
...
@@ -79,12 +74,32 @@ func (c *redisCache) Put(ctx context.Context, key string, value string) error {
...
@@ -79,12 +74,32 @@ func (c *redisCache) Put(ctx context.Context, key string, value string) error {
return
err
return
err
}
}
func
(
c
*
redisCache
)
Remove
(
ctx
context
.
Context
,
key
string
)
error
{
type
cacheWithCompression
struct
{
err
:=
c
.
rdb
.
Del
(
ctx
,
key
)
.
Err
()
cache
Cache
}
func
newCacheWithCompression
(
cache
Cache
)
*
cacheWithCompression
{
return
&
cacheWithCompression
{
cache
}
}
func
(
c
*
cacheWithCompression
)
Get
(
ctx
context
.
Context
,
key
string
)
(
string
,
error
)
{
encodedVal
,
err
:=
c
.
cache
.
Get
(
ctx
,
key
)
if
err
!=
nil
{
if
err
!=
nil
{
RecordRedisError
(
"CacheDel"
)
return
""
,
err
}
}
return
err
if
encodedVal
==
""
{
return
""
,
nil
}
val
,
err
:=
snappy
.
Decode
(
nil
,
[]
byte
(
encodedVal
))
if
err
!=
nil
{
return
""
,
err
}
return
string
(
val
),
nil
}
func
(
c
*
cacheWithCompression
)
Put
(
ctx
context
.
Context
,
key
string
,
value
string
)
error
{
encodedVal
:=
snappy
.
Encode
(
nil
,
[]
byte
(
value
))
return
c
.
cache
.
Put
(
ctx
,
key
,
string
(
encodedVal
))
}
}
type
GetLatestBlockNumFn
func
(
ctx
context
.
Context
)
(
uint64
,
error
)
type
GetLatestBlockNumFn
func
(
ctx
context
.
Context
)
(
uint64
,
error
)
...
@@ -92,11 +107,7 @@ type GetLatestGasPriceFn func(ctx context.Context) (uint64, error)
...
@@ -92,11 +107,7 @@ type GetLatestGasPriceFn func(ctx context.Context) (uint64, error)
type
RPCCache
interface
{
type
RPCCache
interface
{
GetRPC
(
ctx
context
.
Context
,
req
*
RPCReq
)
(
*
RPCRes
,
error
)
GetRPC
(
ctx
context
.
Context
,
req
*
RPCReq
)
(
*
RPCRes
,
error
)
PutRPC
(
ctx
context
.
Context
,
req
*
RPCReq
,
res
*
RPCRes
)
error
// The blockNumberSync is used to enforce Sequential Consistency for cache invalidation. We make the following assumptions to do this:
// 1. blockNumberSync is monotonically increasing (sans reorgs)
// 2. blockNumberSync is ordered before block state of the RPCRes
PutRPC
(
ctx
context
.
Context
,
req
*
RPCReq
,
res
*
RPCRes
,
blockNumberSync
uint64
)
error
}
}
type
rpcCache
struct
{
type
rpcCache
struct
{
...
@@ -104,15 +115,15 @@ type rpcCache struct {
...
@@ -104,15 +115,15 @@ type rpcCache struct {
handlers
map
[
string
]
RPCMethodHandler
handlers
map
[
string
]
RPCMethodHandler
}
}
func
newRPCCache
(
cache
Cache
,
getLatestBlockNumFn
GetLatestBlockNumFn
,
getLatestGasPriceFn
GetLatestGasPriceFn
)
RPCCache
{
func
newRPCCache
(
cache
Cache
,
getLatestBlockNumFn
GetLatestBlockNumFn
,
getLatestGasPriceFn
GetLatestGasPriceFn
,
numBlockConfirmations
int
)
RPCCache
{
handlers
:=
map
[
string
]
RPCMethodHandler
{
handlers
:=
map
[
string
]
RPCMethodHandler
{
"eth_chainId"
:
&
StaticMethodHandler
{},
"eth_chainId"
:
&
StaticMethodHandler
{},
"net_version"
:
&
StaticMethodHandler
{},
"net_version"
:
&
StaticMethodHandler
{},
"eth_getBlockByNumber"
:
&
EthGetBlockByNumberMethodHandler
{
cache
,
getLatestBlockNumFn
},
"eth_getBlockByNumber"
:
&
EthGetBlockByNumberMethodHandler
{
cache
,
getLatestBlockNumFn
,
numBlockConfirmations
},
"eth_getBlockRange"
:
&
EthGetBlockRangeMethodHandler
{
cache
,
getLatestBlockNumFn
},
"eth_getBlockRange"
:
&
EthGetBlockRangeMethodHandler
{
cache
,
getLatestBlockNumFn
,
numBlockConfirmations
},
"eth_blockNumber"
:
&
EthBlockNumberMethodHandler
{
getLatestBlockNumFn
},
"eth_blockNumber"
:
&
EthBlockNumberMethodHandler
{
getLatestBlockNumFn
},
"eth_gasPrice"
:
&
EthGasPriceMethodHandler
{
getLatestGasPriceFn
},
"eth_gasPrice"
:
&
EthGasPriceMethodHandler
{
getLatestGasPriceFn
},
"eth_call"
:
&
EthCallMethodHandler
{
cache
,
getLatestBlockNumFn
},
"eth_call"
:
&
EthCallMethodHandler
{
cache
,
getLatestBlockNumFn
,
numBlockConfirmations
},
}
}
return
&
rpcCache
{
return
&
rpcCache
{
cache
:
cache
,
cache
:
cache
,
...
@@ -136,10 +147,10 @@ func (c *rpcCache) GetRPC(ctx context.Context, req *RPCReq) (*RPCRes, error) {
...
@@ -136,10 +147,10 @@ func (c *rpcCache) GetRPC(ctx context.Context, req *RPCReq) (*RPCRes, error) {
return
res
,
err
return
res
,
err
}
}
func
(
c
*
rpcCache
)
PutRPC
(
ctx
context
.
Context
,
req
*
RPCReq
,
res
*
RPCRes
,
blockNumberSync
uint64
)
error
{
func
(
c
*
rpcCache
)
PutRPC
(
ctx
context
.
Context
,
req
*
RPCReq
,
res
*
RPCRes
)
error
{
handler
:=
c
.
handlers
[
req
.
Method
]
handler
:=
c
.
handlers
[
req
.
Method
]
if
handler
==
nil
{
if
handler
==
nil
{
return
nil
return
nil
}
}
return
handler
.
PutRPCMethod
(
ctx
,
req
,
res
,
blockNumberSync
)
return
handler
.
PutRPCMethod
(
ctx
,
req
,
res
)
}
}
go/proxyd/cache_test.go
View file @
2b34a1ee
This diff is collapsed.
Click to expand it.
go/proxyd/config.go
View file @
2b34a1ee
...
@@ -15,8 +15,9 @@ type ServerConfig struct {
...
@@ -15,8 +15,9 @@ type ServerConfig struct {
}
}
type
CacheConfig
struct
{
type
CacheConfig
struct
{
Enabled
bool
`toml:"enabled"`
Enabled
bool
`toml:"enabled"`
BlockSyncRPCURL
string
`toml:"block_sync_rpc_url"`
BlockSyncRPCURL
string
`toml:"block_sync_rpc_url"`
NumBlockConfirmations
int
`toml:"num_block_confirmations"`
}
}
type
RedisConfig
struct
{
type
RedisConfig
struct
{
...
...
go/proxyd/lvc.go
View file @
2b34a1ee
...
@@ -2,7 +2,6 @@ package proxyd
...
@@ -2,7 +2,6 @@ package proxyd
import
(
import
(
"context"
"context"
"sync"
"time"
"time"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethclient"
...
@@ -11,20 +10,21 @@ import (
...
@@ -11,20 +10,21 @@ import (
const
cacheSyncRate
=
1
*
time
.
Second
const
cacheSyncRate
=
1
*
time
.
Second
type
lvcUpdateFn
func
(
context
.
Context
,
*
ethclient
.
Client
)
(
interface
{}
,
error
)
type
lvcUpdateFn
func
(
context
.
Context
,
*
ethclient
.
Client
)
(
string
,
error
)
type
EthLastValueCache
struct
{
type
EthLastValueCache
struct
{
client
*
ethclient
.
Client
client
*
ethclient
.
Client
cache
Cache
key
string
updater
lvcUpdateFn
updater
lvcUpdateFn
quit
chan
struct
{}
quit
chan
struct
{}
mutex
sync
.
RWMutex
value
interface
{}
}
}
func
newLVC
(
client
*
ethclient
.
Client
,
updater
lvcUpdateFn
)
*
EthLastValueCache
{
func
newLVC
(
client
*
ethclient
.
Client
,
cache
Cache
,
cacheKey
string
,
updater
lvcUpdateFn
)
*
EthLastValueCache
{
return
&
EthLastValueCache
{
return
&
EthLastValueCache
{
client
:
client
,
client
:
client
,
cache
:
cache
,
key
:
cacheKey
,
updater
:
updater
,
updater
:
updater
,
quit
:
make
(
chan
struct
{}),
quit
:
make
(
chan
struct
{}),
}
}
...
@@ -38,15 +38,18 @@ func (h *EthLastValueCache) Start() {
...
@@ -38,15 +38,18 @@ func (h *EthLastValueCache) Start() {
for
{
for
{
select
{
select
{
case
<-
ticker
.
C
:
case
<-
ticker
.
C
:
lvcPollTimeGauge
.
WithLabelValues
(
h
.
key
)
.
SetToCurrentTime
()
value
,
err
:=
h
.
getUpdate
()
value
,
err
:=
h
.
getUpdate
()
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Error
(
"error retrieving latest value"
,
"error"
,
err
)
log
.
Error
(
"error retrieving latest value"
,
"
key"
,
h
.
key
,
"
error"
,
err
)
continue
continue
}
}
log
.
Trace
(
"polling latest value"
,
"value"
,
value
)
log
.
Trace
(
"polling latest value"
,
"value"
,
value
)
h
.
mutex
.
Lock
()
h
.
value
=
value
if
err
:=
h
.
cache
.
Put
(
context
.
Background
(),
h
.
key
,
value
);
err
!=
nil
{
h
.
mutex
.
Unlock
()
log
.
Error
(
"error writing last value to cache"
,
"key"
,
h
.
key
,
"error"
,
err
)
}
case
<-
h
.
quit
:
case
<-
h
.
quit
:
return
return
...
@@ -55,31 +58,30 @@ func (h *EthLastValueCache) Start() {
...
@@ -55,31 +58,30 @@ func (h *EthLastValueCache) Start() {
}()
}()
}
}
func
(
h
*
EthLastValueCache
)
getUpdate
()
(
interface
{}
,
error
)
{
func
(
h
*
EthLastValueCache
)
getUpdate
()
(
string
,
error
)
{
const
maxRetries
=
5
const
maxRetries
=
5
var
err
error
var
err
error
for
i
:=
0
;
i
<=
maxRetries
;
i
++
{
for
i
:=
0
;
i
<=
maxRetries
;
i
++
{
var
value
interface
{}
var
value
string
value
,
err
=
h
.
updater
(
context
.
Background
(),
h
.
client
)
value
,
err
=
h
.
updater
(
context
.
Background
(),
h
.
client
)
if
err
!=
nil
{
if
err
!=
nil
{
backoff
:=
calcBackoff
(
i
)
backoff
:=
calcBackoff
(
i
)
log
.
Warn
(
"http operation failed. retrying..."
,
"error"
,
err
,
"backoff"
,
backoff
)
log
.
Warn
(
"http operation failed. retrying..."
,
"error"
,
err
,
"backoff"
,
backoff
)
lvcErrorsTotal
.
WithLabelValues
(
h
.
key
)
.
Inc
()
time
.
Sleep
(
backoff
)
time
.
Sleep
(
backoff
)
continue
continue
}
}
return
value
,
nil
return
value
,
nil
}
}
return
0
,
wrapErr
(
err
,
"exceeded retries"
)
return
""
,
wrapErr
(
err
,
"exceeded retries"
)
}
}
func
(
h
*
EthLastValueCache
)
Stop
()
{
func
(
h
*
EthLastValueCache
)
Stop
()
{
close
(
h
.
quit
)
close
(
h
.
quit
)
}
}
func
(
h
*
EthLastValueCache
)
Read
()
interface
{}
{
func
(
h
*
EthLastValueCache
)
Read
(
ctx
context
.
Context
)
(
string
,
error
)
{
h
.
mutex
.
RLock
()
return
h
.
cache
.
Get
(
ctx
,
h
.
key
)
defer
h
.
mutex
.
RUnlock
()
return
h
.
value
}
}
go/proxyd/methods.go
View file @
2b34a1ee
This diff is collapsed.
Click to expand it.
go/proxyd/metrics.go
View file @
2b34a1ee
...
@@ -145,7 +145,7 @@ var (
...
@@ -145,7 +145,7 @@ var (
requestPayloadSizesGauge
=
promauto
.
NewHistogramVec
(
prometheus
.
HistogramOpts
{
requestPayloadSizesGauge
=
promauto
.
NewHistogramVec
(
prometheus
.
HistogramOpts
{
Namespace
:
MetricsNamespace
,
Namespace
:
MetricsNamespace
,
Name
:
"request_payload_sizes"
,
Name
:
"request_payload_sizes"
,
Help
:
"
Gauge
of client request payload sizes."
,
Help
:
"
Histogram
of client request payload sizes."
,
Buckets
:
PayloadSizeBuckets
,
Buckets
:
PayloadSizeBuckets
,
},
[]
string
{
},
[]
string
{
"auth"
,
"auth"
,
...
@@ -154,7 +154,7 @@ var (
...
@@ -154,7 +154,7 @@ var (
responsePayloadSizesGauge
=
promauto
.
NewHistogramVec
(
prometheus
.
HistogramOpts
{
responsePayloadSizesGauge
=
promauto
.
NewHistogramVec
(
prometheus
.
HistogramOpts
{
Namespace
:
MetricsNamespace
,
Namespace
:
MetricsNamespace
,
Name
:
"response_payload_sizes"
,
Name
:
"response_payload_sizes"
,
Help
:
"
Gauge
of client response payload sizes."
,
Help
:
"
Histogram
of client response payload sizes."
,
Buckets
:
PayloadSizeBuckets
,
Buckets
:
PayloadSizeBuckets
,
},
[]
string
{
},
[]
string
{
"auth"
,
"auth"
,
...
@@ -176,6 +176,22 @@ var (
...
@@ -176,6 +176,22 @@ var (
"method"
,
"method"
,
})
})
lvcErrorsTotal
=
promauto
.
NewCounterVec
(
prometheus
.
CounterOpts
{
Namespace
:
MetricsNamespace
,
Name
:
"lvc_errors_total"
,
Help
:
"Count of lvc errors."
,
},
[]
string
{
"key"
,
})
lvcPollTimeGauge
=
promauto
.
NewGaugeVec
(
prometheus
.
GaugeOpts
{
Namespace
:
MetricsNamespace
,
Name
:
"lvc_poll_time_gauge"
,
Help
:
"Gauge of lvc poll time."
,
},
[]
string
{
"key"
,
})
rpcSpecialErrors
=
[]
string
{
rpcSpecialErrors
=
[]
string
{
"nonce too low"
,
"nonce too low"
,
"gas price too high"
,
"gas price too high"
,
...
...
go/proxyd/proxyd.go
View file @
2b34a1ee
...
@@ -5,9 +5,9 @@ import (
...
@@ -5,9 +5,9 @@ import (
"crypto/tls"
"crypto/tls"
"errors"
"errors"
"fmt"
"fmt"
"math/big"
"net/http"
"net/http"
"os"
"os"
"strconv"
"time"
"time"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethclient"
...
@@ -111,12 +111,7 @@ func Start(config *Config) (func(), error) {
...
@@ -111,12 +111,7 @@ func Start(config *Config) (func(), error) {
opts
=
append
(
opts
,
WithStrippedTrailingXFF
())
opts
=
append
(
opts
,
WithStrippedTrailingXFF
())
}
}
opts
=
append
(
opts
,
WithProxydIP
(
os
.
Getenv
(
"PROXYD_IP"
)))
opts
=
append
(
opts
,
WithProxydIP
(
os
.
Getenv
(
"PROXYD_IP"
)))
back
,
err
:=
NewBackend
(
name
,
rpcURL
,
wsURL
,
lim
,
opts
...
)
back
:=
NewBackend
(
name
,
rpcURL
,
wsURL
,
lim
,
opts
...
)
if
err
!=
nil
{
return
nil
,
err
}
back
.
Start
()
defer
back
.
Stop
()
backendNames
=
append
(
backendNames
,
name
)
backendNames
=
append
(
backendNames
,
name
)
backendsByName
[
name
]
=
back
backendsByName
[
name
]
=
back
log
.
Info
(
"configured backend"
,
"name"
,
name
,
"rpc_url"
,
rpcURL
,
"ws_url"
,
wsURL
)
log
.
Info
(
"configured backend"
,
"name"
,
name
,
"rpc_url"
,
rpcURL
,
"ws_url"
,
wsURL
)
...
@@ -169,9 +164,18 @@ func Start(config *Config) (func(), error) {
...
@@ -169,9 +164,18 @@ func Start(config *Config) (func(), error) {
}
}
}
}
var
rpcCache
RPCCache
var
(
stopLVCs
:=
make
(
chan
struct
{})
rpcCache
RPCCache
blockNumLVC
*
EthLastValueCache
gasPriceLVC
*
EthLastValueCache
)
if
config
.
Cache
.
Enabled
{
if
config
.
Cache
.
Enabled
{
var
(
cache
Cache
blockNumFn
GetLatestBlockNumFn
gasPriceFn
GetLatestGasPriceFn
)
if
config
.
Cache
.
BlockSyncRPCURL
==
""
{
if
config
.
Cache
.
BlockSyncRPCURL
==
""
{
return
nil
,
fmt
.
Errorf
(
"block sync node required for caching"
)
return
nil
,
fmt
.
Errorf
(
"block sync node required for caching"
)
}
}
...
@@ -180,7 +184,6 @@ func Start(config *Config) (func(), error) {
...
@@ -180,7 +184,6 @@ func Start(config *Config) (func(), error) {
return
nil
,
err
return
nil
,
err
}
}
var
cache
Cache
if
redisURL
!=
""
{
if
redisURL
!=
""
{
if
cache
,
err
=
newRedisCache
(
redisURL
);
err
!=
nil
{
if
cache
,
err
=
newRedisCache
(
redisURL
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -195,9 +198,10 @@ func Start(config *Config) (func(), error) {
...
@@ -195,9 +198,10 @@ func Start(config *Config) (func(), error) {
return
nil
,
err
return
nil
,
err
}
}
defer
ethClient
.
Close
()
defer
ethClient
.
Close
()
blockNumFn
:=
makeGetLatestBlockNumFn
(
ethClient
,
stopLVCs
)
gasPriceFn
:=
makeGetLatestGasPriceFn
(
ethClient
,
stopLVCs
)
blockNumLVC
,
blockNumFn
=
makeGetLatestBlockNumFn
(
ethClient
,
cache
)
rpcCache
=
newRPCCache
(
cache
,
blockNumFn
,
gasPriceFn
)
gasPriceLVC
,
gasPriceFn
=
makeGetLatestGasPriceFn
(
ethClient
,
cache
)
rpcCache
=
newRPCCache
(
newCacheWithCompression
(
cache
),
blockNumFn
,
gasPriceFn
,
config
.
Cache
.
NumBlockConfirmations
)
}
}
srv
:=
NewServer
(
srv
:=
NewServer
(
...
@@ -250,8 +254,12 @@ func Start(config *Config) (func(), error) {
...
@@ -250,8 +254,12 @@ func Start(config *Config) (func(), error) {
return
func
()
{
return
func
()
{
log
.
Info
(
"shutting down proxyd"
)
log
.
Info
(
"shutting down proxyd"
)
// TODO(inphi): Stop LVCs here
if
blockNumLVC
!=
nil
{
close
(
stopLVCs
)
blockNumLVC
.
Stop
()
}
if
gasPriceLVC
!=
nil
{
gasPriceLVC
.
Stop
()
}
srv
.
Shutdown
()
srv
.
Shutdown
()
if
err
:=
lim
.
FlushBackendWSConns
(
backendNames
);
err
!=
nil
{
if
err
:=
lim
.
FlushBackendWSConns
(
backendNames
);
err
!=
nil
{
log
.
Error
(
"error flushing backend ws conns"
,
"err"
,
err
)
log
.
Error
(
"error flushing backend ws conns"
,
"err"
,
err
)
...
@@ -285,38 +293,38 @@ func configureBackendTLS(cfg *BackendConfig) (*tls.Config, error) {
...
@@ -285,38 +293,38 @@ func configureBackendTLS(cfg *BackendConfig) (*tls.Config, error) {
return
tlsConfig
,
nil
return
tlsConfig
,
nil
}
}
func
makeGetLatestBlockNumFn
(
client
*
ethclient
.
Client
,
quit
<-
chan
struct
{})
GetLatestBlockNumFn
{
func
makeUint64LastValueFn
(
client
*
ethclient
.
Client
,
cache
Cache
,
key
string
,
updater
lvcUpdateFn
)
(
*
EthLastValueCache
,
func
(
context
.
Context
)
(
uint64
,
error
))
{
lvc
:=
newLVC
(
client
,
func
(
ctx
context
.
Context
,
c
*
ethclient
.
Client
)
(
interface
{},
error
)
{
lvc
:=
newLVC
(
client
,
cache
,
key
,
updater
)
return
c
.
BlockNumber
(
ctx
)
})
lvc
.
Start
()
lvc
.
Start
()
go
func
()
{
return
lvc
,
func
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
<-
quit
value
,
err
:=
lvc
.
Read
(
ctx
)
lvc
.
Stop
()
if
err
!=
nil
{
}()
return
0
,
err
return
func
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
}
value
:=
lvc
.
Read
()
if
value
==
""
{
if
value
==
nil
{
return
0
,
fmt
.
Errorf
(
"%s is unavailable"
,
key
)
return
0
,
fmt
.
Errorf
(
"block number is unavailable"
)
}
}
valueUint
,
err
:=
strconv
.
ParseUint
(
value
,
10
,
64
)
return
value
.
(
uint64
),
nil
if
err
!=
nil
{
return
0
,
err
}
return
valueUint
,
nil
}
}
}
}
func
makeGetLatestGasPriceFn
(
client
*
ethclient
.
Client
,
quit
<-
chan
struct
{})
GetLatestGasPriceFn
{
func
makeGetLatestBlockNumFn
(
client
*
ethclient
.
Client
,
cache
Cache
)
(
*
EthLastValueCache
,
GetLatestBlockNumFn
)
{
lvc
:=
newLVC
(
client
,
func
(
ctx
context
.
Context
,
c
*
ethclient
.
Client
)
(
interface
{},
error
)
{
return
makeUint64LastValueFn
(
client
,
cache
,
"lvc:block_number"
,
func
(
ctx
context
.
Context
,
c
*
ethclient
.
Client
)
(
string
,
error
)
{
return
c
.
SuggestGasPrice
(
ctx
)
blockNum
,
err
:=
c
.
BlockNumber
(
ctx
)
return
strconv
.
FormatUint
(
blockNum
,
10
),
err
})
}
func
makeGetLatestGasPriceFn
(
client
*
ethclient
.
Client
,
cache
Cache
)
(
*
EthLastValueCache
,
GetLatestGasPriceFn
)
{
return
makeUint64LastValueFn
(
client
,
cache
,
"lvc:gas_price"
,
func
(
ctx
context
.
Context
,
c
*
ethclient
.
Client
)
(
string
,
error
)
{
gasPrice
,
err
:=
c
.
SuggestGasPrice
(
ctx
)
if
err
!=
nil
{
return
""
,
err
}
return
gasPrice
.
String
(),
nil
})
})
lvc
.
Start
()
go
func
()
{
<-
lvc
.
quit
lvc
.
Stop
()
}()
return
func
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
value
:=
lvc
.
Read
()
if
value
==
nil
{
return
0
,
fmt
.
Errorf
(
"gas price is unavailable"
)
}
return
value
.
(
*
big
.
Int
)
.
Uint64
(),
nil
}
}
}
go/proxyd/server.go
View file @
2b34a1ee
...
@@ -218,9 +218,7 @@ func (s *Server) handleSingleRPC(ctx context.Context, req *RPCReq) *RPCRes {
...
@@ -218,9 +218,7 @@ func (s *Server) handleSingleRPC(ctx context.Context, req *RPCReq) *RPCRes {
return
backendRes
return
backendRes
}
}
// NOTE: We call into the specific backend here to ensure that the RPCRes is synchronized with the blockNum.
backendRes
,
err
=
s
.
backendGroups
[
group
]
.
Forward
(
ctx
,
req
)
var
blockNum
uint64
backendRes
,
blockNum
,
err
=
s
.
backendGroups
[
group
]
.
Forward
(
ctx
,
req
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Error
(
log
.
Error
(
"error forwarding RPC request"
,
"error forwarding RPC request"
,
...
@@ -232,7 +230,7 @@ func (s *Server) handleSingleRPC(ctx context.Context, req *RPCReq) *RPCRes {
...
@@ -232,7 +230,7 @@ func (s *Server) handleSingleRPC(ctx context.Context, req *RPCReq) *RPCRes {
}
}
if
backendRes
.
Error
==
nil
{
if
backendRes
.
Error
==
nil
{
if
err
=
s
.
cache
.
PutRPC
(
ctx
,
req
,
backendRes
,
blockNum
);
err
!=
nil
{
if
err
=
s
.
cache
.
PutRPC
(
ctx
,
req
,
backendRes
);
err
!=
nil
{
log
.
Warn
(
log
.
Warn
(
"cache put error"
,
"cache put error"
,
"req_id"
,
GetReqID
(
ctx
),
"req_id"
,
GetReqID
(
ctx
),
...
@@ -427,6 +425,6 @@ func (n *NoopRPCCache) GetRPC(context.Context, *RPCReq) (*RPCRes, error) {
...
@@ -427,6 +425,6 @@ func (n *NoopRPCCache) GetRPC(context.Context, *RPCReq) (*RPCRes, error) {
return
nil
,
nil
return
nil
,
nil
}
}
func
(
n
*
NoopRPCCache
)
PutRPC
(
context
.
Context
,
*
RPCReq
,
*
RPCRes
,
uint64
)
error
{
func
(
n
*
NoopRPCCache
)
PutRPC
(
context
.
Context
,
*
RPCReq
,
*
RPCRes
)
error
{
return
nil
return
nil
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment