m.Handle("/get-merkle-proof", jsonHandler(a.getMerkleProof))
m.Handle("/get-vote-result", jsonHandler(a.getVoteResult))
+ m.Handle("/get-blocker", jsonHandler(a.getBlocker))
m.HandleFunc("/websocket-subscribe", a.websocketHandler)
"sort"
chainjson "github.com/vapor/encoding/json"
+ "github.com/vapor/protocol/bc/types"
)
type voteInfo struct {
}
type voteInfoSlice []*voteInfo
-func (v voteInfoSlice) Len() int { return len(v) }
+
+func (v voteInfoSlice) Len() int { return len(v) }
func (v voteInfoSlice) Less(i, j int) bool { return v[i].VoteNum > v[j].VoteNum }
-func (v voteInfoSlice) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
+func (v voteInfoSlice) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
func (a *API) getVoteResult(req struct {
BlockHash chainjson.HexBytes `json:"block_hash"`
sort.Sort(voteInfoSlice(voteInfos))
return NewSuccessResponse(voteInfos)
}
+
+type getBlockerResp struct {
+ PubKey string `json:"pub_key"`
+}
+
+func (a *API) getBlocker(req struct {
+ BlockHash chainjson.HexBytes `json:"block_hash"`
+ BlockHeight uint64 `json:"block_height"`
+}) Response {
+ var blockHeader *types.BlockHeader
+ var err error
+ if len(req.BlockHash) == 32 {
+ blockHash := hexBytesToHash(req.BlockHash)
+ blockHeader, err = a.chain.GetHeaderByHash(&blockHash)
+ } else {
+ blockHeader, err = a.chain.GetHeaderByHeight(req.BlockHeight)
+ }
+
+ if err != nil {
+ return NewErrorResponse(err)
+ }
+
+ pubKey, err := a.chain.GetBlocker(&blockHeader.PreviousBlockHash, blockHeader.Timestamp)
+ if err != nil {
+ return NewErrorResponse(err)
+ }
+ return NewSuccessResponse(&getBlockerResp{PubKey: pubKey})
+}
}
// IsBlocker returns whether the consensus node is a blocker at the specified time
-func (c *Chain) IsBlocker(prevBlockHash *bc.Hash, pubkey string, timeStamp uint64) (bool, error) {
- return c.consensusNodeManager.isBlocker(prevBlockHash, pubkey, timeStamp)
+func (c *Chain) IsBlocker(prevBlockHash *bc.Hash, pubKey string, timeStamp uint64) (bool, error) {
+ xPub, err := c.consensusNodeManager.getBlocker(prevBlockHash, timeStamp)
+ if err != nil {
+ return false, err
+ }
+ return xPub == pubKey, nil
+}
+
+// GetBlock return blocker by specified timestamp
+func (c *Chain) GetBlocker(prevBlockHash *bc.Hash, timestamp uint64) (string, error) {
+ return c.consensusNodeManager.getBlocker(prevBlockHash, timestamp)
}
// ProcessBlockSignature process the received block signature messages
return err
}
- isBlocker, err := c.consensusNodeManager.isBlocker(&block.PreviousBlockHash, pubKey, block.Timestamp)
+ isBlocker, err := c.IsBlocker(&block.PreviousBlockHash, pubKey, block.Timestamp)
if err != nil {
return err
}
return node, nil
}
-func (c *consensusNodeManager) isBlocker(prevBlockHash *bc.Hash, pubKey string, timeStamp uint64) (bool, error) {
+func (c *consensusNodeManager) getBlocker(prevBlockHash *bc.Hash, timeStamp uint64) (string, error) {
consensusNodeMap, err := c.getConsensusNodes(prevBlockHash)
if err != nil {
- return false, err
- }
-
- consensusNode := consensusNodeMap[pubKey]
- if consensusNode == nil {
- return false, nil
+ return "", err
}
prevVoteRoundLastBlock, err := c.getPrevRoundLastBlock(prevBlockHash)
if err != nil {
- return false, err
+ return "", err
}
startTimestamp := prevVoteRoundLastBlock.Timestamp + consensus.BlockTimeInterval
- begin := getLastBlockTimeInTimeRange(startTimestamp, timeStamp, consensusNode.Order, uint64(len(consensusNodeMap)))
- end := begin + consensus.BlockNumEachNode*consensus.BlockTimeInterval
- return timeStamp >= begin && timeStamp < end, nil
+
+ for xPub, consensusNode := range consensusNodeMap {
+ begin := getLastBlockTimeInTimeRange(startTimestamp, timeStamp, consensusNode.Order, uint64(len(consensusNodeMap)))
+ end := begin + consensus.BlockNumEachNode*consensus.BlockTimeInterval
+ if timeStamp >= begin && timeStamp < end {
+ return xPub, nil
+ }
+ }
+ // impossible occur
+ return "", errors.New("can not find blocker by given timestamp")
}
func getLastBlockTimeInTimeRange(startTimestamp, endTimestamp, order, numOfConsensusNode uint64) uint64 {