github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/bft/rpc/core/consensus.go (about) 1 package core 2 3 import ( 4 cstypes "github.com/gnolang/gno/tm2/pkg/bft/consensus/types" 5 ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" 6 rpctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" 7 sm "github.com/gnolang/gno/tm2/pkg/bft/state" 8 "github.com/gnolang/gno/tm2/pkg/bft/types" 9 ) 10 11 // Get the validator set at the given block height. 12 // If no height is provided, it will fetch the current validator set. 13 // Note the validators are sorted by their address - this is the canonical 14 // order for the validators in the set as used in computing their Merkle root. 15 // 16 // ```shell 17 // curl 'localhost:26657/validators' 18 // ``` 19 // 20 // ```go 21 // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket") 22 // err := client.Start() 23 // 24 // if err != nil { 25 // // handle error 26 // } 27 // 28 // defer client.Stop() 29 // state, err := client.Validators() 30 // ``` 31 // 32 // The above command returns JSON structured like this: 33 // 34 // ```json 35 // 36 // { 37 // "error": "", 38 // "result": { 39 // "validators": [ 40 // { 41 // "proposer_priority": "0", 42 // "voting_power": "10", 43 // "pub_key": { 44 // "data": "68DFDA7E50F82946E7E8546BED37944A422CD1B831E70DF66BA3B8430593944D", 45 // "type": "ed25519" 46 // }, 47 // "address": "E89A51D60F68385E09E716D353373B11F8FACD62" 48 // } 49 // ], 50 // "block_height": "5241" 51 // }, 52 // "id": "", 53 // "jsonrpc": "2.0" 54 // } 55 // 56 // ``` 57 func Validators(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultValidators, error) { 58 // The latest validator that we know is the 59 // NextValidator of the last block. 60 height := consensusState.GetState().LastBlockHeight + 1 61 height, err := getHeight(height, heightPtr) 62 if err != nil { 63 return nil, err 64 } 65 66 validators, err := sm.LoadValidators(stateDB, height) 67 if err != nil { 68 return nil, err 69 } 70 return &ctypes.ResultValidators{ 71 BlockHeight: height, 72 Validators: validators.Validators, 73 }, nil 74 } 75 76 // DumpConsensusState dumps consensus state. 77 // UNSTABLE 78 // 79 // ```shell 80 // curl 'localhost:26657/dump_consensus_state' 81 // ``` 82 // 83 // ```go 84 // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket") 85 // err := client.Start() 86 // 87 // if err != nil { 88 // // handle error 89 // } 90 // 91 // defer client.Stop() 92 // state, err := client.DumpConsensusState() 93 // ``` 94 // 95 // The above command returns JSON structured like this: 96 // 97 // ```json 98 // 99 // { 100 // "jsonrpc": "2.0", 101 // "id": "", 102 // "result": { 103 // "round_state": { 104 // "height": "7185", 105 // "round": "0", 106 // "step": "1", 107 // "start_time": "2018-05-12T13:57:28.440293621-07:00", 108 // "commit_time": "2018-05-12T13:57:27.440293621-07:00", 109 // "validators": { 110 // "validators": [ 111 // { 112 // "address": "B5B3D40BE53982AD294EF99FF5A34C0C3E5A3244", 113 // "pub_key": { 114 // "type": "tendermint/PubKeyEd25519", 115 // "value": "SBctdhRBcXtBgdI/8a/alTsUhGXqGs9k5ylV1u5iKHg=" 116 // }, 117 // "voting_power": "10", 118 // "proposer_priority": "0" 119 // } 120 // ], 121 // "proposer": { 122 // "address": "B5B3D40BE53982AD294EF99FF5A34C0C3E5A3244", 123 // "pub_key": { 124 // "type": "tendermint/PubKeyEd25519", 125 // "value": "SBctdhRBcXtBgdI/8a/alTsUhGXqGs9k5ylV1u5iKHg=" 126 // }, 127 // "voting_power": "10", 128 // "proposer_priority": "0" 129 // } 130 // }, 131 // "proposal": null, 132 // "proposal_block": null, 133 // "proposal_block_parts": null, 134 // "locked_round": "0", 135 // "locked_block": null, 136 // "locked_block_parts": null, 137 // "valid_round": "0", 138 // "valid_block": null, 139 // "valid_block_parts": null, 140 // "votes": [ 141 // { 142 // "round": "0", 143 // "prevotes": "_", 144 // "precommits": "_" 145 // } 146 // ], 147 // "commit_round": "-1", 148 // "last_commit": { 149 // "votes": [ 150 // "Vote{0:B5B3D40BE539 7184/00/2(Precommit) 14F946FA7EF0 /702B1B1A602A.../ @ 2018-05-12T20:57:27.342Z}" 151 // ], 152 // "votes_bit_array": "x", 153 // "peer_maj_23s": {} 154 // }, 155 // "last_validators": { 156 // "validators": [ 157 // { 158 // "address": "B5B3D40BE53982AD294EF99FF5A34C0C3E5A3244", 159 // "pub_key": { 160 // "type": "tendermint/PubKeyEd25519", 161 // "value": "SBctdhRBcXtBgdI/8a/alTsUhGXqGs9k5ylV1u5iKHg=" 162 // }, 163 // "voting_power": "10", 164 // "proposer_priority": "0" 165 // } 166 // ], 167 // "proposer": { 168 // "address": "B5B3D40BE53982AD294EF99FF5A34C0C3E5A3244", 169 // "pub_key": { 170 // "type": "tendermint/PubKeyEd25519", 171 // "value": "SBctdhRBcXtBgdI/8a/alTsUhGXqGs9k5ylV1u5iKHg=" 172 // }, 173 // "voting_power": "10", 174 // "proposer_priority": "0" 175 // } 176 // } 177 // }, 178 // "peers": [ 179 // { 180 // "node_address": "30ad1854af22506383c3f0e57fb3c7f90984c5e8@172.16.63.221:26656", 181 // "peer_state": { 182 // "round_state": { 183 // "height": "7185", 184 // "round": "0", 185 // "step": "1", 186 // "start_time": "2018-05-12T13:57:27.438039872-07:00", 187 // "proposal": false, 188 // "proposal_block_parts_header": { 189 // "total": "0", 190 // "hash": "" 191 // }, 192 // "proposal_block_parts": null, 193 // "proposal_pol_round": "-1", 194 // "proposal_pol": "_", 195 // "prevotes": "_", 196 // "precommits": "_", 197 // "last_commit_round": "0", 198 // "last_commit": "x", 199 // "catchup_commit_round": "-1", 200 // "catchup_commit": "_" 201 // }, 202 // "stats": { 203 // "last_vote_height": "7184", 204 // "votes": "255", 205 // "last_block_part_height": "7184", 206 // "block_parts": "255" 207 // } 208 // } 209 // } 210 // ] 211 // } 212 // } 213 // 214 // ``` 215 func DumpConsensusState(ctx *rpctypes.Context) (*ctypes.ResultDumpConsensusState, error) { 216 // Get Peer consensus states. 217 peers := p2pPeers.Peers().List() 218 peerStates := make([]ctypes.PeerStateInfo, len(peers)) 219 for i, peer := range peers { 220 peerState, ok := peer.Get(types.PeerStateKey).(interface { 221 GetExposed() cstypes.PeerStateExposed 222 }) 223 if !ok { // peer does not have a state yet 224 continue 225 } 226 peerStateJSON, err := peerState.GetExposed().ToJSON() 227 if err != nil { 228 return nil, err 229 } 230 peerStates[i] = ctypes.PeerStateInfo{ 231 // Peer basic info. 232 NodeAddress: peer.SocketAddr().String(), 233 // Peer consensus state. 234 PeerState: peerStateJSON, 235 } 236 } 237 // Get self round state. 238 config := consensusState.GetConfigDeepCopy() 239 roundState := consensusState.GetRoundStateDeepCopy() 240 return &ctypes.ResultDumpConsensusState{ 241 Config: config, 242 RoundState: roundState, 243 Peers: peerStates, 244 }, nil 245 } 246 247 // ConsensusState returns a concise summary of the consensus state. 248 // UNSTABLE 249 // 250 // ```shell 251 // curl 'localhost:26657/consensus_state' 252 // ``` 253 // 254 // ```go 255 // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket") 256 // err := client.Start() 257 // 258 // if err != nil { 259 // // handle error 260 // } 261 // 262 // defer client.Stop() 263 // state, err := client.ConsensusState() 264 // ``` 265 // 266 // The above command returns JSON structured like this: 267 // 268 // ```json 269 // 270 // { 271 // "jsonrpc": "2.0", 272 // "id": "", 273 // "result": { 274 // "round_state": { 275 // "height/round/step": "9336/0/1", 276 // "start_time": "2018-05-14T10:25:45.72595357-04:00", 277 // "proposal_block_hash": "", 278 // "locked_block_hash": "", 279 // "valid_block_hash": "", 280 // "height_vote_set": [ 281 // { 282 // "round": "0", 283 // "prevotes": [ 284 // "nil-Vote" 285 // ], 286 // "prevotes_bit_array": "BA{1:_} 0/10 = 0.00", 287 // "precommits": [ 288 // "nil-Vote" 289 // ], 290 // "precommits_bit_array": "BA{1:_} 0/10 = 0.00" 291 // } 292 // ] 293 // } 294 // } 295 // } 296 // 297 // ``` 298 func ConsensusState(ctx *rpctypes.Context) (*ctypes.ResultConsensusState, error) { 299 // Get self round state. 300 rs := consensusState.GetRoundStateSimple() 301 return &ctypes.ResultConsensusState{RoundState: rs}, nil 302 } 303 304 // Get the consensus parameters at the given block height. 305 // If no height is provided, it will fetch the current consensus params. 306 // 307 // ```shell 308 // curl 'localhost:26657/consensus_params' 309 // ``` 310 // 311 // ```go 312 // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket") 313 // err := client.Start() 314 // 315 // if err != nil { 316 // // handle error 317 // } 318 // 319 // defer client.Stop() 320 // state, err := client.ConsensusParams() 321 // ``` 322 // 323 // The above command returns JSON structured like this: 324 // 325 // ```json 326 // 327 // { 328 // "jsonrpc": "2.0", 329 // "id": "", 330 // "result": { 331 // "block_height": "1", 332 // "consensus_params": { 333 // "block_size_params": { 334 // "max_txs_bytes": "22020096", 335 // "max_gas": "-1" 336 // }, 337 // "evidence_params": { 338 // "max_age": "100000" 339 // } 340 // } 341 // } 342 // } 343 // 344 // ``` 345 func ConsensusParams(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultConsensusParams, error) { 346 height := consensusState.GetState().LastBlockHeight + 1 347 height, err := getHeight(height, heightPtr) 348 if err != nil { 349 return nil, err 350 } 351 352 consensusparams, err := sm.LoadConsensusParams(stateDB, height) 353 if err != nil { 354 return nil, err 355 } 356 return &ctypes.ResultConsensusParams{ 357 BlockHeight: height, 358 ConsensusParams: consensusparams, 359 }, nil 360 }