@@ -4,6 +4,10 @@ use sha256::digest;
44
55use rs_merkle:: { algorithms:: Sha256 , Hasher , MerkleTree } ;
66
7+ use crate :: constants:: {
8+ BLOCK_GENERATION_INTERVAL_MINUTE , BLOCK_GENERATION_MILLIS , DIFFICULTY_ADJUSTMENT_INTERVAL_COUNT ,
9+ } ;
10+
711#[ derive( Debug , PartialEq , Clone ) ] // TODO : Copy 와 Clone 의 차이점?
812pub struct Block {
913 header : BlockHeader ,
@@ -17,19 +21,82 @@ impl Block {
1721 let data = vec ! [ Self :: GENESIS_DATA . to_string( ) ] ;
1822
1923 Ok ( Block {
20- header : BlockHeader :: make ( 0 , & [ "0" ; 64 ] . join ( "" ) , 0 , & data) ?,
24+ header : BlockHeader :: make (
25+ 0 ,
26+ Self :: unsafe_get_timestamp ( ) ,
27+ & [ "0" ; 64 ] . join ( "" ) ,
28+ 0 ,
29+ 0 ,
30+ & data,
31+ ) ?,
2132 data : data,
2233 } )
2334 }
2435
25- pub fn new ( previous_block : & Block , nonce : i32 , data : & Vec < String > ) -> Result < Block , String > {
36+ pub fn new (
37+ previous_block : & Block ,
38+ nonce : i32 ,
39+ data : & Vec < String > ,
40+ adjustment_block : & Block ,
41+ ) -> Result < Block , String > {
2642 let p_header = & previous_block. header ;
2743
44+ let new_height = p_header. height + 1 ;
45+ let new_timestamp = Self :: unsafe_get_timestamp ( ) ;
46+
47+ let difficulty =
48+ Self :: get_difficulty ( new_height, new_timestamp, previous_block, adjustment_block) ;
49+
2850 Ok ( Block {
29- header : BlockHeader :: make ( p_header. height + 1 , & p_header. hash , nonce, data) ?,
30- data : data. clone ( ) ,
51+ header : BlockHeader :: make (
52+ p_header. height + 1 ,
53+ new_timestamp,
54+ & p_header. hash ,
55+ nonce,
56+ difficulty,
57+ data,
58+ ) ?,
59+ data : data. clone ( ) , // TODO : clone 이 맞을까?
3160 } )
3261 }
62+
63+ fn get_difficulty (
64+ new_height : i32 ,
65+ new_timestamp : u64 ,
66+ previous_block : & Block ,
67+ adjustment_block : & Block ,
68+ ) -> i32 {
69+ match new_height {
70+ 0 ..=9 => 0 ,
71+ 10 ..=19 => 1 ,
72+ h if h % 10 != i32:: from ( DIFFICULTY_ADJUSTMENT_INTERVAL_COUNT ) => {
73+ previous_block. header . difficulty
74+ }
75+ _ => {
76+ let time_taken = new_timestamp - adjustment_block. header . timestamp ;
77+ let time_expected = u64:: from (
78+ DIFFICULTY_ADJUSTMENT_INTERVAL_COUNT
79+ * BLOCK_GENERATION_INTERVAL_MINUTE
80+ * BLOCK_GENERATION_MILLIS ,
81+ ) ;
82+
83+ if time_taken < time_expected / 2 {
84+ adjustment_block. header . difficulty + 1
85+ } else if time_taken > time_expected * 2 {
86+ adjustment_block. header . difficulty - 1
87+ } else {
88+ adjustment_block. header . difficulty
89+ }
90+ }
91+ }
92+ }
93+
94+ fn unsafe_get_timestamp ( ) -> u64 {
95+ SystemTime :: now ( )
96+ . duration_since ( UNIX_EPOCH )
97+ . unwrap ( )
98+ . as_secs ( )
99+ }
33100}
34101
35102#[ derive( Debug , PartialEq , Clone ) ]
@@ -46,27 +113,30 @@ struct BlockHeader {
46113
47114impl BlockHeader {
48115 const VERSION : & str = "1.0.0" ;
49- const DIFFICULTY : i32 = 0 ;
50116
51117 fn make (
52118 height : i32 ,
119+ timestamp : u64 ,
53120 previous_hash : & String ,
54121 nonce : i32 ,
122+ difficulty : i32 ,
55123 data : & Vec < String > ,
56124 ) -> Result < BlockHeader , String > {
57- let version = Self :: VERSION . to_string ( ) ;
58- let timestamp = SystemTime :: now ( )
59- . duration_since ( UNIX_EPOCH )
60- . unwrap ( )
61- . as_secs ( ) ;
62- let difficulty = Self :: DIFFICULTY ;
63125 let merkle_root = Self :: make_merkle_root ( data) . ok_or ( "Merkle Tree Parsing Failed" ) ?;
64126
65127 Ok ( BlockHeader {
66- version,
128+ version : Self :: VERSION . to_string ( ) ,
67129 height,
68130 timestamp,
69- hash : Self :: make_hash ( timestamp, & merkle_root, previous_hash, nonce) ,
131+ hash : Self :: make_block_hash (
132+ // TODO : 여기서 바로 마이닝을 하자.
133+ height,
134+ timestamp,
135+ & merkle_root,
136+ previous_hash,
137+ nonce,
138+ difficulty,
139+ ) ,
70140 previous_hash : Some ( previous_hash. clone ( ) ) ,
71141 merkle_root,
72142 nonce,
@@ -83,18 +153,23 @@ impl BlockHeader {
83153 merkle_tree. root_hex ( )
84154 }
85155
86- fn make_hash (
156+ fn make_block_hash (
157+ height : i32 ,
87158 timestamp : u64 ,
88159 merkle_root : & String ,
89160 previous_hash : & String ,
90161 nonce : i32 ,
162+ difficulty : i32 ,
91163 ) -> String {
92164 let target = format ! (
93- "{}{}{}{}" ,
165+ "{}{}{}{}{}{}{}" ,
166+ Self :: VERSION . to_string( ) ,
167+ height. to_string( ) ,
94168 timestamp. to_string( ) ,
95169 merkle_root,
96170 previous_hash,
97- nonce. to_string( )
171+ nonce. to_string( ) ,
172+ difficulty. to_string( )
98173 ) ;
99174 digest ( target)
100175 }
0 commit comments