Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended chain module (by PAN tx's struct) #1

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion src/chain/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
[package]
name = "chain"
version = "0.1.0"
authors = ["debris <marek.kotewicz@gmail.com>"]
authors = ["debris <marek.kotewicz@gmail.com>",
"extended by Sergey <korostelyov@panaadoraboxchain.ai>",
"and Julian <https://github.com/konchunas>"]

[dependencies]
rustc-serialize = "0.3"
heapsize = "0.4"
keys = { path = "../keys"}
bitcrypto = { path = "../crypto" }
primitives = { path = "../primitives" }
serialization = { path = "../serialization" }
Expand Down
101 changes: 50 additions & 51 deletions src/chain/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,77 +2,76 @@ use hex::FromHex;
use hash::H256;
use ser::{deserialize};
use merkle_root::merkle_root;
use {BlockHeader, Transaction};
use block_header::BlockHeader;
use super::RepresentH256;
//TODO refer realisation for Transaction enum
use payment_transaction::PaymentTransaction;

#[derive(Debug, PartialEq, Clone, Serializable, Deserializable)]
pub struct Block {
pub block_header: BlockHeader,
pub transactions: Vec<Transaction>,
pub block_header: BlockHeader,
pub transactions: Vec<PaymentTransaction>,
}

impl From<&'static str> for Block {
fn from(s: &'static str) -> Self {
deserialize(&s.from_hex().unwrap() as &[u8]).unwrap()
}
fn from(s: &'static str) -> Self {
deserialize(&s.from_hex().unwrap() as &[u8]).unwrap()
}
}

impl RepresentH256 for Block {
fn h256(&self) -> H256 { self.hash() }
fn h256(&self) -> H256 { self.hash() }
}

impl Block {
pub fn new(header: BlockHeader, transactions: Vec<Transaction>) -> Self {
Block { block_header: header, transactions: transactions }
}
pub fn new(header: BlockHeader, transactions: Vec<PaymentTransaction>) -> Self {
Block {block_header: header, transactions}
}

/// Returns block's merkle root.
pub fn merkle_root(&self) -> H256 {
let hashes = self.transactions.iter().map(Transaction::hash).collect::<Vec<H256>>();
merkle_root(&hashes)
}
/// Returns block's merkle root.
pub fn merkle_root(&self) -> H256 {
let hashes = self.transactions.iter().map(PaymentTransaction::hash).collect::<Vec<H256>>();
merkle_root(&hashes)
}

/// Returns block's witness merkle root.
pub fn witness_merkle_root(&self) -> H256 {
let hashes = match self.transactions.split_first() {
None => vec![],
Some((_, rest)) => {
let mut hashes = vec![H256::from(0)];
hashes.extend(rest.iter().map(Transaction::witness_hash));
hashes
},
};
merkle_root(&hashes)
}
/// Returns block's witness merkle root.
pub fn witness_merkle_root(&self) -> H256 {
let hashes = match self.transactions.split_first() {
None => vec![],
Some((_, rest)) => {
let mut hashes = vec![H256::from(0)];
hashes.extend(rest.iter().map(PaymentTransaction::witness_hash));
hashes
},
};
merkle_root(&hashes)
}

pub fn transactions(&self) -> &[Transaction] {
&self.transactions
}
pub fn header(&self) -> &BlockHeader {
&self.block_header
}

pub fn header(&self) -> &BlockHeader {
&self.block_header
}
pub fn transactions(&self) -> &Vec<PaymentTransaction> {
&self.transactions
}

pub fn hash(&self) -> H256 {
self.block_header.hash()
}
pub fn hash(&self) -> H256 {
self.block_header.hash()
}
}

