Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0153620
feat: implement canonical serialization and add unit tests
sanaica Mar 22, 2026
2359fe4
refactor: implement canonical p2p broadcasting and cross-instance tests
sanaica Mar 22, 2026
1319419
fix: address reviewer feedback for type safety and determinism
sanaica Mar 22, 2026
2e8efb5
fix: security: include miner in canonical hash and restrict p2p host
sanaica Mar 22, 2026
90a3194
fixed
sanaica Mar 22, 2026
6625e38
fix: include top-level miner in p2p envelope for main.py compatibility
sanaica Mar 22, 2026
423c4dd
Merge branch 'main' into main
sanaica Mar 28, 2026
48703eb
fix: address CodeRabbit review for p2p payload and tests
sanaica Mar 28, 2026
50afef2
Merge branch 'main' of https://github.com/sanaica/MiniChain
sanaica Mar 28, 2026
98d882c
refactor(p2p): make broadcast_block strictly read-only
sanaica Mar 28, 2026
9091307
chore: trigger CI
sanaica Mar 28, 2026
e2a0cd5
fix(p2p): restore miner kwarg for backward compatibility
sanaica Mar 28, 2026
464e951
chore: trigger CI
sanaica Mar 28, 2026
e91e497
refactor(p2p): strictly enforce read-only broadcast_block
sanaica Mar 28, 2026
00ed340
fix(main): update broadcast_block caller to match new API
sanaica Mar 28, 2026
08533b5
fix(main): set block miner before chain admission to prevent state mi…
sanaica Mar 28, 2026
1f7eddc
fix(main): set block miner before chain admission as per Claude/CodeR…
sanaica Mar 28, 2026
e90dd22
chore: trigger CI build
sanaica Mar 28, 2026
f674b2a
fix(security): include miner in hash, verify merkle root, and update …
sanaica Mar 28, 2026
8aaee28
fix(security): remove duplicate miner assignment, add hash verificati…
sanaica Mar 28, 2026
7421205
chore: add miner type hint, update test assertions, and invoke tamper…
sanaica Mar 28, 2026
5b9fb54
fix: deduplicate merkle tamper test and reuse to_body_dict in to_dict
sanaica Mar 28, 2026
9033681
fix(block): make transactions immutable and support legacy block hashes
sanaica Mar 29, 2026
ecb7031
fix(block): validate block invariants before generating canonical_pay…
sanaica Mar 29, 2026
128f2c0
fix(block): cast integral header fields to int in from_dict to ensure…
sanaica Mar 29, 2026
ec74fae
chore(block): apply CodeRabbit nitpicks for typing, casting, and opti…
sanaica Mar 29, 2026
c552316
chore(block): apply CodeRabbit nitpicks for typing, casting, and opti…
sanaica Mar 29, 2026
504a9e4
chore(block): update type hint for _calculate_merkle_root to Sequence
sanaica Mar 29, 2026
785cedd
chore: force CodeRabbit status update
sanaica Mar 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion minichain/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import hashlib
from typing import List, Optional
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
from .transaction import Transaction
from .serialization import canonical_json_hash
from .serialization import canonical_json_hash, canonical_json_bytes

def _sha256(data: str) -> str:
return hashlib.sha256(data.encode()).hexdigest()
Expand Down Expand Up @@ -117,3 +117,8 @@ def from_dict(cls, payload: dict):
if "merkle_root" in payload:
block.merkle_root = payload["merkle_root"]
return block
Comment thread
coderabbitai[bot] marked this conversation as resolved.

@property
def canonical_payload(self) -> bytes:
"""Returns the full block (header + body) as canonical bytes for networking."""
return canonical_json_bytes(self.to_dict())
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
52 changes: 52 additions & 0 deletions tests/test_serialization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from minichain.serialization import canonical_json_hash
from minichain.transaction import Transaction
from minichain.block import Block

def test_raw_data_determinism():
print("--- Testing Raw Data Determinism ---")
# Same data, different key order
data_v1 = {"amount": 100, "nonce": 1, "receiver": "Alice", "sender": "Bob"}
data_v2 = {"sender": "Bob", "receiver": "Alice", "nonce": 1, "amount": 100}

hash_1 = canonical_json_hash(data_v1)
hash_2 = canonical_json_hash(data_v2)

print(f"Hash 1: {hash_1}")
print(f"Hash 2: {hash_2}")
assert hash_1 == hash_2
print("Success: Raw hashes match regardless of key order!\n")

def test_transaction_id_stability():
print("--- Testing Transaction ID Stability ---")
# Create a transaction
tx = Transaction(sender="Alice_PK", receiver="Bob_PK", amount=50, nonce=1)

first_id = tx.tx_id
# Re-triggering the ID calculation
second_id = tx.tx_id

print(f"TX ID: {first_id}")
assert first_id == second_id
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
print("Success: Transaction ID is stable and deterministic!\n")

def test_block_hash_consistency():
print("--- Testing Block Hash Consistency ---")
# Create a block with one transaction
tx = Transaction(sender="A", receiver="B", amount=10, nonce=5)
block = Block(index=1, previous_hash="0"*64, transactions=[tx], difficulty=2)

initial_hash = block.compute_hash()
print(f"Initial Block Hash: {initial_hash}")

# Manually re-computing to ensure it's identical
assert block.compute_hash() == initial_hash
print("Success: Block hash is consistent!\n")

Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
if __name__ == "__main__":
try:
test_raw_data_determinism()
test_transaction_id_stability()
test_block_hash_consistency()
print("ALL CANONICAL TESTS PASSED!")
except AssertionError as e:
print("TEST FAILED: Serialization is not deterministic!")
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
Loading