// waitSync blocks execution until the chain is synchronized with the network, // which usually entails waiting until syncing reports false, with the added // criteria that we actually have a decently current block (< 3 mins). func waitSync(freshness time.Duration, api *geth.API) { notified := false for { // Wait until sync reports false for { // Fetch the sync status status, err := api.Syncing() if err != nil { log15.Error("Failed to retrieve sync status", "error", err) } else if status == nil { break } // Sleep if syncing time.Sleep(250 * time.Millisecond) } // We're supposedly in sync, double check the block timestamp head, err := api.BlockNumber() if err != nil { log15.Error("Failed to retrieve head block number", "error", err) break } mined, err := api.GetBlockTime(head) if err != nil { log15.Error("Failed to retrieve head block timestamp", "number", head, "error", err) break } if time.Since(mined) <= freshness { log15.Info("In sync with the network", "block", head, "freshness", time.Since(mined)) return } // Seems we're not in sync, wait a bit and retry if !notified { log15.Info("You seem out of sync, updating...", "freshness", time.Since(mined), "allowed", freshness) log15.Warn("We're sorry this isn't faster, test network's feisty :)") notified = true } time.Sleep(250 * time.Millisecond) } }