You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
236 lines
4.8 KiB
236 lines
4.8 KiB
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
|
|
}
|
|
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
})()
|
|
|