From 3254c6db3e505429c2f1d27729231cbe23c41b9c Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 1 Sep 2026 16:10:29 -0400 Subject: [PATCH] add cached storage insert of self build --- adapters.go | 24 ++++++++++++++++++------ adapters_test.go | 34 ++++++++++++++++++++++++++++++++++ instance.go | 4 ++-- msm/msm.go | 16 ++++++++++++++-- 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/adapters.go b/adapters.go index 4abcf515..9697cfd1 100644 --- a/adapters.go +++ b/adapters.go @@ -211,15 +211,24 @@ func (n *NoopAuxiliaryInfoApp) DefaultVersionID() common.VersionID { return 0 } -type BlockBuilderWaiter struct { +type blockBuilderWaiter struct { lock sync.Mutex cancel context.CancelFunc msm *metadata.StateMachine + cs *CachedStorage e *simplex.Epoch vm VM } -func (bw *BlockBuilderWaiter) stop() { +func newBlockBuilderWaiter(msm *metadata.StateMachine, cs *CachedStorage, vm VM) *blockBuilderWaiter { + return &blockBuilderWaiter{ + msm: msm, + cs: cs, + vm: vm, + } +} + +func (bw *blockBuilderWaiter) stop() { bw.lock.Lock() defer bw.lock.Unlock() if bw.cancel != nil { @@ -228,7 +237,7 @@ func (bw *BlockBuilderWaiter) stop() { } } -func (bw *BlockBuilderWaiter) WaitForPendingBlock(ctx context.Context) { +func (bw *blockBuilderWaiter) WaitForPendingBlock(ctx context.Context) { bw.lock.Lock() if bw.cancel != nil { bw.cancel() @@ -242,18 +251,21 @@ func (bw *BlockBuilderWaiter) WaitForPendingBlock(ctx context.Context) { bw.msm.WaitForPendingBlock(ctx, md) } -func (bw *BlockBuilderWaiter) BuildBlock(ctx context.Context, metadata common.ProtocolMetadata, blacklist common.Blacklist) (common.VerifiedBlock, bool) { +func (bw *blockBuilderWaiter) BuildBlock(ctx context.Context, metadata common.ProtocolMetadata, blacklist common.Blacklist) (common.VerifiedBlock, bool) { block, err := bw.msm.BuildBlock(ctx, metadata, blacklist) if err != nil { return nil, false } - pb := ParsedBlock{ + pb := &ParsedBlock{ StateMachineBlock: *block, msm: bw.msm, } - return &pb, true + // Ensure the builders block is in the cache after verification + bw.cs.insertBlock(pb) + + return pb, true } type blockDeserializer struct { diff --git a/adapters_test.go b/adapters_test.go index 84eb8a53..b889432d 100644 --- a/adapters_test.go +++ b/adapters_test.go @@ -209,3 +209,37 @@ func TestCachedStoragePopulatedByWal(t *testing.T) { return got.BlockHeader().Digest == block.BlockHeader().Digest }, 20*time.Second, 100*time.Millisecond) } + +// TestCachedStoragePopulatedBySelfBuiltBlock asserts that a block a node builds for its +// own proposal is inserted into the CachedStorage, retrievable by seq and digest before +// it is finalized and indexed. +func TestCachedStoragePopulatedBySelfBuiltBlock(t *testing.T) { + genesisBlock := &testInnerBlock{Height_: 0, TS: time.Now(), Payload: []byte("genesis")} + cs := NewCachedStorage(newStorageWithGenesis(t, genesisBlock)) + + msm, err := metadata.NewStateMachine(&metadata.Config{ + Logger: testutil.MakeLogger(t, 1), + GetBlock: cs.RetrieveBlock, + LastNonSimplexInnerBlock: genesisBlock, + GenesisValidatorSet: metadata.NodeBLSMappings{ + {NodeID: avalanchego.NodeID{1}, BLSKey: []byte{1}, Weight: 1}, + }, + AuxiliaryInfoApp: &NoopAuxiliaryInfoApp{}, + }) + require.NoError(t, err) + cs.msm = msm + + bw := newBlockBuilderWaiter(msm, cs, newTestVM()) + + // Build a block on top of genesis + genesis := &ParsedBlock{StateMachineBlock: metadata.StateMachineBlock{InnerBlock: genesisBlock}} + md := common.ProtocolMetadata{Seq: 1, Prev: genesis.BlockHeader().Digest} + vb, built := bw.BuildBlock(t.Context(), md, common.Blacklist{}) + require.True(t, built) + require.Equal(t, md.Seq, vb.BlockHeader().Seq) + + cached, fin, err := cs.Retrieve(md.Seq, vb.BlockHeader().Digest) + require.NoError(t, err) + require.Nil(t, fin) + require.Same(t, vb, cached) +} diff --git a/instance.go b/instance.go index 9341d3f6..2f12beee 100644 --- a/instance.go +++ b/instance.go @@ -494,7 +494,7 @@ func (i *Instance) createEpochConfig(epoch uint64, validators common.Nodes) (*ep return nil, err } - blockBuilder := &BlockBuilderWaiter{vm: i.Config.VM, msm: msm} + blockBuilder := newBlockBuilderWaiter(msm, i.cs, i.Config.VM) comm := newCommunication(i.Config.Sender, i.Config.Broadcaster, validators) @@ -574,5 +574,5 @@ func (i *Instance) startAtEpoch(validators common.Nodes, epoch uint64) error { type epochConfig struct { simplex.EpochConfig - bbw *BlockBuilderWaiter + bbw *blockBuilderWaiter } diff --git a/msm/msm.go b/msm/msm.go index 72d4831c..0ce8f0f8 100644 --- a/msm/msm.go +++ b/msm/msm.go @@ -300,7 +300,13 @@ func (sm *StateMachine) WaitForPendingBlock(ctx context.Context, currentRoundMet parentBlock, finalization, err := sm.GetBlock(prevBlockSeq, currentRoundMetadata.Prev) if err != nil { - sm.Logger.Debug("WaitForPendingBlock failed to get block", zap.Uint64("seq", prevBlockSeq), zap.Error(err)) + sm.Logger.Debug( + "WaitForPendingBlock failed to get block", + zap.Uint64("Current Seq", currentRoundMetadata.Seq), + zap.Uint64("Current Round", currentRoundMetadata.Round), + zap.Uint64("seq", prevBlockSeq), + zap.Error(err), + ) sm.BlockBuilder.WaitForPendingBlock(ctx) return } @@ -367,7 +373,13 @@ func (sm *StateMachine) WaitForPendingBlock(ctx context.Context, currentRoundMet blockBuildingDecider := sm.createBlockBuildingDecider(pChainReferenceHeight) _, err = blockBuildingDecider.shouldBuildBlock(ctx) if err != nil { - sm.Logger.Debug("Error while deciding whether to build a block", zap.Error(err)) + sm.Logger.Debug( + "Error while deciding whether to build a block", + zap.Uint64("Current Round", currentRoundMetadata.Round), + zap.Uint64("Current Seq", currentRoundMetadata.Seq), + zap.Stringer("Prev Digest", currentRoundMetadata.Prev), + zap.Error(err), + ) return } }