Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
13 changes: 11 additions & 2 deletions cmd/rpc/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,20 @@ func (s *Server) Order(w http.ResponseWriter, r *http.Request, _ httprouter.Para
// Orders retrieves the order book for a committee with optional filters and pagination
func (s *Server) Orders(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
// Invoke helper with the HTTP request, response writer and an inline callback
s.ordersParams(w, r, func(s *fsm.StateMachine, req *ordersRequest) (any, lib.ErrorI) {
s.ordersParams(w, r, func(sm *fsm.StateMachine, req *ordersRequest) (any, lib.ErrorI) {
// validate mutual exclusion: cannot filter by both seller and buyer address
if req.SellersSendAddress != "" && req.BuyerSendAddress != "" {
return nil, lib.NewError(lib.CodeInvalidArgument, lib.RPCModule, "cannot filter by both sellersSendAddress and buyerSendAddress")
}
// validate that address-based queries are only allowed when indexing is enabled
if !sm.Config.StateMachineConfig.IndexOrdersByAddresses {
if req.SellersSendAddress != "" {
return nil, lib.NewError(lib.CodeInvalidArgument, lib.RPCModule, "sellersSendAddress filtering is disabled; set indexOrdersByAddresses=true in config")
}
if req.BuyerSendAddress != "" {
return nil, lib.NewError(lib.CodeInvalidArgument, lib.RPCModule, "buyerSendAddress filtering is disabled; set indexOrdersByAddresses=true in config")
}
}
// convert seller address if provided
var sellerAddr []byte
if req.SellersSendAddress != "" {
Expand All @@ -308,7 +317,7 @@ func (s *Server) Orders(w http.ResponseWriter, r *http.Request, _ httprouter.Par
}
}
// use paginated query
return s.GetOrdersPaginated(sellerAddr, buyerAddr, req.Committee, req.PageParams)
return sm.GetOrdersPaginated(sellerAddr, buyerAddr, req.Committee, req.PageParams)
})
}

Expand Down
38 changes: 24 additions & 14 deletions fsm/swap.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,21 +276,28 @@ func (s *StateMachine) SetOrder(order *lib.SellOrder, chainId uint64) (err lib.E
if err = s.Set(KeyForOrder(chainId, order.Id), protoBytes); err != nil {
return
}
// set the secondary index for seller address lookup (value is empty, key is sufficient)
if err = s.Set(KeyForOrderBySeller(order.SellersSendAddress, chainId, order.Id), []byte{}); err != nil {
return
}
// set the secondary index for buyer address lookup if buyer exists (locked order)
if len(order.BuyerSendAddress) > 0 {
if err = s.Set(KeyForOrderByBuyer(order.BuyerSendAddress, chainId, order.Id), []byte{}); err != nil {
// set secondary indexes only if configured
if s.Config.StateMachineConfig.IndexOrdersByAddresses {
// set the secondary index for seller address lookup (value is empty, key is sufficient)
if err = s.Set(KeyForOrderBySeller(order.SellersSendAddress, chainId, order.Id), []byte{}); err != nil {
return
}
// set the secondary index for buyer address lookup if buyer exists (locked order)
if len(order.BuyerSendAddress) > 0 {
if err = s.Set(KeyForOrderByBuyer(order.BuyerSendAddress, chainId, order.Id), []byte{}); err != nil {
return
}
}
}
return
}

// cleanupStaleBuyerIndex() removes the old buyer index entry if the buyer changed or was removed
func (s *StateMachine) cleanupStaleBuyerIndex(order *lib.SellOrder, chainId uint64) lib.ErrorI {
// skip if indexing is disabled
if !s.Config.StateMachineConfig.IndexOrdersByAddresses {
return nil
}
// check if order already exists
existingOrder, err := s.GetOrder(order.Id, chainId)
// if order not found, nothing to clean up
Expand Down Expand Up @@ -321,15 +328,18 @@ func (s *StateMachine) DeleteOrder(orderId []byte, chainId uint64) (err lib.Erro
if err = s.Delete(KeyForOrder(chainId, orderId)); err != nil {
return
}
// delete the seller secondary index entry
if err = s.Delete(KeyForOrderBySeller(order.SellersSendAddress, chainId, orderId)); err != nil {
return
}
// delete the buyer secondary index entry if buyer exists
if len(order.BuyerSendAddress) > 0 {
if err = s.Delete(KeyForOrderByBuyer(order.BuyerSendAddress, chainId, orderId)); err != nil {
// delete secondary indexes only if configured
if s.Config.StateMachineConfig.IndexOrdersByAddresses {
// delete the seller secondary index entry
if err = s.Delete(KeyForOrderBySeller(order.SellersSendAddress, chainId, orderId)); err != nil {
return
}
// delete the buyer secondary index entry if buyer exists
if len(order.BuyerSendAddress) > 0 {
if err = s.Delete(KeyForOrderByBuyer(order.BuyerSendAddress, chainId, orderId)); err != nil {
return
}
}
}
return
}
Expand Down
16 changes: 10 additions & 6 deletions lib/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,21 +158,25 @@ const (
DefaultInitialTokensPerBlock = uint64(80 * 1000000) // 80 CNPY
// the number of blocks between each halvening (block reward is cut in half) event
DefaultBlocksPerHalvening = uint64(3150000) // ~ 2 years - 20 second blocks
// whether to index orders by seller/buyer address for efficient lookups
DefaultIndexOrdersByAddresses = true
)

// StateMachineConfig houses FSM level options
type StateMachineConfig struct {
InitialTokensPerBlock uint64 `json:"initialTokensPerBlock"` // initial micro tokens minted per block (before halvenings)
BlocksPerHalvening uint64 `json:"blocksPerHalvening"` // number of blocks between block reward halvings
FaucetAddress string `json:"faucetAddress"` // if set: "send" txs from this address will auto-mint on insufficient funds (dev/test only)
InitialTokensPerBlock uint64 `json:"initialTokensPerBlock"` // initial micro tokens minted per block (before halvenings)
BlocksPerHalvening uint64 `json:"blocksPerHalvening"` // number of blocks between block reward halvings
FaucetAddress string `json:"faucetAddress"` // if set: "send" txs from this address will auto-mint on insufficient funds (dev/test only)
IndexOrdersByAddresses bool `json:"indexOrdersByAddresses"` // index orders by seller/buyer address for efficient lookups
}

// DefaultStateMachineConfig returns FSM defaults
func DefaultStateMachineConfig() StateMachineConfig {
return StateMachineConfig{
InitialTokensPerBlock: DefaultInitialTokensPerBlock,
BlocksPerHalvening: DefaultBlocksPerHalvening,
FaucetAddress: "",
InitialTokensPerBlock: DefaultInitialTokensPerBlock,
BlocksPerHalvening: DefaultBlocksPerHalvening,
FaucetAddress: "",
IndexOrdersByAddresses: DefaultIndexOrdersByAddresses,
}
}

Expand Down
Loading