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
149
150
151
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.

// Parity 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.

// Parity 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 Parity.  If not, see <http://www.gnu.org/licenses/>.

//! Generalization of a state machine for a consensus engine.
//! This will define traits for the header, block, and state of a blockchain.

extern crate ethereum_types;

use ethereum_types::{H256, U256, Address};

/// A header. This contains important metadata about the block, as well as a
/// "seal" that indicates validity to a consensus engine.
pub trait Header {
	/// Cryptographic hash of the header, excluding the seal.
	fn bare_hash(&self) -> H256;

	/// Cryptographic hash of the header, including the seal.
	fn hash(&self) -> H256;

	/// Get a reference to the seal fields.
	fn seal(&self) -> &[Vec<u8>];

	/// The author of the header.
	fn author(&self) -> &Address;

	/// The number of the header.
	fn number(&self) -> u64;
}

/// A header with an associated score (difficulty in PoW terms)
pub trait ScoredHeader: Header {
	type Value;

	/// Get the score of this header.
	fn score(&self) -> &Self::Value;

	/// Set the score of this header.
	fn set_score(&mut self, score: Self::Value);
}

/// A header with associated total score.
pub trait TotalScoredHeader: Header {
	type Value;

	/// Get the total score of this header.
	fn total_score(&self) -> Self::Value;
}

/// A header with finalized information.
pub trait FinalizableHeader: Header {
	/// Get whether this header is considered finalized, so that it will never be replaced in reorganization.
	fn is_finalized(&self) -> bool;
}

/// A header with metadata information.
pub trait WithMetadataHeader: Header {
	/// Get the current header metadata.
	fn metadata(&self) -> Option<&[u8]>;
}

/// A "live" block is one which is in the process of the transition.
/// The state of this block can be mutated by arbitrary rules of the
/// state transition function.
pub trait LiveBlock: 'static {
	/// The block header type;
	type Header: Header;

	/// Get a reference to the header.
	fn header(&self) -> &Self::Header;

	/// Get a reference to the uncle headers. If the block type doesn't
	/// support uncles, return the empty slice.
	fn uncles(&self) -> &[Self::Header];
}

/// Trait for blocks which have a transaction type.
pub trait Transactions: LiveBlock {
	/// The transaction type.
	type Transaction;

	/// Get a reference to the transactions in this block.
	fn transactions(&self) -> &[Self::Transaction];
}

/// Trait for blocks which have finalized information.
pub trait Finalizable: LiveBlock {
	/// Get whether the block is finalized.
	fn is_finalized(&self) -> bool;
	/// Mark the block as finalized.
	fn mark_finalized(&mut self);
}

/// A state machine with block metadata.
pub trait WithMetadata: LiveBlock {
	/// Get the current live block metadata.
	fn metadata(&self) -> Option<&[u8]>;
	/// Set the current live block metadata.
	fn set_metadata(&mut self, value: Option<Vec<u8>>);
}

/// Generalization of types surrounding blockchain-suitable state machines.
pub trait Machine: for<'a> LocalizedMachine<'a> {
	/// The block header type.
	type Header: Header;
	/// The live block type.
	type LiveBlock: LiveBlock<Header=Self::Header>;
	/// Block header with metadata information.
	type ExtendedHeader: Header;
	/// A handle to a blockchain client for this machine.
	type EngineClient: ?Sized;
	/// A description of needed auxiliary data.
	type AuxiliaryRequest;
	/// Actions taken on ancestry blocks when commiting a new block.
	type AncestryAction;

	/// Errors which can occur when querying or interacting with the machine.
	type Error;
}

/// Machine-related types localized to a specific lifetime.
// TODO: this is a workaround for a lack of associated type constructors in the language.
pub trait LocalizedMachine<'a>: Sync + Send {
	/// Definition of auxiliary data associated to a specific block.
	type AuxiliaryData: 'a;
	/// A context providing access to the state in a controlled capacity.
	/// Generally also provides verifiable proofs.
	type StateContext: ?Sized + 'a;
}

/// A state machine that uses balances.
pub trait WithBalances: Machine {
	/// Get the balance, in base units, associated with an account.
	/// Extracts data from the live block.
	fn balance(&self, live: &Self::LiveBlock, address: &Address) -> Result<U256, Self::Error>;

	/// Increment the balance of an account in the state of the live block.
	fn add_balance(&self, live: &mut Self::LiveBlock, address: &Address, amount: &U256) -> Result<(), Self::Error>;
}