#!/usr/bin/env python3 def exact_div(x, y): assert x % y == 0 return x // y # floor(u/x + v/y) def div2(u, x, v, y): return (u*y + v*x) // (x*y) TESTNET = 0 MAINNET = 1 class Network: # def __init__(self, network): self.BlossomActivationHeight = 653600 if network == MAINNET else 584000 SlowStartInterval = 20000 MaxBlockSubsidy = 1250000000 # 12.5 ZEC PreBlossomHalvingInterval = 840000 PreBlossomPoWTargetSpacing = 150 PostBlossomPoWTargetSpacing = 75 # def IsBlossomActivated(self, height): return height >= self.BlossomActivationHeight BlossomPoWTargetSpacingRatio = exact_div(PreBlossomPoWTargetSpacing, PostBlossomPoWTargetSpacing) PostBlossomHalvingInterval = PreBlossomHalvingInterval * BlossomPoWTargetSpacingRatio # must be an integer # SlowStartShift = exact_div(SlowStartInterval, 2) SlowStartRate = exact_div(MaxBlockSubsidy, SlowStartInterval) def Halving(self, height): if height < self.SlowStartShift: return 0 elif not self.IsBlossomActivated(height): return (height - self.SlowStartShift) // self.PreBlossomHalvingInterval else: return div2(self.BlossomActivationHeight - self.SlowStartShift, self.PreBlossomHalvingInterval, height - self.BlossomActivationHeight, self.PostBlossomHalvingInterval) def BlockSubsidy(self, height): if height < self.SlowStartShift: return self.SlowStartRate * height elif self.SlowStartShift <= height and height < self.SlowStartInterval: return self.SlowStartRate * (height + 1) elif self.SlowStartInterval <= height and not self.IsBlossomActivated(height): return self.MaxBlockSubsidy // (1 << self.Halving(height)) else: return self.MaxBlockSubsidy // (self.BlossomPoWTargetSpacingRatio << self.Halving(height)) def SupplyAfterHeight(self, height): return sum((self.BlockSubsidy(h) for h in range(height+1))) print(Network(MAINNET).SupplyAfterHeight(1799152)) # September 6th 2022 12:15 UTC print(Network(MAINNET).SupplyAfterHeight(1875375)) # November 11th 2022 11:35 UTC