Posts

BLURT is under heavy spam attack right now

avatar of @holger80
25
@holger80
·
·
0 views
·
4 min read

When viewing the stats on https://blocktivity.info/ its seems that BLURT has almost reached the same activity as HIVE:

The blockchain operation counts are correct this time, so I wrote a python script to count the different operation types.

import sys 
from datetime import datetime, timedelta 
from prettytable import PrettyTable 
import argparse 
from timeit import default_timer as timer 
import logging 
from beem.blockchain import Blockchain 
from beem.block import Block 
from beem import Hive, Blurt, Steem 
from beem.utils import parse_time 
from beem.nodelist import NodeList 
 
log = logging.getLogger(__name__) 
logging.basicConfig(level=logging.INFO) 
 
 
def parse_args(args=None): 
    d = 'Show op type stats for either hive, blurt or steem.' 
    parser = argparse.ArgumentParser(description=d) 
    parser.add_argument('blockchain', type=str, nargs='?', 
                        default=sys.stdin, 
                        help='Blockchain (hive, blurt or steem)') 
    return parser.parse_args(args) 
 
 
def main(args=None): 
     
    args = parse_args(args) 
    blockchain = args.blockchain 
     
    nodelist = NodeList() 
    nodelist.update_nodes(weights={"block": 1}) 
     
    if blockchain == "hive" or blockchain is None: 
        max_batch_size = 50 
        threading = False 
        thread_num = 16 
        block_debug = 1000 
         
        nodes = nodelist.get_hive_nodes() 
        blk_inst = Hive(node=nodes, num_retries=3, num_retries_call=3, timeout=30) 
    elif blockchain == "blurt": 
        max_batch_size = None 
        threading = False 
        thread_num = 8 
        block_debug = 20 
        nodes = ["https://rpc.blurt.buzz/", "https://api.blurt.blog", "https://rpc.blurtworld.com", "https://rpc.blurtworld.com"] 
        blk_inst = Blurt(node=nodes, num_retries=3, num_retries_call=3, timeout=30) 
    elif blockchain == "steem": 
        max_batch_size = 50 
        threading = False 
        thread_num = 16 
        block_debug = 1000 
        nodes = nodelist.get_steem_nodes() 
        blk_inst = Steem(node=nodes, num_retries=3, num_retries_call=3, timeout=30) 
    else: 
        raise Exception("Wrong parameter, can be hive, blurt or steem") 
    print(blk_inst) 
    block_count = 0 
    total_ops = 0 
    total_trx = 0 
    duration_s = 60 <em> 60 </em> 1 
    blocksperday = int(duration_s / 3) 
     
    blockchain = Blockchain(blockchain_instance=blk_inst, ) 
    current_block_num = blockchain.get_current_block_num() 
    last_block_id = current_block_num - blocksperday 
 
    last_block = Block(last_block_id, blockchain_instance=blk_inst) 
 
    stopTime = last_block.time() + timedelta(seconds=duration_s) 
 
    start = timer() 
    op_stats = {} 
    for entry in blockchain.blocks(start=last_block_id, max_batch_size=max_batch_size, threading=threading, thread_num=thread_num): 
        if "block" in entry: 
            block_time = parse_time(entry["block"]["timestamp"]) 
        else: 
            block_time = entry["timestamp"] 
        if block_time > stopTime: 
            break 
        block_count += 1 
        if "block" in entry: 
            trxs = entry["block"]["transactions"] 
        else: 
            trxs = entry["transactions"] 
        for tx in trxs: 
            total_trx += 1 
            for op in tx["operations"]: 
                if "_operation" in op["type"]: 
                    op_type = op["type"][:-10] 
                else: 
                    op_type = op["type"] 
                if op_type in op_stats: 
                    op_stats[op_type] += 1 
                else: 
                    op_stats[op_type] = 1 
                total_ops += 1 
 
        ops_per_day = total_ops / block_count * blocksperday 
        if block_count % (block_debug) == 0: 
            print("%d blocks remaining... estimated ops per day: %.1f" % (blocksperday - block_count, ops_per_day)) 
 
    duration = timer() - start     
    t = PrettyTable(["Type", "Count", "percentage"]) 
    t.align = "l" 
    op_list = [] 
    for o in op_stats: 
        op_list.append({"type": o, "n": op_stats[o], "perc": op_stats[o] / total_ops * 100}) 
    op_list_sorted = sorted(op_list, key=lambda x: x['n'], reverse=True) 
    for op in op_list_sorted: 
        t.add_row([op["type"], op["n"], "%.2f %%" % op["perc"]]) 
    print(t) 
