| 62 | } |
| 63 | |
| 64 | func (a *API) leaderInfo(ctx context.Context) (map[string]interface{}, error) { |
| 65 | var generatorHeight uint64 |
| 66 | var generatorFetched time.Time |
| 67 | |
| 68 | a.downloadingSnapshotMu.Lock() |
| 69 | snapshot := a.downloadingSnapshot |
| 70 | a.downloadingSnapshotMu.Unlock() |
| 71 | |
| 72 | localHeight := a.chain.Height() |
| 73 | |
| 74 | if a.config.IsGenerator { |
| 75 | now := time.Now() |
| 76 | generatorHeight = localHeight |
| 77 | generatorFetched = now |
| 78 | } else { |
| 79 | fetchHeight, fetchTime := fetch.GeneratorHeight() |
| 80 | // Because everything is asynchronous, it's possible for the localHeight to |
| 81 | // be higher than our cached generator height. In that case, display the |
| 82 | // local height as the generator height. |
| 83 | if localHeight > fetchHeight { |
| 84 | fetchHeight = localHeight |
| 85 | } |
| 86 | |
| 87 | // fetchTime might be the zero time if we're having trouble connecting |
| 88 | // to the remote generator. Only set the height & time if we have it. |
| 89 | // The dashboard will handle zeros correctly. |
| 90 | if !fetchTime.IsZero() { |
| 91 | generatorHeight, generatorFetched = fetchHeight, fetchTime |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | var ( |
| 96 | configuredAtSecs int64 = int64(a.config.ConfiguredAt / 1000) |
| 97 | configuredAtNSecs int64 = int64((a.config.ConfiguredAt % 1000) * 1e6) |
| 98 | ) |
| 99 | |
| 100 | m := map[string]interface{}{ |
| 101 | "state": a.leader.State().String(), |
| 102 | "is_configured": true, |
| 103 | "configured_at": time.Unix(configuredAtSecs, configuredAtNSecs).UTC(), |
| 104 | "is_signer": a.config.IsSigner, |
| 105 | "is_generator": a.config.IsGenerator, |
| 106 | "generator_url": a.config.GeneratorUrl, |
| 107 | "generator_access_token": obfuscateTokenSecret(a.config.GeneratorAccessToken), |
| 108 | "blockchain_id": a.config.BlockchainId, |
| 109 | "block_height": localHeight, |
| 110 | "generator_block_height": generatorHeight, |
| 111 | "generator_block_height_fetched_at": generatorFetched, |
| 112 | "network_rpc_version": crosscoreRPCVersion, // "Network" is legacy terminology for "Cross-core" |
| 113 | "crosscore_rpc_version": crosscoreRPCVersion, |
| 114 | "core_id": a.config.Id, |
| 115 | "version": config.Version, |
| 116 | "build_commit": config.BuildCommit, |
| 117 | "build_date": config.BuildDate, |
| 118 | "build_config": config.BuildConfig, |
| 119 | "health": a.health(), |
| 120 | } |
| 121 | |