From 61dbc2304227b8e844fd19a8b7c5f1cf46f79379 Mon Sep 17 00:00:00 2001
From: Daniel Wang <99078276+dantaik@users.noreply.github.com>
Date: Wed, 8 Feb 2023 14:50:43 +0800
Subject: [PATCH] feat(protocol): add a script to calculate
 `slotSmoothingFactor` (#13109)

---
 packages/protocol/CHANGELOG.md                | 26 ++++-----
 .../protocol/utils/generate_config/README.md  | 12 ++++
 .../protocol/utils/generate_config/main.py    | 57 +++++++++++++++++++
 3 files changed, 81 insertions(+), 14 deletions(-)
 create mode 100644 packages/protocol/utils/generate_config/README.md
 create mode 100644 packages/protocol/utils/generate_config/main.py

diff --git a/packages/protocol/CHANGELOG.md b/packages/protocol/CHANGELOG.md
index f3385aa9c0d..c2c5163db20 100644
--- a/packages/protocol/CHANGELOG.md
+++ b/packages/protocol/CHANGELOG.md
@@ -2,25 +2,23 @@
 
 ## [0.2.0](https://github.com/taikoxyz/taiko-mono/compare/protocol-v0.1.0...protocol-v0.2.0) (2023-01-31)
 
-
 ### Features
 
-* **protocol:** add `proto_broker` / `oracle_prover` addresses into `AddressManager` in deploy_L1 script ([#13079](https://github.com/taikoxyz/taiko-mono/issues/13079)) ([f3bea40](https://github.com/taikoxyz/taiko-mono/commit/f3bea40fbcdf4139cc84903ab69d1e0daf641c7c))
-* **protocol:** add special logics for alpha-2 testnet ([#12987](https://github.com/taikoxyz/taiko-mono/issues/12987)) ([3b71285](https://github.com/taikoxyz/taiko-mono/commit/3b712857b5d5ede2a3683d949d1974c8cceeb69a))
-* **protocol:** deploy the generated Yul plonk verifier ([#13016](https://github.com/taikoxyz/taiko-mono/issues/13016)) ([eb5d564](https://github.com/taikoxyz/taiko-mono/commit/eb5d564ec469b1ec79619b4d563c3f9989d264c2))
-* **protocol:** enable two dimensional circuit/verifier lookup. ([#13066](https://github.com/taikoxyz/taiko-mono/issues/13066)) ([51d1f67](https://github.com/taikoxyz/taiko-mono/commit/51d1f67aa45fec8e2de73c1ed5a992306c6339c1))
-* **protocol:** implement `Bridge.isMessageFailed` ([#13004](https://github.com/taikoxyz/taiko-mono/issues/13004)) ([45153d9](https://github.com/taikoxyz/taiko-mono/commit/45153d92cbcd0e80438c925d5ce5c52df3abd696))
-* **protocol:** implement releaseEther & releaseERC20 ([#13008](https://github.com/taikoxyz/taiko-mono/issues/13008)) ([088933e](https://github.com/taikoxyz/taiko-mono/commit/088933e74f7163459e328d61d8331235ab87e388))
-* **protocol:** improve sync header storage on L2 ([#13041](https://github.com/taikoxyz/taiko-mono/issues/13041)) ([86c9fe4](https://github.com/taikoxyz/taiko-mono/commit/86c9fe44a3200490032610c017bfc88c3a57a8dd))
-* **protocol:** temporarily force an `oracle prover` to be the first prover ([#13070](https://github.com/taikoxyz/taiko-mono/issues/13070)) ([d7401a2](https://github.com/taikoxyz/taiko-mono/commit/d7401a20c66a3c52330c4f92c95c71c902d74452))
-
+- **protocol:** add `proto_broker` / `oracle_prover` addresses into `AddressManager` in deploy_L1 script ([#13079](https://github.com/taikoxyz/taiko-mono/issues/13079)) ([f3bea40](https://github.com/taikoxyz/taiko-mono/commit/f3bea40fbcdf4139cc84903ab69d1e0daf641c7c))
+- **protocol:** add special logics for alpha-2 testnet ([#12987](https://github.com/taikoxyz/taiko-mono/issues/12987)) ([3b71285](https://github.com/taikoxyz/taiko-mono/commit/3b712857b5d5ede2a3683d949d1974c8cceeb69a))
+- **protocol:** deploy the generated Yul plonk verifier ([#13016](https://github.com/taikoxyz/taiko-mono/issues/13016)) ([eb5d564](https://github.com/taikoxyz/taiko-mono/commit/eb5d564ec469b1ec79619b4d563c3f9989d264c2))
+- **protocol:** enable two dimensional circuit/verifier lookup. ([#13066](https://github.com/taikoxyz/taiko-mono/issues/13066)) ([51d1f67](https://github.com/taikoxyz/taiko-mono/commit/51d1f67aa45fec8e2de73c1ed5a992306c6339c1))
+- **protocol:** implement `Bridge.isMessageFailed` ([#13004](https://github.com/taikoxyz/taiko-mono/issues/13004)) ([45153d9](https://github.com/taikoxyz/taiko-mono/commit/45153d92cbcd0e80438c925d5ce5c52df3abd696))
+- **protocol:** implement releaseEther & releaseERC20 ([#13008](https://github.com/taikoxyz/taiko-mono/issues/13008)) ([088933e](https://github.com/taikoxyz/taiko-mono/commit/088933e74f7163459e328d61d8331235ab87e388))
+- **protocol:** improve sync header storage on L2 ([#13041](https://github.com/taikoxyz/taiko-mono/issues/13041)) ([86c9fe4](https://github.com/taikoxyz/taiko-mono/commit/86c9fe44a3200490032610c017bfc88c3a57a8dd))
+- **protocol:** temporarily force an `oracle prover` to be the first prover ([#13070](https://github.com/taikoxyz/taiko-mono/issues/13070)) ([d7401a2](https://github.com/taikoxyz/taiko-mono/commit/d7401a20c66a3c52330c4f92c95c71c902d74452))
 
 ### Bug Fixes
 
-* **protocol:** fix `test:integration` waiting node timeout ([#13006](https://github.com/taikoxyz/taiko-mono/issues/13006)) ([07debb7](https://github.com/taikoxyz/taiko-mono/commit/07debb779c1a142cf6050c31a5a8c9b72f26d376))
-* **protocol:** fix a downloading `solc` binary script bug ([#13074](https://github.com/taikoxyz/taiko-mono/issues/13074)) ([8167e9d](https://github.com/taikoxyz/taiko-mono/commit/8167e9dda0b0f70405e969f590f714b45af5b192))
-* **protocol:** fix two protocol bugs ([#13034](https://github.com/taikoxyz/taiko-mono/issues/13034)) ([1bfa69b](https://github.com/taikoxyz/taiko-mono/commit/1bfa69b4458f7edc4b72efe9c2d8cf9c7050853e))
-* **protocol:** update `ProofVerifier` address name in `AddressManager` ([#13063](https://github.com/taikoxyz/taiko-mono/issues/13063)) ([4144f4b](https://github.com/taikoxyz/taiko-mono/commit/4144f4bda154116f5e34759ced173a16f409202f))
+- **protocol:** fix `test:integration` waiting node timeout ([#13006](https://github.com/taikoxyz/taiko-mono/issues/13006)) ([07debb7](https://github.com/taikoxyz/taiko-mono/commit/07debb779c1a142cf6050c31a5a8c9b72f26d376))
+- **protocol:** fix a downloading `solc` binary script bug ([#13074](https://github.com/taikoxyz/taiko-mono/issues/13074)) ([8167e9d](https://github.com/taikoxyz/taiko-mono/commit/8167e9dda0b0f70405e969f590f714b45af5b192))
+- **protocol:** fix two protocol bugs ([#13034](https://github.com/taikoxyz/taiko-mono/issues/13034)) ([1bfa69b](https://github.com/taikoxyz/taiko-mono/commit/1bfa69b4458f7edc4b72efe9c2d8cf9c7050853e))
+- **protocol:** update `ProofVerifier` address name in `AddressManager` ([#13063](https://github.com/taikoxyz/taiko-mono/issues/13063)) ([4144f4b](https://github.com/taikoxyz/taiko-mono/commit/4144f4bda154116f5e34759ced173a16f409202f))
 
 ## [0.1.0](https://github.com/taikoxyz/taiko-mono/compare/protocol-v0.0.1...protocol-v0.1.0) (2023-01-19)
 
diff --git a/packages/protocol/utils/generate_config/README.md b/packages/protocol/utils/generate_config/README.md
new file mode 100644
index 00000000000..d8d3c7986e8
--- /dev/null
+++ b/packages/protocol/utils/generate_config/README.md
@@ -0,0 +1,12 @@
+# README
+
+A script to calculate `slotSmoothingFactor` in `TaikoData.Config` given:
+
+- expected block time
+- expected proof time
+- expected slot availability multiplier
+  ...
+
+## How to run
+
+`python3 main.py`
diff --git a/packages/protocol/utils/generate_config/main.py b/packages/protocol/utils/generate_config/main.py
new file mode 100644
index 00000000000..1597eb71de6
--- /dev/null
+++ b/packages/protocol/utils/generate_config/main.py
@@ -0,0 +1,57 @@
+import math
+
+
+if __name__ == "__main__":
+    print("Expected block time (seconds)", end=": ")
+    block_time = int(input())
+
+    print("Expected proof time (minutes)", end=": ")
+    proof_time = int(input()) * 60
+
+    print("Slot availability multiplier", end=": ")
+    slot_availability_multiplier = int(input())
+    if slot_availability_multiplier <= 5:
+        print("error: Slot availability multiplier must be greater than 5")
+        exit(1)
+
+    print("Number of ZKPs required per block before verificaiton", end=": ")
+    zk_proofs_per_block = int(input())
+
+    if zk_proofs_per_block < 1 or zk_proofs_per_block > 5:
+        print("error: Number of ZKPs must be between 1 and 5")
+        exit(1)
+
+    if zk_proofs_per_block == 1:
+        min_num_slots = math.ceil(1.0 * proof_time / block_time)
+        initial_uncle_delay = proof_time
+    else:
+        print("Inital uncle proof delay (minutes)", end=": ")
+        initial_uncle_delay = int(input()) * 60
+        min_num_slots = math.ceil(1.0 * (proof_time + initial_uncle_delay) / block_time)
+
+    print("Extra slots (e.g, 50 means 50% more slots)", end=": ")
+    extra_slots = int(input())
+
+    print("---------")
+
+    print("min num slots:", min_num_slots)
+    max_num_slots = min_num_slots + math.ceil(min_num_slots * extra_slots / 100) + 1
+
+    k = slot_availability_multiplier
+    n = max_num_slots
+
+    # https://www.wolframalpha.com/input?i=solve++%28n%2Bx%29%28n%2Bx-1%29%3Dk*%281%2Bx%29x+for+x
+    fee_smoothing_factor = (
+        k - 2 * n + 1 - math.sqrt(k * (k + 4 * n * n - 8 * n + 2) + 1.0)
+    ) / (2 - 2 * k)
+
+    fee_smoothing_factor = int(fee_smoothing_factor * 1000)
+
+    # f = fee_smoothing_factor
+    # print(1.0*(f+n*1000)*(f+n*1000-1000)/((f+1000)*f))
+
+    print("---------")
+    print("initialUncleDelay:", int(initial_uncle_delay / 60), "minutes")
+    print("maxNumBlocks:", max_num_slots)
+    print("zkProofsPerBlock:", zk_proofs_per_block)
+    print("slotSmoothingFactor:", fee_smoothing_factor)