Skip to content

Instantly share code, notes, and snippets.

@kushti
Created January 30, 2023 11:41
Show Gist options
  • Save kushti/28335995b36f2023bdef72b213aed813 to your computer and use it in GitHub Desktop.
Save kushti/28335995b36f2023bdef72b213aed813 to your computer and use it in GitHub Desktop.
EIP-37 DAA simulator
package org.ergoplatform.tools
import org.ergoplatform.mining.difficulty.{DifficultyAdjustment, RequiredDifficulty}
import org.ergoplatform.modifiers.history.header.Header
import org.ergoplatform.settings.{Args, ErgoSettings, NetworkType}
import java.util.concurrent.TimeUnit
import scala.collection.mutable
import scala.concurrent.duration.FiniteDuration
import scala.util.Random
object AdaptiveSimulator extends App {
import io.circe.parser._
implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global
private val altSettings: ErgoSettings =
ErgoSettings.read(Args(Some("/home/kushti/ergo/mainnet/alt.conf"), Some(NetworkType.MainNet)))
val ldc = new DifficultyAdjustment(altSettings.chainSettings)
val h1Json =
"""
|{
| "extensionId" : "af4c9de8106960b47964d21e6eb2acdad7e3e168791e595f0806ebfb036ee7de",
| "difficulty" : "1199990374400",
| "votes" : "000000",
| "timestamp" : 1561978977137,
| "size" : 279,
| "stateRoot" : "18b7a08878f2a7ee4389c5a1cece1e2724abe8b8adc8916240dd1bcac069177303",
| "height" : 1,
| "nBits" : 100734821,
| "version" : 1,
| "id" : "b0244dfc267baca974a4caee06120321562784303a8a688976ae56170e4d175b",
| "adProofsRoot" : "766ab7a313cd2fb66d135b0be6662aa02dfa8e5b17342c05a04396268df0bfbb",
| "transactionsRoot" : "93fb06aa44413ff57ac878fda9377207d5db0e78833556b331b4d9727b3153ba",
| "extensionHash" : "0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8",
| "powSolutions" : {
| "pk" : "03be7ad70c74f691345cbedba19f4844e7fc514e1188a7929f5ae261d5bb00bb66",
| "w" : "02da9385ac99014ddcffe88d2ac5f28ce817cd615f270a0a5eae58acfb9fd9f6a0",
| "n" : "000000030151dc63",
| "d" : 46909460813884299753486408728361968139945651324239558400157099627
| },
| "adProofsId" : "cfc4af9743534b30ef38deec118a85ce6f0a3741b79b7d294f3e089c118188dc",
| "transactionsId" : "fc13e7fd2d1ddbd10e373e232814b3c9ee1b6fbdc4e6257c288ecd9e6da92633",
| "parentId" : "0000000000000000000000000000000000000000000000000000000000000000"
|}""".stripMargin
val h1 = Header.jsonDecoder.decodeJson(parse(h1Json).toOption.get).toOption.get
var totalError = 0
var maxDelay = 0
(1 to 100).foreach { _ =>
var blockDelay = altSettings.chainSettings.blockInterval
val epochLength = altSettings.chainSettings.epochLength
var price = 100000
val medianChange = 3 // price going up 1% epoch on average
val variance = 10 // with +-20%
val blocks = mutable.Map[Int, Header]()
blocks.put(0, h1.copy(height = 0)) // put genesis block
blocks.put(1, h1) // put genesis block
val precision = BigInt("10000000000000000")
// t = d*c / p
// c = t*p/d
val c = blockDelay.toMillis * price * precision / h1.requiredDifficulty
println("c: " + c)
129.to(32 * 1024 + 1, 128).foreach { h =>
println("================================")
println("height: " + h)
val newPrice = price +
Random.nextInt(price * medianChange / 100) +
(if (Random.nextBoolean()) {
Random.nextInt(price * variance / 100)
} else {
-Random.nextInt(price * variance / 100)
})
/*
val epoch = (h - 1) / 128
val newPrice = if(epoch%16 <8){
price + Random.nextInt(price * variance / 100)
} else {
price - Random.nextInt(price * variance / 100)
} */
println("price: " + newPrice)
val newBlockDelay = (blocks(h - 128).requiredDifficulty * c / precision / newPrice).toLong
val blockBefore = h1.copy(height = h - 1, timestamp = blocks(h - 128).timestamp + 127 * newBlockDelay, nBits = blocks(h - 128).nBits)
blocks.put(h - 1, blockBefore)
val heights = ldc.previousHeadersRequiredForRecalculation(h, epochLength)
val hs = heights.map(blocks.apply)
val newDiff = ldc.eip37Calculate(hs, epochLength)
println("newDiff: " + newDiff)
val block = h1.copy(height = h, timestamp = blockBefore.timestamp + newBlockDelay, nBits = RequiredDifficulty.encodeCompactBits(newDiff))
blocks.put(h, block)
price = newPrice
blockDelay = FiniteDuration(newBlockDelay, TimeUnit.MILLISECONDS)
println("block delay: " + blockDelay.toSeconds + " s.")
totalError += Math.abs(altSettings.chainSettings.blockInterval.toMillis - blockDelay.toMillis).toInt
if (blockDelay.toSeconds > maxDelay) {
maxDelay = blockDelay.toSeconds.toInt
}
}
}
println("Planned block time: " + altSettings.chainSettings.blockInterval)
println("Total error: " + totalError / 1000)
println("Max delay: " + maxDelay)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment