# Hueristic balance spec The idea behind this spec is to map out the design for Bundlr's new balance systems which looks to increase the TPS limit. Currently Bundlr is limited to ~300-500 txs per address per second. We suspect this can reach 10k TPS per address per second under certain loads. ## Design This section outlines the design of the current system and the planned new system based on heuristics. ### Upload process 1) Pipe body to file 2) Verify transaction 3) Check if the user has enough balance 4) Insert data into DB and return signed response 1, 2 and 4 don't change but 3 will be the big problem to solve. --- ### Solution to balance checks Bundlr will need to adopt a heuristic balance function which allows us to estimate whether they have enough balance with a high level of accuracy. We'll need to define a full agorithm which allows us to control the risk factor when using this system. #### New functions ##### estimate_has_balance A function which returns `true` or `false` based on whether we estimate the user has enough balance. Can be easily define as the below formula. Inputs: - address: `string` - currency: `string` Output: `boolean` ```estimate_has_balance(address, currency, fee) = fee < latest_rollup_balance(address, currency) + get_redis_cached_balance_difference(address, currency)``` Implementation: ``` balance_multiple = 1000 currency = <some-currency> address = <some-address> size = <numer-of-bytes> fee = <some-fee> if size >= 100MB return exact_has_balance(address, currency, fee) estimated_balance = estimated_balace(address, curency) if ((estimated_balance*balance_multiple) > fee) return true else return exact_has_balance(address, currency, fee) ``` ##### get_redis_cached_balance_difference The key component to this system is a cached balance value in Redis which stores the difference between the latest rollup value and now. This value will be updated every 10 seconds with the correct value in the database. Upon uploading successfully this value will be incremented (using `incrbyfloat`). The known limitation of `incrbyfloat` is that we can an only do up to `1e48`. Inputs: - address: `string` - currency: `string` Output: `number` ##### exact_has_balance Check if the user has the exact balance required to upload. We define "exact" as `>=fee`. This function will use a Postgres function internally. --- ### Balance check algorithm ``` currency = <some-currency> address = <some-address> size = <numer-of-bytes> fee = <some-fee> if size >= 100MB return exact_has_balance(address, currency, fee) else return estimate_has_balance(address, curency, size, fee) ``` --- ### Problems to solve #### Cached balance difference accuracy A key problem here is to make sure the cached Redis value is accurate. Measures to make the Redis value accurate: - Every 10 seconds, make all cached values accurate - Each successful upload will increment the Redis value - When consolidating the Redis value we'll get the difference in balance from Redis and include in the new value #### Bad performance There are going to be some edge cases where performance is affected: - When a user reaches 0 balance then we'll cache in Redis and upon new funds in the DB we'll delete the cached value #### Allow accurate balance checks The main problem is supporting apps which use balance lookups as a key component for things like automated funding and warning mechanisms. TODO: Efficient mechanism for exact balance lookups. Probably just use an index or something --- ## Side effects and risks: - Balances could become potentially far less accurate - Balance lookup route will be slower - This system is more complex are more likely to fail - More load on the DB read replica