1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use serde::{Serialize, Serializer};
use super::hash::H256;
use super::uint::U256;
use super::block::RawBlock;

/// Response to getblock RPC request
#[derive(Debug)]
pub enum GetBlockResponse {
	/// When asking for short response
	Raw(RawBlock),
	/// When asking for verbose response
	Verbose(VerboseBlock),
}

/// Verbose block information
#[derive(Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct VerboseBlock {
	/// Block hash
	pub hash: H256,
	/// Number of confirmations. -1 if block is on the side chain
	pub confirmations: i64,
	/// Block size
	pub size: u32,
	/// Block size, excluding witness data
	pub strippedsize: u32,
	/// Block weight
	pub weight: u32,
	/// Block height
	/// TODO: bitcoind always returns value, but we hold this value for main chain blocks only
	pub height: Option<u32>,
	/// Block version
	pub version: u32,
	/// Block version as hex
	#[serde(rename = "versionHex")]
	pub version_hex: String,
	/// Merkle root of this block
	pub merkleroot: H256,
	/// Transactions ids
	pub tx: Vec<H256>,
	/// Block time in seconds since epoch (Jan 1 1970 GMT)
	pub time: u32,
	/// Median block time in seconds since epoch (Jan 1 1970 GMT)
	/// TODO: bitcoind always returns value, but we can calculate this only if height(block) > 2
	pub mediantime: Option<u32>,
	/// Block nonce
	pub nonce: u32,
	/// Block nbits
	pub bits: u32,
	/// Block difficulty
	pub difficulty: f64,
	/// Expected number of hashes required to produce the chain up to this block (in hex)
	pub chainwork: U256,
	/// Hash of previous block
	pub previousblockhash: Option<H256>,
	/// Hash of next block
	pub nextblockhash: Option<H256>,
}

impl Serialize for GetBlockResponse {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
		match *self {
			GetBlockResponse::Raw(ref raw_block) => raw_block.serialize(serializer),
			GetBlockResponse::Verbose(ref verbose_block) => verbose_block.serialize(serializer),
		}
	}
}

#[cfg(test)]
mod tests {
	use super::super::bytes::Bytes;
	use super::super::hash::H256;
	use super::super::uint::U256;
	use serde_json;
	use super::*;

	#[test]
	fn verbose_block_serialize() {
		let block = VerboseBlock::default();
		assert_eq!(serde_json::to_string(&block).unwrap(), r#"{"hash":"0000000000000000000000000000000000000000000000000000000000000000","confirmations":0,"size":0,"strippedsize":0,"weight":0,"height":null,"version":0,"versionHex":"","merkleroot":"0000000000000000000000000000000000000000000000000000000000000000","tx":[],"time":0,"mediantime":null,"nonce":0,"bits":0,"difficulty":0.0,"chainwork":"0","previousblockhash":null,"nextblockhash":null}"#);

		let block = VerboseBlock {
			hash: H256::from(1),
			confirmations: -1,
			size: 500000,
			strippedsize: 444444,
			weight: 5236235,
			height: Some(3513513),
			version: 1,
			version_hex: "01".to_owned(),
			merkleroot: H256::from(2),
			tx: vec![H256::from(3), H256::from(4)],
			time: 111,
			mediantime: Some(100),
			nonce: 124,
			bits: 13513,
			difficulty: 555.555,
			chainwork: U256::from(3),
			previousblockhash: Some(H256::from(4)),
			nextblockhash: Some(H256::from(5)),
		};
		assert_eq!(serde_json::to_string(&block).unwrap(), r#"{"hash":"0100000000000000000000000000000000000000000000000000000000000000","confirmations":-1,"size":500000,"strippedsize":444444,"weight":5236235,"height":3513513,"version":1,"versionHex":"01","merkleroot":"0200000000000000000000000000000000000000000000000000000000000000","tx":["0300000000000000000000000000000000000000000000000000000000000000","0400000000000000000000000000000000000000000000000000000000000000"],"time":111,"mediantime":100,"nonce":124,"bits":13513,"difficulty":555.555,"chainwork":"3","previousblockhash":"0400000000000000000000000000000000000000000000000000000000000000","nextblockhash":"0500000000000000000000000000000000000000000000000000000000000000"}"#);
	}

	#[test]
	fn verbose_block_deserialize() {
		let block = VerboseBlock::default();
		assert_eq!(
			serde_json::from_str::<VerboseBlock>(r#"{"hash":"0000000000000000000000000000000000000000000000000000000000000000","confirmations":0,"size":0,"strippedsize":0,"weight":0,"height":null,"version":0,"versionHex":"","merkleroot":"0000000000000000000000000000000000000000000000000000000000000000","tx":[],"time":0,"mediantime":null,"nonce":0,"bits":0,"difficulty":0.0,"chainwork":"0","previousblockhash":null,"nextblockhash":null}"#).unwrap(),
			block);

		let block = VerboseBlock {
			hash: H256::from(1),
			confirmations: -1,
			size: 500000,
			strippedsize: 444444,
			weight: 5236235,
			height: Some(3513513),
			version: 1,
			version_hex: "01".to_owned(),
			merkleroot: H256::from(2),
			tx: vec![H256::from(3), H256::from(4)],
			time: 111,
			mediantime: Some(100),
			nonce: 124,
			bits: 13513,
			difficulty: 555.555,
			chainwork: U256::from(3),
			previousblockhash: Some(H256::from(4)),
			nextblockhash: Some(H256::from(5)),
		};
		assert_eq!(
			serde_json::from_str::<VerboseBlock>(r#"{"hash":"0100000000000000000000000000000000000000000000000000000000000000","confirmations":-1,"size":500000,"strippedsize":444444,"weight":5236235,"height":3513513,"version":1,"versionHex":"01","merkleroot":"0200000000000000000000000000000000000000000000000000000000000000","tx":["0300000000000000000000000000000000000000000000000000000000000000","0400000000000000000000000000000000000000000000000000000000000000"],"time":111,"mediantime":100,"nonce":124,"bits":13513,"difficulty":555.555,"chainwork":"3","previousblockhash":"0400000000000000000000000000000000000000000000000000000000000000","nextblockhash":"0500000000000000000000000000000000000000000000000000000000000000"}"#).unwrap(),
			block);
	}

	#[test]
	fn get_block_response_raw_serialize() {
		let raw_response = GetBlockResponse::Raw(Bytes::new(vec![0]));
		assert_eq!(serde_json::to_string(&raw_response).unwrap(), r#""00""#);
	}

	#[test]
	fn get_block_response_verbose_serialize() {
		let block = VerboseBlock::default();
		let verbose_response = GetBlockResponse::Verbose(block);
		assert_eq!(serde_json::to_string(&verbose_response).unwrap(), r#"{"hash":"0000000000000000000000000000000000000000000000000000000000000000","confirmations":0,"size":0,"strippedsize":0,"weight":0,"height":null,"version":0,"versionHex":"","merkleroot":"0000000000000000000000000000000000000000000000000000000000000000","tx":[],"time":0,"mediantime":null,"nonce":0,"bits":0,"difficulty":0.0,"chainwork":"0","previousblockhash":null,"nextblockhash":null}"#);
	}
}