github.com/deso-protocol/core@v1.2.9/lib/supply_test.go (about) 1 package lib 2 3 import ( 4 "fmt" 5 "math" 6 "testing" 7 "time" 8 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 ) 12 13 const ( 14 satoshisPerBitcoin = 100000000 15 ) 16 17 func TestTotalMiningSupply(t *testing.T) { 18 require := require.New(t) 19 20 // Sum all of the mining intervals to make sure there is no overflow. 21 totalMiningSupply := uint64(0) 22 for intervalIndex, currentInterval := range MiningSupplyIntervals { 23 if intervalIndex == 0 { 24 // Skip the first index 25 continue 26 } 27 prevInterval := MiningSupplyIntervals[intervalIndex-1] 28 blockRewardNanos := prevInterval.BlockRewardNanos 29 numBlocksInInterval := currentInterval.StartBlockHeight - prevInterval.StartBlockHeight 30 31 numNanosMinedInInterval := blockRewardNanos * uint64(numBlocksInInterval) 32 totalMiningSupply += numNanosMinedInInterval 33 } 34 require.Equal(int64(276238800000000), int64(totalMiningSupply)) 35 } 36 37 func TestCalcBlockReward(t *testing.T) { 38 require := require.New(t) 39 40 blocksPerYear := (time.Hour * 24 * 365 / DeSoMainnetParams.TimeBetweenBlocks) 41 require.Equal(int64(blocksPerYear), int64(BlocksPerYear)) 42 43 require.Equal(1*NanosPerUnit, CalcBlockRewardNanos(0)) 44 require.Equal(1*NanosPerUnit, CalcBlockRewardNanos(1)) 45 46 // .75 47 require.Equal(1*NanosPerUnit, CalcBlockRewardNanos(DeflationBombBlockRewardAdjustmentBlockHeight-1)) 48 require.Equal(int64(float64(NanosPerUnit) * .75), int64(CalcBlockRewardNanos(DeflationBombBlockRewardAdjustmentBlockHeight))) 49 // .5 50 require.Equal(int64(float64(NanosPerUnit) * .75), int64(CalcBlockRewardNanos(DeflationBombBlockRewardAdjustmentBlockHeight + 288 - 1))) 51 require.Equal(int64(float64(NanosPerUnit) * .5), int64(CalcBlockRewardNanos(DeflationBombBlockRewardAdjustmentBlockHeight + 288))) 52 // .25 53 require.Equal(int64(float64(NanosPerUnit) * .5), int64(CalcBlockRewardNanos(DeflationBombBlockRewardAdjustmentBlockHeight + 2*288 - 1))) 54 require.Equal(int64(float64(NanosPerUnit) * .25), int64(CalcBlockRewardNanos(DeflationBombBlockRewardAdjustmentBlockHeight + 2*288))) 55 // .125 56 require.Equal(int64(float64(NanosPerUnit) * .25), int64(CalcBlockRewardNanos(DeflationBombBlockRewardAdjustmentBlockHeight + 3*288 - 1))) 57 require.Equal(int64(float64(NanosPerUnit) * .125), int64(CalcBlockRewardNanos(DeflationBombBlockRewardAdjustmentBlockHeight + 3*288))) 58 // .1 59 require.Equal(int64(float64(NanosPerUnit) * .125), int64(CalcBlockRewardNanos(DeflationBombBlockRewardAdjustmentBlockHeight + 4*288 - 1))) 60 require.Equal(int64(float64(NanosPerUnit) * .1), int64(CalcBlockRewardNanos(DeflationBombBlockRewardAdjustmentBlockHeight + 4*288))) 61 62 // .05 63 require.Equal(int64(1*NanosPerUnit/10), int64(CalcBlockRewardNanos(15*BlocksPerYear-1))) 64 require.Equal(NanosPerUnit/20, CalcBlockRewardNanos(15*BlocksPerYear)) 65 require.Equal(NanosPerUnit/20, CalcBlockRewardNanos(15*BlocksPerYear+1)) 66 // 0 67 require.Equal(NanosPerUnit/20, CalcBlockRewardNanos(32*BlocksPerYear-1)) 68 require.Equal(uint64(0), CalcBlockRewardNanos(32*BlocksPerYear)) 69 require.Equal(uint64(0), CalcBlockRewardNanos(32*BlocksPerYear+1)) 70 require.Equal(uint64(0), CalcBlockRewardNanos(35*BlocksPerYear+1)) 71 require.Equal(uint64(0), CalcBlockRewardNanos(math.MaxUint32)) 72 } 73 74 func TestGetPrice(t *testing.T) { 75 oldInitialUSDCentsPerBitcoinExchangeRate := InitialUSDCentsPerBitcoinExchangeRate 76 InitialUSDCentsPerBitcoinExchangeRate = 1350000 77 defer func() { 78 InitialUSDCentsPerBitcoinExchangeRate = oldInitialUSDCentsPerBitcoinExchangeRate 79 }() 80 assert := assert.New(t) 81 { 82 startPriceSatoshis := GetStartPriceSatoshisPerDeSo(InitialUSDCentsPerBitcoinExchangeRate) 83 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(0, InitialUSDCentsPerBitcoinExchangeRate))) 84 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(1, InitialUSDCentsPerBitcoinExchangeRate))) 85 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(10, InitialUSDCentsPerBitcoinExchangeRate))) 86 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(1000, InitialUSDCentsPerBitcoinExchangeRate))) 87 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(1000000000, InitialUSDCentsPerBitcoinExchangeRate))) 88 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(10000000000, InitialUSDCentsPerBitcoinExchangeRate))) 89 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(100000000000, InitialUSDCentsPerBitcoinExchangeRate))) 90 assert.Equal(int64(startPriceSatoshis+2), int64(GetSatoshisPerUnitExchangeRate(1000*NanosPerUnit, InitialUSDCentsPerBitcoinExchangeRate))) 91 assert.Equal(int64(2*startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(1000000*NanosPerUnit, InitialUSDCentsPerBitcoinExchangeRate))) 92 assert.Equal(int64(16135), int64(GetSatoshisPerUnitExchangeRate(2123456*NanosPerUnit, InitialUSDCentsPerBitcoinExchangeRate))) 93 assert.Equal(int64(8*startPriceSatoshis-1), int64(GetSatoshisPerUnitExchangeRate(3000000*NanosPerUnit, InitialUSDCentsPerBitcoinExchangeRate))) 94 assert.Equal(int64(8*startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(3000001*NanosPerUnit, InitialUSDCentsPerBitcoinExchangeRate))) 95 assert.Equal(int64(262144*startPriceSatoshis-1), int64(GetSatoshisPerUnitExchangeRate(18000000*NanosPerUnit, InitialUSDCentsPerBitcoinExchangeRate))) 96 assert.Equal(int64(33554432*startPriceSatoshis-1), int64(GetSatoshisPerUnitExchangeRate(25000000*NanosPerUnit, InitialUSDCentsPerBitcoinExchangeRate))) 97 } 98 // Doubling the exchange rate should double the price outputted. 99 { 100 startPriceSatoshis := GetStartPriceSatoshisPerDeSo(2 * InitialUSDCentsPerBitcoinExchangeRate) 101 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(0, 2*InitialUSDCentsPerBitcoinExchangeRate))) 102 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(1, 2*InitialUSDCentsPerBitcoinExchangeRate))) 103 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(10, 2*InitialUSDCentsPerBitcoinExchangeRate))) 104 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(1000, 2*InitialUSDCentsPerBitcoinExchangeRate))) 105 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(1000000000, 2*InitialUSDCentsPerBitcoinExchangeRate))) 106 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(10000000000, 2*InitialUSDCentsPerBitcoinExchangeRate))) 107 assert.Equal(int64(startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(100000000000, 2*InitialUSDCentsPerBitcoinExchangeRate))) 108 assert.Equal(int64(startPriceSatoshis+1), int64(GetSatoshisPerUnitExchangeRate(1000*NanosPerUnit, 2*InitialUSDCentsPerBitcoinExchangeRate))) 109 assert.Equal(int64(2*startPriceSatoshis), int64(GetSatoshisPerUnitExchangeRate(1000000*NanosPerUnit, 2*InitialUSDCentsPerBitcoinExchangeRate))) 110 assert.Equal(int64(16135/2-2), int64(GetSatoshisPerUnitExchangeRate(2123456*NanosPerUnit, 2*InitialUSDCentsPerBitcoinExchangeRate))) 111 assert.Equal(int64(8*startPriceSatoshis-1), int64(GetSatoshisPerUnitExchangeRate(3000000*NanosPerUnit, 2*InitialUSDCentsPerBitcoinExchangeRate))) 112 assert.Equal(int64(262144*startPriceSatoshis-1), int64(GetSatoshisPerUnitExchangeRate(18000000*NanosPerUnit, 2*InitialUSDCentsPerBitcoinExchangeRate))) 113 assert.Equal(int64(33554432*startPriceSatoshis-1), int64(GetSatoshisPerUnitExchangeRate(25000000*NanosPerUnit, 2*InitialUSDCentsPerBitcoinExchangeRate))) 114 } 115 } 116 117 func TestCalcNanosToCreate(t *testing.T) { 118 assert := assert.New(t) 119 require := require.New(t) 120 121 oldInitialUSDCentsPerBitcoinExchangeRate := InitialUSDCentsPerBitcoinExchangeRate 122 InitialUSDCentsPerBitcoinExchangeRate = 1350000 123 defer func() { 124 InitialUSDCentsPerBitcoinExchangeRate = oldInitialUSDCentsPerBitcoinExchangeRate 125 }() 126 127 // Comment this in to test specific fields. 128 // 129 startNanos := uint64(8157483223947843) 130 //satoshisToBurn := uint64(500000000) 131 usdCentsPerBitcoin := uint64(5400000) 132 xxx := float64(GetSatoshisPerUnitExchangeRate(startNanos, usdCentsPerBitcoin)) / 1e8 * float64(5700000) / 100.0 133 fmt.Println(xxx) 134 return 135 136 //nanosToCreate1 := CalcNanosToCreate( 137 //startNanos [>startNanos*/, satoshisToBurn /*satoshisToBurn*/, usdCentsPerBitcoin /*usdCentsPerBitcoin<]) 138 //fmt.Println(nanosToCreate1) 139 //nanosToCreate2 := CalcNanosToCreate( 140 //startNanos+nanosToCreate1 [>startNanos*/, satoshisToBurn /*satoshisToBurn*/, usdCentsPerBitcoin /*usdCentsPerBitcoin<]) 141 //diff := nanosToCreate1 - nanosToCreate2 142 //fmt.Println(diff) 143 //fmt.Println(float64(diff) / float64(nanosToCreate2)) 144 145 //startPriceSatoshisPerDeSo := GetStartPriceSatoshisPerDeSo(usdCentsPerBitcoin) 146 //assert.Equal(int64(1805), int64(startPriceSatoshisPerDeSo)) 147 148 //nanosComponent := Div(NewFloat().SetUint64(NanosPerUnit), NewFloat().SetUint64(TrancheSizeNanos)) 149 //{ 150 //x, _ := nanosComponent.Float64() 151 //assert.Equal(float64(1e-06), x) 152 //} 153 154 //bitcoinComponent := Div(NewFloat().SetUint64(satoshisToBurn), NewFloat().SetUint64(startPriceSatoshisPerDeSo)) 155 //{ 156 //x, _ := bitcoinComponent.Float64() 157 //assert.Equal(float64(5.511003236565097e+06), x) 158 //} 159 160 //bigFloatFinalDeSoNanos := Mul(NewFloat().SetUint64(TrancheSizeNanos), BigFloatLog2( 161 //Add(Mul(nanosComponent, Mul(bitcoinComponent, NaturalLogOfTwo)), 162 //BigFloatPow(BigTwo, Div(NewFloat().SetUint64(startNanos), NewFloat().SetUint64(TrancheSizeNanos)))))) 163 164 //{ 165 //x, _ := Div(NewFloat().SetUint64(startNanos), NewFloat().SetUint64(TrancheSizeNanos)).Float64() 166 //assert.Equal(float64(29.525895384803288), x) 167 //} 168 //{ 169 //fmt.Println("RIGHT BEFORE FAILING TEST") 170 //x, _ := BigFloatPow(BigTwo, Div(NewFloat().SetUint64(startNanos), NewFloat().SetUint64(TrancheSizeNanos))).Float64() 171 //fmt.Println("RIGHT AFTER FAILING TEST") 172 //assert.Equal(float64(7.730011849578111e+08), x) 173 //} 174 //{ 175 //x, _ := Mul(nanosComponent, Mul(bitcoinComponent, NaturalLogOfTwo)).Float64() 176 //assert.Equal(float64(3.8199363554818304), x) 177 //} 178 //{ 179 //x, _ := Add(Mul(nanosComponent, Mul(bitcoinComponent, NaturalLogOfTwo)), 180 //BigFloatPow(BigTwo, Div(NewFloat().SetUint64(startNanos), NewFloat().SetUint64(TrancheSizeNanos)))).Float64() 181 //assert.Equal(float64(7.730011887777475e+08), x) 182 //} 183 //{ 184 //x, _ := BigFloatLog2( 185 //Add(Mul(nanosComponent, Mul(bitcoinComponent, NaturalLogOfTwo)), 186 //BigFloatPow(BigTwo, Div(NewFloat().SetUint64(startNanos), NewFloat().SetUint64(TrancheSizeNanos))))).Float64() 187 //assert.Equal(float64(29.52589539193265), x) 188 //} 189 //{ 190 //x, _ := Mul(NewFloat().SetUint64(TrancheSizeNanos), BigFloatLog2( 191 //Add(Mul(nanosComponent, Mul(bitcoinComponent, NaturalLogOfTwo)), 192 //BigFloatPow(BigTwo, Div(NewFloat().SetUint64(startNanos), NewFloat().SetUint64(TrancheSizeNanos)))))).Float64() 193 //assert.Equal(float64(2.9525895391932652e+16), x) 194 //} 195 196 //{ 197 //x, _ := bigFloatFinalDeSoNanos.Float64() 198 //assert.Equal(float64(2.9525895391932652e+16), x) 199 //} 200 //require.Equal(int64(7129365), int64(nanosToCreate)) 201 //} 202 203 { 204 for ii := 0; ii < len(randomStartNanos); ii++ { 205 nanosToCreate := CalcNanosToCreate( 206 randomStartNanos[ii] /*startNanos*/, randomSatoshisToBurn[ii] /*satoshisToBurn*/, randomUsdCentsPerBitcoinExchangeRate[ii] /*usdCentsPerBitcoin*/) 207 208 //if nanosToCreate == 7129365 { 209 //fmt.Println("DELETEME: xxx") 210 //fmt.Println(randomStartNanos[ii] [>startNanos*/, randomSatoshisToBurn[ii] /*satoshisToBurn*/, randomUsdCentsPerBitcoinExchangeRate[ii] /*usdCentsPerBitcoin<]) 211 //} 212 213 calcDiff := int64(expectedRandomNanosToCreate[ii]) - int64(nanosToCreate) 214 assert.Equalf(int64(expectedRandomNanosToCreate[ii]), int64(nanosToCreate), "Off by: %v", calcDiff) 215 require.Less(math.Abs(float64(calcDiff)), float64(16), "Error too large") 216 } 217 218 // Run this to regenerate the supplydata_test.go data. Make sure you delete the 219 // data in that file first, though. 220 // 221 //for startNanosIter := uint64(0); startNanosIter < 30000000*1e9; startNanosIter += 500000 * 1e9 { 222 //for satoshisToBurnIter := uint64(10); satoshisToBurnIter < 100*1e8; satoshisToBurnIter += 1e8 { 223 //for usdCentsPerBitcoinExchangeRateIter := uint64(100); usdCentsPerBitcoinExchangeRateIter < 100000*100; usdCentsPerBitcoinExchangeRateIter += 2500 * 100 { 224 //startNanos := startNanosIter + uint64(float64(500000*1e9*rand.Float64())) 225 //satoshisToBurn := satoshisToBurnIter + uint64(float64(1e8*rand.Float64())) 226 //usdCentsPerBitcoinExchangeRate := usdCentsPerBitcoinExchangeRateIter + uint64(float64(1000*100*rand.Float64())) 227 228 //// Zero satoshi means zero nanos 229 //nanosToCreate := CalcNanosToCreate( 230 //startNanos [>startNanos*/, satoshisToBurn /*satoshisToBurn*/, usdCentsPerBitcoinExchangeRate /*usdCentsPerBitcoin<]) 231 232 //randomStartNanos = append(randomStartNanos, startNanos) 233 //randomSatoshisToBurn = append(randomSatoshisToBurn, satoshisToBurn) 234 //randomUsdCentsPerBitcoinExchangeRate = append(randomUsdCentsPerBitcoinExchangeRate, usdCentsPerBitcoinExchangeRate) 235 //expectedRandomNanosToCreate = append(expectedRandomNanosToCreate, nanosToCreate) 236 //} 237 //} 238 //} 239 } 240 241 // Run this to regenerate the supplydata_test.go data. Make sure you delete the 242 // data in that file first, though. 243 // 244 //fmt.Println("StartNanos") 245 //for ii := 0; ii < len(randomStartNanos); ii++ { 246 //fmt.Printf("%v, ", randomStartNanos[ii]) 247 //} 248 //fmt.Println("\nSatoshisToBurn") 249 //for ii := 0; ii < len(randomStartNanos); ii++ { 250 //fmt.Printf("%v, ", randomSatoshisToBurn[ii]) 251 //} 252 //fmt.Println("\nusdCentsPerBitcoinExchangeRate") 253 //for ii := 0; ii < len(randomStartNanos); ii++ { 254 //fmt.Printf("%v, ", randomUsdCentsPerBitcoinExchangeRate[ii]) 255 //} 256 //fmt.Println("\nnanosToCreate") 257 //for ii := 0; ii < len(randomStartNanos); ii++ { 258 //fmt.Printf("%v, ", expectedRandomNanosToCreate[ii]) 259 //} 260 261 { 262 // Zero satoshi means zero nanos 263 nanosToCreate := CalcNanosToCreate( 264 945603607309490 /*startNanos*/, 650000000 /*satoshisToBurn*/, 1550000 /*usdCentsPerBitcoin*/) 265 assert.Equal(int64(101026173281102), int64(nanosToCreate)) 266 } 267 { 268 // Zero satoshi means zero nanos 269 nanosToCreate := CalcNanosToCreate( 270 1046606985637137 /*startNanos*/, 1287001287 /*satoshisToBurn*/, 1554000 /*usdCentsPerBitcoin*/) 271 assert.Equal(int64(181730399315476), int64(nanosToCreate)) 272 } 273 { 274 // Zero satoshi means zero nanos 275 nanosToCreate := CalcNanosToCreate(0, 0, InitialUSDCentsPerBitcoinExchangeRate) 276 assert.Equal(uint64(0), nanosToCreate) 277 } 278 { 279 // This amount of satoshis should print zero nanos at this price. 280 nanosToCreate := CalcNanosToCreate(10, 0, InitialUSDCentsPerBitcoinExchangeRate) 281 assert.Equal(uint64(0), nanosToCreate) 282 } 283 { 284 // Zero satoshi means zero nanos: second tranche 285 nanosToCreate := CalcNanosToCreate(1000001*NanosPerUnit, 0, InitialUSDCentsPerBitcoinExchangeRate) 286 assert.Equal(uint64(0), nanosToCreate) 287 } 288 { 289 // Zero satoshis should print zero nanos, even when the supply is very large. 290 nanosToCreate := CalcNanosToCreate(18000001*NanosPerUnit, 0, InitialUSDCentsPerBitcoinExchangeRate) 291 assert.Equal(uint64(0), nanosToCreate) 292 } 293 { 294 // Zero satoshis should print zero nanos, even when the supply is very large. 295 nanosToCreate := CalcNanosToCreate(25000001*NanosPerUnit, 0, InitialUSDCentsPerBitcoinExchangeRate) 296 assert.Equal(uint64(0), nanosToCreate) 297 } 298 { 299 // One satoshi should print zero nanos when the supply is large. 300 nanosToCreate := CalcNanosToCreate(18000001*NanosPerUnit, 1, InitialUSDCentsPerBitcoinExchangeRate) 301 assert.Equal(uint64(0), nanosToCreate) 302 } 303 { 304 nanosToCreate := CalcNanosToCreate(10000001*NanosPerUnit, 1, InitialUSDCentsPerBitcoinExchangeRate) 305 assert.Equal(int64(262), int64(nanosToCreate)) 306 } 307 { 308 // <131 satoshis should not hurdle the threshold. 309 nanosToCreate := CalcNanosToCreate(20000001*NanosPerUnit, 125, InitialUSDCentsPerBitcoinExchangeRate) 310 assert.Equal(int64(0), int64(nanosToCreate)) 311 } 312 { 313 // >131 satoshis should hurdle the threshold and print some. 314 nanosToCreate := CalcNanosToCreate(18000001*NanosPerUnit, 135, InitialUSDCentsPerBitcoinExchangeRate) 315 assert.Equal(int64(140), int64(nanosToCreate)) 316 } 317 { 318 // One satoshi should print zero nanos when the supply is large. 319 nanosToCreate := CalcNanosToCreate(25000001*NanosPerUnit, 1, InitialUSDCentsPerBitcoinExchangeRate) 320 assert.Equal(uint64(0), nanosToCreate) 321 } 322 { 323 // One satoshi should print X minus the discount initially. 324 nanosToCreate := CalcNanosToCreate(0*NanosPerUnit, 1, InitialUSDCentsPerBitcoinExchangeRate) 325 assert.Equal(int64(270051), int64(nanosToCreate)) 326 } 327 { 328 // One satoshi should print X minus the discount initially. 329 nanosToCreate := CalcNanosToCreate(10*NanosPerUnit, 10, InitialUSDCentsPerBitcoinExchangeRate) 330 assert.Equal(int64(2700494), int64(nanosToCreate)) 331 } 332 { 333 // Print 1 BTC at the beginning. Should be about 10k DeSo, but less 334 // than that because the price is increasing slightly as they buy it. 335 nanosToCreate := CalcNanosToCreate(0*NanosPerUnit, satoshisPerBitcoin+1, InitialUSDCentsPerBitcoinExchangeRate) 336 assert.Equal(int64(26755493480681), int64(nanosToCreate)) 337 } 338 { 339 // The first purchase should work even if it's large. 340 nanosToCreate := CalcNanosToCreate(0*NanosPerUnit, 200*satoshisPerBitcoin+1, InitialUSDCentsPerBitcoinExchangeRate) 341 assert.Equal(int64(2246014623084247), int64(nanosToCreate)) 342 } 343 { 344 // Making a purchase part-way through the first tranche should work. Should 345 // cost <10k but not too much less than that. 346 nanosToCreate := CalcNanosToCreate(200001*NanosPerUnit, satoshisPerBitcoin+1, InitialUSDCentsPerBitcoinExchangeRate) 347 assert.Equal(int64(23319824667603), int64(nanosToCreate)) 348 } 349 { 350 // Make a large purchase partway through the first tranche. 351 nanosToCreate := CalcNanosToCreate(200001*NanosPerUnit, 200*satoshisPerBitcoin+1, InitialUSDCentsPerBitcoinExchangeRate) 352 assert.Equal(int64(2090542905078737), int64(nanosToCreate)) 353 } 354 { 355 // A purchase part-way through a middle tranche should work. 356 nanosToCreate := CalcNanosToCreate(6123456123456789, 5712345678, InitialUSDCentsPerBitcoinExchangeRate) 357 assert.Equal(int64(21958743502996), int64(nanosToCreate)) 358 } 359 360 { 361 startVal := uint64(6123456123456789) 362 nanosToCreate := CalcNanosToCreate(startVal, 560988080987, InitialUSDCentsPerBitcoinExchangeRate) 363 // Be careful: Your calculator will lose precision when you try to calculate this 364 // to check it if you let it do floating point at any step. 365 assert.Equal(int64(7448955216307525), int64(nanosToCreate)+int64(startVal)) 366 } 367 368 { 369 // Try a weird situation where there is less than one satoshi left worth of nanos 370 // at the end of a tranche and the purchaser tries to buy zero satoshis. This should 371 // result in zero nanos being created. 372 startVal := uint64(7000000000000000 - 99) 373 nanosToCreate := CalcNanosToCreate(startVal, 0, InitialUSDCentsPerBitcoinExchangeRate) 374 assert.Equal(int64(0), int64(nanosToCreate)) 375 } 376 { 377 // Try a weird situation where there is less than one satoshi left worth of nanos 378 // at the end of a tranche and the purchaser tries to buy one satoshi worth of nanos. 379 startVal := uint64(7000000000000000 - 99) 380 nanosToCreate := CalcNanosToCreate(startVal, 1, InitialUSDCentsPerBitcoinExchangeRate) 381 assert.Equal(int64(2111), int64(nanosToCreate)) 382 } 383 { 384 startVal := uint64(16000000123456789) 385 satoshisToCleanOutTranche := uint64(655359919091358) 386 nanosToCreate := CalcNanosToCreate(startVal, satoshisToCleanOutTranche, InitialUSDCentsPerBitcoinExchangeRate) 387 assert.Equal(int64(17521981851378602), int64(startVal+nanosToCreate)) 388 } 389 { 390 // Try a situation where a user starts in the last tranche right at the end 391 // and zero satoshis are burned. 392 startVal := uint64(16999999999999998) 393 // satoshisPerUnit := uint64(655360000) 394 // (17000000*NanosPerUnit - startVal) * satoshisPerUnit / NanosPerUnit 395 nanosToCreate := CalcNanosToCreate(startVal, 0, InitialUSDCentsPerBitcoinExchangeRate) 396 assert.Equal(int64(0), int64(nanosToCreate)) 397 } 398 { 399 // Try a situation where a user starts in the last tranche right at the end 400 // and 1 satoshi is burned. This should result in zero since it doesn't hurdle 401 // the floating point threshold. 402 startVal := uint64(16999999999999998) 403 nanosToCreate := CalcNanosToCreate(startVal, 1, InitialUSDCentsPerBitcoinExchangeRate) 404 assert.Equal(int64(0), int64(nanosToCreate)) 405 } 406 { 407 // Try a situation where a user starts in the last tranche right at the end 408 // and 2 satoshi is burned. Should still be zero. 409 startVal := uint64(16999999999999998) 410 // satoshisPerUnit := uint64(655360000) 411 // (17000000*NanosPerUnit - startVal) * satoshisPerUnit / NanosPerUnit 412 nanosToCreate := CalcNanosToCreate(startVal, 2, InitialUSDCentsPerBitcoinExchangeRate) 413 assert.Equal(int64(0), int64(nanosToCreate)) 414 } 415 { 416 // Try a situation where a user starts in the last tranche right at the end 417 // and 3 satoshi is burned. In this case we should not cross the threshold. 418 startVal := uint64(16999999999999998) 419 nanosToCreate := CalcNanosToCreate(startVal, 3, InitialUSDCentsPerBitcoinExchangeRate) 420 assert.Equal(int64(0), int64(nanosToCreate)) 421 } 422 { 423 // Try a situation where a user starts in the last tranche and buys just *beyond* 424 // the end (i.e. fully completes the last tranche). 425 startVal := uint64(16000000123456789) 426 // satoshisPerUnit := uint64(655360000) 427 // (17000000*NanosPerUnit - startVal) * satoshisPerUnit / NanosPerUnit 428 satoshisToCleanOutTranche := uint64(655359919091359) 429 nanosToCreate := CalcNanosToCreate(startVal, satoshisToCleanOutTranche, InitialUSDCentsPerBitcoinExchangeRate) 430 assert.Equal(int64(17521981851378602), int64(startVal+nanosToCreate)) 431 } 432 { 433 // Try a situation where a user starts in the last tranche and buys way *beyond* 434 // the end (i.e. fully completes the last tranche). 435 startVal := uint64(16000000123456789) 436 // satoshisPerUnit := uint64(655360000) 437 // (17000000*NanosPerUnit - startVal) * satoshisPerUnit / NanosPerUnit 438 satoshisToCleanOutTranche := uint64(665359919091359) 439 nanosToCreate := CalcNanosToCreate(startVal, satoshisToCleanOutTranche, InitialUSDCentsPerBitcoinExchangeRate) 440 assert.Equal(int64(17536259392211874), int64(startVal+nanosToCreate)) 441 } 442 { 443 // Try a situation where a user starts at the end and buys zero. Should result 444 // in no nanos being created. 445 startVal := uint64(17000000000000000) 446 nanosToCreate := CalcNanosToCreate(startVal, 0, InitialUSDCentsPerBitcoinExchangeRate) 447 assert.Equal(int64(0), int64(nanosToCreate)) 448 } 449 { 450 // Try a situation where a user starts at the end and burns one satoshi. Should result 451 // in no nanos being created. 452 startVal := uint64(17000000000000000) 453 nanosToCreate := CalcNanosToCreate(startVal, 1, InitialUSDCentsPerBitcoinExchangeRate) 454 assert.Equal(int64(0), int64(nanosToCreate)) 455 } 456 { 457 // Try a situation where a user starts beyond the end and burns one satoshi. 458 // Should never happen but should result in no nanos being created nevertheless. 459 startVal := uint64(17000000000000001) 460 nanosToCreate := CalcNanosToCreate(startVal, 1, InitialUSDCentsPerBitcoinExchangeRate) 461 assert.Equal(int64(0), int64(nanosToCreate)) 462 } 463 { 464 // Spending a million Bitcoin at the max should be near-zero 465 startVal := uint64(MaxNanos) 466 nanosToCreate := CalcNanosToCreate(startVal, 1000000*100000000, InitialUSDCentsPerBitcoinExchangeRate) 467 assert.Greater(int64(100*NanosPerUnit), int64(nanosToCreate)) 468 } 469 } 470 471 func TestBigFloat(t *testing.T) { 472 //assert := assert.New(t) 473 require := require.New(t) 474 475 require.Equal(NewFloat().SetFloat64(0.33403410169116804), BigFloatPow(NewFloat().SetFloat64(0.6938468198960861), NewFloat().SetUint64(uint64(3)))) 476 } 477 478 func TestSumBalances(t *testing.T) { 479 assert := assert.New(t) 480 require := require.New(t) 481 _, _ = assert, require 482 483 // Balances should sum to the amount purchased. 484 params := &DeSoMainnetParams 485 amounts := uint64(0) 486 balancesByPublicKey := make(map[string]int64) 487 for _, seedBal := range params.SeedBalances { 488 amounts += seedBal.AmountNanos 489 pkStr := PkToStringMainnet(seedBal.PublicKey) 490 if amountFound, exists := balancesByPublicKey[pkStr]; exists { 491 require.Fail(fmt.Sprintf("Public key %v found twice in map: %v %v", 492 pkStr, int64(seedBal.AmountNanos), int64(amountFound))) 493 } 494 balancesByPublicKey[pkStr] = int64(seedBal.AmountNanos) 495 } 496 require.Equal(int64(params.DeSoNanosPurchasedAtGenesis)+int64(2e6*NanosPerUnit), int64(amounts)) 497 498 // Spot-check a few balances 499 _checkBalance := func(pkStr string, expectedVal int64) { 500 val, exists := balancesByPublicKey[pkStr] 501 assert.Truef(exists, "Public key %v must exist in genesis block", pkStr) 502 assert.Equal(expectedVal, int64(val)) 503 } 504 505 _checkBalance("BC1YLjAkTwNw5AKy1TCHT8qjZjmdEojvtNpB7wgFdguZ78scMu3KeBo", 285857902913000) 506 _checkBalance("BC1YLhX3HZsZKYyJiv8aaoAdR5mgtf87RUiC2PyFDUFaRT7cMhtNiep", 8333340003200) 507 _checkBalance("BC1YLfqL4neTSBPiiURxTyajt1y1jhkqG4qUHqEuYDtZwDD2mPo3ff6", 2888778956800) 508 _checkBalance("BC1YLjTYqQV5CfH3ckQZAdwdbkEu1uSWJg1FNBu6CmL3DQZJwLceHXH", 267648349450008) 509 _checkBalance("BC1YLiYxGdXeuPc3QMzgBv26EwfxrpwemdGxGZAZbh5qXgf7DennfhL", 379387259042300) 510 _checkBalance("BC1YLgnKq3aJ9SL7zmiMexjRRqvenLeHQoVNRKnbCiNM4QxPgn9QU1q", 91625252862600) 511 _checkBalance("BC1YLitnSuYscJ2GyHt9g3SfQKWz5ht1Ee5LUxBNk22Jo8Cde7Wupy7", 91625252862600) 512 _checkBalance("BC1YLhgrsxAejRUyhYmZRexhXq3nNbBgWH45TC56rxErHCjrKEhseYq", 166000000000000) 513 _checkBalance("BC1YLgGUvSCBToN9gbThF3cETR4B2dhcaFBTyUy64NCmY4Y483WfHUX", 30000000000000) 514 _checkBalance("BC1YLg26dcBA1HjTkDwXPH4oog7bVGbsQKj4G6rmHkZ6o7ApUzW4S8j", 62500000000000) 515 }