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
8e3d9aba
Commit
8e3d9aba
authored
Jun 02, 2023
by
Felipe Andrade
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
translate only methods with block params
parent
28a74e28
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
148 additions
and
107 deletions
+148
-107
README.md
proxyd/README.md
+10
-17
backend.go
proxyd/backend.go
+56
-63
consensus_test.go
proxyd/integration_tests/consensus_test.go
+73
-25
server.go
proxyd/server.go
+9
-2
No files found.
proxyd/README.md
View file @
8e3d9aba
...
...
@@ -95,43 +95,36 @@ To support backends with different specifications in the same backend group,
proxyd exposes a convenient method to fetch receipts abstracting away
what specific backend will serve the request.
Each backend can specify their preferred method to fetch receipts with
`consensus_receipts_target`
.
Each backend specifies their preferred method to fetch receipts with
`consensus_receipts_target`
config,
which will be translated from
`consensus_getReceipts`
.
This method takes
**both**
the blockNumberOrHash
**and**
list of transaction hashes to fetch the receipts,
and then after selecting the backend to serve the request,
it translates to the correct target with the appropriate parameters.
This method takes a
`blockNumberOrHash`
(i.e.
`tag|qty|hash`
)
and returns the receipts for all transactions in the block.
Note that only one of the parameters will be actually used depending on the target.
Request params
Request example
```
json
{
"jsonrpc"
:
"2.0"
,
"id"
:
1
,
"params"
:
{
"blockNumberOrHash"
:
"0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b"
,
"transactions"
:
[
"0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"
,
"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b"
]
}
"params"
:
[
"0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b"
]
}
```
It currently supports translation to the following targets:
*
`debug_getRawReceipts(blockOrHash)`
(default)
*
`alchemy_getTransactionReceipts(blockOrHash)`
*
`eth_getTransactionReceipt(txHash)`
batched
*
`parity_getBlockReceipts(blockOrHash)`
*
`eth_getBlockReceipts(blockOrHash)`
The selected target is returned in the response, in a wrapped result.
Response
Response
example
```
json
{
"jsonrpc"
:
"2.0"
,
"id"
:
1
,
"result"
:
{
"method"
:
"
eth_getTransactionReceipt
"
,
"method"
:
"
debug_getRawReceipts
"
,
"result"
:
{
//
the
actual
raw
result
from
backend
}
...
...
proxyd/backend.go
View file @
8e3d9aba
...
...
@@ -17,11 +17,9 @@ import (
"sync"
"time"
sw
"github.com/ethereum-optimism/optimism/proxyd/pkg/avg-sliding-window"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
"github.com/google/uuid"
sw
"github.com/ethereum-optimism/optimism/proxyd/pkg/avg-sliding-window"
"github.com/ethereum/go-ethereum/log"
"github.com/gorilla/websocket"
...
...
@@ -103,6 +101,7 @@ var (
ErrBackendUnexpectedJSONRPC
=
errors
.
New
(
"backend returned an unexpected JSON-RPC response"
)
ErrConsensusGetReceiptsCantBeBatched
=
errors
.
New
(
"consensus_getReceipts cannot be batched"
)
ErrConsensusGetReceiptsInvalidTarget
=
errors
.
New
(
"unsupported consensus_receipts_target"
)
)
func
ErrInvalidRequest
(
msg
string
)
*
RPCErr
{
...
...
@@ -252,20 +251,28 @@ type indexedReqRes struct {
}
const
ConsensusGetReceiptsMethod
=
"consensus_getReceipts"
const
ReceiptsTargetEthTransactionReceipt
=
"eth_getTransactionReceipt"
const
ReceiptsTargetDebugGetRawReceipts
=
"debug_getRawReceipts"
const
ReceiptsTargetGetTransactionReceipts
=
"alchemy_getTransactionReceipts"
const
ReceiptsTargetAlchemyGetTransactionReceipts
=
"alchemy_getTransactionReceipts"
const
ReceiptsTargetParityGetTransactionReceipts
=
"parity_getBlockReceipts"
const
ReceiptsTargetEthGetTransactionReceipts
=
"eth_getBlockReceipts"
type
ConsensusGetReceiptsReq
struct
{
type
ConsensusGetReceiptsReq
uest
struct
{
BlockOrHash
*
rpc
.
BlockNumberOrHash
`json:"blockOrHash"`
Transactions
[]
common
.
Hash
`json:"transactions"`
}
type
ConsensusGetReceiptsRes
struct
{
type
ConsensusGetReceiptsRes
ult
struct
{
Method
string
`json:"method"`
Result
interface
{}
`json:"result"`
}
// BlockHashOrNumberParameter is a non-conventional wrapper used by alchemy_getTransactionReceipts
type
BlockHashOrNumberParameter
struct
{
BlockHash
*
common
.
Hash
`json:"blockHash"`
BlockNumber
*
rpc
.
BlockNumber
`json:"blockNumber"`
}
func
NewBackend
(
name
string
,
rpcURL
string
,
...
...
@@ -331,12 +338,19 @@ func (b *Backend) Forward(ctx context.Context, reqs []*RPCReq, isBatch bool) ([]
switch
err
{
case
nil
:
// do nothing
case
ErrConsensusGetReceiptsCantBeBatched
:
log
.
Debug
(
log
.
Warn
(
"Received unsupported batch request for consensus_getReceipts"
,
"name"
,
b
.
Name
,
"req_id"
,
GetReqID
(
ctx
),
"err"
,
err
,
)
case
ErrConsensusGetReceiptsInvalidTarget
:
log
.
Error
(
"Unsupported consensus_receipts_target for consensus_getReceipts"
,
"name"
,
b
.
Name
,
"req_id"
,
GetReqID
(
ctx
),
"err"
,
err
,
)
// ErrBackendUnexpectedJSONRPC occurs because infura responds with a single JSON-RPC object
// to a batch request whenever any Request Object in the batch would induce a partial error.
// We don't label the backend offline in this case. But the error is still returned to
...
...
@@ -414,58 +428,56 @@ func (b *Backend) doForward(ctx context.Context, rpcReqs []*RPCReq, isBatch bool
// we are concerned about network error rates, so we record 1 request independently of how many are in the batch
b
.
networkRequestsSlidingWindow
.
Incr
()
originalRequests
:=
rpcReqs
translatedReqs
:=
make
(
map
[
string
]
*
RPCReq
,
len
(
rpcReqs
))
derivedRequests
:=
make
([]
*
RPCReq
,
0
)
// translate consensus_getReceipts to receipts target
// right now we only support non-batched
if
!
isBatch
{
if
isBatch
{
for
_
,
rpcReq
:=
range
rpcReqs
{
if
rpcReq
.
Method
==
ConsensusGetReceiptsMethod
{
return
nil
,
ErrConsensusGetReceiptsCantBeBatched
}
}
}
else
{
for
_
,
rpcReq
:=
range
rpcReqs
{
if
rpcReq
.
Method
==
ConsensusGetReceiptsMethod
{
translatedReqs
[
string
(
rpcReq
.
ID
)]
=
rpcReq
rpcReq
.
Method
=
b
.
receiptsTarget
var
reqParams
[]
ConsensusGetReceiptsReq
var
reqParams
[]
ConsensusGetReceiptsReq
uest
err
:=
json
.
Unmarshal
(
rpcReq
.
Params
,
&
reqParams
)
if
err
!=
nil
{
return
nil
,
ErrInvalidRequest
(
"invalid request"
)
}
bnh
:=
reqParams
[
0
]
.
BlockOrHash
switch
b
.
receiptsTarget
{
var
translatedParams
[]
byte
switch
rpcReq
.
Method
{
case
ReceiptsTargetDebugGetRawReceipts
,
ReceiptsTargetGetTransactionReceipts
:
// block or hash
ReceiptsTargetEthGetTransactionReceipts
,
ReceiptsTargetParityGetTransactionReceipts
:
// conventional methods use an array of strings having either block number or block hash
// i.e. ["0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b"]
params
:=
make
([]
string
,
1
)
if
bnh
.
BlockNumber
!=
nil
{
params
[
0
]
=
bnh
.
BlockNumber
.
String
()
}
else
{
params
[
0
]
=
bnh
.
BlockHash
.
Hex
()
}
rawParams
:=
mustMarshalJSON
(
params
)
rpcReq
.
Params
=
rawParams
case
ReceiptsTargetEthTransactionReceipt
:
// list of tx hashes
for
_
,
txHash
:=
range
reqParams
[
0
]
.
Transactions
{
params
:=
make
([]
common
.
Hash
,
1
)
params
[
0
]
=
txHash
rawParams
:=
mustMarshalJSON
(
params
)
randomID
:=
mustMarshalJSON
(
uuid
.
New
()
.
String
())
dReq
:=
&
RPCReq
{
JSONRPC
:
rpcReq
.
JSONRPC
,
Method
:
ReceiptsTargetEthTransactionReceipt
,
Params
:
rawParams
,
ID
:
randomID
,
}
derivedRequests
=
append
(
derivedRequests
,
dReq
)
translatedParams
=
mustMarshalJSON
(
params
)
case
ReceiptsTargetAlchemyGetTransactionReceipts
:
// alchemy uses an array of object with either block number or block hash
// i.e. [{ blockHash: "0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b" }]
params
:=
make
([]
BlockHashOrNumberParameter
,
1
)
if
bnh
.
BlockNumber
!=
nil
{
params
[
0
]
.
BlockNumber
=
bnh
.
BlockNumber
}
else
{
params
[
0
]
.
BlockHash
=
bnh
.
BlockHash
}
translatedParams
=
mustMarshalJSON
(
params
)
default
:
return
nil
,
ErrConsensusGetReceiptsInvalidTarget
}
}
}
// replace the original request with the derived requests
if
len
(
derivedRequests
)
>
0
{
rpcReqs
=
derivedRequests
}
}
else
{
for
_
,
rpcReq
:=
range
rpcReqs
{
if
rpcReq
.
Method
==
ConsensusGetReceiptsMethod
{
return
nil
,
ErrConsensusGetReceiptsCantBeBatched
rpcReq
.
Params
=
translatedParams
}
}
}
...
...
@@ -582,32 +594,14 @@ func (b *Backend) doForward(ctx context.Context, rpcReqs []*RPCReq, isBatch bool
for
_
,
res
:=
range
rpcRes
{
translatedReq
,
exist
:=
translatedReqs
[
string
(
res
.
ID
)]
if
exist
{
res
.
Result
=
ConsensusGetReceiptsRes
{
res
.
Result
=
ConsensusGetReceiptsRes
ult
{
Method
:
translatedReq
.
Method
,
Result
:
res
.
Result
,
}
}
}
sortBatchRPCResponse
(
rpcReqs
,
rpcRes
)
// if the translated requests originated derived requests, wrap their results
if
len
(
derivedRequests
)
>
0
{
results
:=
make
([]
interface
{},
0
,
len
(
rpcRes
))
for
_
,
res
:=
range
rpcRes
{
results
=
append
(
results
,
res
.
Result
)
}
wrappedRes
:=
&
RPCRes
{
JSONRPC
:
originalRequests
[
0
]
.
JSONRPC
,
Result
:
ConsensusGetReceiptsRes
{
Method
:
rpcReqs
[
0
]
.
Method
,
Result
:
results
,
},
ID
:
originalRequests
[
0
]
.
ID
,
}
rpcRes
=
[]
*
RPCRes
{
wrappedRes
}
}
sortBatchRPCResponse
(
rpcReqs
,
rpcRes
)
return
rpcRes
,
nil
}
...
...
@@ -728,10 +722,9 @@ func (bg *BackendGroup) Forward(ctx context.Context, rpcReqs []*RPCReq, isBatch
if
len
(
rpcReqs
)
>
0
{
res
,
err
=
back
.
Forward
(
ctx
,
rpcReqs
,
isBatch
)
if
errors
.
Is
(
err
,
ErrConsensusGetReceiptsCantBeBatched
)
{
return
nil
,
err
}
if
errors
.
Is
(
err
,
ErrMethodNotWhitelisted
)
{
if
errors
.
Is
(
err
,
ErrConsensusGetReceiptsCantBeBatched
)
||
errors
.
Is
(
err
,
ErrConsensusGetReceiptsInvalidTarget
)
||
errors
.
Is
(
err
,
ErrMethodNotWhitelisted
)
{
return
nil
,
err
}
if
errors
.
Is
(
err
,
ErrBackendOffline
)
{
...
...
proxyd/integration_tests/consensus_test.go
View file @
8e3d9aba
...
...
@@ -788,6 +788,10 @@ func TestConsensus(t *testing.T) {
t
.
Run
(
"translate consensus_getReceipts to debug_getRawReceipts"
,
func
(
t
*
testing
.
T
)
{
reset
()
useOnlyNode1
()
update
()
// reset request counts
nodes
[
"node1"
]
.
mockBackend
.
Reset
()
resRaw
,
statusCode
,
err
:=
client
.
SendRPC
(
"consensus_getReceipts"
,
[]
interface
{}{
map
[
string
]
interface
{}{
"blockOrHash"
:
"0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b"
}})
...
...
@@ -811,6 +815,10 @@ func TestConsensus(t *testing.T) {
t
.
Run
(
"translate consensus_getReceipts to debug_getRawReceipts with latest block tag"
,
func
(
t
*
testing
.
T
)
{
reset
()
useOnlyNode1
()
update
()
// reset request counts
nodes
[
"node1"
]
.
mockBackend
.
Reset
()
resRaw
,
statusCode
,
err
:=
client
.
SendRPC
(
"consensus_getReceipts"
,
[]
interface
{}{
map
[
string
]
interface
{}{
"blockOrHash"
:
"latest"
}})
...
...
@@ -834,6 +842,10 @@ func TestConsensus(t *testing.T) {
t
.
Run
(
"translate consensus_getReceipts to debug_getRawReceipts with block number"
,
func
(
t
*
testing
.
T
)
{
reset
()
useOnlyNode1
()
update
()
// reset request counts
nodes
[
"node1"
]
.
mockBackend
.
Reset
()
resRaw
,
statusCode
,
err
:=
client
.
SendRPC
(
"consensus_getReceipts"
,
[]
interface
{}{
map
[
string
]
interface
{}{
"blockOrHash"
:
"0x55"
}})
...
...
@@ -854,9 +866,13 @@ func TestConsensus(t *testing.T) {
require
.
Equal
(
t
,
"debug_getRawReceipts"
,
resJsonMap
[
"result"
]
.
(
map
[
string
]
interface
{})[
"result"
]
.
(
map
[
string
]
interface
{})[
"_"
])
})
t
.
Run
(
"translate consensus_getReceipts to alchemy_getTransactionReceipts"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"translate consensus_getReceipts to alchemy_getTransactionReceipts
with block hash
"
,
func
(
t
*
testing
.
T
)
{
reset
()
useOnlyNode1
()
update
()
// reset request counts
nodes
[
"node1"
]
.
mockBackend
.
Reset
()
nodes
[
"node1"
]
.
backend
.
Override
(
proxyd
.
WithConsensusReceiptTarget
(
"alchemy_getTransactionReceipts"
))
defer
nodes
[
"node1"
]
.
backend
.
Override
(
proxyd
.
WithConsensusReceiptTarget
(
"debug_getRawReceipts"
))
...
...
@@ -871,7 +887,7 @@ func TestConsensus(t *testing.T) {
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
"alchemy_getTransactionReceipts"
,
reqJsonMap
[
"method"
])
require
.
Equal
(
t
,
"0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b"
,
reqJsonMap
[
"params"
]
.
([]
interface
{})[
0
])
require
.
Equal
(
t
,
"0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b"
,
reqJsonMap
[
"params"
]
.
([]
interface
{})[
0
]
.
(
map
[
string
]
interface
{})[
"blockHash"
]
)
var
resJsonMap
map
[
string
]
interface
{}
err
=
json
.
Unmarshal
(
resRaw
,
&
resJsonMap
)
...
...
@@ -881,47 +897,79 @@ func TestConsensus(t *testing.T) {
require
.
Equal
(
t
,
"alchemy_getTransactionReceipts"
,
resJsonMap
[
"result"
]
.
(
map
[
string
]
interface
{})[
"result"
]
.
(
map
[
string
]
interface
{})[
"_"
])
})
t
.
Run
(
"translate consensus_getReceipts to
eth_getTransactionReceipt batched
"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"translate consensus_getReceipts to
alchemy_getTransactionReceipts with block number
"
,
func
(
t
*
testing
.
T
)
{
reset
()
useOnlyNode1
()
update
()
nodes
[
"node1"
]
.
backend
.
Override
(
proxyd
.
WithConsensusReceiptTarget
(
"eth_getTransactionReceipt"
))
// reset request counts
nodes
[
"node1"
]
.
mockBackend
.
Reset
()
nodes
[
"node1"
]
.
backend
.
Override
(
proxyd
.
WithConsensusReceiptTarget
(
"alchemy_getTransactionReceipts"
))
defer
nodes
[
"node1"
]
.
backend
.
Override
(
proxyd
.
WithConsensusReceiptTarget
(
"debug_getRawReceipts"
))
resRaw
,
statusCode
,
err
:=
client
.
SendRPC
(
"consensus_getReceipts"
,
[]
interface
{}{
map
[
string
]
interface
{}{
"blockOrHash"
:
"0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b"
,
"transactions"
:
[]
string
{
"0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c5"
,
"0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c6"
,
"0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c7"
,
"0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c8"
,
}}})
"blockOrHash"
:
"0x55"
}})
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
200
,
statusCode
)
var
reqJsonMap
[]
map
[
string
]
interface
{}
var
reqJsonMap
map
[
string
]
interface
{}
err
=
json
.
Unmarshal
(
nodes
[
"node1"
]
.
mockBackend
.
Requests
()[
0
]
.
Body
,
&
reqJsonMap
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
4
,
len
(
reqJsonMap
))
for
_
,
req
:=
range
reqJsonMap
{
require
.
Equal
(
t
,
"eth_getTransactionReceipt"
,
req
[
"method"
])
}
require
.
Equal
(
t
,
"0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c5"
,
reqJsonMap
[
0
][
"params"
]
.
([]
interface
{})[
0
])
require
.
Equal
(
t
,
"0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c6"
,
reqJsonMap
[
1
][
"params"
]
.
([]
interface
{})[
0
])
require
.
Equal
(
t
,
"0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c7"
,
reqJsonMap
[
2
][
"params"
]
.
([]
interface
{})[
0
])
require
.
Equal
(
t
,
"0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c8"
,
reqJsonMap
[
3
][
"params"
]
.
([]
interface
{})[
0
])
require
.
Equal
(
t
,
"alchemy_getTransactionReceipts"
,
reqJsonMap
[
"method"
])
require
.
Equal
(
t
,
"0x55"
,
reqJsonMap
[
"params"
]
.
([]
interface
{})[
0
]
.
(
map
[
string
]
interface
{})[
"blockNumber"
])
var
resJsonMap
map
[
string
]
interface
{}
err
=
json
.
Unmarshal
(
resRaw
,
&
resJsonMap
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
"eth_getTransactionReceipt"
,
resJsonMap
[
"result"
]
.
(
map
[
string
]
interface
{})[
"method"
]
.
(
string
))
require
.
Equal
(
t
,
4
,
len
(
resJsonMap
[
"result"
]
.
(
map
[
string
]
interface
{})[
"result"
]
.
([]
interface
{})))
for
_
,
res
:=
range
resJsonMap
[
"result"
]
.
(
map
[
string
]
interface
{})[
"result"
]
.
([]
interface
{})
{
require
.
Equal
(
t
,
"eth_getTransactionReceipt"
,
res
.
(
map
[
string
]
interface
{})[
"_"
])
}
require
.
Equal
(
t
,
"alchemy_getTransactionReceipts"
,
resJsonMap
[
"result"
]
.
(
map
[
string
]
interface
{})[
"method"
]
.
(
string
))
require
.
Equal
(
t
,
"alchemy_getTransactionReceipts"
,
resJsonMap
[
"result"
]
.
(
map
[
string
]
interface
{})[
"result"
]
.
(
map
[
string
]
interface
{})[
"_"
])
})
t
.
Run
(
"translate consensus_getReceipts to alchemy_getTransactionReceipts with latest block tag"
,
func
(
t
*
testing
.
T
)
{
reset
()
useOnlyNode1
()
update
()
// reset request counts
nodes
[
"node1"
]
.
mockBackend
.
Reset
()
nodes
[
"node1"
]
.
backend
.
Override
(
proxyd
.
WithConsensusReceiptTarget
(
"alchemy_getTransactionReceipts"
))
defer
nodes
[
"node1"
]
.
backend
.
Override
(
proxyd
.
WithConsensusReceiptTarget
(
"debug_getRawReceipts"
))
resRaw
,
statusCode
,
err
:=
client
.
SendRPC
(
"consensus_getReceipts"
,
[]
interface
{}{
map
[
string
]
interface
{}{
"blockOrHash"
:
"latest"
}})
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
200
,
statusCode
)
var
reqJsonMap
map
[
string
]
interface
{}
err
=
json
.
Unmarshal
(
nodes
[
"node1"
]
.
mockBackend
.
Requests
()[
0
]
.
Body
,
&
reqJsonMap
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
"alchemy_getTransactionReceipts"
,
reqJsonMap
[
"method"
])
require
.
Equal
(
t
,
"0x101"
,
reqJsonMap
[
"params"
]
.
([]
interface
{})[
0
]
.
(
map
[
string
]
interface
{})[
"blockNumber"
])
var
resJsonMap
map
[
string
]
interface
{}
err
=
json
.
Unmarshal
(
resRaw
,
&
resJsonMap
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
"alchemy_getTransactionReceipts"
,
resJsonMap
[
"result"
]
.
(
map
[
string
]
interface
{})[
"method"
]
.
(
string
))
require
.
Equal
(
t
,
"alchemy_getTransactionReceipts"
,
resJsonMap
[
"result"
]
.
(
map
[
string
]
interface
{})[
"result"
]
.
(
map
[
string
]
interface
{})[
"_"
])
})
t
.
Run
(
"translate consensus_getReceipts to unsupported consensus_receipts_target"
,
func
(
t
*
testing
.
T
)
{
reset
()
useOnlyNode1
()
nodes
[
"node1"
]
.
backend
.
Override
(
proxyd
.
WithConsensusReceiptTarget
(
"unsupported_consensus_receipts_target"
))
defer
nodes
[
"node1"
]
.
backend
.
Override
(
proxyd
.
WithConsensusReceiptTarget
(
"debug_getRawReceipts"
))
_
,
statusCode
,
err
:=
client
.
SendRPC
(
"consensus_getReceipts"
,
[]
interface
{}{
map
[
string
]
interface
{}{
"blockOrHash"
:
"latest"
}})
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
400
,
statusCode
)
})
t
.
Run
(
"consensus_getReceipts should not be used in a batch"
,
func
(
t
*
testing
.
T
)
{
...
...
proxyd/server.go
View file @
8e3d9aba
...
...
@@ -347,7 +347,8 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) {
writeRPCError
(
ctx
,
w
,
nil
,
ErrGatewayTimeout
)
return
}
if
errors
.
Is
(
err
,
ErrConsensusGetReceiptsCantBeBatched
)
{
if
errors
.
Is
(
err
,
ErrConsensusGetReceiptsCantBeBatched
)
||
errors
.
Is
(
err
,
ErrConsensusGetReceiptsInvalidTarget
)
{
writeRPCError
(
ctx
,
w
,
nil
,
ErrInvalidRequest
(
err
.
Error
()))
return
}
...
...
@@ -364,6 +365,11 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) {
rawBody
:=
json
.
RawMessage
(
body
)
backendRes
,
cached
,
err
:=
s
.
handleBatchRPC
(
ctx
,
[]
json
.
RawMessage
{
rawBody
},
isLimited
,
false
)
if
err
!=
nil
{
if
errors
.
Is
(
err
,
ErrConsensusGetReceiptsCantBeBatched
)
||
errors
.
Is
(
err
,
ErrConsensusGetReceiptsInvalidTarget
)
{
writeRPCError
(
ctx
,
w
,
nil
,
ErrInvalidRequest
(
err
.
Error
()))
return
}
writeRPCError
(
ctx
,
w
,
nil
,
ErrInternal
)
return
}
...
...
@@ -489,7 +495,8 @@ func (s *Server) handleBatchRPC(ctx context.Context, reqs []json.RawMessage, isL
elems
:=
cacheMisses
[
start
:
end
]
res
,
err
:=
s
.
BackendGroups
[
group
.
backendGroup
]
.
Forward
(
ctx
,
createBatchRequest
(
elems
),
isBatch
)
if
err
!=
nil
{
if
errors
.
Is
(
err
,
ErrConsensusGetReceiptsCantBeBatched
)
{
if
errors
.
Is
(
err
,
ErrConsensusGetReceiptsCantBeBatched
)
||
errors
.
Is
(
err
,
ErrConsensusGetReceiptsInvalidTarget
)
{
return
nil
,
false
,
err
}
log
.
Error
(
...
...
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