consensus/p2pool/sidechain/share.go
DataHoarder 03f19ae2ed
Some checks are pending
continuous-integration/drone/push Build is running
Improve base58 encode/decode and PackedAddress storage
2023-07-23 01:02:43 +02:00

104 lines
2.2 KiB
Go

package sidechain
import (
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/address"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
"slices"
"sync"
)
type Shares []*Share
func (s Shares) Index(addr address.PackedAddress) int {
return slices.IndexFunc(s, func(share *Share) bool {
return share.Address == addr
})
}
// Sort Consensus way of sorting Shares
func (s Shares) Sort() {
slices.SortFunc(s, func(a *Share, b *Share) int {
// Fast tests first. Skips further checks
if diff := int(a.Address[address.PackedAddressSpend][crypto.PublicKeySize-1]) - int(b.Address[address.PackedAddressSpend][crypto.PublicKeySize-1]); diff != 0 {
return diff
}
if a.Address == b.Address {
return 0
}
return a.Address.ComparePacked(&b.Address)
})
}
func (s Shares) Clone() (o Shares) {
o = make(Shares, len(s))
preAllocatedStructs := make([]Share, len(s))
for i := range s {
o[i] = &preAllocatedStructs[i]
o[i].Address = s[i].Address
o[i].Weight = s[i].Weight
}
return o
}
// Compact Merges duplicate Share entries based on Address
// len(s) must be greater than 0
func (s Shares) Compact() Shares {
if len(s) == 0 {
return s
}
// Sort shares based on address
s.Sort()
index := 0
for _, share := range s[1:] {
if s[index].Address == share.Address {
s[index].Weight = s[index].Weight.Add(share.Weight)
} else {
index++
s[index].Address = share.Address
s[index].Weight = share.Weight
}
}
return s[:index+1]
}
type PreAllocatedSharesPool struct {
pool sync.Pool
}
func NewPreAllocatedSharesPool[T uint64 | int](n T) *PreAllocatedSharesPool {
p := &PreAllocatedSharesPool{}
p.pool.New = func() any {
return PreAllocateShares(n)
}
return p
}
func (p *PreAllocatedSharesPool) Get() Shares {
return p.pool.Get().(Shares)
}
func (p *PreAllocatedSharesPool) Put(s Shares) {
p.pool.Put(s)
}
func PreAllocateShares[T uint64 | int](n T) Shares {
preAllocatedShares := make(Shares, n)
// Preserve locality
preAllocatedStructs := make([]Share, n)
for i := range preAllocatedShares {
preAllocatedShares[i] = &preAllocatedStructs[i]
}
return preAllocatedShares
}
type Share struct {
Address address.PackedAddress
Weight types.Difficulty
}