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
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of Tetsy Vapory.

// Tetsy Vapory is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Tetsy Vapory is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Tetsy Vapory.  If not, see <http://www.gnu.org/licenses/>.

//! Base data structure of this module is `Block`.
//!
//! Blocks can be produced by a local node or they may be received from the network.
//!
//! Other block types are found in `vapcore`

use bytes::Bytes;
use vapory_types::{H256, U256};
use tetsy_util_mem::MallocSizeOf;

use crate::BlockNumber;
use crate::header::Header;
use tetsy_rlp::{Rlp, RlpStream, Decodable, DecoderError};
use crate::transaction::{UnverifiedTransaction, SignedTransaction};

/// A block, encoded as it is on the block chain.
#[derive(Default, Debug, Clone, PartialEq)]
pub struct Block {
	/// The header of this block.
	pub header: Header,
	/// The transactions in this block.
	pub transactions: Vec<UnverifiedTransaction>,
	/// The uncles of this block.
	pub uncles: Vec<Header>,
}

impl Block {
	/// Get the RLP-encoding of the block with the seal.
	pub fn rlp_bytes(&self) -> Bytes {
		let mut block_rlp = RlpStream::new_list(3);
		block_rlp.append(&self.header);
		block_rlp.append_list(&self.transactions);
		block_rlp.append_list(&self.uncles);
		block_rlp.out()
	}
}

impl Decodable for Block {
	fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
		if rlp.as_raw().len() != rlp.payload_info()?.total() {
			return Err(DecoderError::RlpIsTooBig);
		}
		if rlp.item_count()? != 3 {
			return Err(DecoderError::RlpIncorrectListLen);
		}
		Ok(Block {
			header: rlp.val_at(0)?,
			transactions: rlp.list_at(1)?,
			uncles: rlp.list_at(2)?,
		})
	}
}

/// Preprocessed block data gathered in `verify_block_unordered` call
#[derive(MallocSizeOf)]
pub struct PreverifiedBlock {
	/// Populated block header
	pub header: Header,
	/// Populated block transactions
	pub transactions: Vec<SignedTransaction>,
	/// Populated block uncles
	pub uncles: Vec<Header>,
	/// Block bytes
	pub bytes: Bytes,
}

/// Brief info about inserted block.
#[derive(Clone)]
pub struct BlockInfo {
	/// Block hash.
	pub hash: H256,
	/// Block number.
	pub number: BlockNumber,
	/// Total block difficulty.
	pub total_difficulty: U256,
	/// Block location in blockchain.
	pub location: BlockLocation
}

/// Describes location of newly inserted block.
#[derive(Debug, Clone, PartialEq)]
pub enum BlockLocation {
	/// It's part of the canon chain.
	CanonChain,
	/// It's not a part of the canon chain.
	Branch,
	/// It's part of the fork which should become canon chain,
	/// because its total difficulty is higher than current
	/// canon chain difficulty.
	BranchBecomingCanonChain(BranchBecomingCanonChainData),
}

/// Info about heaviest fork
#[derive(Debug, Clone, PartialEq)]
pub struct BranchBecomingCanonChainData {
	/// Hash of the newest common ancestor with old canon chain.
	pub ancestor: H256,
	/// Hashes of the blocks between ancestor and this block.
	pub enacted: Vec<H256>,
	/// Hashes of the blocks which were invalidated.
	pub retracted: Vec<H256>,
}