Skip to content

Commit

Permalink
Storing the best node set on stop and retrieving on launch
Browse files Browse the repository at this point in the history
  • Loading branch information
gameofpointers committed Nov 11, 2024
1 parent 080c7d5 commit ea81e49
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 50 deletions.
149 changes: 108 additions & 41 deletions cmd/utils/hierarchical_coordinator.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const (

var (
c_currentExpansionNumberKey = []byte("cexp")
c_bestNodeKey = []byte("best")
)

type Node struct {
Expand All @@ -45,10 +46,61 @@ type Node struct {
entropy *big.Int
}

func (ch *Node) ProtoEncode() *ProtoNode {

Check failure on line 49 in cmd/utils/hierarchical_coordinator.go

View workflow job for this annotation

GitHub Actions / call-common-workflow / buildDeployDevGo / build

undefined: ProtoNode
protoNumber := make([][]byte, common.HierarchyDepth)
for i, num := range ch.number {
protoNumber[i] = num.Bytes()
}
protoNode := &ProtoNode{

Check failure on line 54 in cmd/utils/hierarchical_coordinator.go

View workflow job for this annotation

GitHub Actions / call-common-workflow / buildDeployDevGo / build

undefined: ProtoNode
Hash: ch.hash.ProtoEncode(),
Number: protoNumber,
Location: ch.location.ProtoEncode(),
Entropy: ch.entropy.Bytes(),
}
return protoNode
}

func (ch *Node) ProtoDecode(protoNode *ProtoNode) {

Check failure on line 63 in cmd/utils/hierarchical_coordinator.go

View workflow job for this annotation

GitHub Actions / call-common-workflow / buildDeployDevGo / build

undefined: ProtoNode
hash := &common.Hash{}
hash.ProtoDecode(protoNode.GetHash())
ch.hash = *hash

number := make([]*big.Int, common.HierarchyDepth)
for i, num := range protoNode.GetNumber() {
number[i] = new(big.Int).SetBytes(num)
}
ch.number = number

location := &common.Location{}
location.ProtoDecode(protoNode.GetLocation())
ch.location = *location

ch.entropy = new(big.Int).SetBytes(protoNode.GetEntropy())
}

type NodeSet struct {
nodes map[string]Node
}

func (ns *NodeSet) ProtoEncode() *ProtoNodeSet {

Check failure on line 85 in cmd/utils/hierarchical_coordinator.go

View workflow job for this annotation

GitHub Actions / call-common-workflow / buildDeployDevGo / build

undefined: ProtoNodeSet
protoNodeSet := &ProtoNodeSet{}

Check failure on line 86 in cmd/utils/hierarchical_coordinator.go

View workflow job for this annotation

GitHub Actions / call-common-workflow / buildDeployDevGo / build

undefined: ProtoNodeSet
protoNodeSet.NodeSet = make(map[string]*ProtoNode)

Check failure on line 87 in cmd/utils/hierarchical_coordinator.go

View workflow job for this annotation

GitHub Actions / call-common-workflow / buildDeployDevGo / build

undefined: ProtoNode

for loc, node := range ns.nodes {
node := node.ProtoEncode()
protoNodeSet.NodeSet[loc] = node
}
return protoNodeSet
}

func (ns *NodeSet) ProtoDecode(protoNodeSet *ProtoNodeSet) {

Check failure on line 96 in cmd/utils/hierarchical_coordinator.go

View workflow job for this annotation

GitHub Actions / call-common-workflow / buildDeployDevGo / build

undefined: ProtoNodeSet
for loc, protoNode := range protoNodeSet.NodeSet {
node := &Node{}
node.ProtoDecode(protoNode)
ns.nodes[loc] = *node
}
}

func (ch *Node) Empty() bool {
return ch.hash == common.Hash{} && ch.location.Equal(common.Location{}) && ch.entropy == nil
}
Expand Down Expand Up @@ -137,6 +189,8 @@ func (hc *HierarchicalCoordinator) InitPendingHeaders() {
}
}
hc.Add(new(big.Int).SetUint64(0), nodeSet, hc.pendingHeaders)

hc.LoadBestNodeSet()
}

