-
Notifications
You must be signed in to change notification settings - Fork 138
rfq+rfqmsg: add structured price oracle error codes #1766
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
base: main
Are you sure you want to change the base?
Conversation
ErrRejectWithCustomMsg constructs a RejectErr with error code 0 and the specified error message.
Formalizes the 'Code' of an 'OracleError' as an 'OracleErrorCode', and adds a couple of values corresponding to structured error cases.
Ensure the error code is part of an OracleError response, and pass the error intact in query{Bid,Ask}FromPriceOracle, instead of formatting it as a string.
Uses the OracleError returned by an oracle to customize the rejection message sent to a peer. If the OracleError contains a "transparent" code that's deemed to be suitable for passing on to a peer, then simply relay that error. Otherwise relay an opaque "unknown reject error" message.
Avoids a blunt cast of the wire code, and also refrains from relaying the full Error() message to the peer.
Simply passes an error code of 1 (unsupported subject asset) where appropriate in the mock oracle. The raw code is used instead of oraclerpc.UNSUPPORTED or similar to avoid dependency changes at present. Also adds the mock oracle's log to gitignore.
0a5e9ab
to
6bdb36a
Compare
Pull Request Test Coverage Report for Build 17268575857Details
💛 - Coveralls |
Result: &oraclerpc.QueryAssetRatesResponse_Error{ | ||
Error: &oraclerpc.QueryAssetRatesErrResponse{ | ||
Message: "unsupported subject asset", | ||
Code: 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there an enum val from our lib that we can use here instead of 1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used a raw '1' at present to avoid updating the mock oracle's dependencies (it looks like there have been other RPC changes since it was last updated as well). Perhaps best to avoid changing the mock oracle for now, and just update it to use the latest RPC definitions in another PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(If you agree, I'll drop the commit that changes the mock oracle before merge.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that if we want to go ahead and update this price oracle it should include a version bump too.
Having said that, I believe it's okay to just leave the Code
field unspecified and let it default to 0
, in order to not have to populate it with magic numbers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used a raw '1' at present to avoid updating the mock oracle's dependencies (it looks like there have been other RPC changes since it was last updated as well). Perhaps best to avoid changing the mock oracle for now, and just update it to use the latest RPC definitions in another PR?
I think updating the mock oracle in a separate PR makes sense to me. We can wait until 0.7 for example.
rfq/negotiator.go
Outdated
if oracleResponse.Err != nil { | ||
return nil, fmt.Errorf("failed to query price oracle for "+ | ||
"buy price: %s", oracleResponse.Err) | ||
return nil, oracleResponse.Err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the additional context that was here previously was useful to distinguish between buy/sell price related error. Is there a good reason for removing the additional context here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, yeah. Re-added context in a structured form in 5eaf8a9.
rfq/oracle.go
Outdated
const ( | ||
// ErrUnspecifiedOracleError represents the case where the oracle has | ||
// declined to give a more specific reason for the error. | ||
ErrUnspecifiedOracleError OracleErrorCode = iota |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we usually start error type names with Err...
. Maybe we should use names UnspecifiedOracleErrorCode
and UnsupportedAssetOracleErrorCode
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used your suggestion, fixed in 6130dac.
rfqmsg/reject.go
Outdated
// it with a custom error message. | ||
func ErrRejectWithCustomMsg(msg string) RejectErr { | ||
return RejectErr{ | ||
Code: 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use enum const here instead of 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 79308a2. There were also some existing cases in that file that used the raw code, so I fixed those too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should squash or amend the commits in this PR.
Also, to stay consistent with the naming pattern used elsewhere in the code, we should probably call this NewRejectErr
.
enum ErrorCode { | ||
// ERROR_UNSPECIFIED indicates an unspecified error. | ||
ERROR_UNSPECIFIED = 0; | ||
|
||
// UNSUPPORTED indicates the asset is not supported. | ||
ERROR_UNSUPPORTED = 1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these fields should follow the enum filed names in our code so: UNSUPPORTED_ASSET_ORACLE_ERROR_CODE
etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, fixed in 6ff7217.
Changes these to avoid the 'Err..' convention presently reserved for type names.
Defines specific consts for the two RejectErr error codes, and uses those in place of the raw uint8 values.
Changes 'ERROR_UNSPECIFIED' and 'ERROR_SUPPORTED' to more closely match the OracleErrorCode values in rfq/oracle.go.
Introduces a structured QueryError that wraps an arbitrary error (usually from a price oracle) with arbitrary context, and adjusts query{Buy,Sell}FromPriceOracle to return these errors where appropriate. Also adjusts createCustomRejectErr to handle QueryErrors, instead of OracleErrors.
rfq/negotiator.go
Outdated
|
||
// The rejection message will state that the oracle doesn't | ||
// support the asset. | ||
case ErrUnsupportedOracleAsset: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in the future would we append to this switch
all the cases for codes that are considered public?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I read the iota
list of all error codes I don't really have some information source as to whether they are public or internal error codes.
We could follow a convention that all non-zero codes are public (with appropriate docs in the definitions ofcs)
Or further extend the oracle error with a direct Internal bool
flag, that explicitly indicates whether this code/msg should be shared or not
|
||
// code is the error code. | ||
uint32 code = 2; | ||
ErrorCode code = 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth noting that this doesn't break backwards compatibility as both uint32
and enum
are encoded as varints on the wire.
rfq/oracle.go
Outdated
switch code { | ||
case oraclerpc.ErrorCode_ERROR_UNSPECIFIED: | ||
return ErrUnspecifiedOracleError | ||
case oraclerpc.ErrorCode_ERROR_UNSUPPORTED: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we add an empty line before a new switch case
case oraclerpc.ErrorCode_ERROR_UNSUPPORTED: | |
case oraclerpc.ErrorCode_ERROR_UNSUPPORTED: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
except for the first case (but including the default
case below)
Result: &oraclerpc.QueryAssetRatesResponse_Error{ | ||
Error: &oraclerpc.QueryAssetRatesErrResponse{ | ||
Message: "unsupported subject asset", | ||
Code: 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that if we want to go ahead and update this price oracle it should include a version bump too.
Having said that, I believe it's okay to just leave the Code
field unspecified and let it default to 0
, in order to not have to populate it with magic numbers
rfq/negotiator.go
Outdated
if errors.As(err, &oracleError) { | ||
// The error is of the expected type, so switch on the error | ||
// code returned by the oracle. If the code is benign, then the | ||
// RejectErr will simply relay the oracle's message. Otherwise, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eventually we should squash all the following fix related commits to their original commit
// based on an error response from a price oracle. | ||
func createCustomRejectErr(err error) rfqmsg.RejectErr { | ||
var queryError *QueryError | ||
// Check if the error we've received is the expected QueryError, and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
newline before the comments
// Check if the error we've received is the expected QueryError, and | |
var queryError *QueryError | |
// Check if the error we've received is the expected QueryError, and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've taken another look through this.
IMO needs commit squash and then we can review the set of commits which will be merged.
rfqmsg/reject.go
Outdated
// it with a custom error message. | ||
func ErrRejectWithCustomMsg(msg string) RejectErr { | ||
return RejectErr{ | ||
Code: 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should squash or amend the commits in this PR.
Also, to stay consistent with the naming pattern used elsewhere in the code, we should probably call this NewRejectErr
.
Result: &oraclerpc.QueryAssetRatesResponse_Error{ | ||
Error: &oraclerpc.QueryAssetRatesErrResponse{ | ||
Message: "unsupported subject asset", | ||
Code: 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used a raw '1' at present to avoid updating the mock oracle's dependencies (it looks like there have been other RPC changes since it was last updated as well). Perhaps best to avoid changing the mock oracle for now, and just update it to use the latest RPC definitions in another PR?
I think updating the mock oracle in a separate PR makes sense to me. We can wait until 0.7 for example.
@jtobin, remember to re-request review from reviewers when ready |
Adds some structure to price oracle error codes, along with some custom handling for them. In particular, a code of '1' now corresponds to an 'unsupported asset' error, which, considered a 'public' error, is forwarded in the customizable message field of the reject messages sent to peers. An error with any other code continues, at present, to be treated as an unspecified error.
Resolves #1749, #1326.
(This is a refinement over the closed #1751, which forwarded errors indiscriminately.)