Skip to content

Commit

Permalink
feat: refine API error codes (#215)
Browse files Browse the repository at this point in the history
Co-authored-by: carlcarl <carl.h@binance.com>
  • Loading branch information
carlcarl and carl-h-20230331 authored Oct 17, 2022
1 parent 02b49c1 commit 9c379fb
Show file tree
Hide file tree
Showing 30 changed files with 205 additions and 75 deletions.
70 changes: 68 additions & 2 deletions core/block_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package core
import (
"fmt"

"github.com/bnb-chain/zkbnb-crypto/wasm/txtypes"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"

"github.com/bnb-chain/zkbnb/core/executor"
Expand Down Expand Up @@ -83,12 +85,76 @@ func (p *APIProcessor) Process(tx *tx.Tx) error {
err = executor.Prepare()
if err != nil {
logx.Error("fail to prepare:", err)
return types.AppErrInternal
return mappingPrepareErrors(err)
}
err = executor.VerifyInputs(false)
if err != nil {
return types.AppErrInvalidTxField.RefineError(err.Error())
return mappingVerifyInputsErrors(err)
}

return nil
}

func mappingPrepareErrors(err error) error {
switch e := errors.Cause(err).(type) {
case types.Error:
return e
default:
return types.AppErrInternal
}
}

func mappingVerifyInputsErrors(err error) error {
e := errors.Cause(err)
switch e {
case txtypes.ErrAccountIndexTooLow, txtypes.ErrAccountIndexTooHigh,
txtypes.ErrCreatorAccountIndexTooLow, txtypes.ErrCreatorAccountIndexTooHigh,
txtypes.ErrFromAccountIndexTooLow, txtypes.ErrFromAccountIndexTooHigh,
txtypes.ErrToAccountIndexTooLow, txtypes.ErrToAccountIndexTooHigh:
return types.AppErrInvalidAccountIndex
case txtypes.ErrGasAccountIndexTooLow, txtypes.ErrGasAccountIndexTooHigh:
return types.AppErrInvalidGasFeeAccount
case txtypes.ErrGasFeeAssetIdTooLow, txtypes.ErrGasFeeAssetIdTooHigh:
return types.AppErrInvalidGasFeeAsset
case txtypes.ErrGasFeeAssetAmountTooLow, txtypes.ErrGasFeeAssetAmountTooHigh:
return types.AppErrInvalidGasFeeAmount
case txtypes.ErrNonceTooLow:
return types.AppErrInvalidNonce
case txtypes.ErrOfferTypeInvalid:
return types.AppErrInvalidOfferType
case txtypes.ErrOfferIdTooLow:
return types.AppErrInvalidOfferId
case txtypes.ErrNftIndexTooLow:
return types.AppErrInvalidNftIndex
case txtypes.ErrAssetIdTooLow, txtypes.ErrAssetIdTooHigh:
return types.AppErrInvalidAssetId
case txtypes.ErrAssetAmountTooLow, txtypes.ErrAssetAmountTooHigh:
return types.AppErrInvalidAssetAmount
case txtypes.ErrListedAtTooLow:
return types.AppErrInvalidListTime
case txtypes.ErrTreasuryRateTooLow, txtypes.ErrTreasuryRateTooHigh,
txtypes.ErrCreatorTreasuryRateTooLow, txtypes.ErrCreatorTreasuryRateTooHigh:
return types.AppErrInvalidTreasuryRate
case txtypes.ErrCollectionNameTooShort, txtypes.ErrCollectionNameTooLong:
return types.AppErrInvalidCollectionName
case txtypes.ErrIntroductionTooLong:
return types.AppErrInvalidIntroduction
case txtypes.ErrNftContentHashInvalid:
return types.AppErrInvalidNftContenthash
case txtypes.ErrNftCollectionIdTooLow, txtypes.ErrNftCollectionIdTooHigh:
return types.AppErrInvalidCollectionId
case txtypes.ErrCallDataHashInvalid:
return types.AppErrInvalidCallDataHash
case txtypes.ErrToAccountNameHashInvalid:
return types.AppErrInvalidToAccountNameHash
case txtypes.ErrToAddressInvalid:
return types.AppErrInvalidToAddress
case txtypes.ErrBuyOfferInvalid:
return types.AppErrInvalidBuyOffer
case txtypes.ErrSellOfferInvalid:
return types.AppErrInvalidSellOffer

default:
return types.AppErrInvalidTxField.RefineError(err.Error())
}
}
15 changes: 8 additions & 7 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/bnb-chain/zkbnb/dao/sysconfig"
"github.com/bnb-chain/zkbnb/dao/tx"
"github.com/bnb-chain/zkbnb/tree"
"github.com/bnb-chain/zkbnb/types"
)

const (
Expand Down Expand Up @@ -258,11 +259,11 @@ func (bc *BlockChain) commitNewBlock(blockSize int, createdAt int64) (*block.Blo
func (bc *BlockChain) VerifyExpiredAt(expiredAt int64) error {
if !bc.dryRun {
if expiredAt < bc.currentBlock.CreatedAt.UnixMilli() {
return errors.New("invalid expired time")
return types.AppErrInvalidExpireTime
}
} else {
if expiredAt < time.Now().UnixMilli() {
return errors.New("invalid expired time")
return types.AppErrInvalidExpireTime
}
}
return nil
Expand All @@ -275,15 +276,15 @@ func (bc *BlockChain) VerifyNonce(accountIndex int64, nonce int64) error {
return err
}
if nonce != expectNonce {
return errors.New("invalid nonce")
return types.AppErrInvalidNonce
}
} else {
pendingNonce, err := bc.Statedb.GetPendingNonce(accountIndex)
if err != nil {
return err
}
if pendingNonce != nonce {
return errors.New("invalid nonce")
return types.AppErrInvalidNonce
}
}
return nil
Expand All @@ -295,7 +296,7 @@ func (bc *BlockChain) VerifyGas(gasAccountIndex, gasFeeAssetId int64, txType int
return err
}
if gasAccountIndex != cfgGasAccountIndex {
return errors.New("invalid gas fee account")
return types.AppErrInvalidGasFeeAccount
}

cfgGasFee, err := bc.Statedb.GetGasConfig()
Expand All @@ -306,7 +307,7 @@ func (bc *BlockChain) VerifyGas(gasAccountIndex, gasFeeAssetId int64, txType int
gasAsset, ok := cfgGasFee[uint32(gasFeeAssetId)]
if !ok {
logx.Errorf("cannot find gas config for asset id: %d", gasFeeAssetId)
return errors.New("invalid gas fee asset")
return types.AppErrInvalidGasFeeAsset
}

if !skipGasAmtChk {
Expand All @@ -315,7 +316,7 @@ func (bc *BlockChain) VerifyGas(gasAccountIndex, gasFeeAssetId int64, txType int
return errors.New("invalid tx type")
}
if gasFeeAmount.Cmp(big.NewInt(gasFee)) < 0 {
return errors.New("invalid gas fee amount")
return types.AppErrInvalidGasFeeAmount
}
}
return nil
Expand Down
26 changes: 13 additions & 13 deletions core/executor/atomic_match_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (e *AtomicMatchExecutor) Prepare() error {
matchNft, err := e.bc.StateDB().PrepareNft(txInfo.SellOffer.NftIndex)
if err != nil {
logx.Errorf("prepare nft failed")
return errors.New("internal error")
return err
}

// Set the right treasury and creator treasury amount.
Expand Down Expand Up @@ -79,16 +79,16 @@ func (e *AtomicMatchExecutor) VerifyInputs(skipGasAmtChk bool) error {

if txInfo.BuyOffer.Type != types.BuyOfferType ||
txInfo.SellOffer.Type != types.SellOfferType {
return errors.New("invalid offer type")
return types.AppErrInvalidOfferType
}
if txInfo.BuyOffer.AccountIndex == txInfo.SellOffer.AccountIndex {
return errors.New("same buyer and seller")
return types.AppErrSameBuyerAndSeller
}
if txInfo.SellOffer.NftIndex != txInfo.BuyOffer.NftIndex ||
txInfo.SellOffer.AssetId != txInfo.BuyOffer.AssetId ||
txInfo.SellOffer.AssetAmount.String() != txInfo.BuyOffer.AssetAmount.String() ||
txInfo.SellOffer.TreasuryRate != txInfo.BuyOffer.TreasuryRate {
return errors.New("buy offer mismatches sell offer")
return types.AppErrBuyOfferMismatchSellOffer
}

// only gas assets are allowed for atomic match
Expand All @@ -99,15 +99,15 @@ func (e *AtomicMatchExecutor) VerifyInputs(skipGasAmtChk bool) error {
}
}
if !found {
return errors.New("invalid asset of offer")
return types.AppErrInvalidAssetOfOffer
}

// Check offer expired time.
if err := e.bc.VerifyExpiredAt(txInfo.BuyOffer.ExpiredAt); err != nil {
return errors.New("invalid BuyOffer.ExpiredAt")
return types.AppErrInvalidBuyOfferExpireTime
}
if err := e.bc.VerifyExpiredAt(txInfo.SellOffer.ExpiredAt); err != nil {
return errors.New("invalid SellOffer.ExpiredAt")
return types.AppErrInvalidSellOfferExpireTime
}

fromAccount, err := bc.StateDB().GetFormatAccount(txInfo.AccountIndex)
Expand All @@ -127,26 +127,26 @@ func (e *AtomicMatchExecutor) VerifyInputs(skipGasAmtChk bool) error {
if txInfo.AccountIndex == txInfo.BuyOffer.AccountIndex && txInfo.GasFeeAssetId == txInfo.SellOffer.AssetId {
totalBalance := ffmath.Add(txInfo.GasFeeAssetAmount, txInfo.BuyOffer.AssetAmount)
if fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance.Cmp(totalBalance) < 0 {
return errors.New("sender balance is not enough")
return types.AppErrSellerBalanceNotEnough
}
} else {
if fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance.Cmp(txInfo.GasFeeAssetAmount) < 0 {
return errors.New("sender balance is not enough")
return types.AppErrSellerBalanceNotEnough
}

if buyAccount.AssetInfo[txInfo.BuyOffer.AssetId].Balance.Cmp(txInfo.BuyOffer.AssetAmount) < 0 {
return errors.New("buy balance is not enough")
return types.AppErrBuyerBalanceNotEnough
}
}

// Check offer canceled or finalized.
sellOffer := sellAccount.AssetInfo[e.sellOfferAssetId].OfferCanceledOrFinalized
if sellOffer.Bit(int(e.sellOfferIndex)) == 1 {
return errors.New("sell offer canceled or finalized")
return types.AppErrInvalidSellOfferState
}
buyOffer := buyAccount.AssetInfo[e.buyOfferAssetId].OfferCanceledOrFinalized
if buyOffer.Bit(int(e.buyOfferIndex)) == 1 {
return errors.New("buy offer canceled or finalized")
return types.AppErrInvalidBuyOfferState
}

// Check the seller is the owner of the nft.
Expand All @@ -155,7 +155,7 @@ func (e *AtomicMatchExecutor) VerifyInputs(skipGasAmtChk bool) error {
return err
}
if nft.OwnerAccountIndex != txInfo.SellOffer.AccountIndex {
return errors.New("seller is not owner")
return types.AppErrSellerNotOwner
}

// Verify offer signature.
Expand Down
3 changes: 1 addition & 2 deletions core/executor/base_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package executor
import (
"github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"

"github.com/bnb-chain/zkbnb-crypto/wasm/txtypes"
Expand Down Expand Up @@ -55,7 +54,7 @@ func (e *BaseExecutor) Prepare() error {
err := e.bc.StateDB().PrepareAccountsAndAssets(e.dirtyAccountsAndAssetsMap)
if err != nil {
logx.Errorf("prepare accounts and assets failed: %s", err.Error())
return errors.New("internal error")
return err
}
return nil
}
Expand Down
4 changes: 2 additions & 2 deletions core/executor/cancel_offer_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (e *CancelOfferExecutor) VerifyInputs(skipGasAmtChk bool) error {
return err
}
if fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance.Cmp(txInfo.GasFeeAssetAmount) < 0 {
return errors.New("balance is not enough")
return types.AppErrBalanceNotEnough
}

offerAssetId := txInfo.OfferId / 128
Expand All @@ -66,7 +66,7 @@ func (e *CancelOfferExecutor) VerifyInputs(skipGasAmtChk bool) error {
if offerAsset != nil && offerAsset.OfferCanceledOrFinalized != nil {
xBit := offerAsset.OfferCanceledOrFinalized.Bit(int(offerIndex))
if xBit == 1 {
return errors.New("invalid offer id, already confirmed or canceled")
return types.AppErrInvalidOfferState
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/executor/create_collection_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (e *CreateCollectionExecutor) VerifyInputs(skipGasAmtChk bool) error {
return err
}
if fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance.Cmp(txInfo.GasFeeAssetAmount) < 0 {
return errors.New("balance is not enough")
return types.AppErrBalanceNotEnough
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion core/executor/deposit_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (e *DepositExecutor) VerifyInputs(skipGasAmtChk bool) error {
txInfo := e.txInfo

if txInfo.AssetAmount.Cmp(types.ZeroBigInt) < 0 {
return errors.New("invalid asset amount")
return types.AppErrInvalidAssetAmount
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion core/executor/deposit_nft_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (e *DepositNftExecutor) VerifyInputs(skipGasAmtChk bool) error {
return err
}
if nft.NftContentHash != types.EmptyNftContentHash {
return errors.New("invalid nft index, already exist")
return types.AppErrNftAlreadyExist
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion core/executor/full_exit_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func NewFullExitExecutor(bc IBlockchain, tx *tx.Tx) (TxExecutor, error) {
txInfo, err := types.ParseFullExitTxInfo(tx.TxInfo)
if err != nil {
logx.Errorf("parse full exit tx failed: %s", err.Error())
return nil, errors.New("invalid tx info")
return nil, types.AppErrInvalidTxInfo
}

return &FullExitExecutor{
Expand Down
6 changes: 3 additions & 3 deletions core/executor/mint_nft_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,18 @@ func (e *MintNftExecutor) VerifyInputs(skipGasAmtChk bool) error {
return err
}
if creatorAccount.CollectionNonce <= txInfo.NftCollectionId {
return errors.New("nft collection id is not less than account collection nonce")
return types.AppErrInvalidCollectionId
}
if creatorAccount.AssetInfo[txInfo.GasFeeAssetId].Balance.Cmp(txInfo.GasFeeAssetAmount) < 0 {
return errors.New("balance is not enough")
return types.AppErrBalanceNotEnough
}

toAccount, err := e.bc.StateDB().GetFormatAccount(txInfo.ToAccountIndex)
if err != nil {
return err
}
if txInfo.ToAccountNameHash != toAccount.AccountNameHash {
return errors.New("invalid ToAccountNameHash")
return types.AppErrInvalidToAccountNameHash
}

return nil
Expand Down
4 changes: 2 additions & 2 deletions core/executor/register_zns_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ func (e *RegisterZnsExecutor) VerifyInputs(skipGasAmtChk bool) error {

_, err := bc.StateDB().GetAccountByName(txInfo.AccountName)
if err == nil {
return errors.New("invalid account name, already registered")
return types.AppErrAccountNameAlreadyRegistered
}

if txInfo.AccountIndex != bc.StateDB().GetNextAccountIndex() {
return errors.New("invalid account index")
return types.AppErrInvalidAccountIndex
}

return nil
Expand Down
8 changes: 4 additions & 4 deletions core/executor/transfer_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,19 @@ func (e *TransferExecutor) VerifyInputs(skipGasAmtChk bool) error {
return err
}
if txInfo.ToAccountNameHash != toAccount.AccountNameHash {
return errors.New("invalid to account name hash")
return types.AppErrInvalidToAccountNameHash
}
if txInfo.GasFeeAssetId != txInfo.AssetId {
if fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance.Cmp(txInfo.GasFeeAssetAmount) < 0 {
return errors.New("invalid gas asset amount")
return types.AppErrInvalidGasFeeAmount
}
if fromAccount.AssetInfo[txInfo.AssetId].Balance.Cmp(txInfo.AssetAmount) < 0 {
return errors.New("invalid asset amount")
return types.AppErrInvalidAssetAmount
}
} else {
deltaBalance := ffmath.Add(txInfo.AssetAmount, txInfo.GasFeeAssetAmount)
if fromAccount.AssetInfo[txInfo.AssetId].Balance.Cmp(deltaBalance) < 0 {
return errors.New("invalid asset amount")
return types.AppErrInvalidAssetAmount
}
}

Expand Down
Loading

0 comments on commit 9c379fb

Please sign in to comment.