Tried posting this on reddit, but it seems that new accounts can't do that.
Status of tx flooding attack + partial solution
I've been looking at the tx flooding attack of ETN for some time and today I've decided to do something to help the coin. I'll give some suggestions below, but I would like to start with some facts. All the facts come from the current state of affairs and from looking at the electroneum source code.
* blockexplorer.electroneum.com is mostly misrepresenting the size of the transaction pool. Right now it says "no of txs: 2252" and electroneum daemon on on of my servers (restarted few hours ago, otherwise numbers would be higher) shows:
7407 tx(es), 62708270 bytes total (min 473, max 18335, avg 8466)
fees 646.32 (avg 0.08 per tx, 0.00 per byte)
0 not relayed, 0 failing, 7259 older than 10 minutes (oldest 4 hours ago), estimated 3136 block (3136 minutes) backlog
Age Txes Bytes
00:00:00 370 2700389
00:30:21 601 4867303
01:00:43 977 7682079
01:31:05 899 6599388
02:01:27 940 8608865
02:31:49 804 7092333
03:02:11 788 7017459
03:32:33 686 6090759
04:02:55 894 7972295
04:44:53 448 4077400
* The current formula for block reward (what miner gets for mining a block) is: there is this thing called "block size", which is important for miner reward and is somewhat proportional to the numer of transactions in the block. Median of the last 100 block sizes is calculated (imagine sorting the sizes and taking average of 50th and 51th value). Also there is some value called "base_reward", that is based on amount of already mined coins and is very slowly decreasing with each block. The maximum a miner can get from mining a block is base_reward+some transaction feed. However the miner can algo get (significantly) less than base_reward. As long as miner keeps the mined block strictly under or equal of median block size, the miner collects base_reward+fees of the transactions he manages to squeeze in the block. The miner is allowed to create a block with size between basically zero (0.2 kb in reality for "empty" block) and twice the median size. However if the produced block size is over median size, he gets less than base_reward. The exact formula for what miner gets for miner reward when it produces block that is larger than median is base_reward*(median_size*2-block_size)*block_size/median_size/median_size+fees. It is optimal to produce a block equal to median size. If you go over median, for 5% over your reward will be 99.75% of base_reward, for 10% over median you get 99%, for 12.5% over median the payout is 98.44%, for 15% over is 97.75%, for 20% over 96%, for 25% over - 93.75%, for 30% over - 91%, for 40% over - 84%, for 50% over - 75%, for 60% over - 64%. The picture is clear, you get exponentially lower payment for going over median. If you manage to go exactly twice - your reward will be zero. In case somebody is not convinced I've mined a block with as close to the twice the median as I could - look at block number 237226 in the block explorer and as you can see I've got 363.59 in miner rewards (normally around 6400 for block nowadays).
* Current algorithm for creating a block is the following: keep adding the most profitable transactions to the block until the block is over median size. That mean that in presence of transactions in the pool, the block size will be over the median size on average by half of a transaction size. With the current fee structure this means that almost always a miner with unmodified daemon gets less reward than base_reward and lower than maximum possible reward. So there is a incentive for generating empty blocks. A miner can get slightly more by including some transactions without going over the median block size.
* With the cryptonote protocol your if your wallet does not really "own" the amount you have in the balance. Your wallet has "unspent_outputs" (displayed by unspent_outputs command in cli wallet) that is equivalent sum of decimal digits in incoming transactions. That is if you receive 754.43 ETN you wallet receive one "output" of 700, one 50, one 4, one 0.4 and one 0.03. If you receive two transactions of 56.54 and 34.44 you wallet will have the following outputs: 50, 30, 6, 4, 0.5, 0.5, 0.04, 0.04.
* When are sending a transaction, you are listing the "outputs" you are willing to spend. The more outputs you list, the bigger is the transaction. That is if you are sending 1000 ETN from your wallet and you've been receiving transactions of say 30-50 ETN from your minnig pool - your transactions will be a big one. Sometimes it will be too big and the wallet will suggest that what you want to send will be split in multiple transaction. One tricky point - what I'm calling "unspent outputs" once in a transaction become "inputs" of the transaction.
* It generally costs the same to send an unspent output of 10 ETN and 100000 ETN.
* Transactions have two properties that are relevant to inclusion in a block: size in kilobytes and fee per kilobyte. You can't really control the size - it is proportional to the number of unspent outputs/inputs you are sending. However you can set the price you are willing to pay per kilobyte (0.01, 0.04 and 1.66 ETN/kb are levels in the default wallet, if I'm not mistaken). It is also worth mentioning that for purposes of fee calculations sizes are rounded up to a full kilobyte size. That is the fee for sending a 0.3kb and 0.9kb transaction is the same, but 0.3kb transaction will use less space in the block, so a miner will generally prefer it.
All of the above are mathematical/algorithmic facts. Now I'll cite some facts from the current state of blockchain. I prefer to call those "observations", so they are in a different section.
* There are significant number of "empty" blocks in the blockchain, that is ones without any transactions. It is my belief that even when those blocks were "blocktemplates" that miners mined on, there were many transactions to be included in the block. Examples: blocks 237477 and 237479.
* Normally if all participants in the network would mine with unmodified, normal daemon, in a presence of many transactions in the pool, the median size block will and therefore number of transactions in a block will slowly grow - every block will have size sligtly over the median of last 100 blocks, so the median will slowly grow. In the presence of numerous "empty" blocks that is not happening.
* Up until today the attacker would employ techniques to create the largest possible transactions. Today the attacker(s) realized that it is far more beneficial to create transactions around 0.5kb in size. Those will still pay 0.01 ETN to be included in block, but are twice more profitable than 1kb transactions for the miners. Therefore unmodified miners would prefer those "attack" transactions over any other larger ones (except if the sender sets higher fee).
OK, what can be done? Well, we can modify our daemons not to prioritize small transactions. Generally an attacker can't really flood the network with large transactions, since it will lock too much funds (think of 5000 transactions of 10000 ETN). I've modified the daemon code in such a way and I've been mining for hours with some of my gear and mostly with nicehash. Here are few of the last blocks I've mined: 237537, 237530, 237527, 237520, 237516, 237507.
As you can see, mostly large transactions in the block and not spammy ones. Also as of now, empty block get rewards of 6401.92, my block are rewarded like 6340-6360 - like 1% lower, but those blocks are trying to actually increase the median size without sacrificing more than 1.2% of the income.
My modification prefers larger transactions (however it threats all transactions over 5000 ETN as equal in size) and give lower priority to transactions with very high ring sizes (which translate in size in kilobytes). However I can't do it by myself. If at least some pools would use my modifications, I believe we can achieve a goal of "transactions over 100 ETN are fast", which would be a start.
I'm not arguing that this is a long-term solution, so I'm not submitting a pull request to the official electroneum github repo. Instead, I'm providing a link to a patch:
https://my.pcloud.com/publink/show?code=XZ4kgQ7ZyARUX262JupgngVRLDuG1RiAqEV7You can apply it to your source by going to the "electroneum" directory and executing "patch -p1 < ../electro-txfee.patch", where "../electro-txfee.patch" is the path to the downloaded file. As everybody can see, the changes are minimal and concern only one function in one file. The current logic allows the blocks size to go up to 12.5% over the median for 98.44% of the maximum payout. In practice it will almost always achieve over 99% of the maximum payout.
There are many options for long term solutions, but if I would be in the shoes of electroneum team right now, I would modify my daemon to mine blocks as close as twice the median as possible and I would mine with all the hashing power there is for sale (at a reasonable price) as possible. Most of the long term solutions are already implemented in the code, given that it's borrowed from Monero. Electroneum just have to bump the version. However, for the time being and for the prices being, a working solution would have to increase transaction prices significantly.
Best,
Very concerned citizen