Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend: handle null response from Eth server #287

Merged
merged 5 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/GWallet.Backend/Ether/EtherExceptions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type RpcErrorCode =
| CannotFulfillRequest = -32046
| ResourceNotFound = -32001
| InternalError = -32603
| UnparsableResponseType = -39000

type ServerCannotBeResolvedException =
inherit CommunicationUnsuccessfulException
Expand Down Expand Up @@ -95,3 +96,10 @@ type UnhandledWebException =
}
new (info: SerializationInfo, context: StreamingContext) =
{ inherit Exception (info, context) }

/// Exception indicating that response JSON contains null value where it should not.
/// E.g. {"jsonrpc":"2.0","id":1,"result":null}
type AbnormalNullValueInJsonResponseException(message: string) =
inherit CommunicationUnsuccessfulException(message)

static member BalanceJobErrorMessage = "Abnormal null response from balance job"
37 changes: 30 additions & 7 deletions src/GWallet.Backend/Ether/EtherServer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ module Server =
raise <| ServerTimedOutException(exMsg, httpReqEx)
if HttpRequestExceptionMatchesErrorCode httpReqEx (int CloudFlareError.OriginUnreachable) then
raise <| ServerTimedOutException(exMsg, httpReqEx)
if HttpRequestExceptionMatchesErrorCode httpReqEx (int HttpStatusCode.RequestTimeout) then
raise <| ServerTimedOutException(exMsg, httpReqEx)

if HttpRequestExceptionMatchesErrorCode httpReqEx (int CloudFlareError.OriginSslHandshakeError) then
raise <| ServerChannelNegotiationException(exMsg, CloudFlareError.OriginSslHandshakeError, httpReqEx)
Expand Down Expand Up @@ -226,6 +228,8 @@ module Server =
raise <| ServerMisconfiguredException(exMsg, rpcResponseEx)
| i when i = int RpcErrorCode.InternalError ->
raise <| ServerFaultException(exMsg, rpcResponseEx)
| j when j = int RpcErrorCode.UnparsableResponseType ->
raise <| ServerFaultException(exMsg, rpcResponseEx)
| _ ->
raise
<| Exception (SPrintF3 "RpcResponseException with RpcError Code <%i> and Message '%s' (%s)"
Expand Down Expand Up @@ -464,7 +468,10 @@ module Server =
let! cancelToken = Async.CancellationToken
let task =
web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(address, null, cancelToken)
return! Async.AwaitTask task
let! txCount = Async.AwaitTask task
if isNull txCount then
raise <| AbnormalNullValueInJsonResponseException "Abnormal null response from tx count job"
return txCount
}
GetRandomizedFuncs currency web3Func
return! faultTolerantEtherClient.Query
Expand All @@ -480,7 +487,7 @@ module Server =
web3.Eth.Blocks.GetBlockNumber.SendRequestAsync (null, cancelToken)
|> Async.AwaitTask
if isNull latestBlock then
failwith "latestBlock somehow is null"
raise <| AbnormalNullValueInJsonResponseException "latestBlock somehow is null"

let blockToCheck = BigInteger.Subtract(latestBlock.Value,
NUMBER_OF_CONFIRMATIONS_TO_CONSIDER_BALANCE_CONFIRMED)
Expand Down Expand Up @@ -542,8 +549,10 @@ module Server =
let task = web3.Eth.GetBalance.SendRequestAsync (address, null, cancelToken)
return! Async.AwaitTask task
}
if Object.ReferenceEquals(balance, null) then
failwith "Weird null response from balance job"
if isNull balance then
raise <|
AbnormalNullValueInJsonResponseException
AbnormalNullValueInJsonResponseException.BalanceJobErrorMessage
return UnitConversion.Convert.FromWei(balance.Value, UnitConversion.EthUnit.Ether)
}
GetRandomizedFuncs currency web3Func
Expand Down Expand Up @@ -573,7 +582,7 @@ module Server =

let contractHandler = web3.Eth.GetContractHandler contractAddress
if isNull contractHandler then
failwith "contractHandler somehow is null"
raise <| AbnormalNullValueInJsonResponseException "contractHandler somehow is null"

let! cancelToken = Async.CancellationToken
cancelToken.ThrowIfCancellationRequested()
Expand Down Expand Up @@ -635,7 +644,10 @@ module Server =
let! cancelToken = Async.CancellationToken
let task =
contractHandler.EstimateGasAsync<TransferFunction>(transferFunctionMsg, cancelToken)
return! Async.AwaitTask task
let! fee = Async.AwaitTask task
if isNull fee then
raise <| AbnormalNullValueInJsonResponseException "Abnormal null response from transfer fee job"
return fee
}
GetRandomizedFuncs account.Currency web3Func
return! faultTolerantEtherClient.Query
Expand All @@ -658,6 +670,8 @@ module Server =
let! cancelToken = Async.CancellationToken
let task = web3.Eth.GasPrice.SendRequestAsync(null, cancelToken)
let! hexBigInteger = Async.AwaitTask task
if isNull hexBigInteger then
raise <| AbnormalNullValueInJsonResponseException "Abnormal null response from gas price job"
if hexBigInteger.Value = BigInteger 0 then
return failwith "Some server returned zero for gas price, which is invalid"
return hexBigInteger
Expand Down Expand Up @@ -688,7 +702,12 @@ module Server =
let! cancelToken = Async.CancellationToken
let task =
web3.Eth.Transactions.SendRawTransaction.SendRequestAsync(transaction, null, cancelToken)
return! Async.AwaitTask task
let! response = Async.AwaitTask task
if isNull response then
raise <|
AbnormalNullValueInJsonResponseException
"Abnormal null response from broadcast transaction job"
return response
}
GetRandomizedFuncs currency web3Func
try
Expand Down Expand Up @@ -719,6 +738,10 @@ module Server =
let task =
web3.TransactionManager.TransactionReceiptService.PollForReceiptAsync(txHash, cancelToken)
let! transactionReceipt = Async.AwaitTask task
if isNull transactionReceipt || isNull transactionReceipt.GasUsed || isNull transactionReceipt.Status then
raise <|
AbnormalNullValueInJsonResponseException
(SPrintF1 "Abnormal null response when getting details from tx receipt (%A)" transactionReceipt)
return {
GasUsed = transactionReceipt.GasUsed.Value
Status = transactionReceipt.Status.Value
Expand Down
4 changes: 4 additions & 0 deletions src/GWallet.Backend/ServerManager.fs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ module ServerManager =
let web3Func (web3: Ether.SomeWeb3): Async<decimal> =
async {
let! balance = Async.AwaitTask (web3.Eth.GetBalance.SendRequestAsync ETH_GENESISBLOCK_ADDRESS)
if isNull balance then
raise <|
Ether.AbnormalNullValueInJsonResponseException
Ether.AbnormalNullValueInJsonResponseException.BalanceJobErrorMessage
return balance.Value |> decimal
}

Expand Down
Loading