diff --git a/core/src/block.rs b/core/src/block.rs index b200dfd752..585b23e67b 100644 --- a/core/src/block.rs +++ b/core/src/block.rs @@ -32,7 +32,7 @@ use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}; use std::collections::HashSet; /// A block, encoded as it is on the block chain. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone)] pub struct Block { /// The header of this block pub header: Header, diff --git a/sync/src/block/message/mod.rs b/sync/src/block/message/mod.rs index f9f656aff6..8d0d0fb9f7 100644 --- a/sync/src/block/message/mod.rs +++ b/sync/src/block/message/mod.rs @@ -58,7 +58,7 @@ impl Decodable for MessageID { } } -#[derive(Debug, PartialEq)] +#[derive(Debug)] pub enum Message { Status { seq: U256, @@ -156,23 +156,34 @@ impl Decodable for Message { #[cfg(test)] mod tests { + use super::*; use primitives::H256; - use rlp::rlp_encode_and_decode_test; - use super::*; + /// For a type that does not have PartialEq, uses Debug instead. + fn assert_eq_by_debug(a: &T, b: &T) { + assert_eq!(format!("{:?}", a), format!("{:?}", b)); + } #[test] fn status_message_rlp() { - rlp_encode_and_decode_test!(Message::Status { + let status_message = Message::Status { seq: U256::zero(), best_hash: H256::default().into(), genesis_hash: H256::default().into(), - }); + }; + let encoded = rlp::encode(&status_message); + let decoded: Message = rlp::decode(&encoded).unwrap(); + + assert_eq_by_debug(&status_message, &decoded) } #[test] fn request_bodies_message_rlp() { let request_id = 10; - rlp_encode_and_decode_test!(Message::Request(request_id, RequestMessage::Bodies(vec![]))); + let message = Message::Request(request_id, RequestMessage::Bodies(vec![])); + let encoded = rlp::encode(&message); + let decoded: Message = rlp::decode(&encoded).unwrap(); + + assert_eq_by_debug(&message, &decoded) } } diff --git a/sync/src/block/message/response.rs b/sync/src/block/message/response.rs index 0179212843..a5303bbcee 100644 --- a/sync/src/block/message/response.rs +++ b/sync/src/block/message/response.rs @@ -19,7 +19,7 @@ use ccore::UnverifiedTransaction; use ctypes::Header; use rlp::{DecoderError, Encodable, Rlp, RlpStream}; -#[derive(Debug, PartialEq)] +#[derive(Debug)] pub enum ResponseMessage { Headers(Vec
), Bodies(Vec>), @@ -125,6 +125,11 @@ mod tests { ResponseMessage::decode(id, &rlp).unwrap() } + /// For a type that does not have PartialEq, uses Debug instead. + fn assert_eq_by_debug(a: &T, b: &T) { + assert_eq!(format!("{:?}", a), format!("{:?}", b)); + } + #[test] fn headers_message_rlp() { let headers = vec![Header::default()]; @@ -133,13 +138,13 @@ mod tests { }); let message = ResponseMessage::Headers(headers); - assert_eq!(message, decode_bytes(message.message_id(), message.rlp_bytes().as_ref())); + assert_eq_by_debug(&message, &decode_bytes(message.message_id(), message.rlp_bytes().as_ref())) } #[test] fn bodies_message_rlp() { let message = ResponseMessage::Bodies(vec![vec![]]); - assert_eq!(message, decode_bytes(message.message_id(), message.rlp_bytes().as_ref())); + assert_eq_by_debug(&message, &decode_bytes(message.message_id(), message.rlp_bytes().as_ref())); let tx = UnverifiedTransaction::new( Transaction { @@ -156,12 +161,12 @@ mod tests { ); let message = ResponseMessage::Bodies(vec![vec![tx]]); - assert_eq!(message, decode_bytes(message.message_id(), message.rlp_bytes().as_ref())); + assert_eq_by_debug(&message, &decode_bytes(message.message_id(), message.rlp_bytes().as_ref())); } #[test] fn state_chunk_message_rlp() { let message = ResponseMessage::StateChunk(vec![]); - assert_eq!(message, decode_bytes(message.message_id(), message.rlp_bytes().as_ref())); + assert_eq_by_debug(&message, &decode_bytes(message.message_id(), message.rlp_bytes().as_ref())); } } diff --git a/sync/src/transaction/message.rs b/sync/src/transaction/message.rs index d9883bdf27..e0b1a2b6b4 100644 --- a/sync/src/transaction/message.rs +++ b/sync/src/transaction/message.rs @@ -63,17 +63,23 @@ impl Decodable for Message { #[cfg(test)] mod tests { - use rlp::rlp_encode_and_decode_test; - use ccore::UnverifiedTransaction; use ckey::{Ed25519Public as Public, Signature}; use ctypes::transaction::{Action, Transaction}; use super::Message; + /// For a type that does not have PartialEq, uses Debug instead. + fn assert_eq_by_debug(a: &T, b: &T) { + assert_eq!(format!("{:?}", a), format!("{:?}", b)); + } + #[test] fn transactions_message_rlp() { - rlp_encode_and_decode_test!(Message::Transactions(Vec::new())); + let message = Message::Transactions(Vec::new()); + let encoded = rlp::encode(&message); + let decoded: Message = rlp::decode(&encoded).unwrap(); + assert_eq_by_debug(&message, &decoded); } #[test] @@ -92,6 +98,9 @@ mod tests { Public::random(), ); - rlp_encode_and_decode_test!(Message::Transactions(vec![tx])); + let message = Message::Transactions(vec![tx]); + let encoded = rlp::encode(&message); + let decoded: Message = rlp::decode(&encoded).unwrap(); + assert_eq_by_debug(&message, &decoded); } } diff --git a/test/src/helper/mock/cHeader.ts b/test/src/helper/mock/cHeader.ts index 0f12cf0fe3..55389c771e 100644 --- a/test/src/helper/mock/cHeader.ts +++ b/test/src/helper/mock/cHeader.ts @@ -52,6 +52,25 @@ export class Header { return header; } + + public static default(): Header { + return new Header( + new H256( + "0000000000000000000000000000000000000000000000000000000000000000" + ), + new U256(0), + new U256(0), + new H256( + "0000000000000000000000000000000000000000000000000000000000000000" + ), + Buffer.alloc(0), + BLAKE_NULL_RLP, + BLAKE_NULL_RLP, + BLAKE_NULL_RLP, + [] + ); + } + private parentHash: H256; private timestamp: U256; private number: U256; @@ -60,7 +79,7 @@ export class Header { private transactionsRoot: H256; private stateRoot: H256; private nextValidatorSetHash: H256; - private seal: number[][]; + private seal: any[]; private hash: null | H256; private bareHash: null | H256; @@ -73,7 +92,7 @@ export class Header { transactionsRoot: H256, stateRoot: H256, nextValidatorSetHash: H256, - seal: number[][], + seal: any[], hash?: H256, bareHash?: H256 ) { @@ -122,10 +141,14 @@ export class Header { this.nextValidatorSetHash = root; } - public setSeal(seal: number[][]) { + public setSeal(seal: any[]) { this.seal = seal; } + public getParentHash(): H256 | null { + return this.parentHash; + } + public getHash(): H256 | null { return this.hash; } @@ -134,24 +157,6 @@ export class Header { return this.bareHash; } - public default(): Header { - return new Header( - new H256( - "0000000000000000000000000000000000000000000000000000000000000000" - ), - new U256(0), - new U256(0), - new H256( - "0000000000000000000000000000000000000000000000000000000000000000" - ), - Buffer.alloc(0), - BLAKE_NULL_RLP, - BLAKE_NULL_RLP, - BLAKE_NULL_RLP, - [] - ); - } - public toEncodeObject(): Array { return [ this.parentHash.toEncodeObject(), @@ -162,7 +167,7 @@ export class Header { this.number.toEncodeObject(), this.timestamp.toEncodeObject(), this.extraData - ].concat(this.seal.map(seal => Buffer.of(...seal))); + ].concat(this.seal); } public rlpBytes(): Buffer { diff --git a/test/src/helper/mock/test/header.test.ts b/test/src/helper/mock/test/header.test.ts new file mode 100644 index 0000000000..6194fc991b --- /dev/null +++ b/test/src/helper/mock/test/header.test.ts @@ -0,0 +1,64 @@ +import { Buffer } from "buffer"; +import { expect } from "chai"; +import "mocha"; +import * as RLP from "rlp"; +import { + getPublicFromPrivate, + H256, + signEd25519, + U256 +} from "../../../primitives/src"; +import { blake256 } from "../../../primitives/src/hash"; +import { Header } from "../cHeader"; + +describe("Check Header RLP encoding", function() { + it("empty Header RLP encoding test", function() { + const header = Header.default(); + // Find the empty header's rlp encoded data in the unit test in header.rs file + expect(header.rlpBytes().toString("hex")).deep.equal( + "f8a8a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a045b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0a045b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0a045b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0808080" + ); + }); + + it("Header RLP encoding test", function() { + const privateKey = + "5a0391789b130315eebeb333d4fa641aee07242081ba8858ed3f36a937ca84653b21399e52ae4d7582032df537c00eaa3f4611210b3305ce48ac5407cd8f91bf"; + const publicKey = getPublicFromPrivate(privateKey); + const header = Header.default(); + header.setNumber(new U256(4)); + header.setAuthor(new H256(publicKey)); + const bitset = Buffer.alloc(100, 0); + bitset[0] = 4; + const signature = createPrecommit({ + height: 3, + view: 0, + step: 2, + parentHash: header.getParentHash()!, + privateKey + }); + header.setSeal([0, 0, [Buffer.from(signature, "hex")], bitset]); + // Find the header's rlp encoded data in the unit test in the tendermint/mod.rs file + expect(header.rlpBytes().toString("hex")).deep.equal( + "f90154a00000000000000000000000000000000000000000000000000000000000000000a03b21399e52ae4d7582032df537c00eaa3f4611210b3305ce48ac5407cd8f91bfa045b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0a045b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0a045b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c00480808080f842b8404752ae46a97e2e4ff11b8212b85610f81ae63c5b541cc5f1e89238150c122be650b9abc954bab919de4be9a2f1dba992e88b9aa5596d2bdf2645597163697d07b86404000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + ); + }); + + function createPrecommit({ + height, + view, + step, + parentHash, + privateKey + }: { + height: number; + view: number; + step: number; + parentHash: H256; + privateKey: string; + }): string { + const voteOn = [[height, view, step], [parentHash.toEncodeObject()]]; + const serializedVoteOn = RLP.encode(voteOn); + const message = blake256(serializedVoteOn); + return signEd25519(message, privateKey); + } +}); diff --git a/types/src/header.rs b/types/src/header.rs index 9de0528c95..0567cdfd97 100644 --- a/types/src/header.rs +++ b/types/src/header.rs @@ -33,7 +33,7 @@ pub enum Seal { /// A block header. /// Note : you must modify /core/src/views/header.rs too when you modify this. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone)] pub struct Header { /// Parent hash. parent_hash: BlockHash, @@ -322,3 +322,16 @@ impl Encodable for Header { self.stream_rlp(s, &Seal::With); } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn serialize_deserialize_test() { + let empty = Header::default(); + let encoded = rlp::encode(&empty); + let decoded: Header = rlp::decode(&encoded).unwrap(); + assert_eq!(empty.hash(), decoded.hash()); + } +}