github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/wasm/keeper/legacy_querier.go (about)

     1  package keeper
     2  
     3  import (
     4  	"encoding/json"
     5  	"reflect"
     6  	"strconv"
     7  
     8  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     9  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    10  	abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types"
    11  
    12  	"github.com/fibonacci-chain/fbc/x/wasm/types"
    13  )
    14  
    15  const (
    16  	QueryListContractByCode        = "list-contracts-by-code"
    17  	QueryGetContract               = "contract-info"
    18  	QueryGetContractState          = "contract-state"
    19  	QueryGetCode                   = "code"
    20  	QueryListCode                  = "list-code"
    21  	QueryContractHistory           = "contract-history"
    22  	QueryListContractBlockedMethod = "list-contract-blocked-method"
    23  	QueryParams                    = "params"
    24  )
    25  
    26  const (
    27  	QueryMethodContractStateSmart = "smart"
    28  	QueryMethodContractStateAll   = "all"
    29  	QueryMethodContractStateRaw   = "raw"
    30  )
    31  
    32  // NewLegacyQuerier creates a new querier
    33  func NewLegacyQuerier(keeper types.ViewKeeper, gasLimit sdk.Gas) sdk.Querier {
    34  	return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) {
    35  		var (
    36  			rsp interface{}
    37  			err error
    38  		)
    39  		switch path[0] {
    40  		case QueryGetContract:
    41  			addr, addrErr := sdk.AccAddressFromBech32(path[1])
    42  			if addrErr != nil {
    43  				return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, addrErr.Error())
    44  			}
    45  			rsp, err = queryContractInfo(ctx, addr, keeper)
    46  		case QueryListContractByCode:
    47  			codeID, parseErr := strconv.ParseUint(path[1], 10, 64)
    48  			if parseErr != nil {
    49  				return nil, sdkerrors.Wrapf(types.ErrInvalid, "code id: %s", parseErr.Error())
    50  			}
    51  			rsp = queryContractListByCode(ctx, codeID, keeper)
    52  		case QueryGetContractState:
    53  			if len(path) < 3 {
    54  				return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown data query endpoint")
    55  			}
    56  			return queryContractState(ctx, path[1], path[2], req.Data, gasLimit, keeper)
    57  		case QueryGetCode:
    58  			codeID, parseErr := strconv.ParseUint(path[1], 10, 64)
    59  			if parseErr != nil {
    60  				return nil, sdkerrors.Wrapf(types.ErrInvalid, "code id: %s", parseErr.Error())
    61  			}
    62  			rsp, err = queryCode(ctx, codeID, keeper)
    63  		case QueryListCode:
    64  			rsp, err = queryCodeList(ctx, keeper)
    65  		case QueryContractHistory:
    66  			contractAddr, addrErr := sdk.AccAddressFromBech32(path[1])
    67  			if addrErr != nil {
    68  				return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, addrErr.Error())
    69  			}
    70  			rsp, err = queryContractHistory(ctx, contractAddr, keeper)
    71  		case QueryListContractBlockedMethod:
    72  			contractAddr, addrErr := sdk.AccAddressFromBech32(path[1])
    73  			if addrErr != nil {
    74  				return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, addrErr.Error())
    75  			}
    76  			rsp = queryListContractBlockedMethod(ctx, contractAddr, keeper)
    77  		case QueryParams:
    78  			rsp = queryParams(ctx, keeper)
    79  		default:
    80  			return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown data query endpoint")
    81  		}
    82  		if err != nil {
    83  			return nil, err
    84  		}
    85  		if rsp == nil || reflect.ValueOf(rsp).IsNil() {
    86  			return nil, nil
    87  		}
    88  		bz, err := json.MarshalIndent(rsp, "", "  ")
    89  		if err != nil {
    90  			return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
    91  		}
    92  		return bz, nil
    93  	}
    94  }
    95  
    96  func queryContractState(ctx sdk.Context, bech, queryMethod string, data []byte, gasLimit sdk.Gas, keeper types.ViewKeeper) (json.RawMessage, error) {
    97  	contractAddr, err := sdk.AccAddressFromBech32(bech)
    98  	if err != nil {
    99  		return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, bech)
   100  	}
   101  
   102  	switch queryMethod {
   103  	case QueryMethodContractStateAll:
   104  		resultData := make([]types.Model, 0)
   105  		// this returns a serialized json object (which internally encoded binary fields properly)
   106  		keeper.IterateContractState(ctx, contractAddr, func(key, value []byte) bool {
   107  			resultData = append(resultData, types.Model{Key: key, Value: value})
   108  			return false
   109  		})
   110  		bz, err := json.Marshal(resultData)
   111  		if err != nil {
   112  			return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
   113  		}
   114  		return bz, nil
   115  	case QueryMethodContractStateRaw:
   116  		// this returns the raw data from the state, base64-encoded
   117  		return keeper.QueryRaw(ctx, contractAddr, data), nil
   118  	case QueryMethodContractStateSmart:
   119  		// we enforce a subjective gas limit on all queries to avoid infinite loops
   120  		ctx.SetGasMeter(sdk.NewGasMeter(gasLimit))
   121  		msg := types.RawContractMessage(data)
   122  		if err := msg.ValidateBasic(); err != nil {
   123  			return nil, sdkerrors.Wrap(err, "json msg")
   124  		}
   125  		// this returns raw bytes (must be base64-encoded)
   126  		bz, err := keeper.QuerySmart(ctx, contractAddr, msg)
   127  		return bz, err
   128  	default:
   129  		return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, queryMethod)
   130  	}
   131  }
   132  
   133  func queryCodeList(ctx sdk.Context, keeper types.ViewKeeper) ([]types.CodeInfoResponse, error) {
   134  	var info []types.CodeInfoResponse
   135  	keeper.IterateCodeInfos(ctx, func(i uint64, res types.CodeInfo) bool {
   136  		info = append(info, types.CodeInfoResponse{
   137  			CodeID:                i,
   138  			Creator:               res.Creator,
   139  			DataHash:              res.CodeHash,
   140  			InstantiatePermission: res.InstantiateConfig,
   141  		})
   142  		return false
   143  	})
   144  	return info, nil
   145  }
   146  
   147  func queryContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress, keeper types.ViewKeeper) ([]types.ContractCodeHistoryEntry, error) {
   148  	history := keeper.GetContractHistory(ctx, contractAddr)
   149  	// redact response
   150  	for i := range history {
   151  		history[i].Updated = nil
   152  	}
   153  	return history, nil
   154  }
   155  
   156  func queryContractListByCode(ctx sdk.Context, codeID uint64, keeper types.ViewKeeper) []string {
   157  	var contracts []string
   158  	keeper.IterateContractsByCode(ctx, codeID, func(addr sdk.AccAddress) bool {
   159  		contracts = append(contracts, addr.String())
   160  		return false
   161  	})
   162  	return contracts
   163  }
   164  
   165  func queryListContractBlockedMethod(ctx sdk.Context, contractAddr sdk.AccAddress, keeper types.ViewKeeper) *types.ContractMethods {
   166  	cmbl := keeper.GetContractMethodBlockedList(ctx, contractAddr.String())
   167  	return cmbl
   168  }
   169  
   170  func queryParams(ctx sdk.Context, keeper types.ViewKeeper) *types.Params {
   171  	params := keeper.GetParams(ctx)
   172  	return &params
   173  }