commit
d3684a8f25
@ -0,0 +1,235 @@
|
|||||||
|
var drawChart
|
||||||
|
(() => {
|
||||||
|
const difficulty_window = 69;
|
||||||
|
const target = 10;
|
||||||
|
|
||||||
|
// possible diff algos: LWMA, Cryptonote, MA, EMA
|
||||||
|
const diffAlgo = "Cryptonote"
|
||||||
|
|
||||||
|
const CryptonoteCut = 0; // 12
|
||||||
|
|
||||||
|
|
||||||
|
document.getElementById("title").innerText = `Diff algo: ${diffAlgo} - window: ${difficulty_window} ${(diffAlgo === "Cryptonote" ? "cut: "+CryptonoteCut : "")}`
|
||||||
|
|
||||||
|
let blocks = []
|
||||||
|
let hashrates = []
|
||||||
|
|
||||||
|
let difficulty = 10;
|
||||||
|
let time = 0;
|
||||||
|
|
||||||
|
|
||||||
|
function mineBlock(hashrate) {
|
||||||
|
time = 0;
|
||||||
|
while (true) {
|
||||||
|
time++;
|
||||||
|
if (hashrate / difficulty > Math.random()) {
|
||||||
|
blocks.push({
|
||||||
|
t: time,
|
||||||
|
d: difficulty,
|
||||||
|
})
|
||||||
|
hashrates.push(hashrate)
|
||||||
|
calculateDifficulty()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let x = 0; x < 5; x++) {
|
||||||
|
for (let i = 0; i < 350; i++) {
|
||||||
|
mineBlock(10)
|
||||||
|
}
|
||||||
|
for (let i = 0; i < 350; i++) {
|
||||||
|
mineBlock(6)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateDifficulty() {
|
||||||
|
if (blocks.length < 2) return;
|
||||||
|
const bScan = Math.min(difficulty_window, blocks.length - 1)
|
||||||
|
let blocksToScan = blocks.slice(blocks.length - bScan - 1, blocks.length - 1)
|
||||||
|
//console.log(blocksToScan)
|
||||||
|
|
||||||
|
let avgTime = 0;
|
||||||
|
let avgDiff = 0;
|
||||||
|
|
||||||
|
if (diffAlgo === "LWMA") {
|
||||||
|
let totalWeights = 0;
|
||||||
|
//console.clear()
|
||||||
|
|
||||||
|
for (i in blocksToScan) {
|
||||||
|
let curW = bScan - (bScan - i) + 1 // i+1
|
||||||
|
//console.log("curW", curW)
|
||||||
|
|
||||||
|
totalWeights += curW
|
||||||
|
|
||||||
|
avgTime += blocksToScan[i].t * curW
|
||||||
|
avgDiff += blocksToScan[i].d * curW
|
||||||
|
|
||||||
|
//console.log("diff",blocksToScan[i].d)
|
||||||
|
}
|
||||||
|
avgTime /= totalWeights
|
||||||
|
avgDiff /= totalWeights // bScan
|
||||||
|
} else if (diffAlgo === "EMA") {
|
||||||
|
let totalWeights = 0;
|
||||||
|
//console.clear()
|
||||||
|
|
||||||
|
for (i in blocksToScan) {
|
||||||
|
let curW = (bScan - (bScan - i) + 1) ** 2 // i+1
|
||||||
|
//console.log("curW", curW)
|
||||||
|
|
||||||
|
totalWeights += curW
|
||||||
|
|
||||||
|
avgTime += blocksToScan[i].t * curW
|
||||||
|
avgDiff += blocksToScan[i].d * curW
|
||||||
|
|
||||||
|
//console.log("diff",blocksToScan[i].d)
|
||||||
|
}
|
||||||
|
avgTime /= totalWeights
|
||||||
|
avgDiff /= totalWeights // bScan
|
||||||
|
} else if (diffAlgo === "MA") {
|
||||||
|
for (i in blocksToScan) {
|
||||||
|
|
||||||
|
avgTime += blocksToScan[i].t
|
||||||
|
avgDiff += blocksToScan[i].d
|
||||||
|
}
|
||||||
|
avgTime /= bScan
|
||||||
|
avgDiff /= bScan // bScan
|
||||||
|
} else if (diffAlgo === "Cryptonote") {
|
||||||
|
let cut = Math.max(Math.min(CryptonoteCut, Math.floor(bScan / 2) - 2), 0)
|
||||||
|
if (bScan < difficulty_window) {
|
||||||
|
cut = 0;
|
||||||
|
}
|
||||||
|
if (cut >= bScan) {
|
||||||
|
throw new Error("invalid cut " + CryptonoteCut + " with window of " + bScan)
|
||||||
|
}
|
||||||
|
|
||||||
|
let blTimes = []
|
||||||
|
for (i of blocksToScan) {
|
||||||
|
blTimes.push(i.t)
|
||||||
|
avgDiff += i.d
|
||||||
|
|
||||||
|
}
|
||||||
|
blTimes = blTimes.slice(cut, blTimes.length - cut)
|
||||||
|
|
||||||
|
for (i of blTimes) {
|
||||||
|
avgTime += i
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
avgTime /= (bScan - cut)
|
||||||
|
avgDiff /= bScan // bScan
|
||||||
|
}
|
||||||
|
diffMultiplier = Math.min(Math.max(target / avgTime, 0.1), 10)
|
||||||
|
//console.log("avgTime: " + avgTime + " avgDiff: " + avgDiff + " multiplier: " + diffMultiplier)
|
||||||
|
difficulty = Math.ceil(avgDiff * diffMultiplier) // Math.round(avgDiff * diffMultiplier)
|
||||||
|
//console.log(difficulty)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let blockDiffs = []
|
||||||
|
let blockTimes = []
|
||||||
|
let blockHeights = []
|
||||||
|
lastBlockTime = target;
|
||||||
|
|
||||||
|
let deviation = 0;
|
||||||
|
let diffDeviation = 0;
|
||||||
|
|
||||||
|
for (i in blocks) {
|
||||||
|
blockDiffs.push(blocks[i].d)
|
||||||
|
const blockTime = (blocks[i].t + lastBlockTime * 30) / 31
|
||||||
|
|
||||||
|
const perfectDiff = hashrates[i] * target
|
||||||
|
console.log("perfectDiff:", perfectDiff)
|
||||||
|
diffDeviation += Math.sqrt(Math.abs(perfectDiff - blocks[i].d))
|
||||||
|
|
||||||
|
deviation += Math.sqrt(Math.abs(blocks[i].t - blockTime))
|
||||||
|
|
||||||
|
blockTimes.push(blockTime)
|
||||||
|
lastBlockTime = blockTime
|
||||||
|
|
||||||
|
|
||||||
|
blockHeights.push(i)
|
||||||
|
|
||||||
|
}
|
||||||
|
deviation /= blocks.length
|
||||||
|
diffDeviation /= blocks.length
|
||||||
|
|
||||||
|
const ctx = document.getElementById("myChart");
|
||||||
|
const stats = document.getElementById("stats");
|
||||||
|
|
||||||
|
stats.innerText = `block time st.devt: ${(deviation / target * 100).toFixed(2)}% - difficulty st.devt. from perfect value: ${diffDeviation.toFixed(2)}`
|
||||||
|
|
||||||
|
|
||||||
|
drawChart = () => {
|
||||||
|
new Chart(ctx, {
|
||||||
|
type: "line",
|
||||||
|
data: {
|
||||||
|
labels: blockHeights,
|
||||||
|
datasets: [{
|
||||||
|
label: "Mean Block Time",
|
||||||
|
data: blockTimes,
|
||||||
|
borderWidth: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Difficulty",
|
||||||
|
data: blockDiffs,
|
||||||
|
yAxisID: "y1",
|
||||||
|
borderWidth: 1
|
||||||
|
}, {
|
||||||
|
label: "Hashrate",
|
||||||
|
data: hashrates,
|
||||||
|
yAxisID: "y2",
|
||||||
|
borderWidth: 1
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
// tension: 0.5,
|
||||||
|
elements: {
|
||||||
|
point: {
|
||||||
|
radius: 0,
|
||||||
|
hoverRadius: 3
|
||||||
|
},
|
||||||
|
line: {
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
type: "linear", // logarithmic
|
||||||
|
display: true,
|
||||||
|
position: "left",
|
||||||
|
max: 20,
|
||||||
|
min: 0
|
||||||
|
},
|
||||||
|
y1: {
|
||||||
|
type: "linear",
|
||||||
|
display: true,
|
||||||
|
position: "right",
|
||||||
|
min: 0,
|
||||||
|
max: 200,
|
||||||
|
|
||||||
|
// grid line settings
|
||||||
|
grid: {
|
||||||
|
drawOnChartArea: false, // only want the grid lines for one axis to show up
|
||||||
|
},
|
||||||
|
},
|
||||||
|
y2: {
|
||||||
|
type: "linear",
|
||||||
|
display: false,
|
||||||
|
min: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
})()
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<body>
|
||||||
|
<div id="title"></div>
|
||||||
|
<div>
|
||||||
|
<canvas id="myChart"></canvas>
|
||||||
|
</div>
|
||||||
|
<button onclick=drawChart()>Draw chart</button>
|
||||||
|
<div id=stats></div>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
|
<script src=main.js></script>
|
||||||
|
|
||||||
|
</body>
|
Loading…
Reference in new issue