#[cfg(test)]
mod tests {
use hash::H256;
use super::Block;
mod test {
//use hash::H256;
//use super::Block;

// Block 80000
// https://blockchain.info/rawblock/000000000043a8c0fd1d6f726790caa2a406010d19efd2780db27bdbbd93baf6
// https://blockchain.info/rawblock/000000000043a8c0fd1d6f726790caa2a406010d19efd2780db27bdbbd93baf6?format=hex
//TODO this test should be remade since we have added witness_merkle_root field
// #[test]
// fn test_block_merkle_root_and_hash() {
// let block: Block = "01000000ba8b9cda965dd8e536670f9ddec10e53aab14b20bacad27b9137190000000000190760b278fe7b8565fda3b968b918d5fd997f993b23674c0af3b6fde300b38f33a5914ce6ed5b1b01e32f570201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704e6ed5b1b014effffffff0100f2052a01000000434104b68a50eaa0287eff855189f949c1c6e5f58b37c88231373d8a59809cbae83059cc6469d65c665ccfd1cfeb75c6e8e19413bba7fbff9bc762419a76d87b16086eac000000000100000001a6b97044d03da79c005b20ea9c0e1a6d9dc12d9f7b91a5911c9030a439eed8f5000000004948304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d1090db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501ffffffff0100f2052a010000001976a914404371705fa9bd789a2fcd52d2c580b65d35549d88ac00000000".into();
// let merkle_root = H256::from("8fb300e3fdb6f30a4c67233b997f99fdd518b968b9a3fd65857bfe78b2600719");
// let hash = H256::from_reversed_str("000000000043a8c0fd1d6f726790caa2a406010d19efd2780db27bdbbd93baf6");
// assert_eq!(block.merkle_root(), merkle_root);
// assert_eq!(block.hash(), hash);
// }
//#[test]
//fn test_block_merkle_root_and_hash() {
//let block: Block = "01000000ba8b9cda965dd8e536670f9ddec10e53aab14b20bacad27b9137190000000000190760b278fe7b8565fda3b968b918d5fd997f993b23674c0af3b6fde300b38f33a5914ce6ed5b1b01e32f570201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704e6ed5b1b014effffffff0100f2052a01000000434104b68a50eaa0287eff855189f949c1c6e5f58b37c88231373d8a59809cbae83059cc6469d65c665ccfd1cfeb75c6e8e19413bba7fbff9bc762419a76d87b16086eac000000000100000001a6b97044d03da79c005b20ea9c0e1a6d9dc12d9f7b91a5911c9030a439eed8f5000000004948304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d1090db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501ffffffff0100f2052a010000001976a914404371705fa9bd789a2fcd52d2c580b65d35549d88ac00000000".into();
//println!("parsed")
//let merkle_root = H256::from("8fb300e3fdb6f30a4c67233b997f99fdd518b968b9a3fd65857bfe78b2600719");
//let hash = H256::from_reversed_str("000000000043a8c0fd1d6f726790caa2a406010d19efd2780db27bdbbd93baf6");
//assert_eq!(block.merkle_root(), merkle_root);
//assert_eq!(block.hash(), hash);
//}
}
88 changes: 82 additions & 6 deletions src/chain/src/block_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use hash::H256;
#[derive(PartialEq, Clone, Serializable, Deserializable)]
pub struct BlockHeader {
pub version: u32,
pub previous_header_hash: H256,
pub previous_header_hash: Vec<H256>,
pub merkle_root_hash: H256,
pub witness_merkle_root_hash: H256,
pub time: u32,
Expand Down Expand Up @@ -44,14 +44,82 @@ impl From<&'static str> for BlockHeader {

#[cfg(test)]
mod tests {
use hash::H256;
use ser::{Reader, Error as ReaderError, Stream};
use super::BlockHeader;

#[test]
fn test_block_header_stream() {
let previous_header_hash: H256 = [2; 32].into();
let hashes = vec![previous_header_hash];

let block_header = BlockHeader {
version: 1,
previous_header_hash: [2; 32].into(),
previous_header_hash: hashes,
merkle_root_hash: [3; 32].into(),
witness_merkle_root_hash: [4; 32].into(),
time: 5,
bits: 6.into(),
nonce: 7,
};

let mut stream = Stream::default();
stream.append(&block_header);

let expected = vec![
1, 0, 0, 0,
1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 0, 0, 0,
6, 0, 0, 0,
7, 0, 0, 0,
].into();

assert_eq!(stream.out(), expected);
}

#[test]
fn test_block_header_reader() {
let buffer = vec![
1, 0, 0, 0,
1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 0, 0, 0,
6, 0, 0, 0,
7, 0, 0, 0,
];

let mut reader = Reader::new(&buffer);

let previous_header_hash: H256 = [2; 32].into();
let hashes = vec![previous_header_hash];
let expected = BlockHeader {
version: 1,
previous_header_hash: hashes,
merkle_root_hash: [3; 32].into(),
witness_merkle_root_hash: [4; 32].into(),
time: 5,
bits: 6.into(),
nonce: 7,
};

assert_eq!(expected, reader.read().unwrap());
assert_eq!(ReaderError::UnexpectedEnd, reader.read::<BlockHeader>().unwrap_err());
}

#[test]
fn test_two_parent_blocks_header_stream() {
let previous_header_hash_1: H256 = [0; 32].into();
let previous_header_hash_2: H256 = [1; 32].into();
let hashes = vec![previous_header_hash_1, previous_header_hash_2];

let block_header = BlockHeader {
version: 1,
previous_header_hash: hashes,
merkle_root_hash: [3; 32].into(),
witness_merkle_root_hash: [4; 32].into(),
time: 4,
Expand All @@ -64,7 +132,9 @@ mod tests {

let expected = vec![
1, 0, 0, 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 0, 0, 0,
Expand All @@ -76,10 +146,12 @@ mod tests {
}

#[test]
fn test_block_header_reader() {
fn test_two_parent_blocks_header_reader() {
let buffer = vec![
1, 0, 0, 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 0, 0, 0,
Expand All @@ -89,9 +161,12 @@ mod tests {

let mut reader = Reader::new(&buffer);

let previous_header_hash_1: H256 = [0; 32].into();
let previous_header_hash_2: H256 = [1; 32].into();
let hashes = vec![previous_header_hash_1, previous_header_hash_2];
let expected = BlockHeader {
version: 1,
previous_header_hash: [2; 32].into(),
previous_header_hash: hashes,
merkle_root_hash: [3; 32].into(),
witness_merkle_root_hash: [4; 32].into(),
time: 4,
Expand All @@ -103,3 +178,4 @@ mod tests {
assert_eq!(ReaderError::UnexpectedEnd, reader.read::<BlockHeader>().unwrap_err());
}
}

64 changes: 64 additions & 0 deletions src/chain/src/commit_random_transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use hash::H256;
use hex::FromHex;
use crypto::dhash256;
use ser::{serialize, deserialize};

#[derive(Debug, PartialEq, Clone, Default, Serializable, Deserializable)]
pub struct CommitRandomTransaction {
pub version: i32,
pub random: Vec<u32>,
pub pubkey_index: u16
}

impl CommitRandomTransaction {
pub fn hash(&self) -> H256 {
dhash256(&serialize(self))
}

pub fn random(&self) -> &Vec<u32> {
&self.random
}

pub fn pubkey_index(&self) -> &u16 {
&self.pubkey_index
}
}

impl From<&'static str> for CommitRandomTransaction {
fn from(s: &'static str) -> Self {
deserialize(&s.from_hex().unwrap() as &[u8]).unwrap()
}
}

#[cfg(test)]
mod test {

use hash::H256;
use ser::Serializable;
use super::CommitRandomTransaction;

#[test]
fn test_transaction_reader() {
let actual : CommitRandomTransaction = "0100000002010000004b0000000100".into();
let expected: CommitRandomTransaction = CommitRandomTransaction {
version:1,
random: vec![1, 75],
pubkey_index:1
};
assert_eq!(actual, expected);
}

#[test]
fn test_transaction_hash() {
let tx: CommitRandomTransaction = "0100000002010000004b0000000100".into();
let hash : H256 = H256::from_reversed_str("3b848c607d9114fc2c010742349fd629c1323a44ad28516bfd25f77f21920657");
assert_eq!(tx.hash(), hash);
}

#[test]
fn test_transaction_serialized_len(){
let raw_tx: &'static str = "0100000002010000004b0000000100";
let tx: CommitRandomTransaction = raw_tx.into();
assert_eq!(tx.serialized_size(), raw_tx.len() / 2);
}
}
Loading