mirror of
https://github.com/logos-blockchain/logos-blockchain-simulations.git
synced 2026-01-06 23:23:08 +00:00
118 lines
3.8 KiB
Python
118 lines
3.8 KiB
Python
from typing import List, Dict, Any, Tuple
|
|
import numpy as np
|
|
np.random.seed(42)
|
|
import pandas as pd
|
|
import tqdm
|
|
|
|
from simulation_parameters import SimulationParameters
|
|
from tx_fees_models import Block, Blockchain, MemPool, TransactionFeeMechanism, \
|
|
EIP1559, StableFee, Transaction, create_demand
|
|
|
|
|
|
def _generate_random_bool(p_true=0.5):
|
|
return np.random.choice([True, False], p=(p_true, 1.-p_true), size=1)[0]
|
|
|
|
|
|
def run_simulation(params: SimulationParameters) -> Tuple[pd.DataFrame, pd.DataFrame]:
|
|
|
|
blockchain:Dict[str,Blockchain] = {
|
|
"EIP": Blockchain(),
|
|
"StableFee": Blockchain()
|
|
}
|
|
|
|
mempool:Dict[str, MemPool] = {
|
|
"EIP": MemPool(),
|
|
"StableFee": MemPool()
|
|
}
|
|
|
|
tf_models:dict[str, TransactionFeeMechanism] = {
|
|
"EIP": EIP1559(),
|
|
"StableFee": StableFee()
|
|
}
|
|
|
|
df_stats:Dict[str, pd.DataFrame] = {
|
|
"EIP": pd.DataFrame(
|
|
0,
|
|
columns=["demand_size", "num_tx", "price", "tot_paid"],
|
|
index=range(params.num_blocks)
|
|
),
|
|
"StableFee": pd.DataFrame(
|
|
0,
|
|
columns=["demand_size", "num_tx", "price", "tot_paid"],
|
|
index=range(params.num_blocks)
|
|
)
|
|
}
|
|
|
|
pbar = tqdm.tqdm(total=params.num_blocks)
|
|
|
|
for b in range(params.num_blocks):
|
|
|
|
# transactions are created with random values
|
|
demand_size:int = np.random.choice(params.demand_sizes, p=params.demand_probabilities, size=1)[0]
|
|
|
|
demand:List[Transaction] = create_demand(
|
|
demand_size,
|
|
fee_cap_range=params.fee_cap_range,
|
|
max_tip_pct=params.max_tip_pct,
|
|
variable_gas=params.variable_gas_limits
|
|
)
|
|
|
|
stop_below_gas_limit:bool = _generate_random_bool(params.probability_stop_below_gas_limit)
|
|
|
|
scale_block_size = np.random.uniform(
|
|
0., params.scale_block_size
|
|
)
|
|
|
|
for chain, pool, tfm, stats in zip(
|
|
blockchain.values(), mempool.values(), tf_models.values(), df_stats.values()
|
|
):
|
|
scaled_demand:List[Transaction] = tfm.scale_demand(demand)
|
|
|
|
# transactions are added to the mempool
|
|
pool.add_txs(scaled_demand)
|
|
|
|
# transactions are selected from the mempool based on the gas premium
|
|
selected_transactions, to_be_purged_transactions = tfm.select_transactions(
|
|
pool,
|
|
stop_below_gas_limit=stop_below_gas_limit,
|
|
scale_block_size=scale_block_size,
|
|
purge_after=params.purge_after
|
|
)
|
|
|
|
# selected transactions are added to the blockchain
|
|
chain.add_block(Block(selected_transactions))
|
|
|
|
# the price is updated based on the selected transactions
|
|
tfm.update_price(chain)
|
|
|
|
# base fee is updated for the next round
|
|
stats.loc[b, "demand_size"] = demand_size
|
|
stats.loc[b, "num_tx"] = len(selected_transactions)
|
|
stats.loc[b, "price"] = tfm.get_current_price()
|
|
stats.loc[b, "tot_paid"] = tfm.total_paid_fees(selected_transactions)
|
|
|
|
# clear the mempool
|
|
pool.remove_txs(selected_transactions)
|
|
pool.remove_txs(to_be_purged_transactions)
|
|
|
|
pbar.update(1)
|
|
|
|
pbar.close()
|
|
|
|
df_stats_merged = pd.concat(
|
|
[df_stats[mechanism].add_suffix("_" + mechanism) for mechanism in df_stats.keys()],
|
|
axis=1
|
|
)
|
|
|
|
df_chain_stats:Dict[str,pd.DataFrame] = {
|
|
"EIP": blockchain["EIP"].compute_stats(),
|
|
"StableFee": blockchain["StableFee"].compute_stats()
|
|
}
|
|
|
|
df_chain_stats_merged = pd.concat(
|
|
[df_chain_stats[mechanism].add_suffix("_" + mechanism) for mechanism in df_stats.keys()],
|
|
axis=1
|
|
)
|
|
|
|
return df_stats_merged, df_chain_stats_merged
|