def test_A(self): """Test gen convergence.""" simpools = SimPoolsNP(MAXBLOCKSIZES, MINFEERATES, blockrate=BLOCKRATE) size_accum = defaultdict(int) interval_accum = 0 for idx, (simblock, blockinterval) in enumerate(simpools.blockgen()): if idx > 100000: break size_accum[simblock.pool.minfeerate] += simblock.pool.maxblocksize interval_accum += blockinterval interval_samplemean = interval_accum / idx logdiff = abs(log(1 / BLOCKRATE) - log(interval_samplemean)) self.assertLess(logdiff, 0.01) feerates, caps = zip( *sorted([(feerate, totalsize / interval_accum) for feerate, totalsize in size_accum.items()])) cumcaps = list(cumsum_gen(caps)) cap_fn = simpools.get_capacityfn() hashrate_fn = simpools.get_hashratefn() print(cap_fn) print(hashrate_fn) for feerate, cap in zip(feerates, cumcaps): print(feerate, cap) ref = cap_fn(feerate) logdiff = abs(log(ref) - log(cap)) self.assertLess(logdiff, 0.01)
def setUp(self): seed(1) self.tx_source = SimTxSource(ref_txsample, ref_txrate) self.feerates = [0, 2000, 10999, 20000] byterates_binned = [ 0, 500*ref_txrate/3., 640*ref_txrate/3., 250*ref_txrate/3.] self.ref_byterates = list(cumsum_gen(reversed(byterates_binned))) self.ref_byterates.reverse()
def get_hashratefn(self): self.check() feerates_all = filter(lambda f: f < float("inf"), self.minfeerates) feerates_count = Counter(feerates_all) feerates, counts = map(list, zip(*sorted(feerates_count.items()))) caps = list(cumsum_gen(counts)) feerates.insert(0, feerates[0]-1) caps.insert(0, 0) return StepFunction(feerates, caps)
def blockgen(self): self.check() poolitems = sorted(self.pools.items(), key=lambda item: item[1].hashrate) cumhashrates = list( cumsum_gen([pool.hashrate for name, pool in poolitems])) totalhashrate = cumhashrates[-1] prop_table = map(lambda hashrate: hashrate/totalhashrate, cumhashrates) while True: poolidx = bisect_left(prop_table, random()) simblock = SimBlock(*poolitems[poolidx]) blockinterval = expovariate(self.blockrate) yield simblock, blockinterval
def get_sizefn(self): entries = sorted(self.entries.values(), key=attrgetter("feerate"), reverse=True) sizebyfee = [ (feerate, sum([entry.size for entry in feegroup])) for feerate, feegroup in groupby(entries, attrgetter("feerate"))] if not sizebyfee: return StepFunction([0, 1], [0, 0]) feerates_rev, sizes = zip(*sizebyfee) cumsize_rev = list(cumsum_gen(sizes)) feerates = list(reversed(feerates_rev)) cumsize = list(reversed(cumsize_rev)) sizefn = StepFunction(feerates, cumsize) sizefn.addpoint(feerates[-1]+1, 0) return sizefn
def get_sizefn(self): entries = sorted(self.entries.values(), key=attrgetter("feerate"), reverse=True) sizebyfee = [ (feerate, sum([entry.size for entry in feegroup])) for feerate, feegroup in groupby(entries, attrgetter("feerate")) ] if not sizebyfee: return StepFunction([0, 1], [0, 0]) feerates_rev, sizes = zip(*sizebyfee) cumsize_rev = list(cumsum_gen(sizes)) feerates = list(reversed(feerates_rev)) cumsize = list(reversed(cumsize_rev)) sizefn = StepFunction(feerates, cumsize) sizefn.addpoint(feerates[-1] + 1, 0) return sizefn
def get_hashratefn(self): """Get cumulative hashrate as function of minfeerate.""" self.check() def hashrate_groupsum(grouptuple): return sum(map(attrgetter("hashrate"), grouptuple[1])) pools = filter( lambda pool: pool.minfeerate < float("inf"), sorted(self.pools.values(), key=attrgetter("minfeerate"))) feerates = sorted(set(map(attrgetter("minfeerate"), pools))) hashrates = list(cumsum_gen( groupby(pools, attrgetter("minfeerate")), mapfn=hashrate_groupsum)) feerates.insert(0, feerates[0]-1) hashrates.insert(0, 0) return StepFunction(feerates, hashrates)
def checkcaps(sim): NUMITERS = 100000 bytecounter = defaultdict(int) stable_byterate = sim.cap.txbyteratefn(sim.stablefeerate) print("The stable feerate is {}.".format(sim.stablefeerate)) print("The stable/total byterate is {}/{}.".format( stable_byterate, sim.cap.txbyteratefn(0))) for idx, simblock in enumerate(sim.run()): bytecounter[simblock.pool.minfeerate] += simblock.size if not idx % 10000: print(idx) if idx == NUMITERS: break mempool_entries = sim.mempool.get_entries() mempool_size = sum(map(attrgetter("size"), mempool_entries.values())) print("final mempool len/size: {}/{}".format(len(mempool_entries), mempool_size)) for feerate in bytecounter: bytecounter[feerate] /= sim.simtime feerates, procrates = zip(*sorted(bytecounter.items())) cumprocrates = list(cumsum_gen(procrates)) try: loweststablemfr = sim.cap.procratesfn._x[0] except IndexError: loweststablemfr = float("inf") for feerate, cumprocrate in zip(feerates, cumprocrates): if feerate < loweststablemfr: continue lowercumprocrate = sum([ procrate for _feerate, procrate in sim.cap.procratesfn if _feerate > feerate ]) upper_byterate = stable_byterate - lowercumprocrate caprate = sim.cap.capfn(feerate) print("feerate/actual byterate/upperbound byterate/cap: {}/{}/{}/{}". format(feerate, cumprocrate, upper_byterate, caprate)) assert cumprocrate < upper_byterate * 1.01 assert upper_byterate < caprate * UTILIZATION_THRESH
def get_capacityfn(self): """Get cumulative capacity as function of minfeerate.""" self.check() totalhashrate = self.calc_totalhashrate() def byterate_groupsum(grouptuple): return sum( [pool.hashrate*pool.maxblocksize for pool in grouptuple[1]])*self.blockrate/totalhashrate pools = filter( lambda pool: pool.minfeerate < float("inf"), sorted(self.pools.values(), key=attrgetter("minfeerate"))) feerates = sorted(set(map(attrgetter("minfeerate"), pools))) caps = list(cumsum_gen( groupby(pools, attrgetter("minfeerate")), mapfn=byterate_groupsum)) feerates.insert(0, feerates[0]-1) caps.insert(0, 0) return StepFunction(feerates, caps)
def test_caps(self): simpools = SimPools(ref_pools) ref_feerates = (999, 1000, 10000, 20000) ref_caps = tuple(cumsum_gen( [0, 0.5*1000000/600, 0.3*750000/600, 0.2*500000/600])) feerates, caps = zip(*simpools.get_capacityfn()) self.assertEqual(feerates, ref_feerates) self.assertEqual(caps, ref_caps) ref_hashrates = (0, 0.5, 0.8, 1) feerates, hashrates = zip(*simpools.get_hashratefn()) self.assertEqual(feerates, ref_feerates) self.assertEqual(hashrates, ref_hashrates) # Duplicate minfeerate newref_pools = deepcopy(ref_pools) newref_pools.update({'pool3': SimPool(0.1, 600000, 1000)}) newref_pools['pool1'].hashrate = 0.2 simpools = SimPools(newref_pools) feerates, caps = zip(*simpools.get_capacityfn()) ref_feerates = (999, 1000, 10000, 20000) ref_caps = tuple(cumsum_gen( [0, 0.5*1000000/600 + 0.1*600000/600, 0.2*750000/600, 0.2*500000/600])) self.assertEqual(feerates, ref_feerates) self.assertEqual(caps, ref_caps) ref_hashrates = (0, 0.6, 0.8, 1) feerates, hashrates = zip(*simpools.get_hashratefn()) self.assertEqual(feerates, ref_feerates) self.assertEqual(hashrates, ref_hashrates) # Inf minfeerate newref_pools = deepcopy(ref_pools) newref_pools['pool0'].minfeerate = float("inf") simpools = SimPools(newref_pools) feerates, caps = zip(*simpools.get_capacityfn()) ref_feerates = (999, 1000, 10000) ref_caps = tuple(cumsum_gen( [0, 0.5*1000000/600, 0.3*750000/600])) self.assertEqual(feerates, ref_feerates) self.assertEqual(caps, ref_caps) ref_hashrates = (0, 0.5, 0.8) feerates, hashrates = zip(*simpools.get_hashratefn()) self.assertEqual(feerates, ref_feerates) self.assertEqual(hashrates, ref_hashrates) # Only inf minfeerate newref_pools = deepcopy(ref_pools) for pool in newref_pools.values(): pool.minfeerate = float("inf") simpools = SimPools(newref_pools) with self.assertRaises(ValueError): feerates, caps = zip(*simpools.get_capacityfn()) with self.assertRaises(ValueError): feerates, caps = zip(*simpools.get_hashratefn()) # Empty pools simpools = SimPools({}) with self.assertRaises(ValueError): simpools.get_capacityfn() with self.assertRaises(ValueError): simpools.get_hashratefn()