Skip to content

Commit

Permalink
Add README.md, docs, and .gitignore.
Browse files Browse the repository at this point in the history
  • Loading branch information
chappjc committed Oct 7, 2017
1 parent 54a0ae3 commit a657e8c
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 6 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
votetime
vendor/
.vscode/
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# votetime

`votetime` is a command line tool to determine the duration of time that your
tickets were live, from maturity to the vote. It will also compute the mean
duration over all of your tickets.

## Installation

go get -u github.com/chappjc/votetime

If there are errors about a vendor folder in another repository, it is safe to
delete those folders as they are automatically generated.

## Usage

To use `votetime`, you only need to point it your running dcrwallet's RPC
server. Ensure that dcrwallet is running and synchronized to the best block.
Next, set the host and authentication information with command line flags:

```none
Usage of ./votetime:
-cert string
wallet RPC TLS certificate (when notls=false) (default "dcrwallet.cert")
-host string
wallet RPC host:port (default "127.0.0.1:9110")
-notls
Disable use of TLS for wallet connection
-pass string
wallet RPC password (default "bananas")
-user string
wallet RPC username (default "dcrwallet")
```

For example:

votetime -user me -pass fluffy -cert ~/.dcrwallet/rpc.cert

If your wallet is running and listening on the network interface and port number
you have specified with the `-host` flag, votetime will begin by listing all of
your wallet's transactions. Next it will make a list of votes (SSGen
transactions) recognized by your wallet. For each vote, it identifies the
corresponding ticket purchase (SSTx) and computes the time elapsed between
ticket maturity (256 blocks after purchase) and redemption (the vote).

## License

`votetime` is distributable under the ISC license. Please see LICENSE for
details.
21 changes: 15 additions & 6 deletions votetime.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
)

var host = flag.String("host", "127.0.0.1:9110", "wallet RPC host:port")
var user = flag.String("user", "dcrd", "wallet RPC username")
var user = flag.String("user", "dcrwallet", "wallet RPC username")
var pass = flag.String("pass", "bananas", "wallet RPC password")
var cert = flag.String("cert", "dcrwallet.cert", "wallet RPC TLS certificate (when notls=false)")
var notls = flag.Bool("notls", false, "Disable use of TLS for wallet connection")
Expand All @@ -42,15 +42,15 @@ func main() {
log.Println("Wallet connected to node? ", walletInfo.DaemonConnected)

log.Println("Listing all transactions...")
allSSGenList, err := wcl.ListTransactionsCountFrom("*", 9999999, 0)
allTxns, err := wcl.ListTransactionsCountFrom("*", 9999999, 0)
if err != nil {
log.Fatalf("ListTransactions failed: %v", err)
}
log.Println("Number of transactions: ", len(allSSGenList))
log.Println("Number of transactions: ", len(allTxns))

// There are repeats in the list, so gather the unique ones with a map
knownVotes := make(map[string]bool)
for _, tx := range allSSGenList {
for _, tx := range allTxns {
if *tx.TxType == "vote" {
knownVotes[tx.TxID] = true
}
Expand All @@ -61,6 +61,7 @@ func main() {
waitBlocks := make([]int64, 0, len(knownVotes))

for txid := range knownVotes {
// Get ticket address from previous outpoint of Vin[1] of SSGen
voteHash, err := chainhash.NewHashFromStr(txid)
if err != nil {
log.Printf("Invalid tx hash %s: %v", txid, err)
Expand All @@ -72,40 +73,48 @@ func main() {
continue
}

// Vin[1] spends the stakesubmission of the ticket purchase
prevout := txRaw.MsgTx().TxIn[1].PreviousOutPoint
ticketHash := &prevout.Hash
ticketBlockOutIndex := prevout.Index
ticketTxOutIndex := prevout.Index

// Get block height and time for the vote
txRawVerbose, err := wcl.GetRawTransactionVerbose(voteHash)
if err != nil {
log.Fatalf("GetRawTransactionVerbose(vote) failed: %v", err)
}
voteHeight := txRawVerbose.BlockHeight
voteTime := time.Unix(txRawVerbose.Blocktime, 0)

// Get block height and time for the ticket
prevTxRaw, err := wcl.GetRawTransactionVerbose(ticketHash)
if err != nil {
log.Fatalf("GetRawTransactionVerbose(ticket) failed: %v", err)
}

// Tickets mature 256 blocks after purchase
ticketPurchaseHeight := prevTxRaw.BlockHeight
//ticketTime := time.Unix(prevTxRaw.Blocktime, 0)
ticketMaturityHeight := ticketPurchaseHeight + int64(activeChainParams.TicketMaturity)
ticketPrice := prevTxRaw.Vout[ticketBlockOutIndex].Value
// Get time of block at this height
ticketMaturityBlockHash, _ := wcl.GetBlockHash(ticketMaturityHeight)
ticketMaturityBlock, _ := wcl.GetBlockHeaderVerbose(ticketMaturityBlockHash)
ticketMaturityTime := time.Unix(ticketMaturityBlock.Time, 0)

// Compute time from maturity to vote
voteWaitBlocks := voteHeight - ticketMaturityHeight
voteWaitSeconds := voteTime.Sub(ticketMaturityTime)
voteWaitDays := voteWaitSeconds.Hours() / 24.0

ticketPrice := prevTxRaw.Vout[ticketTxOutIndex].Value
log.Printf("Ticket %s... (%f DCR) mined in block %d, voted %d blocks (%.2f days) after maturity.",
prevTxRaw.Txid[:8], ticketPrice, ticketPurchaseHeight, voteWaitBlocks, voteWaitDays)

waitBlocks = append(waitBlocks, voteWaitBlocks)
waitSeconds = append(waitSeconds, voteWaitSeconds.Seconds())
}

// Compute mean wait time in blocks and seconds
var avgBlockWait, avgSecondWait float64
for iv := range waitBlocks {
avgBlockWait += float64(waitBlocks[iv])
Expand Down

0 comments on commit a657e8c

Please sign in to comment.