Skip to content

Instantly share code, notes, and snippets.

@daira
Created November 12, 2022 00:03
Show Gist options
  • Save daira/3a5da7a93bbf89214fa27e76b5c487cb to your computer and use it in GitHub Desktop.
Save daira/3a5da7a93bbf89214fa27e76b5c487cb to your computer and use it in GitHub Desktop.
Calculate the Zcash supply after a given block height on Mainnet or Testnet
#!/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:
# <https://zips.z.cash/protocol/protocol.pdf#constants>
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
# <https://zips.z.cash/protocol/protocol.pdf#diffadjustment>
def IsBlossomActivated(self, height):
return height >= self.BlossomActivationHeight
BlossomPoWTargetSpacingRatio = exact_div(PreBlossomPoWTargetSpacing, PostBlossomPoWTargetSpacing)
PostBlossomHalvingInterval = PreBlossomHalvingInterval * BlossomPoWTargetSpacingRatio # must be an integer
# <https://zips.z.cash/protocol/protocol.pdf#subsidies>
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(1875375))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment