diff --git a/database/database_test.go b/database/database_test.go index fed6875..d47aedb 100644 --- a/database/database_test.go +++ b/database/database_test.go @@ -9,13 +9,14 @@ var ( testDb = "test.db" ticket = Ticket{ Hash: "Hash", + CommitmentAddress: "Address", CommitmentSignature: "CommitmentSignature", FeeAddress: "FeeAddress", - Address: "Address", SDiff: 1, BlockHeight: 2, VoteBits: 3, VotingKey: "VotingKey", + Expiration: 4, } db *VspDatabase ) @@ -80,13 +81,14 @@ func testGetFeeAddressByTicketHash(t *testing.T) { // Check ticket fields match expected. if retrieved.Hash != ticket.Hash || + retrieved.CommitmentAddress != ticket.CommitmentAddress || retrieved.CommitmentSignature != ticket.CommitmentSignature || retrieved.FeeAddress != ticket.FeeAddress || - retrieved.Address != ticket.Address || retrieved.SDiff != ticket.SDiff || retrieved.BlockHeight != ticket.BlockHeight || retrieved.VoteBits != ticket.VoteBits || - retrieved.VotingKey != ticket.VotingKey { + retrieved.VotingKey != ticket.VotingKey || + retrieved.Expiration != ticket.Expiration { t.Fatal("retrieved ticket value didnt match expected") } @@ -145,7 +147,7 @@ func testInsertFeeAddressVotingKey(t *testing.T) { // Update values. newVotingKey := ticket.VotingKey + "2" newVoteBits := ticket.VoteBits + 2 - err = db.InsertFeeAddressVotingKey(ticket.Address, newVotingKey, newVoteBits) + err = db.InsertFeeAddressVotingKey(ticket.CommitmentAddress, newVotingKey, newVoteBits) if err != nil { t.Fatalf("error updating votingkey and votebits: %v", err) } diff --git a/database/ticket.go b/database/ticket.go index 7416590..ee6be40 100644 --- a/database/ticket.go +++ b/database/ticket.go @@ -2,22 +2,28 @@ package database import ( "encoding/json" + "errors" "fmt" bolt "go.etcd.io/bbolt" ) type Ticket struct { - Hash string `json:"hash"` - CommitmentSignature string `json:"commitmentsignature"` - FeeAddress string `json:"feeaddress"` - Address string `json:"address"` - SDiff int64 `json:"sdiff"` - BlockHeight int64 `json:"blockheight"` - VoteBits uint16 `json:"votebits"` - VotingKey string `json:"votingkey"` + Hash string `json:"hash"` + CommitmentSignature string `json:"commitmentsignature"` + CommitmentAddress string `json:"commitmentaddress"` + FeeAddress string `json:"feeaddress"` + SDiff float64 `json:"sdiff"` + BlockHeight int64 `json:"blockheight"` + VoteBits uint16 `json:"votebits"` + VotingKey string `json:"votingkey"` + Expiration int64 `json:"expiration"` } +var ( + ErrNoTicketFound = errors.New("no ticket found") +) + func (vdb *VspDatabase) InsertFeeAddress(ticket Ticket) error { return vdb.db.Update(func(tx *bolt.Tx) error { ticketBkt := tx.Bucket(vspBktK).Bucket(ticketBktK) @@ -47,7 +53,7 @@ func (vdb *VspDatabase) InsertFeeAddressVotingKey(address, votingKey string, vot return fmt.Errorf("could not unmarshal ticket: %v", err) } - if ticket.Address == address { + if ticket.CommitmentAddress == address { ticket.VotingKey = votingKey ticket.VoteBits = voteBits ticketBytes, err := json.Marshal(ticket) @@ -128,7 +134,7 @@ func (vdb *VspDatabase) GetFeeAddressByTicketHash(ticketHash string) (Ticket, er ticketBytes := ticketBkt.Get([]byte(ticketHash)) if ticketBytes == nil { - return fmt.Errorf("no ticket found with hash %s", ticketHash) + return ErrNoTicketFound } err := json.Unmarshal(ticketBytes, &ticket) diff --git a/methods.go b/methods.go index 2003d47..07fa1a9 100644 --- a/methods.go +++ b/methods.go @@ -21,6 +21,7 @@ import ( "github.com/decred/dcrd/txscript/v3" "github.com/decred/dcrd/wire" "github.com/gin-gonic/gin" + "github.com/jholdstock/dcrvsp/database" ) const ( @@ -85,8 +86,28 @@ func feeAddress(c *gin.Context) { return } - // TODO: check db for cache response - if expired, reset expiration, but still - // use same feeaddress + /* + // TODO - DB - deal with cached responses + ticket, err := db.GetFeeAddressByTicketHash(ticketHashStr) + if err != nil && !errors.Is(err, database.ErrNoTicketFound) { + c.AbortWithError(http.StatusInternalServerError, errors.New("database error")) + return + } + if err == nil { + // TODO - deal with expiration + if signature == ticket.CommitmentSignature { + sendJSONResponse(feeAddressResponse{ + Timestamp: time.Now().Unix(), + CommitmentSignature: ticket.CommitmentSignature, + FeeAddress: ticket.FeeAddress, + Expiration: ticket.Expiration, + }, http.StatusOK, c) + return + } + c.AbortWithError(http.StatusBadRequest, errors.New("invalid signature")) + return + } + */ ctx := c.Request.Context() @@ -154,7 +175,6 @@ func feeAddress(c *gin.Context) { c.AbortWithError(http.StatusInternalServerError, errors.New("RPC server error")) return } - sDiff := blockHeader.SBits var newAddress string err = nodeConnection.Call(ctx, "getnewaddress", &newAddress, "fees") @@ -163,15 +183,33 @@ func feeAddress(c *gin.Context) { return } - // TODO: Insert into DB - _ = sDiff - now := time.Now() + expire := now.Add(defaultFeeAddressExpiration).Unix() + + dbTicket := database.Ticket{ + Hash: txHash.String(), + CommitmentSignature: signature, + CommitmentAddress: addr.Address(), + FeeAddress: newAddress, + SDiff: blockHeader.SBits, + BlockHeight: int64(blockHeader.Height), + VoteBits: dcrutil.BlockValid, + Expiration: expire, + // VotingKey: set during payfee + } + + // TODO: Insert into DB + err = db.InsertFeeAddress(dbTicket) + if err != nil { + c.AbortWithError(http.StatusInternalServerError, errors.New("database error")) + return + } + sendJSONResponse(feeAddressResponse{ Timestamp: now.Unix(), Request: feeAddressRequest, FeeAddress: newAddress, - Expiration: now.Add(defaultFeeAddressExpiration).Unix(), + Expiration: expire, }, c) } @@ -246,7 +284,7 @@ findAddress: c.AbortWithError(http.StatusInternalServerError, errors.New("database error")) return } - voteAddr, err := dcrutil.DecodeAddress(feeEntry.Address, cfg.netParams) + voteAddr, err := dcrutil.DecodeAddress(feeEntry.CommitmentAddress, cfg.netParams) if err != nil { fmt.Printf("PayFee: DecodeAddress: %v", err) c.AbortWithError(http.StatusInternalServerError, errors.New("database error"))