{ "cells": [ { "cell_type": "markdown", "id": "emotional-assistant", "metadata": {}, "source": [ "## How to use\n", "\n", "In this noteboook we test the rewards given out by the protocol to different types of validators. Our `fast` config reduces the size of most constants to avoid allocating more memory than necessary (we'll only test with a few validators). We also reduce the number of slots per epoch to speed things up. All these changes are without loss of generality.\n", "\n", "You may test various spec versions by renaming either of the `specs_*.py` files in the `beaconrunner` folder to `specs.py`. Current version tested is v1.1.0-alpha.7." ] }, { "cell_type": "code", "execution_count": 1, "id": "structured-shannon", "metadata": {}, "outputs": [], "source": [ "import os, sys\n", "sys.path.insert(1, os.path.realpath(os.path.pardir))\n", "sys.path.insert(1, os.path.realpath(os.path.pardir) + \"/beaconrunner\")\n", "import beaconrunner as br\n", "\n", "import types\n", "from eth2spec.utils.ssz.ssz_impl import hash_tree_root\n", "\n", "from cadCAD_tools.profiling.visualizations import visualize_substep_impact\n", "\n", "import pandas as pd\n", "import plotly.express as px\n", "import plotly.io as pio\n", "pd.options.plotting.backend = \"plotly\"\n", "pio.renderers.default = \"plotly_mimetype+notebook_connected\"\n", "import plotly.graph_objects as go" ] }, { "cell_type": "markdown", "id": "saving-kelly", "metadata": {}, "source": [ "Below are metrics extracted from the state of the simulation. We don't really care about most of them except for `get_current_validator_state`, but they are left here for future use/reference." ] }, { "cell_type": "code", "execution_count": 2, "id": "enhanced-staff", "metadata": {}, "outputs": [], "source": [ "def extract_state(s):\n", " validators = s[\"network\"].validators\n", " validator = validators[1]\n", " head = br.specs.get_head(validator.store)\n", " current_state = validator.store.block_states[head].copy()\n", " return current_state\n", "\n", "def current_slot(params, step, sL, s, _input):\n", " return (\"current_slot\", s[\"network\"].validators[0].data.slot)\n", "\n", "def total_balance_asap(params, step, sL, s, _input):\n", " validators = s[\"network\"].validators\n", " current_state = extract_state(s)\n", " current_epoch = br.specs.get_current_epoch(current_state)\n", " asap_indices = [i for i, v in enumerate(validators) if v.validator_behaviour == \"asap\"]\n", " asap_balances = [b for i, b in enumerate(current_state.balances) if i in asap_indices]\n", " return (\"total_balance_asap\", sum(asap_balances))\n", "\n", "def get_base_reward(params, step, sL, s, _input):\n", " current_state = extract_state(s)\n", " base_reward = br.specs.get_base_reward(current_state, 0)\n", " return (\"base_reward\", base_reward)\n", "\n", "def get_block_proposer(params, step, sL, s, _input):\n", " current_state = extract_state(s)\n", " block_proposer = [v.validator_index for v in s[\"network\"].validators if v.data.current_proposer_duties[s[\"current_slot\"] % br.specs.SLOTS_PER_EPOCH]][0]\n", " return (\"block_proposer\", block_proposer)\n", "\n", "def get_block_proposer_balance(params, step, sL, s, _input):\n", " current_state = extract_state(s)\n", " block_proposer_balance = current_state.balances[s[\"block_proposer\"]]\n", " return (\"block_proposer_balance\", block_proposer_balance)\n", "\n", "def get_sync_committee(params, step, sL, s, _input):\n", " current_state = extract_state(s)\n", " current_epoch = br.specs.get_current_epoch(current_state)\n", " sync_committee = current_state.current_sync_committee.pubkeys\n", " val_pubkeys = [v.pubkey for v in current_state.validators]\n", " sync_committee_indices = [val_pubkeys.index(pubkey) for pubkey in sync_comittee]\n", " return (\"sync_committee\", sync_committee_indices)\n", "\n", "def get_head(params, step, sL, s, _input):\n", " validators = s[\"network\"].validators\n", " validator = validators[0]\n", " head = br.specs.get_head(validator.store).hex()[0:6]\n", " return (\"head\", head)\n", "\n", "def get_current_validator_state(params, step, sL, s, _input):\n", " current_state = extract_state(s)\n", " current_validator_state = []\n", " for v in s[\"network\"].validators:\n", " current_validator_state += [{\n", " \"slot\": v.data.slot,\n", " \"validator_index\": v.validator_index,\n", " \"balance\": current_state.balances[v.validator_index],\n", " \"block_proposer\": 1 if s[\"block_proposer\"] == v.validator_index else 0,\n", " \"attester\": 1 if v.data.current_attest_slot == v.data.slot else 0,\n", " \"sync_committee\": len(v.data.current_sync_committee),\n", " }]\n", " return (\"current_validator_state\", current_validator_state)\n", "\n", "observers = {\n", " \"current_slot\": current_slot,\n", " \"total_balance_asap\": total_balance_asap,\n", " \"base_reward\": get_base_reward,\n", " \"block_proposer\": get_block_proposer,\n", " \"block_proposer_balance\": get_block_proposer_balance,\n", "# \"sync_committee\": get_sync_committee,\n", " \"head\": get_head,\n", " \"current_validator_state\": get_current_validator_state,\n", "}" ] }, { "cell_type": "markdown", "id": "current-piano", "metadata": {}, "source": [ "Run the simulation." ] }, { "cell_type": "code", "execution_count": 3, "id": "silent-abortion", "metadata": { "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:root:Starting simulation 0 / run 0 / subset 0\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "will simulate 4 epochs ( 16 slots ) at frequency 1 moves/second\n", "total 192 simulation steps\n", "19 proposing block for slot 1\n", "6 proposing block for slot 2\n", "7 proposing block for slot 3\n", "14 proposing block for slot 4\n", "9 proposing block for slot 5\n", "10 proposing block for slot 6\n", "0 proposing block for slot 7\n", "10 proposing block for slot 8\n", "13 proposing block for slot 9\n", "timestep 100 of run 1\n", "18 proposing block for slot 10\n", "3 proposing block for slot 11\n", "0 proposing block for slot 12\n", "2 proposing block for slot 13\n", "3 proposing block for slot 14\n", "12 proposing block for slot 15\n", "11 proposing block for slot 16\n" ] } ], "source": [ "from random import sample\n", "from beaconrunner.validators.ASAPValidator import ASAPValidator\n", "\n", "num_validators = 20\n", "\n", "# Initiate validators\n", "validators = []\n", "for i in range(num_validators):\n", " new_validator = ASAPValidator(i)\n", " validators.append(new_validator)\n", "\n", "# Create a genesis state\n", "(genesis_state, genesis_block) = br.simulator.get_genesis_state_block(validators)\n", "\n", "# Validators load the state\n", "[v.load_state(genesis_state.copy(), genesis_block.copy()) for v in validators]\n", "\n", "# We skip the genesis block\n", "br.simulator.skip_genesis_block(validators)\n", "\n", "# Create the network\n", "set_a = br.network.NetworkSet(validators=list(range(num_validators)))\n", "network_sets = list([set_a])\n", "network = br.network.Network(validators = validators, sets = network_sets)\n", "\n", "# Set simulation parameters\n", "parameters = br.simulator.SimulationParameters({\n", " \"num_epochs\": 4,\n", " \"run_index\": 1,\n", " \"frequency\": 1,\n", " \"network_update_rate\": 1.0,\n", "})\n", "\n", "df = br.simulator.simulate(network, parameters, observers) " ] }, { "cell_type": "code", "execution_count": 4, "id": "liable-aurora", "metadata": { "tags": [] }, "outputs": [], "source": [ "df = df.drop(columns=['network'])" ] }, { "cell_type": "markdown", "id": "communist-charleston", "metadata": {}, "source": [ "We collect the validator state data in a separate dataframe, of schema `(slot, validator_index, balance, block_proposer, attester, sync_committee)`. We ignore the first few epochs (rewards aren't given out, or imperfectly) and make sure the key `(slot, validator_index)` is unique." ] }, { "cell_type": "code", "execution_count": 5, "id": "3111b718-767b-43e1-b0c8-3a040944bc9f", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " | current_slot | \n", "total_balance_asap | \n", "base_reward | \n", "block_proposer | \n", "block_proposer_balance | \n", "head | \n", "current_validator_state | \n", "run_time | \n", "simulation | \n", "subset | \n", "run | \n", "substep | \n", "timestep | \n", "substep_label | \n", "
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | \n", "1 | \n", "640000000000 | \n", "2560000 | \n", "19 | \n", "32000000000 | \n", "168f82 | \n", "[{'slot': 1, 'validator_index': 0, 'balance': ... | \n", "0.000000e+00 | \n", "0 | \n", "0 | \n", "1 | \n", "0 | \n", "0 | \n", "Initial State | \n", "
1 | \n", "1 | \n", "640000000000 | \n", "2560000 | \n", "19 | \n", "32000000000 | \n", "168f82 | \n", "[{'slot': 1, 'validator_index': 0, 'balance': ... | \n", "1.626053e+09 | \n", "0 | \n", "0 | \n", "1 | \n", "1 | \n", "1 | \n", "Initial measure runtime | \n", "
2 | \n", "1 | \n", "640000000000 | \n", "2560000 | \n", "19 | \n", "32000000000 | \n", "168f82 | \n", "[{'slot': 1, 'validator_index': 0, 'balance': ... | \n", "1.626053e+09 | \n", "0 | \n", "0 | \n", "1 | \n", "2 | \n", "1 | \n", "Attestations | \n", "
3 | \n", "1 | \n", "640000000000 | \n", "2560000 | \n", "19 | \n", "32000000000 | \n", "168f82 | \n", "[{'slot': 1, 'validator_index': 0, 'balance': ... | \n", "1.626053e+09 | \n", "0 | \n", "0 | \n", "1 | \n", "3 | \n", "1 | \n", "Measure runtime 0 | \n", "
4 | \n", "1 | \n", "640000000000 | \n", "2560000 | \n", "19 | \n", "32000000000 | \n", "168f82 | \n", "[{'slot': 1, 'validator_index': 0, 'balance': ... | \n", "1.626053e+09 | \n", "0 | \n", "0 | \n", "1 | \n", "4 | \n", "1 | \n", "Sync committee | \n", "
... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
1724 | \n", "16 | \n", "640132299955 | \n", "2560000 | \n", "11 | \n", "32004319997 | \n", "0aea1b | \n", "[{'slot': 16, 'validator_index': 0, 'balance':... | \n", "1.626053e+09 | \n", "0 | \n", "0 | \n", "1 | \n", "5 | \n", "192 | \n", "Measure runtime 1 | \n", "
1725 | \n", "16 | \n", "640132299955 | \n", "2560000 | \n", "11 | \n", "32004319997 | \n", "0aea1b | \n", "[{'slot': 16, 'validator_index': 0, 'balance':... | \n", "1.626053e+09 | \n", "0 | \n", "0 | \n", "1 | \n", "6 | \n", "192 | \n", "Block proposals | \n", "
1726 | \n", "16 | \n", "640132299955 | \n", "2560000 | \n", "11 | \n", "32004319997 | \n", "0aea1b | \n", "[{'slot': 16, 'validator_index': 0, 'balance':... | \n", "1.626053e+09 | \n", "0 | \n", "0 | \n", "1 | \n", "7 | \n", "192 | \n", "Measure runtime 2 | \n", "
1727 | \n", "17 | \n", "640132299955 | \n", "2560000 | \n", "11 | \n", "32004319997 | \n", "0aea1b | \n", "[{'slot': 17, 'validator_index': 0, 'balance':... | \n", "1.626053e+09 | \n", "0 | \n", "0 | \n", "1 | \n", "8 | \n", "192 | \n", "Simulation tick | \n", "
1728 | \n", "17 | \n", "640132299955 | \n", "2560000 | \n", "11 | \n", "32004319997 | \n", "0aea1b | \n", "[{'slot': 17, 'validator_index': 0, 'balance':... | \n", "1.626053e+09 | \n", "0 | \n", "0 | \n", "1 | \n", "9 | \n", "192 | \n", "Measure runtime 3 | \n", "
1729 rows × 14 columns
\n", "