-
Notifications
You must be signed in to change notification settings - Fork 159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rpc: add GetTickets command #957
Conversation
7687853
to
a4ac0b4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed the documented changes to the API. Since there are some things that need to be changed and clarified I'm holding off on the code review until it's clear what the API needs to be doing.
rpc/documentation/api.md
Outdated
- `TicketDetails tickets`: A given ticket's details. | ||
|
||
The `TicketDetails` message is used by other methods and is documented | ||
[here](#ticketdetails). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't true, it's a new message that's only used here, and can be documented inline.
rpc/documentation/api.md
Outdated
relevant to the wallet. The message includes details such as which previous | ||
wallet inputs are spent by this transaction, whether each output is controlled | ||
by the wallet or not, the total fee (if calculable), and the earlist time the | ||
transaction was seen. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This description is a copy pasta of TransactionDetails' description and needs to be redone.
rpc/documentation/api.md
Outdated
|
||
- `bytes hash`: The hash of the given ticket. | ||
|
||
- `bytes spender_hash`: The hash of the spender (if applicable, otherwise empty). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of empty, say it uses the default value.
rpc/documentation/api.md
Outdated
- `bytes spender_hash`: The hash of the spender (if applicable, otherwise empty). | ||
|
||
- `int64 ticket_age`: If unspent the blocks since being mined. Otherwise, | ||
the number of blocks from when it was mined to when it was spent. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is confusing to me and I'm not sure how it would be useful, even more so since it will take on different values depending on if it was spent.
rpc/documentation/api.md
Outdated
|
||
- `int64 ticket_price`: The value of the first output from the ticket transaction. | ||
Due to the way tickets are constructed, we know that this is always the 'price' | ||
of any given ticket. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an implementation detail that we don't need to discuss here. We should just document that it is the ticket price. If a ticket was purchased with a price greater than required, reporting that value as the ticket price should be considered a bug and fixed.
rpc/documentation/api.md
Outdated
of any given ticket. | ||
|
||
- `int64 ticket_cost`: The total cost of the wallet to purchase the ticket. Typically, | ||
this would just be the ticket fee. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then why not call this field ticket_fee? What else would contribute to the "cost" that isn't the ticket price itself?
rpc/documentation/api.md
Outdated
|
||
- `int64 spender_return`: The total return from the spender transaction. If a vote, | ||
this number should be positive (PoS vote subsidy - poolfee). If a revocation, | ||
this would be negative (minus txfee and poolfee). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not clear if this is referring to the coins generated by the vote/revocation that this wallet controls, or the total (including fees for split ticket ownership and stakepool tickets).
rpc/documentation/api.md
Outdated
|
||
- `UNMINED`: A ticket that has yet to be mined into a block. | ||
|
||
**Stability**: Unstable: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can nuke the trailing colon if there's no explanation afterwards
rpc/documentation/api.md
Outdated
|
||
- `TicketStatus ticket_status`: The observed status of the given ticket. | ||
|
||
**Nested enum:** `TicketStatus` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ordering of these seems odd. I would start with unmined, then immature, then live, followed by the rest.
wallet/udb/txquery.go
Outdated
@@ -8,6 +8,8 @@ package udb | |||
import ( | |||
"fmt" | |||
|
|||
"github.com/decred/dcrd/blockchain/stake" | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra newline
wallet/wallet.go
Outdated
Tickets []*TicketSummary | ||
} | ||
|
||
// GetTickets implements the rpc request command for gettickets |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment really needs to be more specific regarding its behavior and what all parameters do, and we shouldn't isolate this API as only for the RPC server.
wallet/wallet.go
Outdated
} | ||
|
||
// GetTickets implements the rpc request command for gettickets | ||
func (w *Wallet) GetTickets(startBlock, endBlock *BlockIdentifier, cancel <-chan struct{}) (*GetTicketsResult, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would change this function signature to something more like:
func (w *Wallet) GetTickets(ctx context.Context, startBlock, endBlock *BlockIdentifier, results chan<- *TicketSummary) error
A context should be used for cancellation and should be the first parameter. The channel is used to stream the results back to the caller rather than returning all of the results at once. This will allow the RPC server to actually stream the results to clients as it creates them, instead of loading all of the data up at once into a single slice and then sending messages to the client stream. (This is also a problem with the GetTransactions RPC and should be resolved in a separate commit)
wallet/notifications.go
Outdated
// TicketStatusLive any currently live ticket. | ||
TicketStatusLive TicketStatus = iota | ||
// TicketStatusUnmined any not yet mined ticket. | ||
TicketStatusUnmined |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unmined and immature both come before the ticket being live, so those two should be values 0 and 1 respectively.
wallet/notifications.go
Outdated
live, err := w.chainClient.ExistsLiveTicket(&details.Ticket.Hash) | ||
if err != nil { | ||
log.Errorf("Unable to check if ticket was live for ticket status: %v", &details.Ticket.Hash) | ||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This behavior is not documented at all and will result in a runtime panic later if it occurs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you think it should just set the status to TicketUnknown, log the error and carry on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
wallet/notifications.go
Outdated
txmgrNs := dbtx.ReadBucket(wtxmgrNamespaceKey) | ||
|
||
_, tipHeight := w.TxStore.MainChainTip(txmgrNs) | ||
ticketAge := int64(tipHeight - details.Ticket.Height()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather than calculating the age this way to determine if the ticket is immature or expired, do a check on the number of confirmations. This is the way other code in the wallet does this check. There's also an off by one to be aware of. Grep the wallet package for other uses of TicketMaturity and TicketExpiry to find the correct check.
} | ||
|
||
// TicketStatus describes the current status a ticket can be observed to be. | ||
type TicketStatus int8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we may need an "unknown" value as well. This will allow the ticket results to still be created even if not all info regarding its state can be determined. See the comment about returning nil and the panic above.
wallet/wallet.go
Outdated
} else { | ||
err := walletdb.View(w.db, func(dbtx walletdb.ReadTx) error { | ||
ns := dbtx.ReadBucket(wtxmgrNamespaceKey) | ||
meta, err := w.TxStore.GetBlockMetaForHash(ns, startBlock.hash) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Look up the header and extract the height from that. I want to remove BlockMeta eventually as it is old code that is made irrelevant now that all headers are saved.
wallet/wallet.go
Outdated
} else { | ||
err := walletdb.View(w.db, func(dbtx walletdb.ReadTx) error { | ||
ns := dbtx.ReadBucket(wtxmgrNamespaceKey) | ||
meta, err := w.TxStore.GetBlockMetaForHash(ns, endBlock.hash) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above
wallet/wallet.go
Outdated
// XXX Here is where I would look up the ticket information from the db so I can populate spenderhash and ticket status | ||
ticketInfo, err := w.TxStore.TicketDetails(txmgrNs, &details[i]) | ||
if err != nil { | ||
log.Errorf("error while trying to get ticket details for ") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should return the error instead of logging (and the log is missing the details about what was looked up too)
105fd23
to
1692d1e
Compare
- merge with hx
- merge with hx
Merge for Hx: - Remove context changes added in 90f42ca.
This PR implements a new RPC command for GetTickets.
It uses the same request settings for start/end block as GetTransactions. It then streams GetTicketsResponses back that contain single TicketDetails information in order of the block the ticket was mined.
TicketDetails contains everything that should be needed to collect all the required information about a ticket for the upcoming 'My Tickets' page in decrediton.
Closes #833