From 72ba2ce3b16762dd6082dac3ce816c384860fe68 Mon Sep 17 00:00:00 2001 From: David Hill Date: Fri, 15 May 2020 10:33:20 -0500 Subject: [PATCH] add setvotebits api (#18) --- methods.go | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ responses.go | 13 +++++++++++ router.go | 1 + 3 files changed, 78 insertions(+) diff --git a/methods.go b/methods.go index 542b8b6..2003d47 100644 --- a/methods.go +++ b/methods.go @@ -347,6 +347,70 @@ func PayFee2(ctx context.Context, ticketHash *chainhash.Hash, votingWIF *dcrutil return res, nil } +func setVoteBits(c *gin.Context) { + dec := json.NewDecoder(c.Request.Body) + + var setVoteBitsRequest SetVoteBitsRequest + err := dec.Decode(&setVoteBitsRequest) + if err != nil { + c.AbortWithError(http.StatusBadRequest, errors.New("invalid json")) + return + } + + // ticketHash + ticketHashStr := setVoteBitsRequest.TicketHash + if len(ticketHashStr) != chainhash.MaxHashStringSize { + c.AbortWithError(http.StatusBadRequest, errors.New("invalid ticket hash")) + return + } + txHash, err := chainhash.NewHashFromStr(ticketHashStr) + if err != nil { + c.AbortWithError(http.StatusBadRequest, errors.New("invalid ticket hash")) + return + } + + // signature - sanity check signature is in base64 encoding + signature := setVoteBitsRequest.Signature + if _, err = base64.StdEncoding.DecodeString(signature); err != nil { + c.AbortWithError(http.StatusBadRequest, errors.New("invalid signature")) + return + } + + // votebits + voteBits := setVoteBitsRequest.VoteBits + if !isValidVoteBits(cfg.netParams.Params, currentVoteVersion(cfg.netParams.Params), voteBits) { + c.AbortWithError(http.StatusBadRequest, errors.New("invalid votebits")) + return + } + + // TODO: DB - get commitment address from db (stored from feeaddress) + var addr string + + // verify message + ctx := c.Request.Context() + message := fmt.Sprintf("vsp v3 setvotebits %d %s %d", setVoteBitsRequest.Timestamp, txHash, voteBits) + var valid bool + err = nodeConnection.Call(ctx, "verifymessage", &valid, addr, signature, message) + if err != nil { + c.AbortWithError(http.StatusInternalServerError, errors.New("RPC server error")) + return + } + if !valid { + c.AbortWithError(http.StatusBadRequest, errors.New("message did not pass verification")) + return + } + + // TODO: DB - error if given timestamp is older than any previous requests + + // TODO: DB - store setvotebits receipt in log + + sendJSONResponse(setVoteBitsResponse{ + Timestamp: time.Now().Unix(), + Request: setVoteBitsRequest, + VoteBits: voteBits, + }, c) +} + func ticketStatus(c *gin.Context) { dec := json.NewDecoder(c.Request.Body) diff --git a/responses.go b/responses.go index f93d904..98cd525 100644 --- a/responses.go +++ b/responses.go @@ -37,6 +37,19 @@ type payFeeResponse struct { Request PayFeeRequest `json:"request"` } +type SetVoteBitsRequest struct { + Timestamp int64 `json:"timestamp"` + TicketHash string `json:"ticketHash"` + Signature string `json:"commitmentSignature"` + VoteBits uint16 `json:"voteBits"` +} + +type setVoteBitsResponse struct { + Timestamp int64 `json:"timestamp"` + Request SetVoteBitsRequest `json:"request"` + VoteBits uint16 `json:"voteBits"` +} + type TicketStatusRequest struct { Timestamp int64 `json:"timestamp"` TicketHash string `json:"ticketHash"` diff --git a/router.go b/router.go index d76ff87..f2ec4a7 100644 --- a/router.go +++ b/router.go @@ -38,6 +38,7 @@ func newRouter(releaseMode bool) *gin.Engine { api.POST("/feeaddress", feeAddress) api.GET("/pubkey", pubKey) api.POST("/payfee", payFee) + api.POST("/setvotebits", setVoteBits) api.POST("/ticketstatus", ticketStatus) }