Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions sei-tendermint/internal/p2p/giga_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func (r *GigaRouter) BlockByNumber(ctx context.Context, n atypes.GlobalBlockNumb
// TODO(autobahn): replace this with a direct read from
// sei-db/ledger_db/block.BlockDB.GetBlockByHash once a writer is wired into
// block execution. The data.State-side index can also go away at that point.
func (r *GigaRouter) BlockByHash(_ context.Context, hash atypes.BlockHeaderHash) (*coretypes.ResultBlock, error) {
func (r *GigaRouter) BlockByHash(ctx context.Context, hash atypes.BlockHeaderHash) (*coretypes.ResultBlock, error) {
opt, err := r.data.GlobalBlockByHash(hash)
if err != nil {
return nil, fmt.Errorf("data.GlobalBlockByHash: %w", err)
Expand All @@ -203,12 +203,20 @@ func (r *GigaRouter) BlockByHash(_ context.Context, hash atypes.BlockHeaderHash)

// translateGlobalBlock converts an Autobahn GlobalBlock to the CometBFT
// coretypes.ResultBlock shape used by env.Block / env.BlockByHash and
// downstream evmrpc consumers. Caller must pass a non-nil *GlobalBlock
// with non-nil Header and Payload — that's the contract data.State
// guarantees on a successful lookup, and matches how executeBlock
// dereferences b.Header without a nil-check on the same type. The
// "no such block" case is rejected at the BlockByHash call site
// before delegating here.
// downstream evmrpc consumers. Caller must pass a non-nil *GlobalBlock with
// non-nil Header and Payload — that's the contract data.State guarantees on
// a successful lookup, and matches how executeBlock dereferences b.Header
// without a nil-check on the same type. The "no such block" case is
// rejected at the BlockByHash call site before delegating here.
//
// LastCommit is non-nil with empty Signatures, mirroring executeBlock's
// FinalizeBlock call which passes an empty abci.CommitInfo. Under Autobahn
// the committee is fixed by genesis (no validator-set updates), so the
// application is not in control of jailing — surfacing N "absent sig"
// entries here would make trace replay's BeginBlock bump missed-block
// counters and diverge from production. ToReqBeginBlock skips the per-
// validator loop when Signatures is empty, so empty Votes flow into
// distribution/slashing on both paths.
func (r *GigaRouter) translateGlobalBlock(gb *atypes.GlobalBlock) *coretypes.ResultBlock {
srcTxs := gb.Payload.Txs()
tmTxs := make(types.Txs, len(srcTxs))
Expand All @@ -227,7 +235,8 @@ func (r *GigaRouter) translateGlobalBlock(gb *atypes.GlobalBlock) *coretypes.Res
Height: utils.Clamp[int64](gb.GlobalNumber),
Time: gb.Timestamp,
},
Data: types.Data{Txs: tmTxs},
Data: types.Data{Txs: tmTxs},
LastCommit: &types.Commit{},
},
}
}
Expand Down
8 changes: 8 additions & 0 deletions sei-tendermint/internal/p2p/giga_router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,14 @@ func TestGigaRouter_FinalizeBlocks(t *testing.T) {
require.Equal(t, committed, rb.Block.Height, "router[%v].BlockByNumber(%v) height", i, committed)
require.NotEmpty(t, rb.BlockID.Hash, "router[%v].BlockByNumber(%v) block hash", i, committed)
require.Equal(t, genDoc.ChainID, rb.Block.Header.ChainID, "router[%v].BlockByNumber(%v) chain id", i, committed)
// LastCommit is non-nil with empty Signatures — mirrors
// executeBlock's FinalizeBlock(DecidedLastCommit: empty)
// so trace replay and production both see "no votes" on
// the prior block. ToReqBeginBlock skips the per-val loop
// when Signatures is empty, so this is also enough to
// avoid the OOB deref the original PR was guarding against.
require.NotNil(t, rb.Block.LastCommit, "router[%v].BlockByNumber(%v) LastCommit", i, committed)
require.Empty(t, rb.Block.LastCommit.Signatures, "router[%v].BlockByNumber(%v) Signatures", i, committed)
// Round-trip the just-fetched block hash back through
// BlockByHash and assert we get the same ResultBlock back.
var hashKey atypes.BlockHeaderHash
Expand Down
18 changes: 11 additions & 7 deletions sei-tendermint/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,17 @@ func (b *Block) ToProto() (*tmproto.Block, error) {

func (b *Block) ToReqBeginBlock(vals []*Validator) abci.RequestBeginBlock {
tmHeader := b.Header.ToProto()
votes := make([]abci.VoteInfo, 0, b.LastCommit.Size())
for i, val := range vals {
commitSig := b.LastCommit.Signatures[i]
votes = append(votes, abci.VoteInfo{
Validator: TM2PB.Validator(val),
SignedLastBlock: commitSig.BlockIDFlag != BlockIDFlagAbsent,
})
// b.LastCommit.Signatures is only empty on the trace path.
var votes []abci.VoteInfo
if len(b.LastCommit.Signatures) > 0 {
votes = make([]abci.VoteInfo, 0, b.LastCommit.Size())
for i, val := range vals {
commitSig := b.LastCommit.Signatures[i]
votes = append(votes, abci.VoteInfo{
Validator: TM2PB.Validator(val),
SignedLastBlock: commitSig.BlockIDFlag != BlockIDFlagAbsent,
})
}
}
abciEvidence := b.Evidence.ToABCI()
byzantineValidators := make([]abci.Evidence, 0, len(abciEvidence))
Expand Down
Loading