{"action":"created","issue":{"url":"https://api.github.com/repos/ethereum/EIPs/issues/35","labels_url":"https://api.github.com/repos/ethereum/EIPs/issues/35/labels{/name}","comments_url":"https://api.github.com/repos/ethereum/EIPs/issues/35/comments","events_url":"https://api.github.com/repos/ethereum/EIPs/issues/35/events","html_url":"https://github.com/ethereum/EIPs/issues/35","id":118813928,"number":35,"title":"EIP 103 (Serenity): Blockchain rent","user":{"login":"vbuterin","id":2230894,"avatar_url":"https://avatars.githubusercontent.com/u/2230894?v=3","gravatar_id":"","url":"https://api.github.com/users/vbuterin","html_url":"https://github.com/vbuterin","followers_url":"https://api.github.com/users/vbuterin/followers","following_url":"https://api.github.com/users/vbuterin/following{/other_user}","gists_url":"https://api.github.com/users/vbuterin/gists{/gist_id}","starred_url":"https://api.github.com/users/vbuterin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vbuterin/subscriptions","organizations_url":"https://api.github.com/users/vbuterin/orgs","repos_url":"https://api.github.com/users/vbuterin/repos","events_url":"https://api.github.com/users/vbuterin/events{/privacy}","received_events_url":"https://api.github.com/users/vbuterin/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/ethereum/EIPs/labels/EIP","name":"EIP","color":"bfd4f2"}],"state":"open","locked":false,"assignee":{"login":"vbuterin","id":2230894,"avatar_url":"https://avatars.githubusercontent.com/u/2230894?v=3","gravatar_id":"","url":"https://api.github.com/users/vbuterin","html_url":"https://github.com/vbuterin","followers_url":"https://api.github.com/users/vbuterin/followers","following_url":"https://api.github.com/users/vbuterin/following{/other_user}","gists_url":"https://api.github.com/users/vbuterin/gists{/gist_id}","starred_url":"https://api.github.com/users/vbuterin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vbuterin/subscriptions","organizations_url":"https://api.github.com/users/vbuterin/orgs","repos_url":"https://api.github.com/users/vbuterin/repos","events_url":"https://api.github.com/users/vbuterin/events{/privacy}","received_events_url":"https://api.github.com/users/vbuterin/received_events","type":"User","site_admin":false},"milestone":null,"comments":46,"created_at":"2015-11-25T11:11:21Z","updated_at":"2015-11-28T14:32:05Z","closed_at":null,"body":"### Motivation\r\n\r\nThe Ethereum platform gives users access to a number of computational resources: particularly computational steps, memory, logs / bloom filter usage and permanent storage in the Ethereum state. For most of these resources, the gas system is roughly incentive-compatible, although price-fixing the exchange rates between these resources is, in the current framework, unfortunately required. Storage, however, is unique in that it is not ephemeral; once storage is filled, it must be stored by all full nodes forever until/if it is deliberately cleared. The cost of storage is `bytes * time`, but users are only paying for `bytes`.\r\n\r\nA partial solution exists for Ethereum 1.0 in the form of the `SSTORE` clearing refund, where a user gets up to a net 10000 gas back for converting a filled storage slot into an empty slot. However, this approach is imperfect for two reasons:\r\n\r\n1. During a block where transaction inclusion demand does not reach the gas limit (or even where the opportunity-cost gasprice is cheaper than average), miners have the incentive to fill up storage slots so as to use them as a \"bank\" that expensive transactions can use to grant themselves additional gas at a time when gasprice is expensive; essentially, conducting inter-temporal gas arbitrage with the additional negative externality of requiring all full nodes to store extra data in the meantime.\r\n2. There is no incentive to use storage slots for a short period of time instead of a long period of time.\r\n\r\n### Proposal\r\n\r\nA proposal for solving this is to introduce \"blockchain rent\": rather than charging for bytes, actually charge for bytes * time. Here is a proposed protocol for doing so:\r\n\r\n* In the account RLP, keep track of the variables `last_accessed` and `total_storage_bytes`. `last_accessed` is meant to represent the block number at which storage was most recently changed, and `total_storage_bytes` is meant to represent the total number of bytes in account storage.\r\n* When you perform an `SSTORE(k, v)` operation on the account, let `fee = (TOTFEE[block.number] - TOTFEE[last_accessed]) * account.total_storage_bytes`, where `TOTFEE[n]` is the sum of the data storage fees from block 0 to block n (eg. `TOTFEE[n] = n * c` for some constant `c` would work as a basic policy but one can come up with more dynamic policies that change per block). Set `account.balance -= fee`, `account.last_accessed = block.number` and `account.total_storage_bytes += len(v) + (len(k) if v != '' else 0) - len(old value of account.storage[k]) - (len(k) if old value of account.storage[k] != '' else 0)`. If `account.balance < 0`, destroy the account.\r\n* Create a special type of `ping` transaction which performs a dummy `SSTORE(0, account.storage[0])` operation on any desired account. Miners can run this if they see an account that needs to be deleted in order to process fees and delete it if it is in fact bankrupt. If and only if a ping leads to an account bankruptcy, it requires no gas.\r\n\r\nFor example, suppose that `TOTFEE[n] = n * 10` (ie. 10 wei per block per second), a block was last accessed in block 321070, the current block is 312085, the account has a pre-existing balance of 1000, and it only has two keys in storage:  `{\"cow\": \"dog\", \"horse\": \"doge\"}`. We should have `account.last_accessed = 321070` and `account.total_storage_bytes = 3 + 3 + 5 + 4 = 15`. Now, suppose we have a transaction that sends 10000 wei and, in the process of executing code, sets `SSTORE(\"moose\", \"deer\")`. We compute:\r\n\r\n* Balance increased from `1000` to `11000`\r\n* `fee = (TOTFEE[312085] - TOTFEE[312070]) * 15 = (3120850 - 3120700) * 15 = 2250`\r\n* Balance decreased from `11000` to `8750` due to the fee\r\n* `account.total_storage_bytes += len(\"deer\") + len(\"moose\") - 0 - 0`, ie. increased by 9 for a new total of `15 + 9 = 24`. The values subtracted are both zero because there was nothing pre-existing in that key.\r\n* `account.last_accessed = 312085`\r\n\r\n### Setting `TOTFEE`\r\n\r\nThe hardest challenge in this scheme is setting the `TOTFEE` function. One could set this to a static value (ie. `TOTFEE[n] = c * n`), but this is essentially a form of price-fixing and so is arguably hard to set in a way that is economically efficient. A somewhat more effective strategy is to set a space limit (arguably, this is no less reasonable than setting a gas limit), and targeting `TOTFEE` based on that value. For example, consider a policy where we have some function for setting a space limit `L` (eg. a flat `L = 2**35` or a linearly growing `L = 2**10 * (block.timestamp - genesis.timestamp)`). Then, every block, we set `TOTFEE[n] = TOTFEE[n-1] + 2**(20 * L / (L - total_state_size))` (ie. the fee is 2**20 wei ~= 0.001 shannon initially, then when the total state size increases to 5% of the maximum it doubles, when it increases to 10% of the maximum it doubles again, and so forth, with the doubling intervals decreasing in size and ultimately converging to a singularity at L). In theory, the amount of storage usage should increase until it hits an equilibrium equal to the marginal demand for storage at a supply somewhere less than `L` (in the case of the above example, roughly `L / 2` is plausible); the main tradeoff to be made is in the steepness of the supply function. Steeper supply functions are more robust to mistakes made in the initial supply-function-setting process, but they also lead to more volatile rent charges.\r\n\r\n### Why should I _want_ to support a proposal that adds in a \"weird new tax\" when storage usage per second is free now?\r\n\r\n* The `SSTORE` gas costs may go down, _benefiting_ dapp developers that only use storage for short time durations\r\n* The disk space requirements for a full node will go down"},"comment":{"url":"https://api.github.com/repos/ethereum/EIPs/issues/comments/160305221","html_url":"https://github.com/ethereum/EIPs/issues/35#issuecomment-160305221","issue_url":"https://api.github.com/repos/ethereum/EIPs/issues/35","id":160305221,"user":{"login":"Smithgift","id":10504499,"avatar_url":"https://avatars.githubusercontent.com/u/10504499?v=3","gravatar_id":"","url":"https://api.github.com/users/Smithgift","html_url":"https://github.com/Smithgift","followers_url":"https://api.github.com/users/Smithgift/followers","following_url":"https://api.github.com/users/Smithgift/following{/other_user}","gists_url":"https://api.github.com/users/Smithgift/gists{/gist_id}","starred_url":"https://api.github.com/users/Smithgift/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Smithgift/subscriptions","organizations_url":"https://api.github.com/users/Smithgift/orgs","repos_url":"https://api.github.com/users/Smithgift/repos","events_url":"https://api.github.com/users/Smithgift/events{/privacy}","received_events_url":"https://api.github.com/users/Smithgift/received_events","type":"User","site_admin":false},"created_at":"2015-11-28T14:32:05Z","updated_at":"2015-11-28T14:32:05Z","body":"@niran: It's true that you can't force a miner to store anything. It's also impossible to force a miner to agree 2 ETH + 2 ETH = 4 ETH. The point of archiving being part of the consensus is that the protocol can punish miners who forgot contracts that everyone else has to remember.\r\n\r\nWhile a non-formal rent system like this is elegant, there are issues. Other miners have to verify a transaction. If another miner creates a block using a pruned contract, they have three options:\r\n\r\n1. Take it on faith that the miner of the new block executed the contract accurately. This creates a kind of moral hazard should enough miners do this. (See: the unintentional forks from SPV mining in bitcoin recently.) Should the block be incorrect, and at least 51% are trusting or on the attacker's side, light clients may now be deluded as to what really happened in the contract, which could quickly spread across the entire state.\r\n2. Ignore the block until it's sufficiently deep. This may lead to effective censorship of an older contract if 51% of the miners will not mine on a chain that has a dubious block, which means that the chain is never deep enough for the block to become undubious. Even miners that trust/verify/don't care may still ignore the block on the basis that they don't want to be on the losing chain.\r\n3.  Locate the archive of the contract and verify that it is a real block. This involves spending money and time for which the miner gets nothing in return, except, theoretically, being on the right chain if enough others do the same. A malicious miner could create wild goose chases for contracts that don't exist.\r\n\r\nThere's also the option of rejecting the block completely, in which case we have a fork.\r\n\r\nNote also that any miner may pick any one of these strategies, The effects of all three being done in varying amounts may lead to instability, if nothing else. True, a modified p2p protocol where the miner shoves the contract's state along with the block may help some of these issues. But how does the miner know whether the other miners have the contract or not? If it guesses wrong, it either wastes both their time or the block is rejected.\r\n\r\nNINJA EDIT: If the transaction is high value enough, a miner might reasonably assume that other miners dug up the same archive. There's troll potential in making an enormous contract, letting it be forgotten, then pinging with some ultra-expensive gas which turns out to be the equivalent `function() { throw; }` The miner may not appreciate the small amount of gas he got from it relative to the expense of getting it.\r\n\r\nActually, the true cost of revival is (pretending we live in a world with equal-powered miners) something like (number of miners * cost of acquiring the archive), because the effective reward is averaged between every miner. This is true of every revival system where the user does not provide the contract's state.\r\n\r\nNon-formal rent seems to have merit, but something about it makes me uneasy."}}