Skip to content

Commit 67235b0

Browse files
CopilotSteake
andcommitted
Address code review: add overflow protection, proper error handling, and use MAX_HALVINGS constant
Co-authored-by: Steake <530040+Steake@users.noreply.github.com>
1 parent e7e3d85 commit 67235b0

5 files changed

Lines changed: 46 additions & 20 deletions

File tree

crates/bitcell-node/src/blockchain.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::{Result, MetricsRegistry};
44
use bitcell_consensus::{Block, BlockHeader, Transaction, BattleProof};
55
use bitcell_crypto::{Hash256, PublicKey, SecretKey};
6-
use bitcell_economics::{COIN, INITIAL_BLOCK_REWARD, HALVING_INTERVAL};
6+
use bitcell_economics::{COIN, INITIAL_BLOCK_REWARD, HALVING_INTERVAL, MAX_HALVINGS};
77
use bitcell_state::StateManager;
88
use std::sync::{Arc, RwLock};
99
use std::collections::HashMap;
@@ -112,8 +112,8 @@ impl Blockchain {
112112
/// Calculate block reward based on height (halves every HALVING_INTERVAL blocks)
113113
pub fn calculate_block_reward(height: u64) -> u64 {
114114
let halvings = height / HALVING_INTERVAL;
115-
if halvings >= 64 {
116-
// After 64 halvings, reward is effectively 0
115+
if halvings >= MAX_HALVINGS {
116+
// After MAX_HALVINGS halvings, reward is effectively 0
117117
return 0;
118118
}
119119
INITIAL_BLOCK_REWARD >> halvings
@@ -255,8 +255,15 @@ impl Blockchain {
255255
// Apply block reward to proposer
256256
let reward = Self::calculate_block_reward(block_height);
257257
if reward > 0 {
258-
state.credit_account(*block.header.proposer.as_bytes(), reward);
259-
println!("Block reward credited: {} units to proposer", reward);
258+
match state.credit_account(*block.header.proposer.as_bytes(), reward) {
259+
Ok(_) => {
260+
tracing::info!("Block reward credited: {} units to proposer", reward);
261+
}
262+
Err(e) => {
263+
tracing::error!("Failed to credit block reward: {:?}", e);
264+
return Err(crate::Error::Node("Failed to credit block reward".to_string()));
265+
}
266+
}
260267
}
261268

262269
for tx in &block.transactions {
@@ -269,10 +276,10 @@ impl Blockchain {
269276
) {
270277
Ok(new_state_root) => {
271278
// State updated successfully
272-
println!("Transaction applied, new state root: {:?}", new_state_root);
279+
tracing::debug!("Transaction applied, new state root: {:?}", new_state_root);
273280
}
274281
Err(e) => {
275-
println!("Failed to apply transaction: {:?}", e);
282+
tracing::warn!("Failed to apply transaction: {:?}", e);
276283
// In production, this should rollback the entire block
277284
// For now, we just skip the transaction
278285
}

crates/bitcell-node/src/rpc.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub struct RpcState {
2020
pub tournament_manager: Option<Arc<TournamentManager>>,
2121
pub config: NodeConfig,
2222
pub node_type: String, // "validator", "miner", "full"
23+
pub node_id: String, // Hex-encoded public key
2324
}
2425

2526
/// Start the RPC server
@@ -472,7 +473,7 @@ async fn eth_send_raw_transaction(state: &RpcState, params: Option<Value>) -> Re
472473

473474
async fn bitcell_get_node_info(state: &RpcState) -> Result<Value, JsonRpcError> {
474475
Ok(json!({
475-
"node_id": "TODO_NODE_ID", // TODO: Expose node ID from NetworkManager
476+
"node_id": state.node_id,
476477
"version": "0.1.0",
477478
"protocol_version": "1",
478479
"network_id": "bitcell-testnet",

crates/bitcell-state/src/lib.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ pub enum Error {
3333

3434
#[error("Storage error: {0}")]
3535
StorageError(String),
36+
37+
#[error("Balance overflow")]
38+
BalanceOverflow,
3639
}
3740

3841
/// Global state manager
@@ -217,16 +220,25 @@ impl StateManager {
217220
}
218221

219222
/// Credit an account (minting/coinbase)
220-
pub fn credit_account(&mut self, pubkey: [u8; 33], amount: u64) -> Hash256 {
223+
pub fn credit_account(&mut self, pubkey: [u8; 33], amount: u64) -> Result<Hash256> {
221224
let mut account = self.accounts.get(&pubkey)
222225
.cloned()
223226
.unwrap_or(Account { balance: 0, nonce: 0 });
224227

225-
account.balance += amount;
228+
account.balance = account.balance.checked_add(amount)
229+
.ok_or(Error::BalanceOverflow)?;
230+
231+
tracing::debug!(
232+
pubkey = %hex::encode(&pubkey),
233+
amount = amount,
234+
new_balance = account.balance,
235+
"Credited account"
236+
);
237+
226238
self.accounts.insert(pubkey, account);
227239

228240
self.recompute_root();
229-
self.state_root
241+
Ok(self.state_root)
230242
}
231243
}
232244

crates/bitcell-zkp/src/battle_circuit.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ use ark_snark::SNARK;
8787
use ark_std::rand::thread_rng;
8888

8989
impl BattleCircuit {
90-
pub fn setup() -> (ProvingKey<ark_bn254::Bn254>, VerifyingKey<ark_bn254::Bn254>) {
90+
/// Setup the circuit and generate proving/verifying keys
91+
///
92+
/// Returns an error if the circuit setup fails (e.g., due to constraint system issues).
93+
pub fn setup() -> crate::Result<(ProvingKey<ark_bn254::Bn254>, VerifyingKey<ark_bn254::Bn254>)> {
9194
let rng = &mut thread_rng();
9295
Groth16::<ark_bn254::Bn254>::circuit_specific_setup(
9396
Self {
@@ -99,7 +102,7 @@ impl BattleCircuit {
99102
},
100103
rng,
101104
)
102-
.unwrap()
105+
.map_err(|e| crate::Error::ProofGeneration(format!("Circuit setup failed: {}", e)))
103106
}
104107

105108
pub fn prove(
@@ -129,10 +132,10 @@ mod tests {
129132

130133
#[test]
131134
fn test_battle_circuit_prove_verify() {
132-
// 1. Setup
133-
let (pk, vk) = BattleCircuit::setup();
135+
// 1. Setup - now returns Result
136+
let (pk, vk) = BattleCircuit::setup().expect("Circuit setup should succeed");
134137

135-
// 2. Create circuit instance
138+
// 2. Create circuit instance with valid winner ID (1 = Player B wins)
136139
let circuit = BattleCircuit::new(
137140
Fr::one(), // Mock commitment A
138141
Fr::one(), // Mock commitment B

crates/bitcell-zkp/src/state_circuit.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ impl StateCircuit {
3636
}
3737
}
3838

39-
pub fn setup() -> (ProvingKey<ark_bn254::Bn254>, VerifyingKey<ark_bn254::Bn254>) {
39+
/// Setup the circuit and generate proving/verifying keys
40+
///
41+
/// Returns an error if the circuit setup fails (e.g., due to constraint system issues).
42+
pub fn setup() -> crate::Result<(ProvingKey<ark_bn254::Bn254>, VerifyingKey<ark_bn254::Bn254>)> {
4043
let rng = &mut thread_rng();
4144
Groth16::<ark_bn254::Bn254>::circuit_specific_setup(
4245
Self {
@@ -47,7 +50,7 @@ impl StateCircuit {
4750
},
4851
rng,
4952
)
50-
.unwrap()
53+
.map_err(|e| crate::Error::ProofGeneration(format!("Circuit setup failed: {}", e)))
5154
}
5255

5356
pub fn prove(
@@ -109,8 +112,8 @@ mod tests {
109112

110113
#[test]
111114
fn test_state_circuit_prove_verify() {
112-
// 1. Setup
113-
let (pk, vk) = StateCircuit::setup();
115+
// 1. Setup - now returns Result
116+
let (pk, vk) = StateCircuit::setup().expect("Circuit setup should succeed");
114117

115118
// 2. Create circuit instance
116119
let circuit = StateCircuit::new(

0 commit comments

Comments
 (0)