func (hc *HierarchicalCoordinator) Add(entropy *big.Int, node NodeSet, newPendingHeaders *PendingHeaders) {
Expand Down Expand Up @@ -208,11 +262,14 @@ func (ns *NodeSet) Extendable(wo *types.WorkObject, order int) bool {
func (ns *NodeSet) Entropy(numRegions int, numZones int) *big.Int {
entropy := new(big.Int)

entropy.Add(entropy, ns.nodes[common.Location{}.Name()].entropy)
primeEntropy := ns.nodes[common.Location{}.Name()].entropy
entropy.Add(entropy, primeEntropy)
for i := 0; i < numRegions; i++ {
entropy.Add(entropy, ns.nodes[common.Location{byte(i)}.Name()].entropy)
regionEntropy := ns.nodes[common.Location{byte(i)}.Name()].entropy
entropy.Add(entropy, regionEntropy)
for j := 0; j < numZones; j++ {
entropy.Add(entropy, ns.nodes[common.Location{byte(i), byte(j)}.Name()].entropy)
zoneEntropy := ns.nodes[common.Location{byte(i), byte(j)}.Name()].entropy
entropy.Add(entropy, zoneEntropy)
}
}

Expand Down Expand Up @@ -430,6 +487,7 @@ func (hc *HierarchicalCoordinator) Stop() {
for _, chainEventSub := range hc.chainSubs {
chainEventSub.Unsubscribe()
}
hc.StoreBestNodeSet()
hc.expansionSub.Unsubscribe()
hc.db.Close()
hc.wg.Wait()
Expand Down Expand Up @@ -602,44 +660,6 @@ func (hc *HierarchicalCoordinator) ChainEventLoop(chainEvent chan core.ChainEven
for {
select {
case head := <-chainEvent:
// If this is the first block we have after a restart, then we can
// add this block into the node set directly
// Since on startup we initialize the pending headers cache with the
// genesis block, we can check and see if we are in that state
// We can do that by checking the length of the pendding headers order
// cache length is 1
if len(hc.pendingHeaders.order) == 1 {
// create a nodeset on this block
nodeSet := NodeSet{
nodes: make(map[string]Node),
}

//Initialize for prime
backend := hc.GetBackend(common.Location{})
entropy := backend.TotalLogEntropy(head.Block)
newNode := Node{
hash: head.Block.ParentHash(common.PRIME_CTX),
number: head.Block.NumberArray(),
location: common.Location{},
entropy: entropy,
}
nodeSet.nodes[common.Location{}.Name()] = newNode

regionLocation := common.Location{byte(head.Block.Location().Region())}
backend = hc.GetBackend(regionLocation)
newNode.hash = head.Block.ParentHash(common.REGION_CTX)
newNode.location = regionLocation
newNode.entropy = entropy
nodeSet.nodes[regionLocation.Name()] = newNode

zoneLocation := head.Block.Location()
backend = hc.GetBackend(zoneLocation)
newNode.hash = head.Block.ParentHash(common.ZONE_CTX)
newNode.location = zoneLocation
newNode.entropy = entropy
nodeSet.nodes[zoneLocation.Name()] = newNode
hc.Add(entropy, nodeSet, hc.pendingHeaders)
}

go hc.ReapplicationLoop(head)
go hc.ComputeMapPending(head)
Expand Down Expand Up @@ -1321,3 +1341,50 @@ func (hc *HierarchicalCoordinator) GetBackendForLocationAndOrder(location common
}
return nil
}

func (hc *HierarchicalCoordinator) StoreBestNodeSet() {

log.Global.Info("Storing the best node set on stop")

bestNode, exists := hc.pendingHeaders.collection.Get(hc.bestEntropy.String())
if !exists {
log.Global.Error("best entropy node set doesnt exist in the pending headers collection")
}

protoBestNode := bestNode.ProtoEncode()

data, err := proto.Marshal(protoBestNode)
if err != nil {
log.Global.Error("Error marshalling best node, err: ", err)
return
}

err = hc.db.Put(c_bestNodeKey, data, nil)
if err != nil {
log.Global.Error("Error storing the best node key, err: ", err)
return
}
}

func (hc *HierarchicalCoordinator) LoadBestNodeSet() {
data, err := hc.db.Get(c_bestNodeKey, nil)
if err != nil {
log.Global.Error("Error loading the best node, err: ", err)
return
}

protoNodeSet := &ProtoNodeSet{}

Check failure on line 1376 in cmd/utils/hierarchical_coordinator.go

View workflow job for this annotation

GitHub Actions / call-common-workflow / buildDeployDevGo / build

undefined: ProtoNodeSet
err = proto.Unmarshal(data, protoNodeSet)
if err != nil {
log.Global.Error("Error unmarshalling the proto node set, err: ", err)
return
}

nodeSet := NodeSet{}
nodeSet.nodes = make(map[string]Node)
nodeSet.ProtoDecode(protoNodeSet)

numRegions, numZones := common.GetHierarchySizeForExpansionNumber(hc.currentExpansionNumber)
hc.bestEntropy = nodeSet.Entropy(int(numRegions), int(numZones))
hc.Add(hc.bestEntropy, nodeSet, hc.pendingHeaders)
}
2 changes: 1 addition & 1 deletion core/headerchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -1224,7 +1224,7 @@ func (hc *HeaderChain) ComputeExpansionNumber(parent *types.WorkObject) (uint8,
}

// If the Prime Terminus is genesis the expansion number is the genesis expansion number
if hc.IsGenesisHash(primeTerminusHash) && hc.NodeLocation().Equal(common.Location{0, 0}) {
if hc.IsGenesisHash(primeTerminusHash) && hc.NodeLocation().Equal(common.Location{0, 0}) || hc.config.StartingExpansionNumber != 0 {
return primeTerminus.ExpansionNumber(), nil
} else {
// check if the prime terminus is the block where the threshold count
Expand Down
17 changes: 9 additions & 8 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ var (
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
AllProgpowProtocolChanges = &ChainConfig{big.NewInt(1337), "progpow", new(Blake3powConfig), new(ProgpowConfig), common.Location{}, common.Hash{}, false}
AllProgpowProtocolChanges = &ChainConfig{big.NewInt(1337), "progpow", new(Blake3powConfig), new(ProgpowConfig), common.Location{}, common.Hash{}, false, 0}

TestChainConfig = &ChainConfig{big.NewInt(1), "progpow", new(Blake3powConfig), new(ProgpowConfig), common.Location{}, common.Hash{}, false}
TestChainConfig = &ChainConfig{big.NewInt(1), "progpow", new(Blake3powConfig), new(ProgpowConfig), common.Location{}, common.Hash{}, false, 0}
TestRules = TestChainConfig.Rules(new(big.Int))
)

Expand All @@ -126,12 +126,13 @@ var (
type ChainConfig struct {
ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection
// Various consensus engines
ConsensusEngine string
Blake3Pow *Blake3powConfig `json:"blake3pow,omitempty"`
Progpow *ProgpowConfig `json:"progpow,omitempty"`
Location common.Location
DefaultGenesisHash common.Hash
IndexAddressUtxos bool
ConsensusEngine string
Blake3Pow *Blake3powConfig `json:"blake3pow,omitempty"`
Progpow *ProgpowConfig `json:"progpow,omitempty"`
Location common.Location
DefaultGenesisHash common.Hash
IndexAddressUtxos bool
StartingExpansionNumber uint64
}

// SetLocation sets the location on the chain config
Expand Down
1 change: 1 addition & 0 deletions quai/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ func New(stack *node.Node, p2p NetworkingAPI, config *quaiconfig.Config, nodeCtx
chainConfig.Location = config.NodeLocation // TODO: See why this is necessary
chainConfig.DefaultGenesisHash = config.DefaultGenesisHash
chainConfig.IndexAddressUtxos = config.IndexAddressUtxos
chainConfig.StartingExpansionNumber = startingExpansionNumber
logger.WithFields(log.Fields{
"Ctx": nodeCtx,
"NodeLocation": config.NodeLocation,
Expand Down

0 comments on commit ea81e49

Please sign in to comment.