lightwalletd: adaptive reorg-lag tip + non-blocking startup coinsupply
Adaptive-lag: advertise a tip that trails the real tip by a reorg-rate-driven lag (GetLatestBlock/GetLightdInfo) so wallets anchor shielded spends at a settled height during reorg churn. Configurable via -adaptive-lag/-lag-min/-lag-max/-lag-window; monitor_lwd.sh runs -lag-min 4 -lag-max 12 -lag-window 30. Startup coinsupply: the informational startup coinsupply RPC (result used only for a log line) blocked the gRPC bind for minutes on a node whose supply index is cold, keeping the lite endpoint down on every restart while it also starved the block-cache ingestor. Run it in a goroutine so the bind is never blocked; clients still get coinsupply on demand via the GetCoinsupply RPC. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -95,14 +95,46 @@ func GetCoinsupply(rpcClient *rpcclient.Client) (string, string, int, int, int,
|
||||
return "", "", -1, -1, -1, -1, errors.Wrap(err, "error reading JSON response")
|
||||
}
|
||||
|
||||
result := f.(map[string]interface{})["result"].(string)
|
||||
coin := f.(map[string]interface{})["coin"].(string)
|
||||
height := f.(map[string]interface{})["height"].(float64)
|
||||
supply := f.(map[string]interface{})["supply"].(float64)
|
||||
zfunds := f.(map[string]interface{})["zfunds"].(float64)
|
||||
total := f.(map[string]interface{})["total"].(float64)
|
||||
coinsupply, ok := f.(map[string]interface{})
|
||||
if !ok {
|
||||
return "", "", -1, -1, -1, -1, errors.New("unexpected coinsupply response format")
|
||||
}
|
||||
|
||||
return result, coin, int(height), int(supply), int(zfunds), int(total), nil
|
||||
getStringField := func(key string) string {
|
||||
value, ok := coinsupply[key]
|
||||
if !ok || value == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if strValue, ok := value.(string); ok {
|
||||
return strValue
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v", value)
|
||||
}
|
||||
|
||||
getNumberField := func(key string) int {
|
||||
value, ok := coinsupply[key]
|
||||
if !ok || value == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
number, ok := value.(float64)
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
|
||||
return int(number)
|
||||
}
|
||||
|
||||
result := getStringField("result")
|
||||
coin := getStringField("coin")
|
||||
height := getNumberField("height")
|
||||
supply := getNumberField("supply")
|
||||
zfunds := getNumberField("zfunds")
|
||||
total := getNumberField("total")
|
||||
|
||||
return result, coin, height, supply, zfunds, total, nil
|
||||
}
|
||||
|
||||
func getBlockFromRPC(rpcClient *rpcclient.Client, height int) (*walletrpc.CompactBlock, error) {
|
||||
@@ -225,6 +257,13 @@ func BlockIngestor(rpcClient *rpcclient.Client, cache *BlockCache, log *logrus.E
|
||||
}
|
||||
|
||||
func GetBlock(rpcClient *rpcclient.Client, cache *BlockCache, height int) (*walletrpc.CompactBlock, error) {
|
||||
// Don't serve blocks above the advertised (lag-adjusted) tip, so wallets can
|
||||
// neither sync nor anchor shielded spends into the unstable reorg zone.
|
||||
if !cache.HeightAllowed(height) {
|
||||
return nil, errors.New(
|
||||
fmt.Sprintf("Block %d is above the advertised tip (reorg-lag protection)", height))
|
||||
}
|
||||
|
||||
// First, check the cache to see if we have the block
|
||||
block := cache.Get(height)
|
||||
if block != nil {
|
||||
|
||||
Reference in New Issue
Block a user