if __name__ == '__main__': 
    sys.exit(main()) 

You need to install beem (pip3 install beem) and can then start the script (after stored it as blockstats.py):

python3 blockstats.py hive 
python3 blockstats.py blurt 

As the API speed of BLURT is limited, I limit the time period to the last hour. (It can be adapted at line 62).

Results

Hive

+-------------------------+-------+------------+ 
| Type                    | Count | percentage | 
+-------------------------+-------+------------+ 
| custom_json             | 22413 | 58.24 %    | 
| vote                    | 13786 | 35.82 %    | 
| comment                 | 716   | 1.86 %     | 
| transfer                | 554   | 1.44 %     | 
| claim_reward_balance    | 398   | 1.03 %     | 
| comment_options         | 209   | 0.54 %     | 
| limit_order_create      | 86    | 0.22 %     | 
| claim_account           | 84    | 0.22 %     | 
| feed_publish            | 76    | 0.20 %     | 
| limit_order_cancel      | 57    | 0.15 %     | 
| delegate_vesting_shares | 27    | 0.07 %     | 
| create_claimed_account  | 11    | 0.03 %     | 
| transfer_to_vesting     | 10    | 0.03 %     | 
| update_proposal_votes   | 10    | 0.03 %     | 
| convert                 | 9     | 0.02 %     | 
| account_update          | 8     | 0.02 %     | 
| account_update2         | 8     | 0.02 %     | 
| delete_comment          | 6     | 0.02 %     | 
| witness_set_properties  | 6     | 0.02 %     | 
| account_witness_vote    | 5     | 0.01 %     | 
| withdraw_vesting        | 4     | 0.01 %     | 
| transfer_to_savings     | 1     | 0.00 %     | 
| transfer_from_savings   | 1     | 0.00 %     | 
+-------------------------+-------+------------+ 

BLURT

+------------------------+-------+------------+ 
| Type                   | Count | percentage | 
+------------------------+-------+------------+ 
| witness_set_properties | 37589 | 99.88 %    | 
| claim_reward_balance   | 16    | 0.04 %     | 
| vote                   | 14    | 0.04 %     | 
| comment                | 9     | 0.02 %     | 
| comment_options        | 4     | 0.01 %     | 
| transfer               | 1     | 0.00 %     | 
| custom_json            | 1     | 0.00 %     | 
+------------------------+-------+------------+ 

Spam attack on BLURT

This issue indicates that the broadcasted witness_set_properties operations are indeed an attack to the BLURT blockchain: https://gitlab.com/blurt/blurt/-/issues/89

Transaction fee on BLURT

The bandwidth has increased from 0.01 BLURT/KByte(as far as I remember) to 0.250 BLURT/KByte. As the transaction fee has to be paid in front for every broadcasted operation from the users wallet, this 25x increase is painful.

Blurt price

The BLURT price has reacted to the spam attack and is almost 1 Sat/BLURT:

Conclusion

99.88 % of all operations on the BLURT blockchain are spam witness_set_properties operations. 9 posts/comments have been written in the last hour and 14 votes have been cast. This is not much in comparison to 716 posts / comments and 13786 votes on Hive. This indicates that the attack works and blurt user have almost stopped using the chain. This is also indicated by the price movement.

The strange thing is that the attacker seems not to pay a bandwidth fee for their attack:

https://blocks.blurtwallet.com/#/@gbemyktquwtpfizr As it can be seen that the blurt wallet is almost empty, it seems to me that the attacker have found a way to cast their spam ops for free.

I found the problem: https://gitlab.com/blurt/blurt/-/blob/dev/libraries/plugins/rc/include/blurt/plugins/rc/resource_sizes.hpp : witness_set_properties has no blurt::plugins::rc::state_object_size_info properties, which means that broadcasting a witness_set_properties op seems not to costs any blurt fee.

Posted Using LeoFinance Beta