mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-05 18:42:19 +00:00
02dd405e93
* MGR Make Schedule v0
137 lines
3.3 KiB
Go
137 lines
3.3 KiB
Go
package mgr
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/ledgerwatch/turbo-geth/common"
|
|
"github.com/ledgerwatch/turbo-geth/ethdb"
|
|
"github.com/ledgerwatch/turbo-geth/trie"
|
|
)
|
|
|
|
const (
|
|
TicksPerCycle uint64 = 256
|
|
BlocksPerTick uint64 = 20
|
|
BlocksPerCycle uint64 = BlocksPerTick * TicksPerCycle
|
|
|
|
BytesPerWitness uint64 = 1024 * 1024
|
|
)
|
|
|
|
type Schedule struct {
|
|
Ticks []Tick
|
|
}
|
|
|
|
type Tick struct {
|
|
Number uint64
|
|
FromBlock uint64
|
|
ToBlock uint64
|
|
FromSize uint64
|
|
ToSize uint64
|
|
StateSizeSlices []StateSizeSlice
|
|
}
|
|
|
|
type StateSizeSlice struct {
|
|
FromSize uint64
|
|
ToSize uint64
|
|
}
|
|
|
|
type StateSlice struct {
|
|
From []byte
|
|
To []byte
|
|
}
|
|
|
|
func (s Schedule) String() string { return fmt.Sprintf("Schedule{Ticks:%s}", s.Ticks) }
|
|
func (t Tick) String() string {
|
|
return fmt.Sprintf("Tick{%d,Blocks:%d-%d,Sizes:%d-%d,Slices:%d}", t.Number, t.FromBlock, t.ToBlock, t.FromSize, t.ToSize, t.StateSizeSlices)
|
|
}
|
|
func (ss StateSlice) String() string { return fmt.Sprintf("{%x-%x}", ss.From, ss.To) }
|
|
|
|
func (t Tick) IsLastInCycle() bool {
|
|
return t.Number == TicksPerCycle-1
|
|
}
|
|
|
|
func NewStateSchedule(stateSize, fromBlock, toBlock uint64) Schedule {
|
|
schedule := Schedule{}
|
|
|
|
for fromBlock <= toBlock {
|
|
tick := NewTick(fromBlock, stateSize)
|
|
schedule.Ticks = append(schedule.Ticks, tick)
|
|
fromBlock = tick.ToBlock + 1
|
|
}
|
|
|
|
return schedule
|
|
}
|
|
|
|
func NewTick(blockNr, stateSize uint64) Tick {
|
|
number := blockNr / BlocksPerTick % TicksPerCycle
|
|
fromSize := number * stateSize / TicksPerCycle
|
|
|
|
tick := Tick{
|
|
Number: number,
|
|
FromBlock: blockNr,
|
|
ToBlock: blockNr - blockNr%BlocksPerTick + BlocksPerTick - 1,
|
|
FromSize: fromSize,
|
|
ToSize: fromSize + stateSize/TicksPerCycle - 1,
|
|
}
|
|
|
|
for i := uint64(0); ; i++ {
|
|
ss := StateSizeSlice{
|
|
FromSize: tick.FromSize + i*BytesPerWitness,
|
|
ToSize: min(tick.FromSize+(i+1)*BytesPerWitness-1, tick.ToSize),
|
|
}
|
|
|
|
tick.StateSizeSlices = append(tick.StateSizeSlices, ss)
|
|
if ss.ToSize >= tick.ToSize {
|
|
break
|
|
}
|
|
}
|
|
|
|
return tick
|
|
}
|
|
|
|
func min(a, b uint64) uint64 {
|
|
if a < b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|
|
|
|
// Temporary unoptimal implementation. Get existing short prefixes from trie, then resolve range, and give long prefixes from trie.
|
|
func StateSizeSlice2StateSlice(db ethdb.Database, tr *trie.Trie, in StateSizeSlice) (StateSlice, error) {
|
|
out := StateSlice{}
|
|
|
|
out.From, _ = tr.PrefixByCumulativeWitnessSize(in.FromSize)
|
|
out.To, _ = tr.PrefixByCumulativeWitnessSize(in.ToSize)
|
|
|
|
retain := trie.NewRetainRange(common.CopyBytes(out.From), common.CopyBytes(out.To))
|
|
if err := _resolve(db, tr, retain); err != nil {
|
|
return out, err
|
|
}
|
|
|
|
var found bool
|
|
out.From, found = tr.PrefixByCumulativeWitnessSize(in.FromSize)
|
|
if !found {
|
|
panic(fmt.Sprintf("why? %x\n", out.From))
|
|
}
|
|
out.To, found = tr.PrefixByCumulativeWitnessSize(in.ToSize)
|
|
if !found {
|
|
panic(fmt.Sprintf("why? %x\n", out.To))
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
func _resolve(db ethdb.Database, tr *trie.Trie, decider trie.RetainDecider) error {
|
|
loader := trie.NewSubTrieLoader(0)
|
|
dbPrefixes, fixedbits, hooks := tr.FindSubTriesToLoad(decider)
|
|
subTries, err := loader.LoadSubTries(db, 0, decider, dbPrefixes, fixedbits, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
//fmt.Printf("retain: %s\n", decider)
|
|
//fmt.Printf("dbPrefixes: %x, %d\n", dbPrefixes, len(subTries.Hashes))
|
|
if err := tr.HookSubTries(subTries, hooks); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|