diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index 6b4f669..48c1ffb 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -20150,6 +20150,9 @@ paths: type: string amount: type: string + deadline: + type: string + format: uint64 pagination: type: object properties: @@ -20280,6 +20283,9 @@ paths: type: string amount: type: string + deadline: + type: string + format: uint64 default: description: An unexpected error response. schema: @@ -47457,6 +47463,9 @@ definitions: type: string amount: type: string + deadline: + type: string + format: uint64 cosmostest.cosmostest.Bid: type: object properties: @@ -47501,6 +47510,9 @@ definitions: type: string amount: type: string + deadline: + type: string + format: uint64 pagination: type: object properties: @@ -47557,6 +47569,9 @@ definitions: type: string amount: type: string + deadline: + type: string + format: uint64 cosmostest.cosmostest.QueryGetNextAuctionResponse: type: object properties: diff --git a/go.mod b/go.mod index 95dbda5..ff93dce 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/ignite/cli v0.23.0 + github.com/pkg/errors v0.9.1 github.com/spf13/cast v1.4.1 github.com/spf13/cobra v1.4.0 github.com/stretchr/testify v1.7.1 @@ -127,7 +128,6 @@ require ( github.com/otiai10/copy v1.6.0 // indirect github.com/pelletier/go-toml v1.9.4 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect diff --git a/proto/cosmostest/auction.proto b/proto/cosmostest/auction.proto index 2f0874c..f59ee4e 100644 --- a/proto/cosmostest/auction.proto +++ b/proto/cosmostest/auction.proto @@ -10,5 +10,6 @@ message Auction { string name = 2; string description = 3; Bid topBid = 4; + uint64 deadline = 5; } diff --git a/x/cosmostest/auctionconfig/config.go b/x/cosmostest/auctionconfig/config.go new file mode 100644 index 0000000..ee5a4c3 --- /dev/null +++ b/x/cosmostest/auctionconfig/config.go @@ -0,0 +1,5 @@ +package auctionconfig + +// Length of the auction in blocks-- currently 10. +// Assuming a block time of 3sec, this should be ~30sec. +const AuctionTime = 100 diff --git a/x/cosmostest/config/config.go b/x/cosmostest/config/config.go deleted file mode 100644 index d1cfdc5..0000000 --- a/x/cosmostest/config/config.go +++ /dev/null @@ -1,5 +0,0 @@ -package config - -// Length of the auction in blocks. -// Assuming a block time of 3sec, this should be ~30sec. -const AuctionTime = 10 diff --git a/x/cosmostest/keeper/auction_expiry.go b/x/cosmostest/keeper/auction_expiry.go new file mode 100644 index 0000000..21d4b65 --- /dev/null +++ b/x/cosmostest/keeper/auction_expiry.go @@ -0,0 +1,42 @@ +package keeper + +import ( + "cosmos-test/x/cosmostest/auctionconfig" + "cosmos-test/x/cosmostest/memdb" + + "github.com/cosmos/cosmos-sdk/types" + "github.com/pkg/errors" +) + +func (k *Keeper) AuctionIsExpired(ctx types.Context, auctionId string) (bool, error) { + auction, found := k.GetAuction(ctx, auctionId) + + // make sure the auction exists on-chain + if !found { + return true, errors.Errorf("auction %s not found", auctionId) + } + + return uint64(ctx.BlockHeight()) >= auction.Deadline, nil +} + +func (k *Keeper) EndExpiredAuctions(ctx types.Context) { + memdb.BidDB.ForEachAuction(func(auctionId string) error { + auction, found := k.GetAuction(ctx, auctionId) + // make sure the auction exists on-chain + if !found { + return errors.Errorf("auction %s not found", auctionId) + } + + if uint64(ctx.BlockHeight()) >= auction.Deadline-auctionconfig.AuctionTime { + var err error + auction.TopBid, err = memdb.BidDB.GetHighestBid(auctionId) + if err != nil { + return errors.Errorf("could not get highest bid for auction %s: %s", auctionId, err) + } + k.SetAuction(ctx, auction) + memdb.BidDB.ClearAuction(auctionId) + } + + return nil + }) +} diff --git a/x/cosmostest/keeper/grpc_query_auction_bids.go b/x/cosmostest/keeper/grpc_query_auction_bids.go index e38e694..e9ff565 100644 --- a/x/cosmostest/keeper/grpc_query_auction_bids.go +++ b/x/cosmostest/keeper/grpc_query_auction_bids.go @@ -24,6 +24,10 @@ func (k Keeper) AuctionBids(goCtx context.Context, req *types.QueryAuctionBidsRe return nil, fmt.Errorf("auction %s not found", req.Index) } + if uint64(ctx.BlockHeight()) >= auction.Deadline { + return nil, fmt.Errorf("auction %s is already finalized", req.Index) + } + bids, err := memdb.BidDB.GetBids(auction.Index) if err != nil { return nil, fmt.Errorf("failed to get bids for auction %s: %s", auction.Index, err) diff --git a/x/cosmostest/keeper/msg_server_new_auction.go b/x/cosmostest/keeper/msg_server_new_auction.go index 11c8387..ea2b655 100644 --- a/x/cosmostest/keeper/msg_server_new_auction.go +++ b/x/cosmostest/keeper/msg_server_new_auction.go @@ -5,6 +5,7 @@ import ( "errors" "strconv" + "cosmos-test/x/cosmostest/auctionconfig" "cosmos-test/x/cosmostest/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -24,6 +25,7 @@ func (k msgServer) NewAuction(goCtx context.Context, msg *types.MsgNewAuction) ( Name: msg.Name, Description: msg.Description, TopBid: new(types.Bid), + Deadline: uint64(ctx.BlockHeight()) + auctionconfig.AuctionTime, } k.Keeper.SetAuction(ctx, auction) diff --git a/x/cosmostest/keeper/msg_server_new_bid.go b/x/cosmostest/keeper/msg_server_new_bid.go index f52ecc2..33e2369 100644 --- a/x/cosmostest/keeper/msg_server_new_bid.go +++ b/x/cosmostest/keeper/msg_server_new_bid.go @@ -20,6 +20,14 @@ func (k msgServer) NewBid(goCtx context.Context, msg *types.MsgNewBid) (*types.M return nil, fmt.Errorf("didn't find auction of index %s", msg.AuctionIndex) } + auctionExpired, err := k.Keeper.AuctionIsExpired(ctx, msg.AuctionIndex) + if err != nil { + return nil, fmt.Errorf("error while checking auction %s expiry status: %s", msg.AuctionIndex, err) + } + if auctionExpired { + return nil, fmt.Errorf("auction %s is expired", msg.AuctionIndex) + } + ok := false amt := new(big.Int) amt, ok = amt.SetString(msg.Amount, 10) diff --git a/x/cosmostest/module.go b/x/cosmostest/module.go index 6b3b444..768e17c 100644 --- a/x/cosmostest/module.go +++ b/x/cosmostest/module.go @@ -176,6 +176,9 @@ func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} // EndBlock executes all ABCI EndBlock logic respective to the capability module. It // returns no validator updates. -func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { +func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + + am.keeper.EndExpiredAuctions(ctx) + return []abci.ValidatorUpdate{} } diff --git a/x/cosmostest/types/auction.pb.go b/x/cosmostest/types/auction.pb.go index 0f9ad66..85cf85b 100644 --- a/x/cosmostest/types/auction.pb.go +++ b/x/cosmostest/types/auction.pb.go @@ -27,6 +27,7 @@ type Auction struct { Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` TopBid *Bid `protobuf:"bytes,4,opt,name=topBid,proto3" json:"topBid,omitempty"` + Deadline uint64 `protobuf:"varint,5,opt,name=deadline,proto3" json:"deadline,omitempty"` } func (m *Auction) Reset() { *m = Auction{} } @@ -90,6 +91,13 @@ func (m *Auction) GetTopBid() *Bid { return nil } +func (m *Auction) GetDeadline() uint64 { + if m != nil { + return m.Deadline + } + return 0 +} + func init() { proto.RegisterType((*Auction)(nil), "cosmostest.cosmostest.Auction") } @@ -97,20 +105,21 @@ func init() { func init() { proto.RegisterFile("cosmostest/auction.proto", fileDescriptor_631f6f59914101d9) } var fileDescriptor_631f6f59914101d9 = []byte{ - // 202 bytes of a gzipped FileDescriptorProto + // 223 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x48, 0xce, 0x2f, 0xce, 0xcd, 0x2f, 0x2e, 0x49, 0x2d, 0x2e, 0xd1, 0x4f, 0x2c, 0x4d, 0x2e, 0xc9, 0xcc, 0xcf, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x45, 0xc8, 0xe8, 0x21, 0x98, 0x52, 0x22, 0x48, 0x1a, 0x92, - 0x32, 0x53, 0x20, 0x8a, 0x95, 0x3a, 0x19, 0xb9, 0xd8, 0x1d, 0x21, 0xda, 0x85, 0x44, 0xb8, 0x58, - 0x33, 0xf3, 0x52, 0x52, 0x2b, 0x24, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0x20, 0x1c, 0x21, 0x21, - 0x2e, 0x96, 0xbc, 0xc4, 0xdc, 0x54, 0x09, 0x26, 0xb0, 0x20, 0x98, 0x2d, 0xa4, 0xc0, 0xc5, 0x9d, - 0x92, 0x5a, 0x9c, 0x5c, 0x94, 0x59, 0x00, 0xd2, 0x28, 0xc1, 0x0c, 0x96, 0x42, 0x16, 0x12, 0x32, - 0xe2, 0x62, 0x2b, 0xc9, 0x2f, 0x70, 0xca, 0x4c, 0x91, 0x60, 0x51, 0x60, 0xd4, 0xe0, 0x36, 0x92, - 0xd2, 0xc3, 0xea, 0x2a, 0x3d, 0xa7, 0xcc, 0x94, 0x20, 0xa8, 0x4a, 0x27, 0x8b, 0x13, 0x8f, 0xe4, - 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, - 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x92, 0x83, 0xe8, 0xd0, 0x05, 0x3b, 0xbe, 0x42, 0x1f, - 0xc9, 0x27, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c, 0x60, 0xcf, 0x18, 0x03, 0x02, 0x00, 0x00, - 0xff, 0xff, 0xe9, 0x88, 0x26, 0x2e, 0x15, 0x01, 0x00, 0x00, + 0x32, 0x53, 0x20, 0x8a, 0x95, 0x96, 0x32, 0x72, 0xb1, 0x3b, 0x42, 0xb4, 0x0b, 0x89, 0x70, 0xb1, + 0x66, 0xe6, 0xa5, 0xa4, 0x56, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x41, 0x38, 0x42, 0x42, + 0x5c, 0x2c, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0x4c, 0x60, 0x41, 0x30, 0x5b, 0x48, 0x81, 0x8b, 0x3b, + 0x25, 0xb5, 0x38, 0xb9, 0x28, 0xb3, 0x00, 0xa4, 0x51, 0x82, 0x19, 0x2c, 0x85, 0x2c, 0x24, 0x64, + 0xc4, 0xc5, 0x56, 0x92, 0x5f, 0xe0, 0x94, 0x99, 0x22, 0xc1, 0xa2, 0xc0, 0xa8, 0xc1, 0x6d, 0x24, + 0xa5, 0x87, 0xd5, 0x55, 0x7a, 0x4e, 0x99, 0x29, 0x41, 0x50, 0x95, 0x42, 0x52, 0x5c, 0x1c, 0x29, + 0xa9, 0x89, 0x29, 0x39, 0x99, 0x79, 0xa9, 0x12, 0xac, 0x0a, 0x8c, 0x1a, 0x2c, 0x41, 0x70, 0xbe, + 0x93, 0xc5, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, + 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0xc9, 0x41, 0x4c, 0xd3, + 0x05, 0x7b, 0xac, 0x42, 0x1f, 0xc9, 0x97, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c, 0x60, 0x8f, + 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x84, 0x5a, 0xc2, 0xfb, 0x31, 0x01, 0x00, 0x00, } func (m *Auction) Marshal() (dAtA []byte, err error) { @@ -133,6 +142,11 @@ func (m *Auction) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Deadline != 0 { + i = encodeVarintAuction(dAtA, i, uint64(m.Deadline)) + i-- + dAtA[i] = 0x28 + } if m.TopBid != nil { { size, err := m.TopBid.MarshalToSizedBuffer(dAtA[:i]) @@ -202,6 +216,9 @@ func (m *Auction) Size() (n int) { l = m.TopBid.Size() n += 1 + l + sovAuction(uint64(l)) } + if m.Deadline != 0 { + n += 1 + sovAuction(uint64(m.Deadline)) + } return n } @@ -372,6 +389,25 @@ func (m *Auction) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Deadline", wireType) + } + m.Deadline = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuction + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Deadline |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipAuction(dAtA[iNdEx:])