From ff001fc94ad71dc6b8e89cc866333371d2ce55ec Mon Sep 17 00:00:00 2001 From: Yilun Date: Thu, 9 Apr 2020 17:37:54 -0700 Subject: [PATCH] Use error constants whenever possible Signed-off-by: Yilun --- client.go | 24 +++++++++++++----------- error.go | 32 +++++++++++++++++++++++++++++--- message.go | 41 ++++++++++++++++++++--------------------- multiclient.go | 26 ++++++++++++-------------- nanopay.go | 15 +++++++-------- wallet.go | 6 ++---- 6 files changed, 83 insertions(+), 61 deletions(-) diff --git a/client.go b/client.go index 91b99691..7ef83bb4 100644 --- a/client.go +++ b/client.go @@ -8,7 +8,6 @@ import ( "encoding/hex" "encoding/json" "errors" - "fmt" "log" "net/url" "strings" @@ -193,14 +192,14 @@ func (c *Client) getOrComputeSharedKey(remotePublicKey []byte) (*[sharedKeySize] } if len(remotePublicKey) != ed25519.PublicKeySize { - return nil, fmt.Errorf("public key length is %d, expecting %d", len(remotePublicKey), ed25519.PublicKeySize) + return nil, ErrInvalidPubkeySize } var pk [ed25519.PublicKeySize]byte copy(pk[:], remotePublicKey) curve25519PublicKey, ok := ed25519.PublicKeyToCurve25519PublicKey(&pk) if !ok { - return nil, fmt.Errorf("converting public key %x to curve25519 public key failed", remotePublicKey) + return nil, ErrInvalidPubkey } sharedKey = new([sharedKeySize]byte) @@ -373,7 +372,10 @@ func (c *Client) handleMessage(msgType int, data []byte) error { } else if action == setClientAction { c.Close() } - return errors.New(common.ErrMessage[errCode]) + return errorWithCode{ + err: errors.New(common.ErrMessage[errCode]), + code: int32(errCode), + } } switch action { case setClientAction: @@ -623,7 +625,7 @@ func (c *Client) connect(maxRetries int) error { return nil } - return errors.New("max retry reached, connect failed") + return ErrConnectFailed } func (c *Client) reconnect() { @@ -742,7 +744,7 @@ func (c *Client) SendText(dests *StringArray, data string, config *MessageConfig func (c *Client) processDest(dest string) (string, error) { if len(dest) == 0 { - return "", errors.New("destination is empty") + return "", ErrNoDestination } addr := strings.Split(dest, ".") if len(addr[len(addr)-1]) < 2*ed25519.PublicKeySize { @@ -751,7 +753,7 @@ func (c *Client) processDest(dest string) (string, error) { return "", err } if len(reg.Registrant) == 0 { - return "", fmt.Errorf("%s is neither a valid public key nor a registered nam", addr[len(addr)-1]) + return "", ErrInvalidPubkeyOrName } addr[len(addr)-1] = reg.Registrant } @@ -769,7 +771,7 @@ func (c *Client) processDests(dests []string) ([]string, error) { processedDests = append(processedDests, processedDest) } if len(processedDests) == 0 { - return nil, errors.New("all destinations are invalid") + return nil, ErrInvalidDestination } return processedDests, nil } @@ -921,7 +923,7 @@ func (c *Client) sendTimeout(dests []string, payload *payloads.Payload, encrypte for i := range plds { size = len(plds[i]) + len(dests[i]) + ed25519.SignatureSize if size > maxClientMessageSize { - return fmt.Errorf("encoded message is greater than %v bytes", maxClientMessageSize) + return ErrMessageOversize } if totalSize+size > maxClientMessageSize { outboundMsg, err := c.newOutboundMessage(destList, pldList, encrypted, maxHoldingSeconds) @@ -943,7 +945,7 @@ func (c *Client) sendTimeout(dests []string, payload *payloads.Payload, encrypte size += len(dests[i]) + ed25519.SignatureSize } if size > maxClientMessageSize { - return fmt.Errorf("encoded message is greater than %v bytes", maxClientMessageSize) + return ErrMessageOversize } destList = dests pldList = plds @@ -1052,7 +1054,7 @@ func (c *Client) SetWriteDeadline(deadline time.Time) error { c.lock.Lock() defer c.lock.Unlock() if c.conn == nil { - return errors.New("nil websocket connection") + return ErrNilWebsocketConn } return c.conn.SetWriteDeadline(deadline) } diff --git a/error.go b/error.go index 4bb28bb1..61899c04 100644 --- a/error.go +++ b/error.go @@ -1,7 +1,11 @@ package nkn import ( + "errors" + "fmt" + ncp "github.com/nknorg/ncp-go" + "github.com/nknorg/nkn/vault" ) // ErrorWithCode is an error interface that implements error and Code() @@ -23,8 +27,30 @@ func (e errorWithCode) Code() int32 { return e.code } +// Error definitions. var ( - ErrClosed = ncp.NewGenericError("use of closed network connection", true, true) // The error message is meant to be identical to error returned by net package. - ErrKeyNotInMap = ncp.NewGenericError("key not in map", false, false) // for gomobile - ErrInvalidPayloadType = ncp.NewGenericError("invalid payload type", false, false) + ErrClosed = ncp.NewGenericError("use of closed network connection", true, true) // The error message is meant to be identical to error returned by net package. + ErrKeyNotInMap = errors.New("key not in map") // for gomobile + ErrInvalidPayloadType = errors.New("invalid payload type") + ErrConnectFailed = errors.New("connect failed") + ErrNoDestination = errors.New("no destination") + ErrInvalidDestination = errors.New("invalid destination") + ErrInvalidPubkeyOrName = errors.New("invalid public key or name") + ErrInvalidPubkeySize = errors.New("invalid public key size") + ErrInvalidPubkey = errors.New("invalid public key") + ErrMessageOversize = fmt.Errorf("encoded message is greater than %v bytes", maxClientMessageSize) + ErrNilWebsocketConn = errors.New("nil websocket connection") + ErrDecryptFailed = errors.New("decrypt message failed") + ErrAddrNotAllowed = errors.New("address not allowed") + ErrCreateClientFailed = errors.New("failed to create client") + ErrNilClient = errors.New("client is nil") + ErrNotNanoPay = errors.New("not nano pay transaction") + ErrWrongRecipient = errors.New("wrong nano pay recipient") + ErrNanoPayClosed = errors.New("use of closed nano pay claimer") + ErrInsufficientBalance = errors.New("insufficient balance") + ErrInvalidAmount = errors.New("invalid amount") + ErrExpiredNanoPay = errors.New("nanopay expired") + ErrExpiredNanoPayTxn = errors.New("nanopay transaction expired") + ErrWrongPassword = errors.New("wrong password") + ErrInvalidWalletVersion = fmt.Errorf("invalid wallet version, should be between %v and %v", vault.MinCompatibleWalletVersion, vault.MaxCompatibleWalletVersion) ) diff --git a/message.go b/message.go index ed19a83d..29bda736 100644 --- a/message.go +++ b/message.go @@ -2,7 +2,6 @@ package nkn import ( "crypto/rand" - "errors" "github.com/gogo/protobuf/proto" "github.com/nknorg/nkn-sdk-go/payloads" @@ -64,16 +63,16 @@ func decrypt(message []byte, nonce [nonceSize]byte, sharedKey *[sharedKeySize]by decrypted := make([]byte, len(message)-box.Overhead) _, ok := box.OpenAfterPrecomputation(decrypted[:0], message, &nonce, sharedKey) if !ok { - return nil, errors.New("decrypt message failed") + return nil, ErrDecryptFailed } return decrypted, nil } -func newBinaryPayload(data, messageId, replyToId []byte, noReply bool) (*payloads.Payload, error) { - if len(messageId) == 0 && len(replyToId) == 0 { +func newBinaryPayload(data, messageID, replyToID []byte, noReply bool) (*payloads.Payload, error) { + if len(messageID) == 0 && len(replyToID) == 0 { var err error - messageId, err = RandomBytes(MessageIDSize) + messageID, err = RandomBytes(MessageIDSize) if err != nil { return nil, err } @@ -81,17 +80,17 @@ func newBinaryPayload(data, messageId, replyToId []byte, noReply bool) (*payload return &payloads.Payload{ Type: payloads.BINARY, - MessageId: messageId, + MessageId: messageID, Data: data, - ReplyToId: replyToId, + ReplyToId: replyToID, NoReply: noReply, }, nil } -func newTextPayload(text string, messageId, replyToId []byte, noReply bool) (*payloads.Payload, error) { - if len(messageId) == 0 && len(replyToId) == 0 { +func newTextPayload(text string, messageID, replyToID []byte, noReply bool) (*payloads.Payload, error) { + if len(messageID) == 0 && len(replyToID) == 0 { var err error - messageId, err = RandomBytes(MessageIDSize) + messageID, err = RandomBytes(MessageIDSize) if err != nil { return nil, err } @@ -104,39 +103,39 @@ func newTextPayload(text string, messageId, replyToId []byte, noReply bool) (*pa return &payloads.Payload{ Type: payloads.TEXT, - MessageId: messageId, + MessageId: messageID, Data: data, - ReplyToId: replyToId, + ReplyToId: replyToID, NoReply: noReply, }, nil } -func newAckPayload(replyToId []byte) (*payloads.Payload, error) { +func newAckPayload(replyToID []byte) (*payloads.Payload, error) { return &payloads.Payload{ Type: payloads.ACK, - ReplyToId: replyToId, + ReplyToId: replyToID, }, nil } -func newMessagePayload(data interface{}, messageId []byte, noReply bool) (*payloads.Payload, error) { +func newMessagePayload(data interface{}, messageID []byte, noReply bool) (*payloads.Payload, error) { switch v := data.(type) { case []byte: - return newBinaryPayload(v, messageId, nil, noReply) + return newBinaryPayload(v, messageID, nil, noReply) case string: - return newTextPayload(v, messageId, nil, noReply) + return newTextPayload(v, messageID, nil, noReply) default: return nil, ErrInvalidPayloadType } } -func newReplyPayload(data interface{}, replyToId []byte) (*payloads.Payload, error) { +func newReplyPayload(data interface{}, replyToID []byte) (*payloads.Payload, error) { switch v := data.(type) { case []byte: - return newBinaryPayload(v, nil, replyToId, false) + return newBinaryPayload(v, nil, replyToID, false) case string: - return newTextPayload(v, nil, replyToId, false) + return newTextPayload(v, nil, replyToID, false) case nil: - return newAckPayload(replyToId) + return newAckPayload(replyToID) default: return nil, ErrInvalidPayloadType } diff --git a/multiclient.go b/multiclient.go index 6fc9762a..d35a15d6 100644 --- a/multiclient.go +++ b/multiclient.go @@ -2,8 +2,6 @@ package nkn import ( "context" - "errors" - "fmt" "log" "net" "regexp" @@ -13,6 +11,7 @@ import ( "sync" "time" + multierror "github.com/hashicorp/go-multierror" ncp "github.com/nknorg/ncp-go" "github.com/nknorg/nkn-sdk-go/payloads" "github.com/nknorg/nkn/util/address" @@ -37,7 +36,6 @@ const ( var ( multiClientIdentifierRe = regexp.MustCompile(MultiClientIdentifierRe) - errAddrNotAllowed = errors.New("address not allowed") ) // MultiClient sends and receives data using multiple NKN clients concurrently @@ -142,7 +140,7 @@ func NewMultiClient(account *Account, baseIdentifier string, numSubClients int, } err := m.handleSessionMsg(addIdentifier("", i-offset), msg.Src, msg.MessageID, msg.Data) if err != nil { - if err != ncp.ErrSessionClosed && err != errAddrNotAllowed { + if err != ncp.ErrSessionClosed && err != ErrAddrNotAllowed { log.Println(err) } continue @@ -192,7 +190,7 @@ func NewMultiClient(account *Account, baseIdentifier string, numSubClients int, case <-success: return m, nil case <-fail: - return nil, errors.New("failed to create any client") + return nil, ErrCreateClientFailed } } @@ -245,7 +243,7 @@ func (m *MultiClient) GetDefaultClient() *Client { func (m *MultiClient) SendWithClient(clientID int, dests *StringArray, data interface{}, config *MessageConfig) (*OnMessage, error) { client := m.GetClient(clientID) if client == nil { - return nil, fmt.Errorf("client %d is not created or not ready", clientID) + return nil, ErrNilClient } config, err := MergeMessageConfig(m.config.MessageConfig, config) @@ -285,7 +283,7 @@ func (m *MultiClient) SendTextWithClient(clientID int, dests *StringArray, data func (m *MultiClient) sendWithClient(clientID int, dests []string, payload *payloads.Payload, encrypted bool, maxHoldingSeconds int32) error { client := m.GetClient(clientID) if client == nil { - return fmt.Errorf("client %d is not created or not ready", clientID) + return ErrNilClient } return client.send(addMultiClientPrefix(dests, clientID), payload, encrypted, maxHoldingSeconds) } @@ -305,7 +303,7 @@ func (m *MultiClient) Send(dests *StringArray, data interface{}, config *Message } var lock sync.Mutex - var errMsg []string + var errs error var onRawReply *OnMessage onReply := NewOnMessage(1, nil) clients := m.GetClients() @@ -333,7 +331,7 @@ func (m *MultiClient) Send(dests *StringArray, data interface{}, config *Message sent++ } else { lock.Lock() - errMsg = append(errMsg, err.Error()) + errs = multierror.Append(errs, err) lock.Unlock() } } @@ -355,7 +353,7 @@ func (m *MultiClient) Send(dests *StringArray, data interface{}, config *Message case <-success: return onReply, nil case <-fail: - return nil, errors.New(strings.Join(errMsg, "; ")) + return nil, errs } } @@ -373,7 +371,7 @@ func (m *MultiClient) SendText(dests *StringArray, data string, config *MessageC func (m *MultiClient) send(dests []string, payload *payloads.Payload, encrypted bool, maxHoldingSeconds int32) error { var lock sync.Mutex - var errMsg []string + var errs error success := make(chan struct{}, 1) fail := make(chan struct{}, 1) go func() { @@ -388,7 +386,7 @@ func (m *MultiClient) send(dests []string, payload *payloads.Payload, encrypted sent++ } else { lock.Lock() - errMsg = append(errMsg, err.Error()) + errs = multierror.Append(errs, err) lock.Unlock() } } @@ -404,7 +402,7 @@ func (m *MultiClient) send(dests []string, payload *payloads.Payload, encrypted case <-success: return nil case <-fail: - return errors.New(strings.Join(errMsg, "; ")) + return errs } } @@ -470,7 +468,7 @@ func (m *MultiClient) handleSessionMsg(localClientID, src string, sessionID, dat if !ok { if !m.shouldAcceptAddr(remoteAddr) { m.sessionLock.Unlock() - return errAddrNotAllowed + return ErrAddrNotAllowed } session, err = m.newSession(remoteAddr, sessionID, m.config.SessionConfig) diff --git a/nanopay.go b/nanopay.go index e9a2d9a0..233cde0c 100644 --- a/nanopay.go +++ b/nanopay.go @@ -1,7 +1,6 @@ package nkn import ( - "errors" "sync" "time" @@ -277,7 +276,7 @@ func (npc *NanoPayClaimer) Claim(tx *transaction.Transaction) (*Amount, error) { npPayload, ok := payload.(*pb.NanoPay) if !ok { - return nil, npc.closeWithError(errors.New("not nano pay tx")) + return nil, npc.closeWithError(ErrNotNanoPay) } recipient, err := common.Uint160ParseFromBytes(npPayload.Recipient) @@ -286,7 +285,7 @@ func (npc *NanoPayClaimer) Claim(tx *transaction.Transaction) (*Amount, error) { } if recipient.CompareTo(npc.recipientProgramHash) != 0 { - return nil, npc.closeWithError(errors.New("wrong nano pay recipient")) + return nil, npc.closeWithError(ErrWrongRecipient) } if err := chain.VerifyTransaction(tx, 0); err != nil { @@ -312,19 +311,19 @@ func (npc *NanoPayClaimer) Claim(tx *transaction.Transaction) (*Amount, error) { defer npc.lock.Unlock() if npc.closed { - return nil, errors.New("attempt to use closed nano pay claimer") + return nil, ErrNanoPayClosed } if npc.id == nil || *npc.id == npPayload.Id { if senderBalance.ToFixed64() < npc.amount { - return nil, npc.closeWithError(errors.New("insufficient sender balance")) + return nil, npc.closeWithError(ErrInsufficientBalance) } } if npc.id != nil { if *npc.id == npPayload.Id { if npc.amount >= common.Fixed64(npPayload.Amount) { - return nil, npc.closeWithError(errors.New("nano pay balance decreased")) + return nil, npc.closeWithError(ErrInvalidAmount) } } else { if err := npc.flush(); err != nil { @@ -337,11 +336,11 @@ func (npc *NanoPayClaimer) Claim(tx *transaction.Transaction) (*Amount, error) { } if npPayload.TxnExpiration <= uint32(height)+receiverExpirationDelta { - return nil, npc.closeWithError(errors.New("nano pay tx expired")) + return nil, npc.closeWithError(ErrExpiredNanoPayTxn) } if npPayload.NanoPayExpiration <= uint32(height)+receiverExpirationDelta { - return nil, npc.closeWithError(errors.New("nano pay expired")) + return nil, npc.closeWithError(ErrExpiredNanoPay) } npc.tx = tx diff --git a/wallet.go b/wallet.go index 5d79ec4e..fceea8cf 100644 --- a/wallet.go +++ b/wallet.go @@ -5,8 +5,6 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" - "errors" - "fmt" "github.com/nknorg/nkn/common" "github.com/nknorg/nkn/crypto" @@ -106,7 +104,7 @@ func WalletFromJSON(walletJSON string, config *WalletConfig) (*Wallet, error) { } if walletData.Version < vault.MinCompatibleWalletVersion || walletData.Version > vault.MaxCompatibleWalletVersion { - return nil, fmt.Errorf("invalid wallet version %v, should be between %v and %v", walletData.Version, vault.MinCompatibleWalletVersion, vault.MaxCompatibleWalletVersion) + return nil, ErrInvalidWalletVersion } if config == nil { @@ -120,7 +118,7 @@ func WalletFromJSON(walletJSON string, config *WalletConfig) (*Wallet, error) { } pkh := sha256.Sum256(passwordKey) if !bytes.Equal(pkh[:], passwordKeyHash) { - return nil, errors.New("password wrong") + return nil, ErrWrongPassword } iv, err := hex.DecodeString(walletData.IV)