Skip to content

Commit c2a0112

Browse files
committed
feat: include transactions in block
1 parent 8d42ba3 commit c2a0112

File tree

5 files changed

+67
-76
lines changed

5 files changed

+67
-76
lines changed

src/blob.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,21 @@ impl Default for Blob {
1818
}
1919

2020
impl Blob {
21-
pub fn new(data: [u8; BLOB_SIZE]) -> Self {
22-
Self {
23-
data: Bytes::from_iter(data.iter().copied()),
21+
pub fn new(data: Bytes) -> Self {
22+
if data.len() > BLOB_SIZE {
23+
panic!("Data is too large");
2424
}
25+
Self { data }
2526
}
2627
pub fn data(&self) -> &[u8] {
2728
self.data.as_ref()
2829
}
2930
pub fn random() -> Self {
3031
let mut rng = thread_rng();
3132

32-
let mut blob = [0; BLOB_SIZE];
33+
let mut blob = vec![0; BLOB_SIZE];
3334
rng.fill_bytes(&mut blob);
3435

35-
Self::new(blob)
36+
Self::new(Bytes::from(blob))
3637
}
3738
}

src/block.rs

+46-60
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ use eyre::Ok;
66
use frieda::api::commit;
77
use rand::{thread_rng, RngCore};
88
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
9-
use rs_merkle::{algorithms::Sha256, Hasher, MerkleTree};
9+
use rs_merkle::{algorithms::Sha256, MerkleTree};
1010
use tracing::{error, info};
1111

12-
use crate::blob::BLOB_SIZE;
1312
use crate::malachite_types::{address::Address, signing::PrivateKey};
13+
use crate::transactions::Transaction;
1414
use crate::{blob::Blob, error::BlockError, header::Header};
1515

1616
#[derive(Debug, Encode, Decode, Default)]
1717
pub struct Block {
1818
/// Block Header.
1919
header: Header,
2020
/// list of blobs in this block.
21-
blobs: [Blob; 4],
21+
transactions: Vec<Transaction>,
2222
}
2323

2424
impl Block {
@@ -28,50 +28,54 @@ impl Block {
2828
timestamp: u64,
2929
parent_hash: [u8; 32],
3030
proposer_address: Address,
31-
blobs: [Blob; 4],
31+
transactions: Vec<Transaction>,
3232
) -> Self {
33-
let leaves: Vec<[u8; 32]> = blobs.iter().map(|blob| Sha256::hash(blob.data())).collect();
33+
let tx_commitment = if transactions.is_empty() {
34+
[0; 32]
35+
} else if transactions.len() == 1 {
36+
transactions[0].hash()
37+
} else {
38+
let leaves: Vec<[u8; 32]> = transactions.iter().map(|tx| tx.hash()).collect();
3439

35-
let merkle_tree = MerkleTree::<Sha256>::from_leaves(&leaves);
40+
let merkle_tree = MerkleTree::<Sha256>::from_leaves(&leaves);
3641

37-
let data_hash = merkle_tree.root().unwrap();
38-
let da_commitment = blobs
42+
merkle_tree.root().unwrap()
43+
};
44+
45+
let da_commitment = transactions
3946
.par_iter()
40-
.map(|blob| commit(blob.data(), 4))
41-
.collect::<Vec<[u8; 32]>>()
42-
.try_into()
43-
.unwrap();
47+
.flat_map(|tx| tx.data())
48+
.map(|data| commit(data.data(), 4))
49+
.collect::<Vec<[u8; 32]>>();
4450
let header = Header::new(
4551
block_number,
4652
timestamp,
47-
data_hash,
53+
tx_commitment,
4854
proposer_address,
49-
da_commitment,
55+
da_commitment.try_into().unwrap_or_default(),
5056
parent_hash,
5157
);
52-
Self { header, blobs }
58+
Self {
59+
header,
60+
transactions,
61+
}
5362
}
5463
pub fn parent_hash(&self) -> [u8; 32] {
5564
self.header.parent_hash()
5665
}
66+
pub fn blobs(&self) -> Vec<Blob> {
67+
self.transactions
68+
.iter()
69+
.flat_map(|tx| tx.data().clone())
70+
.collect::<Vec<_>>()
71+
}
5772

5873
pub fn hash(&self) -> [u8; 32] {
5974
self.header.block_hash()
6075
}
6176

6277
pub fn genesis() -> Self {
63-
Self::new(
64-
0,
65-
69420,
66-
[0; 32],
67-
Address::default(),
68-
[
69-
Blob::new([0; BLOB_SIZE]),
70-
Blob::new([0; BLOB_SIZE]),
71-
Blob::new([0; BLOB_SIZE]),
72-
Blob::new([0; BLOB_SIZE]),
73-
],
74-
)
78+
Self::new(0, 69420, [0; 32], Address::default(), vec![])
7579
}
7680
pub fn to_bytes(&self) -> eyre::Result<Bytes> {
7781
let bytes = bincode::encode_to_vec(self, standard())?;
@@ -111,17 +115,17 @@ impl Block {
111115
);
112116
return Ok(false);
113117
}
114-
let expected = self.blob_tree_root()?;
115-
let actual = self.header.data_hash;
118+
let expected = self.tx_tree_root()?;
119+
let actual = self.header.tx_commitment;
116120
if expected != actual {
117121
error!(
118-
"Data hash mismatch: expected {:?}, got {:?}",
122+
"tx commitment mismatch: expected {:?}, got {:?}",
119123
expected, actual
120124
);
121125
return Ok(false);
122126
}
123127
let expected_commitments = self
124-
.blobs
128+
.blobs()
125129
.par_iter()
126130
.map(|blob| commit(blob.data(), 4))
127131
.collect::<Vec<[u8; 32]>>();
@@ -147,32 +151,19 @@ impl Block {
147151
Ok(true)
148152
}
149153

150-
/// populate the empty fields in `Header`
151-
pub fn populate(&mut self) -> eyre::Result<()> {
152-
// Set the `data_hash` if not present
153-
let blob_tree_root = self.blob_tree_root()?;
154-
if self.header.data_hash.is_empty() {
155-
self.header.data_hash = blob_tree_root;
156-
} else if self.header.data_hash != blob_tree_root {
157-
return Err(BlockError::DataHashMismatch(blob_tree_root, self.header.data_hash).into());
158-
}
159-
160-
println!("Header population success!");
161-
162-
Ok(())
163-
}
164-
165154
/// Merklize the raw blob data
166-
pub fn blob_tree_root(&self) -> eyre::Result<[u8; 32]> {
167-
let leaves: Vec<[u8; 32]> = self
168-
.blobs
169-
.iter()
170-
.map(|blob| Sha256::hash(blob.data()))
171-
.collect();
155+
pub fn tx_tree_root(&self) -> eyre::Result<[u8; 32]> {
156+
if self.transactions.is_empty() {
157+
Ok([0; 32])
158+
} else if self.transactions.len() == 1 {
159+
Ok(self.transactions[0].hash())
160+
} else {
161+
let leaves: Vec<[u8; 32]> = self.transactions.iter().map(|tx| tx.hash()).collect();
172162

173-
let merkle_tree = MerkleTree::<Sha256>::from_leaves(&leaves);
163+
let merkle_tree = MerkleTree::<Sha256>::from_leaves(&leaves);
174164

175-
merkle_tree.root().ok_or(BlockError::MerkleTreeError.into())
165+
merkle_tree.root().ok_or(BlockError::MerkleTreeError.into())
166+
}
176167
}
177168
}
178169

@@ -196,12 +187,7 @@ mod tests {
196187
Utc::now().timestamp() as u64,
197188
prev_block.hash(),
198189
mock_make_validator(),
199-
[
200-
Blob::random(),
201-
Blob::random(),
202-
Blob::random(),
203-
Blob::random(),
204-
],
190+
vec![Transaction::random()],
205191
);
206192
assert!(block.is_valid(1, &prev_block).unwrap());
207193
}

src/header.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub struct Header {
1818
pub parent_hash: [u8; 32],
1919
/// Merkle root of the data in the current block.
2020
/// Leaves of this tree will be the raw bytes of each blob
21-
pub data_hash: [u8; 32],
21+
pub tx_commitment: [u8; 32],
2222
/// address of proposer of this block.
2323
#[bincode(with_serde)]
2424
pub proposer_address: Address,
@@ -31,7 +31,7 @@ impl Default for Header {
3131
block_hash: [0; 32],
3232
da_commitment: [[0; 32]; 4],
3333
parent_hash: [0; 32],
34-
data_hash: [0; 32],
34+
tx_commitment: [0; 32],
3535
proposer_address: mock_make_validator(),
3636
}
3737
}
@@ -43,7 +43,7 @@ impl Header {
4343
pub fn new(
4444
block_number: u64,
4545
timestamp: u64,
46-
data_hash: [u8; 32],
46+
tx_commitment: [u8; 32],
4747
proposer_address: Address,
4848
da_commitment: [[u8; 32]; 4],
4949
parent_hash: [u8; 32],
@@ -52,7 +52,7 @@ impl Header {
5252
block_number,
5353
timestamp,
5454
da_commitment,
55-
data_hash,
55+
tx_commitment,
5656
proposer_address,
5757
parent_hash,
5858
block_hash: [0; 32],
@@ -81,7 +81,7 @@ impl Header {
8181

8282
hasher.update(self.block_number.to_le_bytes());
8383
hasher.update(self.parent_hash);
84-
hasher.update(self.data_hash);
84+
hasher.update(self.tx_commitment);
8585
hasher.update(self.proposer_address.into_inner());
8686

8787
hasher.finalize().into()
@@ -100,7 +100,7 @@ pub struct HeaderBuilder {
100100
pub parent_hash: Option<[u8; 32]>,
101101
/// Merkle root of the data in the current block.
102102
/// Leaves of this tree will be the raw bytes of each blob
103-
pub data_hash: Option<[u8; 32]>,
103+
pub tx_commitment: Option<[u8; 32]>,
104104
/// address of proposer of this block.
105105
pub proposer_address: Option<Address>,
106106
}
@@ -133,8 +133,8 @@ impl HeaderBuilder {
133133
self
134134
}
135135

136-
pub fn data_hash(mut self, data_hash: [u8; 32]) -> Self {
137-
self.data_hash = Some(data_hash);
136+
pub fn tx_commitment(mut self, tx_commitment: [u8; 32]) -> Self {
137+
self.tx_commitment = Some(tx_commitment);
138138
self
139139
}
140140
pub fn proposer_address(mut self, proposer_address: Address) -> Self {
@@ -146,7 +146,7 @@ impl HeaderBuilder {
146146
Header::new(
147147
self.block_number.unwrap(),
148148
self.timestamp.unwrap(),
149-
self.data_hash.unwrap_or_default(),
149+
self.tx_commitment.unwrap_or_default(),
150150
self.proposer_address.unwrap(),
151151
self.da_commitment.unwrap(),
152152
self.parent_hash.unwrap(),

src/state.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ impl State {
162162
Utc::now().timestamp() as u64,
163163
prev_block.hash(),
164164
self.address,
165-
tx.data().clone(),
165+
vec![tx],
166166
);
167167

168168
let block_data = bincode::encode_to_vec(&block, standard())?;

src/transactions/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
use crate::blob::Blob;
2+
use bincode::{Decode, Encode};
23
use malachitebft_test::{PrivateKey, PublicKey, Signature};
34
use rand::{thread_rng, Rng};
45
use sha3::Digest;
56
use std::cmp::Ordering;
67

78
pub mod pool;
8-
#[derive(Debug, Clone, PartialEq, Eq)]
9+
#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)]
910
pub struct Transaction {
11+
#[bincode(with_serde)]
1012
signature: Signature,
13+
#[bincode(with_serde)]
1114
from: PublicKey,
15+
#[bincode(with_serde)]
1216
to: PublicKey,
1317
value: u64,
1418
data: [Blob; 4],

0 commit comments

Comments
 (0)