package Ġio . horizontal systems . bitcoin core . blocks Ċ Ċ import Ġcom . n ha ar man . mock it ok otlin 2 .* Ċ import Ġio . horizontal systems . bitcoin core . Bitcoin Core Ċ import Ġio . horizontal systems . bitcoin core . core . I Storage Ċ import Ġio . horizontal systems . bitcoin core . core . Kit State Provider Ċ import Ġio . horizontal systems . bitcoin core . extensions . hex To ByteArray Ċ import Ġio . horizontal systems . bitcoin core . managers . B loom Filter Manager Ċ import Ġio . horizontal systems . bitcoin core . managers . PublicKey Manager Ċ import Ġio . horizontal systems . bitcoin core . models . Block Ċ import Ġio . horizontal systems . bitcoin core . models . Block Hash Ċ import Ġio . horizontal systems . bitcoin core . models . Mer kle Block Ċ import Ġio . horizontal systems . bitcoin core . network . Network Ċ import Ġio . horizontal systems . bitcoin core . transactions . Transaction Processor Ċ import Ġorg . junit . Assert . assertEquals Ċ import Ġorg . mockito . Mockito . mock Ċ import Ġorg . mockito . Mockito . reset Ċ import Ġorg . spe k framework . spe k 2 . Spe k Ċ import Ġorg . spe k framework . spe k 2 . style . specification . describe Ċ Ċ object ĠBlock Sync er Test Ġ: ĠSpe k ({ ĊĊĠĠĠ Ġlateinit Ġvar Ġblock Sync er : ĠBlock Sync er ĊĊĠĠĠ Ġval Ġstorage Ġ= Ġmock ( I Storage :: class . java ) ĊĠĠĠ Ġval Ġblockchain Ġ= Ġmock ( Blockchain :: class . java ) ĊĠĠĠ Ġval Ġtransaction Processor Ġ= Ġmock ( Transaction Processor :: class . java ) ĊĠĠĠ Ġval ĠpublicKey Manager Ġ= Ġmock ( PublicKey Manager :: class . java ) ĊĠĠĠ Ġval Ġlistener Ġ= Ġmock ( Kit State Provider :: class . java ) ĊĠĠĠ Ġval Ġnetwork Ġ= Ġmock ( Network :: class . java ) ĊĊĠĠĠ Ġval Ġstate Ġ= Ġmock ( Block Sync er . State :: class . java ) ĊĠĠĠ Ġval Ġcheckpoint Block Ġ= Ġmock ( Block :: class . java ) ĊĊĠĠĠ ĠbeforeEach Test Ġ{ ĊĠĠĠĠĠĠĠ Ġwhenever ( checkpoint Block . height ). thenReturn ( 1 ) ĊĠĠĠĠĠĠĠ Ġwhenever ( network . last Checkpoint Block ). thenReturn ( checkpoint Block ) ĊĊĠĠĠĠĠĠĠ Ġwhenever ( storage . blocks Count ()). thenReturn ( 1 ) ĊĠĠĠĠĠĠĠ Ġwhenever ( storage . last Block ()). thenReturn ( null ) ĊĊĠĠĠĠĠĠĠ Ġblock Sync er Ġ= ĠBlock Sync er ( storage , Ġblockchain , Ġtransaction Processor , ĠpublicKey Manager , Ġlistener , Ġnetwork . last Checkpoint Block , Ġstate ) ĊĠĠĠ Ġ} ĊĊĠĠĠ ĠafterEach Test Ġ{ ĊĠĠĠĠĠĠĠ Ġreset ( storage , Ġblockchain , Ġtransaction Processor , ĠpublicKey Manager , Ġlistener , Ġnetwork , Ġstate ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe ("# init ") Ġ{ ĊĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreset ( storage , Ġlistener ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġthere Ġare Ġsome Ġsaved Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . blocks Count ()). thenReturn ( 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . last Block ()). thenReturn ( checkpoint Block ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBlock Sync er ( storage , Ġblockchain , Ġtransaction Processor , ĠpublicKey Manager , Ġlistener , Ġnetwork . last Checkpoint Block , Ġstate ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" does Ġnot Ġsaves Ġblock Ġto Ġstorage ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( storage , Ġnever ()). save Block ( checkpoint Block ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" triggers Ġ# on Initial Best Block Height Update Ġevent Ġon Ġlistener ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( listener ). on Initial Best Block Height Update ( checkpoint Block . height ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġthere Ġis Ġno Ġblock Ġin Ġstorage ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . blocks Count ()). thenReturn ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . last Block ()). thenReturn ( checkpoint Block ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBlock Sync er ( storage , Ġblockchain , Ġtransaction Processor , ĠpublicKey Manager , Ġlistener , Ġnetwork . last Checkpoint Block , Ġstate ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" triggers Ġ# on Initial Best Block Height Update Ġevent Ġon Ġlistener ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( listener ). on Initial Best Block Height Update ( checkpoint Block . height ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify No More Interactions ( listener ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe ("# local Downloaded Best Block Height ") Ġ{ ĊĠĠĠĠĠĠĠ Ġcontext (" when Ġthere Ġis Ġno Ġblock Ġin Ġstorage ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" returns Ġ 0 Ġas Ġdefault Ġheight ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . last Block ()). thenReturn ( null ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 0 , Ġblock Sync er . local Downloaded Best Block Height ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġthere Ġare Ġsome Ġblocks Ġin Ġstorage ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" returns Ġblock Ġheight ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . last Block ()). thenReturn ( checkpoint Block ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( checkpoint Block . height , Ġblock Sync er . local Downloaded Best Block Height ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe ("# local Known Best Block Height ") Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġblock Hash Ġ= ĠBlock Hash (" abc ". hex To ByteArray (), Ġ 1 ) ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġno ĠBlock Hashes ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getBlock chain Block Hashes ()). thenReturn ( listOf ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . blocks Count ( listOf ())). thenReturn ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext (" when Ġno Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit (" returns Ġ 0 ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 0 , Ġblock Sync er . local Known Best Block Height ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext (" with Ġsome Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit (" returns Ġlast Ġblock Ġheight Ġ+ Ġblocks Ġcount ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . last Block ()). thenReturn ( checkpoint Block ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( checkpoint Block . height , Ġblock Sync er . local Known Best Block Height ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġthere Ġare Ġsome ĠBlock Hashes Ġwhich Ġhaven 't Ġdownloaded Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getBlock chain Block Hashes ()). thenReturn ( listOf ( block Hash )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . blocks Count ( listOf ( block Hash . header Hash ))). thenReturn ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" returns Ġlast B Lock Ġ+ ĠBlock Hashes Ġcount ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġblock Sync er . local Known Best Block Height ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . last Block ()). thenReturn ( checkpoint Block ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( checkpoint Block . height Ġ+ Ġ 1 , Ġblock Sync er . local Known Best Block Height ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġthere Ġare Ġsome ĠBlock Hashes Ġwhich Ġhave Ġdownloaded Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getBlock chain Block Hashes ()). thenReturn ( listOf ( block Hash )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . blocks Count ( listOf ( block Hash . header Hash ))). thenReturn ( 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" returns Ġlast B Lock Ġheight ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 0 , Ġblock Sync er . local Known Best Block Height ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . last Block ()). thenReturn ( checkpoint Block ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( checkpoint Block . height , Ġblock Sync er . local Known Best Block Height ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe ("# prepare For Download ") Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġempty Blocks Ġ= Ġmock < List < Block >>() ĊĠĠĠĠĠĠĠ Ġval Ġblocks Hashes Ġ= ĠlistOf ( byte ArrayOf ( 1 )) ĊĊĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . get Blocks ( any (), Ġany ())). thenReturn ( empty Blocks ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getBlock Hash Header Hashes ( checkpoint Block . header Hash )). thenReturn ( blocks Hashes ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġblock Sync er . prepare For Download () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġit (" handles Ġpartial Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( publicKey Manager ). fill Gap () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( state ). iteration Has Partial Blocks Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġit (" clear s Ġpartial Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( storage ). getBlock Hash Header Hashes ( checkpoint Block . header Hash ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( storage ). get Blocks ( blocks Hashes ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( blockchain ). delete Blocks ( any ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġit (" clear s Ġblock Ġhashes ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( storage ). delete Blockchain Block Hashes () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġit (" handles Ġfork ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( blockchain ). handle Fork () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe ("# download Iteration Completed ") Ġ{ ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġiteration Ġhas Ġpartial Ġblocks ") Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" handles Ġpartial Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( state . iteration Has Partial Blocks ). thenReturn ( true ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġblock Sync er . download Iteration Completed () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( publicKey Manager ). fill Gap () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( state ). iteration Has Partial Blocks Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġiteration Ġhas Ġno Ġpartial Ġblocks ") Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" does Ġnot Ġhandles Ġpartial Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( state . iteration Has Partial Blocks ). thenReturn ( false ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġblock Sync er . download Iteration Completed () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( state ). iteration Has Partial Blocks ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify No More Interactions ( state ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify No More Interactions ( publicKey Manager ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe ("# download Completed ") Ġ{ ĊĠĠĠĠĠĠĠ Ġit (" handles Ġfork ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġblock Sync er . download Completed () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( blockchain ). handle Fork () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe ("# download Failed ") Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġempty Blocks Ġ= Ġmock < List < Block >>() ĊĠĠĠĠĠĠĠ Ġval Ġblocks Hashes Ġ= ĠlistOf ( byte ArrayOf ( 1 )) ĊĊĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . get Blocks ( any (), Ġany ())). thenReturn ( empty Blocks ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getBlock Hash Header Hashes ( checkpoint Block . header Hash )). thenReturn ( blocks Hashes ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġblock Sync er . download Failed () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġit (" handles Ġpartial Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( publicKey Manager ). fill Gap () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( state ). iteration Has Partial Blocks Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġit (" clear s Ġpartial Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( storage ). getBlock Hash Header Hashes ( checkpoint Block . header Hash ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( storage ). get Blocks ( blocks Hashes ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( blockchain ). delete Blocks ( any ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġit (" clear s Ġblock Ġhashes ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( storage ). delete Blockchain Block Hashes () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġit (" handles Ġfork ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( blockchain ). handle Fork () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe ("# getBlock Hashes ") Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠlistOf Block Hashes Ġ= ĠlistOf ( Block Hash (" abc ". hex To ByteArray (), Ġ 1 )) ĊĊĠĠĠĠĠĠĠ Ġit (" returns Ġfirst Ġ 5 0 0 Ġblock Ġhashes ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getBlock Hashes Sorted By Sequence And Height ( limit Ġ= Ġ 5 0 0 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. thenReturn ( listOf Block Hashes ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( listOf Block Hashes , Ġblock Sync er . getBlock Hashes ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe ("# getBlock Locator Hashes ") Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġpeer Last Block Height Ġ= Ġ 9 9 ĊĊĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getLast Blockchain Block Hash ()). thenReturn ( null ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . get Blocks ( checkpoint Block . height , Ġ" height ", Ġ 1 0 )). thenReturn ( listOf ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getBlock ( peer Last Block Height )). thenReturn ( null ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġthere 's Ġno Ġblock Ġor Ġblock Ġhashes ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" return Ġcheckpoint 's Ġheader Ġhash ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( listOf ( checkpoint Block . header Hash ), Ġblock Sync er . getBlock Locator Hashes ( peer Last Block Height )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġthere 's Ġblockchain Ġblock Ġhashes ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġblock Hash Ġ= ĠBlock Hash (" cba ". hex To ByteArray (), Ġ 1 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getLast Blockchain Block Hash ()). thenReturn ( block Hash ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" return Ġlast Ġblock Ġhash Ġand Ġcheckpoint 's Ġheader Ġhash ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( listOf ( block Hash . header Hash , Ġcheckpoint Block . header Hash ), Ġblock Sync er . getBlock Locator Hashes ( peer Last Block Height )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġthere 's Ġno Ġblock Hashes Ġbut Ġthere Ġare Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġblock 1 Ġ= Ġmock ( Block :: class . java ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġblock 2 Ġ= Ġmock ( Block :: class . java ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġblocks Ġ= ĠlistOf ( block 1 , Ġblock 2 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . get Blocks ( height GreaterThan Ġ= Ġcheckpoint Block . height , Ġsorted By Ġ= Ġ" height ", Ġlimit Ġ= Ġ 1 0 )). thenReturn ( blocks ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" returns Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlocator Hashes Ġ= Ġblock Sync er . getBlock Locator Hashes ( peer Last Block Height ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 3 , Ġlocator Hashes . size ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( block 1 . header Hash , Ġlocator Hashes [ 0 ]) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( block 2 . header Hash , Ġlocator Hashes [ 1 ]) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( checkpoint Block . header Hash , Ġlocator Hashes [ 2 ]) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġpeers Ġlast Ġblock Ġalready Ġexists Ġin Ġstorage ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpeer Block Ġ= Ġmock ( Block :: class . java ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġheader Hash Ġ= Ġbyte ArrayOf ( 1 , Ġ 2 , Ġ 3 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġblock Hash Ġ= ĠBlock Hash ( header Hash , Ġ 1 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( peer Block . header Hash ). thenReturn ( header Hash ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getLast Blockchain Block Hash ()). thenReturn ( block Hash ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getBlock ( peer Last Block Height )). thenReturn ( peer Block ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" returns Ġonly Ġone Ġheader Ġhash ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( listOf ( block Hash . header Hash ), Ġblock Sync er . getBlock Locator Hashes ( peer Last Block Height )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe ("# add Block Hashes ") Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġexisting Hashes Ġ= ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbyte ArrayOf ( 1 , Ġ 2 , Ġ 3 ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbyte ArrayOf ( 4 , Ġ 5 , Ġ 6 )) ĊĊĠĠĠĠĠĠĠ Ġval Ġnew Block Hashes Ġ= ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbyte ArrayOf ( 4 , Ġ 5 , Ġ 6 ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbyte ArrayOf ( 5 , Ġ 6 , Ġ 7 )) ĊĊĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getBlock Hash Header Hashes ()). thenReturn ( existing Hashes ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġthere 's Ġsome Ġblock Ġhashes ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġblock Hash Ġ= ĠBlock Hash ( byte ArrayOf ( 1 ), Ġ 9 9 , Ġsequence Ġ= Ġ 9 9 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getLast Block Hash ()). thenReturn ( block Hash ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" set Ġsequence Ġof Ġgiven Ġblock Ġhashes Ġst aring Ġfrom Ġlast Ġblock Ġhash Ġsequence ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġblock Sync er . add Block Hashes ( new Block Hashes ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( storage ). add Block Hashes ( arg That Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . size Ġ== Ġ 1 Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis [ 0 ]. sequence Ġ== Ġblock Hash . sequence Ġ+ Ġ 1 Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis [ 0 ]. header Hash . content Equals ( new Block Hashes [ 1 ]) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġthere 's Ġno Ġblock Ġhashes ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getLast Block Hash ()). thenReturn ( null ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" set Ġsequence Ġof Ġgiven Ġblock Ġhashes Ġst aring Ġfrom Ġ 0 ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġblock Sync er . add Block Hashes ( new Block Hashes ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( storage ). add Block Hashes ( arg That Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . size Ġ== Ġ 1 Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis [ 0 ]. sequence Ġ== Ġ 1 Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis [ 0 ]. header Hash . content Equals ( new Block Hashes [ 1 ]) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe ("# handle Mer kle Block ") Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmax Block Height Ġ= Ġ 1 0 0 ĊĠĠĠĠĠĠĠ Ġval Ġblock Ġ= Ġmock ( Block :: class . java ) ĊĠĠĠĠĠĠĠ Ġval Ġmer kle Block Ġ= Ġmock ( Mer kle Block :: class . java ) ĊĠĠĠĠĠĠĠ Ġval Ġmer kle Height Ġ= Ġ 1 ĊĊĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( mer kle Block . height ). thenReturn ( null ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( mer kle Block . associated Transactions ). thenReturn ( mutable ListOf ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( block . height ). thenReturn ( mer kle Height ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( block . header Hash ). thenReturn ( byte ArrayOf ( 1 , Ġ 2 , Ġ 3 )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( state . iteration Has Partial Blocks ). thenReturn ( true ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( blockchain . connect ( mer kle Block )). thenReturn ( block ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( blockchain . force Add ( mer kle Block , Ġmer kle Height )). thenReturn ( block ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠafterEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreset ( mer kle Block ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġit (" handles Ġmer kle Ġblock ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġblock Sync er . handle Mer kle Block ( mer kle Block , Ġmax Block Height ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( blockchain ). connect ( mer kle Block ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( transaction Processor ). process Incoming ( mer kle Block . associated Transactions , Ġblock , Ġstate . iteration Has Partial Blocks ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( listener ). on Current Best Block Height Update ( block . height , Ġmax Block Height ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġmer kle Ġblock Ġheight Ġit Ġnot Ġnull ") Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( mer kle Block . height ). thenReturn ( mer kle Height ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" force Ġadds Ġmer kle Ġblock ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġblock Sync er . handle Mer kle Block ( mer kle Block , Ġmax Block Height ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( blockchain ). force Add ( mer kle Block , Ġmer kle Height ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġb loom Ġfilter Ġexpired Ġwhile Ġprocessing Ġtransaction ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( transaction Processor . process Incoming ( mer kle Block . associated Transactions , Ġblock , Ġstate . iteration Has Partial Blocks )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. then Throw ( B loom Filter Manager . B loom Filter Expired ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" sets Ġstate Ġas Ġit Ġleft Ġpartially Ġhandled Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġblock Sync er . handle Mer kle Block ( mer kle Block , Ġmax Block Height ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( state ). iteration Has Partial Blocks Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġiteration Ġnot Ġhave Ġpartial Ġblocks ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( state . iteration Has Partial Blocks ). thenReturn ( false ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" delete Ġblock Ġhash ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġblock Sync er . handle Mer kle Block ( mer kle Block , Ġmax Block Height ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( storage ). delete Block Hash ( block . header Hash ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe ("# should Request ") Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġblock Ġ= Ġmock ( Block :: class . java ) ĊĠĠĠĠĠĠĠ Ġval Ġhash Hash Ġ= Ġbyte ArrayOf ( 1 ) ĊĊĠĠĠĠĠĠĠ Ġit (" returns Ġtrue Ġif Ġblock Ġexists ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . getBlock ( hash Hash )). thenReturn ( block ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( false , Ġblock Sync er . should Request ( hash Hash )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe ("# get Checkpoint Block ") Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġb ip 4 4 Checkpoint Block Ġ= Ġmock < Block >() ĊĠĠĠĠĠĠĠ Ġval Ġlast Checkpoint Block Ġ= Ġmock < Block >() ĊĠĠĠĠĠĠĠ Ġval Ġlast Block In DB Ġ= Ġmock < Block >() ĊĊĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( network . bip 4 4 Checkpoint Block ). thenReturn ( bip 4 4 Checkpoint Block ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( network . last Checkpoint Block ). thenReturn ( last Checkpoint Block ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . last Block ()). thenReturn ( last Block In DB ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġsync Ġmode Ġis ĠFull ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsync Mode Ġ= ĠBitcoin Core . Sync Mode . Full () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" equals Ġto Ġb ip 4 4 Checkpoint Block ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġactual Ġ= ĠBlock Sync er . get Checkpoint Block ( sync Mode , Ġnetwork , Ġstorage ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( bip 4 4 Checkpoint Block , Ġactual ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġsync Ġmode Ġis ĠApi Ġor ĠNew ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsync Mode Ġ= ĠBitcoin Core . Sync Mode . Api () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext (" when Ġlast Ġblock Ġin ĠDB Ġearlier Ġthan Ġcheckpoint Ġblock ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( last Block In DB . height ). thenReturn ( 1 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( last Checkpoint Block . height ). thenReturn ( 2 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit (" equals Ġto Ġb ip 4 4 Checkpoint Block ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġactual Ġ= ĠBlock Sync er . get Checkpoint Block ( sync Mode , Ġnetwork , Ġstorage ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( bip 4 4 Checkpoint Block , Ġactual ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext (" when Ġlast Ġblock Ġin ĠDB Ġlater Ġthan Ġcheckpoint Ġblock ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . last Block ()). thenReturn ( last Block In DB ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( last Block In DB . height ). thenReturn ( 2 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( last Checkpoint Block . height ). thenReturn ( 1 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit (" equals Ġto Ġlast Checkpoint Block ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġactual Ġ= ĠBlock Sync er . get Checkpoint Block ( sync Mode , Ġnetwork , Ġstorage ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( last Checkpoint Block , Ġactual ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when ĠDB Ġhas Ġno Ġblock ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( storage . last Block ()). thenReturn ( null ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" s aves Ġcheckpoint Ġblock Ġto ĠDB ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBlock Sync er . get Checkpoint Block ( Bitcoin Core . Sync Mode . Full (), Ġnetwork , Ġstorage ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify ( storage ). save Block ( bip 4 4 Checkpoint Block ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ Ċ }) Ċ