From 7681f889851bbdd1b15c24de2b5f6f236a7a54d0 Mon Sep 17 00:00:00 2001 From: Prathamesh Musale Date: Wed, 14 Feb 2024 10:07:31 +0530 Subject: [PATCH] Add a command to reveal a bid --- x/auction/client/cli/tx.go | 37 ++++++++++++ x/auction/keeper/keeper.go | 112 ++++++++++++++++++++++++++++++++++++- x/auction/msgs.go | 32 ++++++++++- 3 files changed, 177 insertions(+), 4 deletions(-) diff --git a/x/auction/client/cli/tx.go b/x/auction/client/cli/tx.go index 80f4fed3..90e98030 100644 --- a/x/auction/client/cli/tx.go +++ b/x/auction/client/cli/tx.go @@ -1,6 +1,7 @@ package cli import ( + "encoding/hex" "fmt" "os" @@ -28,6 +29,7 @@ func GetTxCmd() *cobra.Command { auctionTxCmd.AddCommand( GetCmdCommitBid(), + GetCmdRevealBid(), ) return auctionTxCmd @@ -91,3 +93,38 @@ func GetCmdCommitBid() *cobra.Command { return cmd } + +// GetCmdRevealBid is the CLI command for revealing a bid. +func GetCmdRevealBid() *cobra.Command { + cmd := &cobra.Command{ + Use: "reveal-bid [auction-id] [reveal-file-path]", + Short: "Reveal bid", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + auctionId := args[0] + revealFilePath := args[1] + + revealBytes, err := os.ReadFile(revealFilePath) + if err != nil { + return err + } + + msg := auctiontypes.NewMsgRevealBid(auctionId, hex.EncodeToString(revealBytes), clientCtx.GetFromAddress()) + err = msg.ValidateBasic() + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/auction/keeper/keeper.go b/x/auction/keeper/keeper.go index 33eae0ea..4f071bff 100644 --- a/x/auction/keeper/keeper.go +++ b/x/auction/keeper/keeper.go @@ -1,6 +1,8 @@ package keeper import ( + "encoding/hex" + "encoding/json" "errors" "cosmossdk.io/collections" @@ -14,6 +16,7 @@ import ( auth "github.com/cosmos/cosmos-sdk/x/auth/keeper" bank "github.com/cosmos/cosmos-sdk/x/bank/keeper" + wnsUtils "git.vdb.to/cerc-io/laconic2d/utils" auctiontypes "git.vdb.to/cerc-io/laconic2d/x/auction" ) @@ -355,7 +358,114 @@ func (k Keeper) CommitBid(ctx sdk.Context, msg auctiontypes.MsgCommitBid) (*auct } func (k Keeper) RevealBid(ctx sdk.Context, msg auctiontypes.MsgRevealBid) (*auctiontypes.Auction, error) { - panic("unimplemented") + if has, err := k.HasAuction(ctx, msg.AuctionId); !has { + if err != nil { + return nil, err + } + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Auction not found.") + } + + auction, err := k.GetAuctionById(ctx, msg.AuctionId) + if err != nil { + return nil, err + } + + if auction.Status != auctiontypes.AuctionStatusRevealPhase { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Auction is not in reveal phase.") + } + + signerAddress, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, err + } + + bidder := signerAddress.String() + bidExists, err := k.HasBid(ctx, msg.AuctionId, bidder) + if err != nil { + return nil, err + } + + if !bidExists { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Bid not found.") + } + + bid, err := k.GetBid(ctx, msg.AuctionId, bidder) + if err != nil { + return nil, err + } + + if bid.Status != auctiontypes.BidStatusCommitted { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Bid not in committed state.") + } + + revealBytes, err := hex.DecodeString(msg.Reveal) + if err != nil { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal string.") + } + + cid, err := wnsUtils.CIDFromJSONBytes(revealBytes) + if err != nil { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal JSON.") + } + + if bid.CommitHash != cid { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Commit hash mismatch.") + } + + var reveal map[string]interface{} + err = json.Unmarshal(revealBytes, &reveal) + if err != nil { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Reveal JSON unmarshal error.") + } + + chainID, err := wnsUtils.GetAttributeAsString(reveal, "chainId") + if err != nil || chainID != ctx.ChainID() { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal chainID.") + } + + auctionID, err := wnsUtils.GetAttributeAsString(reveal, "auctionId") + if err != nil || auctionID != msg.AuctionId { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal auction Id.") + } + + bidderAddress, err := wnsUtils.GetAttributeAsString(reveal, "bidderAddress") + if err != nil { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal bid address.") + } + + if bidderAddress != signerAddress.String() { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Reveal bid address mismatch.") + } + + bidAmountStr, err := wnsUtils.GetAttributeAsString(reveal, "bidAmount") + if err != nil { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal bid amount.") + } + + bidAmount, err := sdk.ParseCoinNormalized(bidAmountStr) + if err != nil { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Invalid reveal bid amount.") + } + + if bidAmount.IsLT(auction.MinimumBid) { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Bid is lower than minimum bid.") + } + + // Lock bid amount. + sdkErr := k.bankKeeper.SendCoinsFromAccountToModule(ctx, signerAddress, auctiontypes.ModuleName, sdk.NewCoins(bidAmount)) + if sdkErr != nil { + return nil, sdkErr + } + + // Update bid. + bid.BidAmount = bidAmount + bid.RevealTime = ctx.BlockTime() + bid.Status = auctiontypes.BidStatusRevealed + if err = k.SaveBid(ctx, &bid); err != nil { + return nil, err + } + + return &auction, nil } // GetParams gets the auction module's parameters. diff --git a/x/auction/msgs.go b/x/auction/msgs.go index ed454d47..3a3ae2d5 100644 --- a/x/auction/msgs.go +++ b/x/auction/msgs.go @@ -20,15 +20,41 @@ func NewMsgCommitBid(auctionID string, commitHash string, signer sdk.AccAddress) // ValidateBasic Implements Msg. func (msg MsgCommitBid) ValidateBasic() error { if msg.Signer == "" { - return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer address.") + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer address") } if msg.AuctionId == "" { - return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid auction ID.") + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid auction id") } if msg.CommitHash == "" { - return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid commit hash.") + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid commit hash") + } + + return nil +} + +// NewMsgRevealBid is the constructor function for MsgRevealBid. +func NewMsgRevealBid(auctionId string, reveal string, signer sdk.AccAddress) MsgRevealBid { + return MsgRevealBid{ + AuctionId: auctionId, + Reveal: reveal, + Signer: signer.String(), + } +} + +// ValidateBasic Implements Msg. +func (msg MsgRevealBid) ValidateBasic() error { + if msg.Signer == "" { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer address") + } + + if msg.AuctionId == "" { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid auction id") + } + + if msg.Reveal == "" { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid reveal data") } return nil