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

Move internal error into protocol package #10

Merged
merged 20 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from 12 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
73 changes: 67 additions & 6 deletions api/protocol/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,16 +231,15 @@ type Message struct {
}

// Error is a protocol Error type that can be used for additional error
// context. It embeds an 8 byte number that can be used to trace calls on both the
// client and server side.
// context. It embeds an 8 byte number that can be used to trace calls on both
// the client and server side.
type Error struct {
Timestamp int64 `json:"timestamp"`
Trace string `json:"trace"`
Message string `json:"error"`
Trace string `json:"trace,omitempty"`
Message string `json:"message"`
}

// Errorf is a client induced protocol error (e.g. "invalid height"). This is a
// pretty printable error on the client and server and is not fatal.
// Errorf returns a protocol Error type with an embedded trace.
func Errorf(msg string, args ...interface{}) *Error {
trace, _ := random(8)
return &Error{
Expand All @@ -250,10 +249,72 @@ func Errorf(msg string, args ...interface{}) *Error {
}
}

// String pretty prints a protocol error.
func (e Error) String() string {
if len(e.Trace) == 0 {
return e.Message
}
return fmt.Sprintf("%v [%v:%v]", e.Message, e.Trace, e.Timestamp)
}

// WireError converts an application error to a protocol Error. This does not
// embed a trace since the error is essentially pass through and therefore won't
// be logged server side.
joshuasing marked this conversation as resolved.
Show resolved Hide resolved
func WireError(err error) *Error {
return &Error{
Timestamp: time.Now().Unix(),
Message: err.Error(),
}
}

// WireErrorf creates a protocol error for the client.
joshuasing marked this conversation as resolved.
Show resolved Hide resolved
func WireErrorf(msg string, args ...any) *Error {
return &Error{
Timestamp: time.Now().Unix(),
Message: fmt.Sprintf(msg, args...),
}
}

// InternalError is an error type that differentiates between caller and callee
// errors. An internal error is used when something internal to the application
// fails. The client should not see the actual error message as those are
// server operator specific.
//
// One can argue that this not belong here but to prevent heavy copy/paste that
// will not age well it has been moved here.
type InternalError struct {
internal *Error
joshuasing marked this conversation as resolved.
Show resolved Hide resolved
actual error
}

// WireError returns the protocol error representation.
func (ie InternalError) WireError() *Error {
return ie.internal
}

// Error satisfies the error interface.
func (ie InternalError) Error() string {
if ie.actual != nil {
return fmt.Sprintf("%v [%v:%v]", ie.actual.Error(),
ie.internal.Timestamp, ie.internal.Trace)
}
return ie.internal.String()
}

// NewInternalErrorf returns an InternalError constructed from the passed
// message and arguments.
func NewInternalErrorf(msg string, args ...interface{}) *InternalError {
return &InternalError{
internal: Errorf("internal error"),
actual: fmt.Errorf(msg, args...),
}
}

// NewInternalError returns an InternalError representation of the passed in error.
func NewInternalError(err error) *InternalError {
return NewInternalErrorf("internal error: %v", err)
}

// Ping
type PingRequest struct {
Timestamp int64 `json:"timestamp"` // Local timestamp
Expand Down
8 changes: 4 additions & 4 deletions e2e/e2e_ext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,7 @@ func TestBFGPublicErrorCases(t *testing.T) {
},
{
name: "bitcoin broadcast deserialize error",
expectedError: "failed to deserialized tx: unexpected EOF",
expectedError: "failed to deserialize tx: unexpected EOF",
requests: []bfgapi.BitcoinBroadcastRequest{
{
Transaction: []byte("invalid..."),
Expand All @@ -1000,7 +1000,7 @@ func TestBFGPublicErrorCases(t *testing.T) {
},
{
name: "bitcoin broadcast database error",
expectedError: "pop_basis already exists",
expectedError: "pop basis already exists",
requests: []bfgapi.BitcoinBroadcastRequest{
{
Transaction: btx,
Expand Down Expand Up @@ -1158,7 +1158,7 @@ func TestBFGPrivateErrorCases(t *testing.T) {
},
{
name: "public key is invalid",
expectedError: "encoding/hex: invalid byte: U+006C 'l'",
expectedError: "public key decode: encoding/hex: invalid byte: U+006C 'l'",
requests: []bfgapi.AccessPublicKeyCreateRequest{
{
PublicKey: "blahblahblah",
Expand Down Expand Up @@ -3315,7 +3315,7 @@ func TestBFGAuthPingThenRemoval(t *testing.T) {

var v interface{}
err = wsjson.Read(ctx, c, &v)
if err != nil && !strings.Contains(err.Error(), "status = StatusCode(4100)") {
if err != nil && !strings.Contains(err.Error(), "status = StatusProtocolError and reason = \"killed\"") {
t.Fatal(err)
}

Expand Down
Loading