diff --git a/pkg/protocol/chain.go b/pkg/protocol/chain.go index 5639c7392..2acbb4a68 100644 --- a/pkg/protocol/chain.go +++ b/pkg/protocol/chain.go @@ -20,6 +20,9 @@ type Chain struct { // ParentChain contains the chain that this chain forked from. ParentChain reactive.Variable[*Chain] + // DivergencePointVerified contains a flag that indicates whether the divergence point of this chain is verified. + DivergencePointVerified reactive.Event + // ChildChains contains the set of all chains that forked from this chain. ChildChains reactive.Set[*Chain] @@ -75,6 +78,7 @@ func newChain(chains *Chains) *Chain { c := &Chain{ ForkingPoint: reactive.NewVariable[*Commitment](), ParentChain: reactive.NewVariable[*Chain](), + DivergencePointVerified: reactive.NewEvent(), ChildChains: reactive.NewSet[*Chain](), LatestCommitment: reactive.NewVariable[*Commitment](), LatestAttestedCommitment: reactive.NewVariable[*Commitment](), @@ -232,6 +236,8 @@ func (c *Chain) initDerivedProperties() (shutdown func()) { c.deriveShouldEvict(forkingPoint, parentChain), ) }), + + c.deriveDivergencePointVerified(forkingPoint), ) }), ), @@ -290,6 +296,17 @@ func (c *Chain) deriveChildChains(child *Chain) (teardown func()) { return } +// deriveDivergencePointVerified defines how a chain determines whether its divergence point is verified. +func (c *Chain) deriveDivergencePointVerified(forkingPoint *Commitment) (shutdown func()) { + return lo.Batch( + c.DivergencePointVerified.InheritFrom(forkingPoint.IsRoot), + + forkingPoint.Parent.WithNonEmptyValue(func(parentOfForkingPoint *Commitment) (teardown func()) { + return c.DivergencePointVerified.InheritFrom(parentOfForkingPoint.IsVerified) + }), + ) +} + // deriveParentChain defines how a chain determines its parent chain from its forking point (it inherits the Chain from // the parent commitment of the forking point or nil if either of them is still unknown). func (c *Chain) deriveParentChain(forkingPoint *Commitment) (shutdown func()) { diff --git a/pkg/protocol/chains.go b/pkg/protocol/chains.go index 89da80693..01ce3d449 100644 --- a/pkg/protocol/chains.go +++ b/pkg/protocol/chains.go @@ -323,13 +323,7 @@ func (c *Chains) initChainSwitching() (shutdown func()) { return lo.BatchReverse( c.HeaviestClaimedCandidate.WithNonEmptyValue(func(heaviestClaimedCandidate *Chain) (shutdown func()) { - return heaviestClaimedCandidate.ForkingPoint.WithNonEmptyValue(func(forkingPoint *Commitment) (teardown func()) { - return forkingPoint.Parent.WithNonEmptyValue(func(parentOfForkingPoint *Commitment) (teardown func()) { - return parentOfForkingPoint.IsVerified.WithNonEmptyValue(func(_ bool) (teardown func()) { - return heaviestClaimedCandidate.RequestAttestations.ToggleValue(true) - }) - }) - }) + return heaviestClaimedCandidate.RequestAttestations.ToggleValue(true) }), c.HeaviestAttestedCandidate.OnUpdate(func(_ *Chain, heaviestAttestedCandidate *Chain) { @@ -351,19 +345,21 @@ func (c *Chains) initChainSwitching() (shutdown func()) { func (c *Chains) trackHeaviestCandidates(chain *Chain) (teardown func()) { return chain.LatestCommitment.OnUpdate(func(_ *Commitment, latestCommitment *Commitment) { - targetSlot := latestCommitment.ID().Index() + chain.DivergencePointVerified.OnTrigger(func() { + targetSlot := latestCommitment.ID().Index() - if evictionEvent := c.protocol.EvictionEvent(targetSlot); !evictionEvent.WasTriggered() { - c.HeaviestClaimedCandidate.registerCommitment(targetSlot, latestCommitment, evictionEvent) + if evictionEvent := c.protocol.EvictionEvent(targetSlot); !evictionEvent.WasTriggered() { + c.HeaviestClaimedCandidate.registerCommitment(targetSlot, latestCommitment, evictionEvent) - latestCommitment.IsAttested.OnTrigger(func() { - c.HeaviestAttestedCandidate.registerCommitment(targetSlot, latestCommitment, evictionEvent) - }) + latestCommitment.IsAttested.OnTrigger(func() { + c.HeaviestAttestedCandidate.registerCommitment(targetSlot, latestCommitment, evictionEvent) + }) - latestCommitment.IsVerified.OnTrigger(func() { - c.HeaviestVerifiedCandidate.registerCommitment(targetSlot, latestCommitment, evictionEvent) - }) - } + latestCommitment.IsVerified.OnTrigger(func() { + c.HeaviestVerifiedCandidate.registerCommitment(targetSlot, latestCommitment, evictionEvent) + }) + } + }) }) }