github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/consensus/clique/api.go (about) 1 package clique 2 3 import ( 4 "fmt" 5 6 "github.com/bigzoro/my_simplechain/common" 7 "github.com/bigzoro/my_simplechain/consensus" 8 "github.com/bigzoro/my_simplechain/core/types" 9 "github.com/bigzoro/my_simplechain/rpc" 10 ) 11 12 // API is a user facing RPC API to allow controlling the signer and voting 13 // mechanisms of the proof-of-authority scheme. 14 type API struct { 15 chain consensus.ChainReader 16 clique *Clique 17 } 18 19 // GetSnapshot retrieves the state snapshot at a given block. 20 func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) { 21 // Retrieve the requested block number (or current if none requested) 22 var header *types.Header 23 if number == nil || *number == rpc.LatestBlockNumber { 24 header = api.chain.CurrentHeader() 25 } else { 26 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 27 } 28 // Ensure we have an actually valid block and return its snapshot 29 if header == nil { 30 return nil, errUnknownBlock 31 } 32 return api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) 33 } 34 35 // GetSnapshotAtHash retrieves the state snapshot at a given block. 36 func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) { 37 header := api.chain.GetHeaderByHash(hash) 38 if header == nil { 39 return nil, errUnknownBlock 40 } 41 return api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) 42 } 43 44 // GetSigners retrieves the list of authorized signers at the specified block. 45 func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) { 46 // Retrieve the requested block number (or current if none requested) 47 var header *types.Header 48 if number == nil || *number == rpc.LatestBlockNumber { 49 header = api.chain.CurrentHeader() 50 } else { 51 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 52 } 53 // Ensure we have an actually valid block and return the signers from its snapshot 54 if header == nil { 55 return nil, errUnknownBlock 56 } 57 snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) 58 if err != nil { 59 return nil, err 60 } 61 return snap.signers(), nil 62 } 63 64 // GetSignersAtHash retrieves the list of authorized signers at the specified block. 65 func (api *API) GetSignersAtHash(hash common.Hash) ([]common.Address, error) { 66 header := api.chain.GetHeaderByHash(hash) 67 if header == nil { 68 return nil, errUnknownBlock 69 } 70 snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) 71 if err != nil { 72 return nil, err 73 } 74 return snap.signers(), nil 75 } 76 77 // Proposals returns the current proposals the node tries to uphold and vote on. 78 func (api *API) Proposals() map[common.Address]bool { 79 api.clique.lock.RLock() 80 defer api.clique.lock.RUnlock() 81 82 proposals := make(map[common.Address]bool) 83 for address, auth := range api.clique.proposals { 84 proposals[address] = auth 85 } 86 return proposals 87 } 88 89 // Propose injects a new authorization proposal that the signer will attempt to 90 // push through. 91 func (api *API) Propose(address common.Address, auth bool) { 92 api.clique.lock.Lock() 93 defer api.clique.lock.Unlock() 94 95 api.clique.proposals[address] = auth 96 } 97 98 // Discard drops a currently running proposal, stopping the signer from casting 99 // further votes (either for or against). 100 func (api *API) Discard(address common.Address) { 101 api.clique.lock.Lock() 102 defer api.clique.lock.Unlock() 103 104 delete(api.clique.proposals, address) 105 } 106 107 type status struct { 108 InturnPercent float64 `json:"inturnPercent"` 109 SigningStatus map[common.Address]int `json:"sealerActivity"` 110 NumBlocks uint64 `json:"numBlocks"` 111 } 112 113 // Status returns the status of the last N blocks, 114 // - the number of active signers, 115 // - the number of signers, 116 // - the percentage of in-turn blocks 117 func (api *API) Status() (*status, error) { 118 var ( 119 numBlocks = uint64(64) 120 header = api.chain.CurrentHeader() 121 diff = uint64(0) 122 optimals = 0 123 ) 124 snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) 125 if err != nil { 126 return nil, err 127 } 128 var ( 129 signers = snap.signers() 130 end = header.Number.Uint64() 131 start = end - numBlocks 132 ) 133 if numBlocks > end { 134 start = 1 135 numBlocks = end - start 136 } 137 signStatus := make(map[common.Address]int) 138 for _, s := range signers { 139 signStatus[s] = 0 140 } 141 for n := start; n < end; n++ { 142 h := api.chain.GetHeaderByNumber(n) 143 if h == nil { 144 return nil, fmt.Errorf("missing block %d", n) 145 } 146 if h.Difficulty.Cmp(diffInTurn) == 0 { 147 optimals++ 148 } 149 diff += h.Difficulty.Uint64() 150 sealer, err := api.clique.Author(h) 151 if err != nil { 152 return nil, err 153 } 154 signStatus[sealer]++ 155 } 156 return &status{ 157 InturnPercent: float64((100 * optimals)) / float64(numBlocks), 158 SigningStatus: signStatus, 159 NumBlocks: numBlocks, 160 }, nil 161 }