From 39734da2e4527616ea73fc864743136a8a53308e Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Wed, 17 May 2017 10:18:00 -0400 Subject: [PATCH] rpcserver: Add existsmissedtickets RPC. This RPC works identically to the existsexpiredtickets RPC but checks for missed rather than expired tickets. --- blockchain/stakeext.go | 17 +++++++++++++++++ dcrjson/dcrdcmds.go | 14 ++++++++++++++ rpcserver.go | 27 +++++++++++++++++++++++++++ rpcserverhelp.go | 6 ++++++ 4 files changed, 64 insertions(+) diff --git a/blockchain/stakeext.go b/blockchain/stakeext.go index 9c2a340ea3..a1582569e1 100644 --- a/blockchain/stakeext.go +++ b/blockchain/stakeext.go @@ -173,6 +173,23 @@ func (b *BlockChain) CheckLiveTickets(hashes []chainhash.Hash) []bool { return existsSlice } +// CheckMissedTickets returns a slice of bools representing whether each ticket +// hash has been missed in the live ticket treap of the best node. +// +// This function is safe for concurrent access. +func (b *BlockChain) CheckMissedTickets(hashes []chainhash.Hash) []bool { + b.chainLock.RLock() + sn := b.bestNode.stakeNode + b.chainLock.RUnlock() + + existsSlice := make([]bool, len(hashes)) + for i := range hashes { + existsSlice[i] = sn.ExistsMissedTicket(hashes[i]) + } + + return existsSlice +} + // CheckExpiredTicket returns whether or not a ticket was ever expired. // // This function is safe for concurrent access. diff --git a/dcrjson/dcrdcmds.go b/dcrjson/dcrdcmds.go index b17c5e7b85..c651b48ab8 100644 --- a/dcrjson/dcrdcmds.go +++ b/dcrjson/dcrdcmds.go @@ -45,6 +45,19 @@ func NewExistsAddressesCmd(addresses []string) *ExistsAddressesCmd { } } +// ExistsMissedTicketsCmd defines the existsmissedtickets JSON-RPC command. +type ExistsMissedTicketsCmd struct { + TxHashBlob string +} + +// NewExistsMissedTicketsCmd returns a new instance which can be used to issue an +// existsmissedtickets JSON-RPC command. +func NewExistsMissedTicketsCmd(txHashBlob string) *ExistsMissedTicketsCmd { + return &ExistsMissedTicketsCmd{ + TxHashBlob: txHashBlob, + } +} + // ExistsExpiredTicketsCmd defines the existsexpiredtickets JSON-RPC command. type ExistsExpiredTicketsCmd struct { TxHashBlob string @@ -281,6 +294,7 @@ func init() { MustRegisterCmd("estimatestakediff", (*EstimateStakeDiffCmd)(nil), flags) MustRegisterCmd("existsaddress", (*ExistsAddressCmd)(nil), flags) MustRegisterCmd("existsaddresses", (*ExistsAddressesCmd)(nil), flags) + MustRegisterCmd("existsmissedtickets", (*ExistsMissedTicketsCmd)(nil), flags) MustRegisterCmd("existsexpiredtickets", (*ExistsExpiredTicketsCmd)(nil), flags) MustRegisterCmd("existsliveticket", (*ExistsLiveTicketCmd)(nil), flags) MustRegisterCmd("existslivetickets", (*ExistsLiveTicketsCmd)(nil), flags) diff --git a/rpcserver.go b/rpcserver.go index 9391b16327..d118dddb94 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -187,6 +187,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{ "estimatestakediff": handleEstimateStakeDiff, "existsaddress": handleExistsAddress, "existsaddresses": handleExistsAddresses, + "existsmissedtickets": handleExistsMissedTickets, "existsexpiredtickets": handleExistsExpiredTickets, "existsliveticket": handleExistsLiveTicket, "existslivetickets": handleExistsLiveTickets, @@ -1605,6 +1606,32 @@ func handleExistsAddresses(s *rpcServer, cmd interface{}, closeChan <-chan struc return hex.EncodeToString([]byte(set)), nil } +// handleExistsMissedTickets implements the existsmissedtickets command. +func handleExistsMissedTickets(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + c := cmd.(*dcrjson.ExistsMissedTicketsCmd) + + hashes, err := dcrjson.DecodeConcatenatedHashes(c.TxHashBlob) + if err != nil { + return nil, err + } + + exists := s.server.blockManager.chain.CheckMissedTickets(hashes) + if len(exists) != len(hashes) { + return nil, rpcInvalidError("Invalid missed ticket count "+ + "got %v, want %v", len(exists), len(hashes)) + } + + // Convert the slice of bools into a compacted set of bit flags. + set := bitset.NewBytes(len(hashes)) + for i := range exists { + if exists[i] { + set.Set(i) + } + } + + return hex.EncodeToString([]byte(set)), nil +} + // handleExistsExpiredTickets implements the existsexpiredtickets command. func handleExistsExpiredTickets(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { c := cmd.(*dcrjson.ExistsExpiredTicketsCmd) diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 9c5c500cb1..2357c33c5b 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -171,6 +171,11 @@ var helpDescsEnUS = map[string]string{ "existsaddresses-addresses": "The addresses to check", "existsaddresses--result0": "Bitset of bools showing if addresses exist or not", + // ExitsMissedTicketsCmd help. + "existsmissedtickets--synopsis": "Test for the existance of the provided tickets in the missed ticket map", + "existsmissedtickets-txhashblob": "Blob containing the hashes to check", + "existsmissedtickets--result0": "Bool blob showing if the ticket exists in the missed ticket database or not", + // ExistsExpiredTicketsCmd help. "existsexpiredtickets--synopsis": "Test for the existance of the provided tickets in the expired ticket map", "existsexpiredtickets-txhashblob": "Blob containing the hashes to check", @@ -879,6 +884,7 @@ var rpcResultTypes = map[string][]interface{}{ "estimatestakediff": {(*dcrjson.EstimateStakeDiffResult)(nil)}, "existsaddress": {(*bool)(nil)}, "existsaddresses": {(*string)(nil)}, + "existsmissedtickets": {(*string)(nil)}, "existsexpiredtickets": {(*string)(nil)}, "existsliveticket": {(*bool)(nil)}, "existslivetickets": {(*string)(nil)},