Refactor PPLNS window display in miner page
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
DataHoarder 2023-06-01 07:35:05 +02:00
parent 2fe65a7a62
commit d40172d479
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
4 changed files with 93 additions and 27 deletions

View file

@ -8,19 +8,29 @@ import (
type PositionChart struct { type PositionChart struct {
totalItems uint64 totalItems uint64
bucket []uint64 bucket []uint64
perBucket int
idle byte idle byte
} }
func (p *PositionChart) Add(index int, value uint64) { func (p *PositionChart) Add(index int, value uint64) {
if index < 0 || index > int(p.totalItems) { if index < 0 || index >= int(p.totalItems) {
return return
} }
if len(p.bucket) == 1 { if len(p.bucket) == 1 {
p.bucket[0] += value p.bucket[0] += value
return return
} }
i := uint64(index) * uint64(len(p.bucket)-1) / (p.totalItems - 1)
p.bucket[i] += value p.bucket[p.indexOf(index)] += value
}
func (p *PositionChart) indexOf(index int) int {
if len(p.bucket) == 1 {
return 0
}
i := (index*len(p.bucket) - 1) / int(p.totalItems-1)
return i
} }
func (p *PositionChart) Total() (result uint64) { func (p *PositionChart) Total() (result uint64) {
@ -61,11 +71,28 @@ func (p *PositionChart) String() string {
return string(position) return string(position)
} }
func (p *PositionChart) StringWithoutDelimiters() string {
position := make([]byte, len(p.bucket))
for i, e := range utils.ReverseSlice(slices.Clone(p.bucket)) {
if e > 0 {
if e > 9 {
position[i] = '+'
} else {
position[i] = 0x30 + byte(e)
}
} else {
position[i] = p.idle
}
}
return string(position)
}
func (p *PositionChart) StringWithSeparator(index int) string { func (p *PositionChart) StringWithSeparator(index int) string {
if index < 0 || index > int(p.totalItems) { if index < 0 || index >= int(p.totalItems) {
return p.String() return p.String()
} }
separatorIndex := index * (len(p.bucket) - 1) / int(p.totalItems-1) separatorIndex := p.indexOf(index)
position := make([]byte, 1+2*2+len(p.bucket)) position := make([]byte, 1+2*2+len(p.bucket))
position[0], position[1] = '[', '<' position[0], position[1] = '[', '<'
position[2+separatorIndex] = '|' position[2+separatorIndex] = '|'
@ -92,9 +119,14 @@ func NewPositionChart(size uint64, totalItems uint64) *PositionChart {
if size < 1 { if size < 1 {
size = 1 size = 1
} }
perBucket := int(totalItems / size)
if totalItems%size > 0 {
perBucket += 1
}
return &PositionChart{ return &PositionChart{
totalItems: totalItems, totalItems: totalItems,
bucket: make([]uint64, size), bucket: make([]uint64, size),
perBucket: perBucket,
idle: '.', idle: '.',
} }
} }

View file

@ -0,0 +1,13 @@
package utils
import (
"testing"
)
func TestChart(t *testing.T) {
p := NewPositionChart(32, 4096)
for i := 0; i < 4096; i++ {
p.Add(i, 1)
}
}

View file

@ -11,13 +11,14 @@ type MinerPage struct {
Refresh int Refresh int
Positions struct { Positions struct {
Resolution int Resolution int
ResolutionWindow int
SeparatorIndex int SeparatorIndex int
Blocks *cmdutils.PositionChart Blocks *cmdutils.PositionChart
Uncles *cmdutils.PositionChart Uncles *cmdutils.PositionChart
BlocksInWindow *cmdutils.PositionChart
UnclesInWindow *cmdutils.PositionChart
Payouts *cmdutils.PositionChart Payouts *cmdutils.PositionChart
} }
SharesInWindow int
UnclesInWindow int
ExpectedRewardPerWindow uint64 ExpectedRewardPerWindow uint64
ExpectedRewardPerDay uint64 ExpectedRewardPerDay uint64
WindowWeight uint64 WindowWeight uint64
@ -136,7 +137,7 @@ type MinerPage struct {
</tr> </tr>
<tr> <tr>
<td title="{%s utc_date(p.Miner.LastShareTimestamp) %}">{%s time_elapsed_short(p.Miner.LastShareTimestamp) %}</td> <td title="{%s utc_date(p.Miner.LastShareTimestamp) %}">{%s time_elapsed_short(p.Miner.LastShareTimestamp) %}</td>
<td>{%d p.SharesInWindow %} blocks (+{%d p.UnclesInWindow %} uncles)</td> <td>{%dul p.Positions.BlocksInWindow.Total() %} blocks (+{%dul p.Positions.UnclesInWindow.Total() %} uncles)</td>
{% code windowWeightRatio := float64(p.WindowWeight) / float64(p.Context().Pool.SideChain.Window.Weight.Lo) %} {% code windowWeightRatio := float64(p.WindowWeight) / float64(p.Context().Pool.SideChain.Window.Weight.Lo) %}
<td>{%s si_units(windowWeightRatio * float64(diff_hashrate(p.Context().Pool.SideChain.Difficulty, p.Context().Consensus.TargetBlockTime)), 3) %}H/s</td> <td>{%s si_units(windowWeightRatio * float64(diff_hashrate(p.Context().Pool.SideChain.Difficulty, p.Context().Consensus.TargetBlockTime)), 3) %}H/s</td>
<td>{%f.3 windowWeightRatio*100 %}%</td> <td>{%f.3 windowWeightRatio*100 %}%</td>
@ -167,16 +168,30 @@ type MinerPage struct {
<div style="text-align: center;"> <div style="text-align: center;">
<h2>Share positions</h2> <h2>Share positions</h2>
<p class="small"> <p class="small">
Shares appear on the right, and get older towards the left. The pipe (<code>|</code>) character denotes the current PPLNS window end. Shares appear on the right, and get older towards the left.
<br/> <br/>
Number denotes the amount of shares per slice, with the plus (<code>+</code>) character being more than 9, and dot (<code>.</code>) being none. Number denotes the amount of shares per slice, with the plus (<code>+</code>) character being more than 9, and dot (<code>.</code>) being none.
<br/> <br/>
Each slice accounts for {%d p.Positions.Resolution %} P2Pool blocks, or around {%dul (uint64(p.Positions.Resolution) * p.Context().Consensus.TargetBlockTime) / 60 %} minutes. Each slice accounts for {%d p.Positions.Resolution %} P2Pool blocks, or around {%dul (uint64(p.Positions.Resolution) * p.Context().Consensus.TargetBlockTime) / 60 %} minutes.
</p> </p>
<h3>Shares during last day</h3> <h3>Shares and uncles in PPLNS window</h3>
<code class="mono">{%s p.Positions.Blocks.StringWithSeparator(p.Positions.SeparatorIndex) %}</code> <p class="small">
Each slice accounts for {%d p.Positions.ResolutionWindow %} P2Pool block heights, or around {%dul (uint64(p.Positions.ResolutionWindow) * p.Context().Consensus.TargetBlockTime) / 60 %} minutes.
<br/>
Shares within the PPLNS window will be weighted towards receiving a payout when any Monero block is found by any P2Pool miner.
</p>
<code class="mono">{%s p.Positions.BlocksInWindow.String() %}</code>
<br/>
<code class="mono">{%s p.Positions.UnclesInWindow.String() %}</code>
<h3>Uncles during last day</h3> <h3>Shares and uncles during last day</h3>
<p class="small">
Each slice accounts for {%d p.Positions.Resolution %} P2Pool block heights, or around {%dul (uint64(p.Positions.Resolution) * p.Context().Consensus.TargetBlockTime) / 60 %} minutes.
<br/>
The pipe (<code>|</code>) character denotes roughly the PPLNS window end.
</p>
<code class="mono">{%s p.Positions.Blocks.StringWithSeparator(p.Positions.SeparatorIndex) %}</code>
<br/>
<code class="mono">{%s p.Positions.Uncles.StringWithSeparator(p.Positions.SeparatorIndex) %}</code> <code class="mono">{%s p.Positions.Uncles.StringWithSeparator(p.Positions.SeparatorIndex) %}</code>
{% if p.Positions.Payouts.Total() > 0 %} {% if p.Positions.Payouts.Total() > 0 %}

View file

@ -896,10 +896,12 @@ func main() {
wg.Wait() wg.Wait()
} }
sharesInWindow := cmdutils.NewPositionChart(30, uint64(poolInfo.SideChain.WindowSize))
unclesInWindow := cmdutils.NewPositionChart(30, uint64(poolInfo.SideChain.WindowSize))
sharesFound := cmdutils.NewPositionChart(30*totalWindows, consensus.ChainWindowSize*totalWindows) sharesFound := cmdutils.NewPositionChart(30*totalWindows, consensus.ChainWindowSize*totalWindows)
unclesFound := cmdutils.NewPositionChart(30*totalWindows, consensus.ChainWindowSize*totalWindows) unclesFound := cmdutils.NewPositionChart(30*totalWindows, consensus.ChainWindowSize*totalWindows)
var sharesInWindow, unclesInWindow uint64
var longDiff, windowDiff types.Difficulty var longDiff, windowDiff types.Difficulty
wend := tipHeight - currentWindowSize wend := tipHeight - currentWindowSize
@ -927,14 +929,14 @@ func main() {
} }
if share.SideHeight > wend { if share.SideHeight > wend {
windowDiff = windowDiff.Add64(uncleWeight) windowDiff = windowDiff.Add64(uncleWeight)
unclesInWindow++ unclesInWindow.Add(int(int64(tipHeight)-int64(share.SideHeight)), 1)
} }
longDiff = longDiff.Add64(uncleWeight) longDiff = longDiff.Add64(uncleWeight)
} else { } else {
sharesFound.Add(int(int64(tipHeight)-toInt64(share.SideHeight)), 1) sharesFound.Add(int(int64(tipHeight)-toInt64(share.SideHeight)), 1)
if share.SideHeight > wend { if share.SideHeight > wend {
windowDiff = windowDiff.Add64(share.Difficulty) windowDiff = windowDiff.Add64(share.Difficulty)
sharesInWindow++ sharesInWindow.Add(int(int64(tipHeight)-toInt64(share.SideHeight)), 1)
} }
longDiff = longDiff.Add64(share.Difficulty) longDiff = longDiff.Add64(share.Difficulty)
} }
@ -947,20 +949,24 @@ func main() {
minerPage := &views.MinerPage{ minerPage := &views.MinerPage{
Refresh: refresh, Refresh: refresh,
Positions: struct { Positions: struct {
Resolution int Resolution int
SeparatorIndex int ResolutionWindow int
Blocks *cmdutils.PositionChart SeparatorIndex int
Uncles *cmdutils.PositionChart Blocks *cmdutils.PositionChart
Payouts *cmdutils.PositionChart Uncles *cmdutils.PositionChart
BlocksInWindow *cmdutils.PositionChart
UnclesInWindow *cmdutils.PositionChart
Payouts *cmdutils.PositionChart
}{ }{
Resolution: int(foundPayout.Resolution()), Resolution: int(foundPayout.Resolution()),
SeparatorIndex: int(consensus.ChainWindowSize*totalWindows - currentWindowSize), ResolutionWindow: int(sharesInWindow.Resolution()),
Blocks: sharesFound, SeparatorIndex: int(consensus.ChainWindowSize*totalWindows - currentWindowSize),
Uncles: unclesFound, Blocks: sharesFound,
Payouts: foundPayout, BlocksInWindow: sharesInWindow,
Uncles: unclesFound,
UnclesInWindow: unclesInWindow,
Payouts: foundPayout,
}, },
SharesInWindow: int(sharesInWindow),
UnclesInWindow: int(unclesInWindow),
Weight: longDiff.Lo, Weight: longDiff.Lo,
WindowWeight: windowDiff.Lo, WindowWeight: windowDiff.Lo,
Miner: miner, Miner: miner,