Skip to content

Commit b40a951

Browse files
committed
Chain 함수 완성. difficulty 증가하지 않는 버그 있음.
1 parent 7d86f9d commit b40a951

6 files changed

Lines changed: 67 additions & 39 deletions

File tree

jaeseung-blockchain/Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jaeseung-blockchain/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ edition = "2021"
55

66
[dependencies]
77
rs_merkle = "1.4"
8-
sha256 = "1.5.0"
8+
sha256 = "1.5.0"
9+
to-binary = "0.4.0"

jaeseung-blockchain/src/block/block.rs

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use sha256::digest;
44

55
use rs_merkle::{algorithms::Sha256, Hasher, MerkleTree};
66

7+
use to_binary::BinaryString;
8+
79
use crate::constants::{
810
BLOCK_GENERATION_INTERVAL_MINUTE, BLOCK_GENERATION_MILLIS, DIFFICULTY_ADJUSTMENT_INTERVAL_COUNT,
911
};
@@ -26,7 +28,6 @@ impl Block {
2628
Self::unsafe_get_timestamp(),
2729
&["0"; 64].join(""),
2830
0,
29-
0,
3031
&data,
3132
)?,
3233
data: data,
@@ -35,7 +36,6 @@ impl Block {
3536

3637
pub fn new(
3738
previous_block: &Block,
38-
nonce: i32,
3939
data: &Vec<String>,
4040
adjustment_block: &Block,
4141
) -> Result<Block, String> {
@@ -52,7 +52,6 @@ impl Block {
5252
p_header.height + 1,
5353
new_timestamp,
5454
&p_header.hash,
55-
nonce,
5655
difficulty,
5756
data,
5857
)?,
@@ -69,7 +68,7 @@ impl Block {
6968
match new_height {
7069
0..=9 => 0,
7170
10..=19 => 1,
72-
h if h % 10 != i32::from(DIFFICULTY_ADJUSTMENT_INTERVAL_COUNT) => {
71+
h if h % 10 != DIFFICULTY_ADJUSTMENT_INTERVAL_COUNT as i32 => {
7372
previous_block.header.difficulty
7473
}
7574
_ => {
@@ -118,25 +117,42 @@ impl BlockHeader {
118117
height: i32,
119118
timestamp: u64,
120119
previous_hash: &String,
121-
nonce: i32,
122120
difficulty: i32,
123121
data: &Vec<String>,
124122
) -> Result<BlockHeader, String> {
123+
let prefix_zero = "0".repeat(difficulty as usize);
124+
125125
let merkle_root = Self::make_merkle_root(data).ok_or("Merkle Tree Parsing Failed")?;
126126

127-
Ok(BlockHeader {
128-
version: Self::VERSION.to_string(),
129-
height,
130-
timestamp,
131-
hash: Self::make_block_hash(
132-
// TODO : 여기서 바로 마이닝을 하자.
127+
let mut nonce = 0;
128+
129+
// TODO : closure 와 꼬리 재귀를 써서 할 순 없을까?
130+
let (nonce, hash) = loop {
131+
nonce += 1;
132+
133+
let hash = Self::make_block_hash(
133134
height,
134135
timestamp,
135136
&merkle_root,
136137
previous_hash,
137138
nonce,
138139
difficulty,
139-
),
140+
);
141+
142+
let binary = BinaryString::from_hex(&hash)
143+
.map_err(|_| "hex to binary failed".to_string())?
144+
.to_string();
145+
146+
if binary.as_str().starts_with(prefix_zero.as_str()) {
147+
break (nonce, hash);
148+
}
149+
};
150+
151+
Ok(BlockHeader {
152+
version: Self::VERSION.to_string(),
153+
height,
154+
timestamp,
155+
hash,
140156
previous_hash: Some(previous_hash.clone()),
141157
merkle_root,
142158
nonce,
@@ -174,20 +190,3 @@ impl BlockHeader {
174190
digest(target)
175191
}
176192
}
177-
178-
#[cfg(test)]
179-
mod tests {
180-
use super::*;
181-
182-
#[test]
183-
fn test_new_genesis() {
184-
let actual = Block::new_genesis().unwrap();
185-
186-
let data = vec![Block::GENESIS_DATA.to_string()];
187-
let expected = Block {
188-
header: BlockHeader::make(0, &["0"; 64].join(""), 0, &data).unwrap(),
189-
data,
190-
};
191-
assert_eq!(actual, expected);
192-
}
193-
}

jaeseung-blockchain/src/chain/chain.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::block::Block;
1+
use crate::{block::Block, constants::DIFFICULTY_ADJUSTMENT_INTERVAL_COUNT};
22

33
#[derive(Debug)]
44
pub struct Chain {
@@ -12,8 +12,8 @@ impl Chain {
1212
})
1313
}
1414

15-
pub fn get_length(&self) -> usize {
16-
self.block_chain.len()
15+
pub fn get_length(&self) -> u32 {
16+
self.block_chain.len() as u32
1717
}
1818

1919
pub fn get_lastest_block(&self) -> Option<&Block> {
@@ -24,11 +24,24 @@ impl Chain {
2424
let previous_block = self
2525
.get_lastest_block()
2626
.ok_or("previous_block not exist.")?;
27-
let new_block = Block::new(previous_block, 0, data)?;
27+
let adjustment_block = self.get_adjustment_block()?;
28+
29+
let new_block = Block::new(previous_block, data, &adjustment_block)?;
2830

2931
self.block_chain.push(new_block); // TODO : 안전할까?
3032
Ok(self)
3133
}
34+
35+
fn get_adjustment_block(&self) -> Result<Block, String> {
36+
let current_length = self.get_length();
37+
38+
match current_length {
39+
..DIFFICULTY_ADJUSTMENT_INTERVAL_COUNT => Block::new_genesis(),
40+
_ => Ok(self.block_chain
41+
[(current_length - DIFFICULTY_ADJUSTMENT_INTERVAL_COUNT) as usize]
42+
.clone()),
43+
}
44+
}
3245
}
3346

3447
#[cfg(test)]
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// 블록 1 묶음의 블록 개수
2-
pub const DIFFICULTY_ADJUSTMENT_INTERVAL_COUNT: u16 = 10;
2+
pub const DIFFICULTY_ADJUSTMENT_INTERVAL_COUNT: u32 = 10;
33

44
// 블록 1 묶음이 생성 되기까지의 예상 시간(분)
5-
pub const BLOCK_GENERATION_INTERVAL_MINUTE: u16 = 10;
5+
pub const BLOCK_GENERATION_INTERVAL_MINUTE: u32 = 10;
66

77
// 블록 1 개가 생성 되기까지의 예상 시간(밀리초)
8-
pub const BLOCK_GENERATION_MILLIS: u16 = 60000;
8+
pub const BLOCK_GENERATION_MILLIS: u32 = 60000;

jaeseung-blockchain/src/main.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@ mod chain;
33
mod constants;
44

55
use block::Block;
6+
use chain::Chain;
67

78
fn main() {
8-
let block = Block::new_genesis();
9+
let mut chain = Chain::new().unwrap();
910

10-
print!("{:?}", block);
11+
for x in 1..30000 {
12+
chain.add_block(&vec![format!("data-{x}").to_string()]);
13+
}
14+
15+
print!("{:#?}", chain);
1116
}

0 commit comments

Comments
 (0)