GetCurrentBP returns nearest hash distance block producer as current node chief block producer.
()
| 177 | |
| 178 | // GetCurrentBP returns nearest hash distance block producer as current node chief block producer. |
| 179 | func GetCurrentBP() (bpNodeID proto.NodeID, err error) { |
| 180 | currentBPLock.Lock() |
| 181 | defer currentBPLock.Unlock() |
| 182 | |
| 183 | if !currentBP.IsEmpty() { |
| 184 | bpNodeID = currentBP |
| 185 | return |
| 186 | } |
| 187 | |
| 188 | var localNodeID proto.NodeID |
| 189 | if localNodeID, err = kms.GetLocalNodeID(); err != nil { |
| 190 | return |
| 191 | } |
| 192 | |
| 193 | // get random block producer first |
| 194 | bpList := route.GetBPs() |
| 195 | |
| 196 | if len(bpList) == 0 { |
| 197 | err = ErrNoChiefBlockProducerAvailable |
| 198 | return |
| 199 | } |
| 200 | |
| 201 | randomBP := bpList[rand.Intn(len(bpList))] |
| 202 | |
| 203 | // call random block producer for nearest block producer node |
| 204 | req := &proto.FindNeighborReq{ |
| 205 | ID: localNodeID, |
| 206 | Roles: []proto.ServerRole{ |
| 207 | proto.Leader, |
| 208 | proto.Follower, |
| 209 | }, |
| 210 | Count: 1, |
| 211 | } |
| 212 | res := new(proto.FindNeighborResp) |
| 213 | if err = NewCaller().CallNode(randomBP, "DHT.FindNeighbor", req, res); err != nil { |
| 214 | return |
| 215 | } |
| 216 | |
| 217 | if len(res.Nodes) <= 0 { |
| 218 | // node not found |
| 219 | err = errors.Wrap(ErrNoChiefBlockProducerAvailable, |
| 220 | "get no hash nearest block producer nodes") |
| 221 | return |
| 222 | } |
| 223 | |
| 224 | if res.Nodes[0].Role != proto.Leader && res.Nodes[0].Role != proto.Follower { |
| 225 | // not block producer |
| 226 | err = errors.Wrap(ErrNoChiefBlockProducerAvailable, |
| 227 | "no suitable nodes with proper block producer role") |
| 228 | return |
| 229 | } |
| 230 | |
| 231 | currentBP = res.Nodes[0].ID |
| 232 | bpNodeID = currentBP |
| 233 | |
| 234 | return |
| 235 | } |
| 236 |