@@ -1686,6 +1686,77 @@ describe('BlockStore', () => {
16861686 } ) ;
16871687 } ) ;
16881688
1689+ describe ( 'getCheckpointsBySlot' , ( ) => {
1690+ // cp1: slot 5, blocks 1-2 | cp2: slot 8, blocks 3-5 | cp3: slot 12, block 6.
1691+ const addCheckpointsAtSlots = async ( ) => {
1692+ const cp1 = makePublishedCheckpoint (
1693+ await Checkpoint . random ( CheckpointNumber ( 1 ) , { numBlocks : 2 , startBlockNumber : 1 , slotNumber : SlotNumber ( 5 ) } ) ,
1694+ 10 ,
1695+ ) ;
1696+ const cp2 = makePublishedCheckpoint (
1697+ await Checkpoint . random ( CheckpointNumber ( 2 ) , {
1698+ numBlocks : 3 ,
1699+ startBlockNumber : 3 ,
1700+ previousArchive : cp1 . checkpoint . blocks . at ( - 1 ) ! . archive ,
1701+ slotNumber : SlotNumber ( 8 ) ,
1702+ } ) ,
1703+ 11 ,
1704+ ) ;
1705+ const cp3 = makePublishedCheckpoint (
1706+ await Checkpoint . random ( CheckpointNumber ( 3 ) , {
1707+ numBlocks : 1 ,
1708+ startBlockNumber : 6 ,
1709+ previousArchive : cp2 . checkpoint . blocks . at ( - 1 ) ! . archive ,
1710+ slotNumber : SlotNumber ( 12 ) ,
1711+ } ) ,
1712+ 12 ,
1713+ ) ;
1714+ await blockStore . addCheckpoints ( [ cp1 , cp2 , cp3 ] ) ;
1715+ } ;
1716+
1717+ const numbersBySlot = ( slot : number , limit : number , reverse : boolean ) =>
1718+ blockStore . getCheckpointsBySlot ( SlotNumber ( slot ) , limit , reverse ) . then ( cps => cps . map ( cp => cp . checkpointNumber ) ) ;
1719+
1720+ it ( 'returns empty array when no checkpoints exist' , async ( ) => {
1721+ expect ( await numbersBySlot ( 10 , 1 , true ) ) . toEqual ( [ ] ) ;
1722+ } ) ;
1723+
1724+ it ( 'returns the latest checkpoint at or before the slot when reverse (exact hit)' , async ( ) => {
1725+ await addCheckpointsAtSlots ( ) ;
1726+ const [ cp ] = await blockStore . getCheckpointsBySlot ( SlotNumber ( 8 ) , 1 , true ) ;
1727+ expect ( cp . checkpointNumber ) . toBe ( 2 ) ;
1728+ expect ( cp . startBlock ) . toBe ( 3 ) ;
1729+ expect ( cp . blockCount ) . toBe ( 3 ) ;
1730+ } ) ;
1731+
1732+ it ( 'walks back to the nearest earlier checkpoint when the slot falls in a gap' , async ( ) => {
1733+ await addCheckpointsAtSlots ( ) ;
1734+ // Slot 10 has no checkpoint; the nearest at or before is cp2 at slot 8.
1735+ expect ( await numbersBySlot ( 10 , 1 , true ) ) . toEqual ( [ 2 ] ) ;
1736+ } ) ;
1737+
1738+ it ( 'returns empty when reverse and the slot precedes the earliest checkpoint' , async ( ) => {
1739+ await addCheckpointsAtSlots ( ) ;
1740+ expect ( await numbersBySlot ( 4 , 1 , true ) ) . toEqual ( [ ] ) ;
1741+ } ) ;
1742+
1743+ it ( 'returns multiple checkpoints nearest-first when reverse' , async ( ) => {
1744+ await addCheckpointsAtSlots ( ) ;
1745+ expect ( await numbersBySlot ( 12 , 2 , true ) ) . toEqual ( [ 3 , 2 ] ) ;
1746+ } ) ;
1747+
1748+ it ( 'returns the earliest checkpoint at or after the slot when forward' , async ( ) => {
1749+ await addCheckpointsAtSlots ( ) ;
1750+ // Slot 6 has no checkpoint; the nearest at or after is cp2 at slot 8.
1751+ expect ( await numbersBySlot ( 6 , 1 , false ) ) . toEqual ( [ 2 ] ) ;
1752+ } ) ;
1753+
1754+ it ( 'returns multiple checkpoints ascending when forward' , async ( ) => {
1755+ await addCheckpointsAtSlots ( ) ;
1756+ expect ( await numbersBySlot ( 5 , 3 , false ) ) . toEqual ( [ 1 , 2 , 3 ] ) ;
1757+ } ) ;
1758+ } ) ;
1759+
16891760 describe ( 'getCheckpointedBlock' , ( ) => {
16901761 beforeEach ( async ( ) => {
16911762 await blockStore . addCheckpoints ( publishedCheckpoints ) ;
0 commit comments