package Ġx . scratch . blockchain Ċ Ċ import Ġx . scratch . blockchain . Blockchain . Block Ċ import Ġjava . security . Message Digest Ċ import Ġjava . time . Duration Ċ import Ġjava . time . Instant Ċ import Ġjava . util . Objects Ċ Ċ private Ġval Ġgenesis Hash Ġ= ĠTime d Hash (" 0 ", ĠDuration . ZERO , Ġ 0 , Ġ 0 ) Ċ Ċ private Ġval Ġdigest s Ġ= Ġmutable Map Of < String , ĠMessage Digest >() Ċ private Ġfun Ġdigest ( function : ĠString ) Ġ= ĊĠĠĠ Ġdigest s . compute If Absent ( function ) Ġ{ ĊĠĠĠĠĠĠĠ ĠMessage Digest . getInstance ( it ) !! ĊĠĠĠ Ġ} Ċ Ċ data Ġclass ĠTime d Hash ( ĊĠĠĠ Ġval Ġhash : ĠString , ĊĠĠĠ Ġval Ġtiming : ĠDuration , ĊĠĠĠ Ġval Ġdifficulty : ĠInt , ĊĠĠĠ Ġval Ġnonce : ĠLong Ċ ) Ċ Ċ class ĠBlock chain Ġprivate Ġconstructor ( ĊĠĠĠ Ġval Ġgenesis Data : ĠString , ĊĠĠĠ Ġpurpose : ĠString , ĊĠĠĠ Ġval Ġdifficulty : ĠInt , Ġ// ĠTODO : ĠProperty Ġof Ġthe Ġchain , Ġnot Ġthe Ġblock ĊĠĠĠ Ġinitial Functions : ĠSet < String >, ĊĠĠĠ Ġgenesis Timestamp : ĠInstant , ĊĠĠĠ Ġ// ĠTODO : ĠKotlin , Ġhow Ġto Ġdelegate Ġto Ġa Ġnon - ctor Ġarg ? ĊĠĠĠ Ġprivate Ġval Ġchain : ĠMutable List < Block > Ġ= Ġmutable ListOf () Ċ ) Ġ: ĠList < Block > Ġby Ġchain Ġ{ ĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġchain Ġ+= Ġgenesis Block ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpurpose Ġ= Ġpurpose , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinitial Functions Ġ= Ġinitial Functions , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgenesis Timestamp Ġ= Ġgenesis Timestamp ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġnew Block ( ĊĠĠĠĠĠĠĠ Ġdata : ĠAny , ĊĠĠĠĠĠĠĠ Ġpurpose : ĠString , ĊĠĠĠĠĠĠĠ Ġfunctions : ĠSet < String > Ġ= Ġprevious Functions (), ĊĠĠĠĠĠĠĠ Ġtimestamp : ĠInstant Ġ= ĠInstant . now () ĊĠĠĠ Ġ) Ġ= Ġapply Ġ{ ĊĠĠĠĠĠĠĠ Ġchain Ġ+= Ġlast (). next ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdata Ġ= Ġdata , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpurpose Ġ= Ġpurpose , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfunctions Ġ= Ġfunctions , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtimestamp Ġ= Ġtimestamp ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġhand Off Block ( ĊĠĠĠĠĠĠĠ Ġdata : ĠAny , ĊĠĠĠĠĠĠĠ Ġpurpose : ĠString , ĊĠĠĠĠĠĠĠ Ġprevious Hash : ĠString , ĊĠĠĠĠĠĠĠ Ġnext Hash : ĠString , ĊĠĠĠĠĠĠĠ Ġtimestamp : ĠInstant Ġ= ĠInstant . now () ĊĠĠĠ Ġ) Ġ= Ġapply Ġ{ ĊĠĠĠĠĠĠĠ Ġverify ( set Of ( previous Hash )) ĊĠĠĠĠĠĠĠ Ġchain Ġ+= Ġlast (). next ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdata Ġ= Ġdata , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpurpose Ġ= Ġpurpose , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfunctions Ġ= Ġset Of ( previous Hash , Ġnext Hash ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtimestamp Ġ= Ġtimestamp ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠLooks Ġup Ġa Ġblock Ġby Ġits Ġdigest Ġfunction Ġand Ġhash , Ġreturning Ġ` null ` Ġif ĊĠĠĠĠ Ġ* Ġnone Ġfound . Ġ ĠExample : ĊĠĠĠĠ Ġ* Ġ``` ĊĠĠĠĠ Ġ* Ġval Ġa Block Ġ= Ġblockchain [" SHA - 2 5 6 ", Ġ" d 7 cce 2 2 abb 7 9 4 5 c 8 1 4 7 1 8 fb 7 1 c 5 a 2 d 2 7 f 2 da 4 7 a 3 9 a 0 1 aee 1 4 e 5 b 2 a 1 c ddb 9 bdd 9 "] ĊĠĠĠĠ Ġ* Ġ``` ĊĠĠĠĠ Ġ* ĠUse Ġthe Ġ` List ` Ġindex Ġoperator Ġto Ġlookup Ġa Ġblock Ġby Ġheight . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoperator Ġfun Ġget ( function : ĠString , Ġhash : ĠString ) Ġ= ĊĠĠĠĠĠĠĠ Ġfirst OrNull Ġ{ Ġhash Ġ== Ġit . hashes [ function ]?. hash Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġequals ( other : ĠAny ?) Ġ= Ġthis Ġ=== Ġother ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ|| Ġother Ġis ĠBlock chain ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ&& Ġchain Ġ== Ġother . chain ĊĊĠĠĠ Ġoverride Ġfun ĠhashCode () Ġ= ĠObjects . hash ( chain ) ĊĊĠĠĠ Ġoverride Ġfun ĠtoString () Ġ= ĊĠĠĠĠĠĠĠ Ġ"${ super . toString () }{ genesis Data =$ genesis Data , Ġdifficulty =$ difficulty , Ġchain =$ chain }" ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠValid ates Ġthe Ġblockchain . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ todo ĠDo Ġnot Ġrequire Ġan Ġinput ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġverify ( functions : ĠSet < String >) Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġprevious Height Ġ= Ġ- 1 L ĊĠĠĠĠĠĠĠ Ġvar Ġprevious Timestamp Ġ= ĠInstant . MIN ĊĠĠĠĠĠĠĠ Ġvar Ġprevious Hashes Ġ= Ġfunctions . map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit Ġto Ġgenesis Hash ĊĠĠĠĠĠĠĠ Ġ}. toMap () ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( block Ġin Ġchain ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( block . height Ġ== Ġprevious Height Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprevious Height Ġ= Ġblock . height ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġerror (" Out Ġof Ġsequence : Ġ$ chain ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO : ĠIs Ġit Ġle git Ġto Ġhave Ġsame Ġtimestamp Ġfor Ġblocks ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( block . timestamp . is After ( previous Timestamp )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprevious Timestamp Ġ= Ġblock . timestamp ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġerror (" Out Ġof Ġorder : Ġ$ chain ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( block . previous Hashes . e quivalent To ( previous Hashes )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprevious Hashes Ġ= Ġblock . hashes ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġerror (" Cor rupted : Ġ$ chain ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġblock . verify () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġgenesis Block ( ĊĠĠĠĠĠĠĠ Ġpurpose : ĠString , ĊĠĠĠĠĠĠĠ Ġinitial Functions : ĠSet < String >, ĊĠĠĠĠĠĠĠ Ġgenesis Timestamp : ĠInstant ĊĠĠĠ Ġ) Ġ= ĠBlock ( ĊĠĠĠĠĠĠĠ Ġheight Ġ= Ġ 0 , ĊĠĠĠĠĠĠĠ Ġtimestamp Ġ= Ġgenesis Timestamp , ĊĠĠĠĠĠĠĠ Ġdata Ġ= Ġgenesis Data , ĊĠĠĠĠĠĠĠ Ġpurpose Ġ= Ġpurpose , ĊĠĠĠĠĠĠĠ Ġfunctions Ġ= Ġinitial Functions , ĊĠĠĠĠĠĠĠ Ġprevious Hashes Ġ= Ġinitial Functions . map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit Ġto Ġgenesis Hash ĊĠĠĠĠĠĠĠ Ġ}. toMap () ĊĠĠĠ Ġ) ĊĊĠĠĠ Ġprivate Ġfun Ġprevious Functions () Ġ= Ġlast (). hashes . keys ĊĊĠĠĠ Ġinner Ġclass ĠBlock Ġinternal Ġconstructor ( ĊĠĠĠĠĠĠĠ Ġval Ġheight : ĠLong , ĊĠĠĠĠĠĠĠ Ġval Ġtimestamp : ĠInstant , ĊĠĠĠĠĠĠĠ Ġval Ġdata : ĠAny , ĊĠĠĠĠĠĠĠ Ġval Ġpurpose : ĠString , ĊĠĠĠĠĠĠĠ Ġfunctions : ĠSet < String >, ĊĠĠĠĠĠĠĠ Ġval Ġprevious Hashes : ĠMap < String , ĠTime d Hash > ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġhashes Ġ= Ġall Hashes With Proof OfWork ( functions ) ĊĊĠĠĠĠĠĠĠ Ġ/** ĠValid ates Ġthe Ġblock . Ġ*/ ĊĠĠĠĠĠĠĠ Ġfun Ġverify () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġoriginal Hashes Ġ= Ġhashes . map Ġ{ Ġ( function , Ġtimed Hash ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfunction Ġto Ġtimed Hash . hash ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. toMap () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġre computed Hashes Ġ= Ġhashes . map Ġ{ Ġ( function , Ġtimed Hash ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfunction Ġto Ġhash With Nonce ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfunction , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtimed Hash . nonce , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprevious Hashes . get OrDefault ( function , Ġgenesis Hash ). hash ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. toMap () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( original Hashes Ġ!= Ġre computed Hashes ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġerror (" Cor rupted : Ġ$ this ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġhash Prefix Ġ= Ġhash Prefix For Difficulty ( difficulty ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( timed Hash Ġin Ġhashes . values ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! timed Hash . hash . startsWith ( hash Prefix )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġerror (" Too Ġeasy : Ġ$ this ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġnext ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdata : ĠAny , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpurpose : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfunctions : ĠSet < String >, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtimestamp : ĠInstant ĊĠĠĠĠĠĠĠ Ġ) Ġ= ĠBlock ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġheight Ġ= Ġheight Ġ+ Ġ 1 , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtimestamp Ġ= Ġtimestamp , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdata Ġ= Ġdata , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpurpose Ġ= Ġpurpose , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfunctions Ġ= Ġfunctions , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprevious Hashes Ġ= Ġhashes ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġhash With Nonce ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfunction : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnonce : ĠLong , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprevious Hash : ĠString ĊĠĠĠĠĠĠĠ Ġ): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġhash For Block ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdigest ( function ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"$ nonce $ height $ timestamp $ data $ purpose $ previous Hash " ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġall Hashes With Proof OfWork ( functions : ĠSet < String >) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ: ĠMap < String , ĠTime d Hash > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġhash Prefix Ġ= Ġhash Prefix For Difficulty ( difficulty ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfun Ġhash With Proof OfWork ( function : ĠString ): ĠTime d Hash Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstart Ġ= ĠInstant . now () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO : ĠUse Ġgenesis Ġhash , Ġor Ġsomething Ġcle ver er ? ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġprevious Hash Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprevious Hashes . get OrDefault ( function , Ġgenesis Hash ). hash ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( nonce Ġin Ġ 0 .. Long . MAX _ VALUE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġhash Ġ= Ġhash With Nonce ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfunction , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnonce , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprevious Hash ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( hash . startsWith ( hash Prefix )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtiming Ġ= ĠDuration . between ( Instant . now (), Ġstart ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠTime d Hash ( hash , Ġtiming , Ġdifficulty , Ġnonce ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġerror (" Unable Ġto Ġcomplete Ġwork : Ġ$ this ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfunctions . map Ġ{ Ġfunction Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfunction Ġto Ġhash With Proof OfWork ( function ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. toMap () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġequals ( other : ĠAny ?) Ġ= Ġthis Ġ=== Ġother ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ|| Ġother Ġis ĠBlock ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ&& Ġhashes Ġ== Ġother . hashes ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun ĠhashCode () Ġ= ĠObjects . hash ( hashes ) ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun ĠtoString () Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ super . toString () }{ height =$ height , Ġtimestamp =$ timestamp , Ġdata =$ data , Ġpurpose =$ purpose , Ġhashes =$ hashes , Ġprevious Hashes =$ previous Hashes }" ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠDEFAULT _ FUNCTION S Ġ= Ġset Of (" SHA - 2 5 6 ") Ġ// ĠSHA 2 ĊĊĠĠĠĠĠĠĠ Ġfun Ġnew ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgenesis Data : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpurpose : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdifficulty : ĠInt Ġ= Ġ 0 , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinitial Functions : ĠSet < String > Ġ= ĠDEFAULT _ FUNCTION S , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgenesis Timestamp : ĠInstant Ġ= ĠInstant . now () ĊĠĠĠĠĠĠĠ Ġ) Ġ= ĠBlock chain ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgenesis Data Ġ= Ġgenesis Data , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpurpose Ġ= Ġpurpose , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdifficulty Ġ= Ġdifficulty , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinitial Functions Ġ= Ġinitial Functions , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgenesis Timestamp Ġ= Ġgenesis Timestamp ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} Ċ } Ċ