Warning: The project is intended for educational purposes only, we do not condone harmful usage on any live systems without explicit authorization.
RANDAO Daemon is a research system, which improves the effectiveness of RANDAO manipulations on Ethereum PoS. Compared to previous works, we used a realistic attestation model. One can verify our results through our REST API. Feel free to implement your own simulator for independent verification or use ours.
We compare our results with the papers Forking the RANDAO and Slot à la carte. We considered the KPI effective stake, which is the probability (%) the adversary can propose and finalize a block / slot. One of the goals of the consensus protocol is to ensure fairness: everyone proposes blocks in proportion to their stake share. It means that if an adversary has an effective stake larger than their stake share, they violated fairness and proposed more blocks than their fair share.
WARNING: The previous 2 works assumed that the adversary has the same amount of voting power in every slot, while RANDAO Daemon uses a more accurate distribution of adversarial proposers/committee.
| Stake of the adversary | Forking the RANDAO | Slot à la carte | RANDAO Daemon | Selfish Mining |
|---|---|---|---|---|
| 5% | 5.05% | 5.07% | 5.20% | 5.24% |
| 10% | 10.19% | 10.23% | 10.57% | 10.92% |
| 15% | 15.42% | 15.51% | 15.78% | 17.01% |
| 20% | 20.95% | 21.00% | 21.56% | 23.51% |
| 25% | 26.60% | 26.80% | 27.97% | 30.48% |
| 30% | 32.83% | 33.43% | 36.09% | 38.06% |
| 35% | 40.28% | 44.36% | 50.01% | 46.55% |
| 40% | 47.49% | 53.08% | 58.30% | 56.74% |
| 45% | 53.77% | 60.00% | 63.20% | 70.94% |
Create your configuration in a yaml similarly to default.yaml:
number_of_validators: 1000000 # ensure that it is divisible by 32
number_of_adv_validators: 280000 # Size of your pool you control
size_postfix: 15 # Number of slots considered at the end of the epoch
epoch_sample_size: 4000 # Number of epoch strings generated randomly with size_postfix. These will be used to create utilities, then train the neural network on
votes_sample: 5000 # Permutations on validators generated. Later, we draw uniformly from this set, because its expensive.
dist_compression_size: 8 # Precision of distributions
diff_cluster_size: 3 # Number of clusters (>=2)
tree_batching: 200 # We rotate this many large trees
iteration: 10 # Number of value iterations
dataset_name: randao
train_weight: 0.8 # Size of epoch_sample_size to be included in the training dataset
val_weight: 0.15 # Size of epoch_sample_size to be included in the val dataset
model_name: daemon
train_rounds: 3 # Number of trains started each task
batch_size: 32
lr: 0.0001 # learning rate
weight_up_zero_class_options: # hyperparameters of one task
- 1.5
- 2.0
- 2.5
epochs: 400 # length of training
save_every: 5 # intervals of saving the models
infer_rounds: 50000 # number of rounds during simulation
slot_capture: false # must be set to false, currently not supported for server setup
warmup_rounds: 10 # number of epochs before the slot we wish to `capture`Ensure you have installed NVIDIA Toolchain
docker build -t randaodaemon:latest .Precomputation produces a run yaml file under .runs folder. The key inference_result holds the number of proposed blocks on average during the simulation. Additionally it produces every model necessary to run the server.
WARNING: The repo folder is mounted even for server setup. For the offline precomputation the model can be saved in the .models folder.
docker run --rm \
--gpus all \
-v $(pwd):/srv \
randaodaemon:latest \
bash -c "git config --global --add safe.directory /srv && python3 -m create_model default.yaml"This phase is only necessary if you wish to verify independently the performance of the produced model and do not trust the simulation.
If you wish not to mount the repo, you must rebuild the docker with the extra row COPY . . and start it without the -v $(pwd):/srv flag.
In config.yaml provide the path of the run yaml file produced in the previous step.
docker run --rm --gpus all -v $(pwd):/srv -p 8001:8001 --network host randaodaemon:latest bash -c "git config --global --add safe.directory /srv && uvicorn main:app --host 0.0.0.0 --port 8001"The server in itself is not standalone. While we implemented the blockchain simulation server, you are welcome to independently verify our results and implement a different simulator. RANDAO Daemon requires an endpoint serving data about the (simulated) blockchain. After which it can return which action to execute (e.g. where to vote or how to build a block).
The server will request information necessary for the attack. The server is ready.
Response:
{
"status": "ok"
}Stops the attack.
Response:
{
"status": "ok"
}Advances the slot to the next slot number and to the next phase.
propose -> vote
vote -> propose - slot := slot + 1
Response:
{
"status": "ok"
}Queries actions for the given slot
Request:
{
"slot": 12,
"phase": "vote",
"subscribe_url": "url"
}where subscribe_url is optional. If provided and the server is busy, the results will be posted there eventually.
Expected response:
{
"status": "ok",
"slot": 12,
"phase": "vote",
"actions": [
{
"action": "vote",
"to_slot": 11,
"from_slot": 11,
"amount": 178000
},
{
"action": "propose",
"slot": 10,
"parent": 9
}
]
}Response in case the server is still computing for the slot:
{
"status": "pending",
"message": "Data does not exists for this slot"
}The implementation of the simulation must follow the given specification
Responds with the current slot and epoch:
{
"status": "ok",
"epoch": 1,
"slot": 35
}Returns who proposes which slot and the adequate number of attestators for each slot.
An epoch string is a 32 long string with "A" and "H" characters. "A" denotes the slots controlled by the adversary, while "H" everone else's slot (honest). Response:
{
"status": "ok",
"epoch": 12,
"success": 1,
"epoch_string": "AHHHAHHHAA...A",
"attestations": [
123,
543,
...,
831
]
}Returns the epoch string and votes corresponding to the input's 32 long canonical strings contains characters "N" and "C" corresponding to the slots of epoch. "N" denotes a noncanonical (i.e. missed or reorged) slot, while "C" a canonical (proposed).
Request:
{
"epoch": 12,
"input": [
"CCCNCCNC...N",
"NCNNCCCC...C"
]
}In the response, success denotes whether the RANDAO and the validators are precomputable at the moment:
{
"status": "ok",
"epoch": 12,
"epochs": [
{
"outcome": "CCCNCCNC...N",
"success": 1,
"epoch_string": "AHHHAHHHAA...A",
"attestations": [
123,
543,
...,
831
]
},
{
"outcome": "NCNNCCCC...C",
"success": 0,
}
]
}
