From 435911b9f04819afb0719d0e66bcb3cc5d82a271 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 20 Dec 2015 12:16:12 +0000 Subject: [PATCH] Repot & introduce various additional components for rest of consensus algorithm. --- src/engine.rs | 129 ++++++++++++++++++++++++++++++ src/env_info.rs | 24 ++++++ src/{blockheader.rs => header.rs} | 0 src/lib.rs | 5 +- src/receipt.rs | 6 ++ src/state.rs | 31 ++----- src/transaction.rs | 15 ++-- 7 files changed, 180 insertions(+), 30 deletions(-) create mode 100644 src/engine.rs create mode 100644 src/env_info.rs rename src/{blockheader.rs => header.rs} (100%) create mode 100644 src/receipt.rs diff --git a/src/engine.rs b/src/engine.rs new file mode 100644 index 000000000..9b1a62980 --- /dev/null +++ b/src/engine.rs @@ -0,0 +1,129 @@ +use util::uint::*; +use util::hash::*; +use util::bytes::*; +use header::Header; +use std::collections::hash_map::*; +use util::error::*; + +/// Definition of the cost schedule and other parameterisations for the EVM. +pub struct EvmSchedule { + pub exceptional_failed_code_deposit: bool, + pub have_delegate_call: bool, + pub stack_limit: U256, + pub tier_step_gas: [U256; 8], + pub exp_gas: U256, + pub exp_byte_gas: U256, + pub sha3_gas: U256, + pub sha3_word_gas: U256, + pub sload_gas: U256, + pub sstore_set_gas: U256, + pub sstore_reset_gas: U256, + pub sstore_refund_gas: U256, + pub jumpdest_gas: U256, + pub log_gas: U256, + pub log_data_gas: U256, + pub log_topic_gas: U256, + pub create_gas: U256, + pub call_gas: U256, + pub call_stipend: U256, + pub call_value_transfer_gas: U256, + pub call_new_account_gas: U256, + pub suicide_refund_gas: U256, + pub memory_gas: U256, + pub quad_coeff_div: U256, + pub create_data_gas: U256, + pub tx_gas: U256, + pub tx_create_gas: U256, + pub tx_data_zero_gas: U256, + pub tx_data_non_zero_gas: U256, + pub copy_gas: U256, +} + +/// Definition of a contract whose implementation is built-in. +pub struct Builtin { + /// The gas cost of running this built-in for the given size of input data. + pub cost: Box U256>, // TODO: U256 should be bignum. + /// Run this built-in function with the input being the first argument and the output + /// being placed into the second. + pub execute: Box, +} + +/// Parameters for a block chain; includes both those intrinsic to the design of the +/// chain and those to be interpreted by the active chain engine. +pub struct Params { + /* + TODO: std::unordered_map precompiled; + */ + pub block_reward: U256, + pub maximum_extra_data_size: U256, + pub account_start_nonce: U256, + pub evm_schedule: EvmSchedule, + pub builtins: HashMap, + pub misc: HashMap, +} + +// TODO: move to ethcore-util +/// A version value with strict meaning. +pub struct SemanticVersion { + /// Major version - API/feature removals & breaking changes. + pub major: u8, + /// Minor version - API/feature additions. + pub minor: u8, + /// Tiny version - bug fixes. + pub tiny: u8, +} + +impl SemanticVersion { + /// Create a new object. + pub fn new(major: u8, minor: u8, tiny: u8) -> SemanticVersion { SemanticVersion{major: major, minor: minor, tiny: tiny} } + + /// Convert to a `u32` representation. + pub fn as_u32(&self) -> u32 { ((self.major as u32) << 16u32) + ((self.minor as u32) << 8u32) + self.tiny as u32 } +} + +// TODO: implement PartialOrdered for SemanticVersion. + +/// A consensus mechanism for the chain. Generally either proof-of-work or proof-of-stake-based. +/// Provides hooks into each of the major parts of block import. +pub trait Engine { + /// The name of this engine. + fn name(&self) -> &str; + /// The version of this engine. Should be of the form + fn version(&self) -> SemanticVersion { SemanticVersion::new(0, 0 ,0) } + + /// The number of additional header fields required for this engine. + fn seal_fields(&self) -> u32 { 0 } + /// Default values of the additional fields RLP-encoded in a raw (non-list) harness. + fn seal_rlp(&self) -> Bytes { vec![] } + + /// Additional engine-specific information for the user/developer concerning `header`. + fn extra_info(&self, _header: &Header) -> HashMap { HashMap::new() } + + /// Verify that `header` is valid. + /// `parent` (the parent header) and `block` (the header's full block) may be provided for additional + /// checks. Returns either a null `Ok` or a general error detailing the problem with import. + fn verify(&self, _header: &Header, _parent: Option<&Header>, _block: Option<&[u8]>) -> Result<(), EthcoreError> { Ok(()) } +/* + virtual void verify(Strictness _s, BlockHeader const& _bi, BlockHeader const& _parent = BlockHeader(), bytesConstRef _block = bytesConstRef()) const; + /// Additional verification for transactions in blocks. + virtual void verifyTransaction(ImportRequirements::value _ir, TransactionBase const& _t, BlockHeader const& _bi) const; + /// Don't forget to call Super::populateFromParent when subclassing & overriding. + virtual void populateFromParent(BlockHeader& _bi, BlockHeader const& _parent) const; +*/ + + /// Get the general parameters of the chain. + fn params(&self) -> &Params; + /// Set the general parameters of the chain. + fn set_params(&mut self, p: Params); +} + +/// An engine which does not provide any consensus mechanism. +pub struct NullEngine { + params: Params, +} + +impl Engine for NullEngine { + fn name(&self) -> &str { "NullEngine" } + fn params(&self) -> &Params { &self.params } + fn set_params(&mut self, params: Params) { self.params = params; } +} \ No newline at end of file diff --git a/src/env_info.rs b/src/env_info.rs new file mode 100644 index 000000000..dec8069ac --- /dev/null +++ b/src/env_info.rs @@ -0,0 +1,24 @@ +use util::uint::*; +use util::hash::*; + +/// Simple vector of hashes, should be at most 256 items large, can be smaller if being used +/// for a block whose number is less than 257. +pub type LastHashes = Vec; + +/// Information concerning the execution environment for a message-call/contract-creation. +pub struct EnvInfo { + /// The block number. + pub number: U256, + /// The block author. + pub author: Address, + /// The block timestamp. + pub timestamp: U256, + /// The block difficulty. + pub difficulty: U256, + /// The block gas limit. + pub gas_limit: U256, + /// The last 256 block hashes. + pub last_hashes: LastHashes, + /// The gas used. + pub gas_used: U256, +} \ No newline at end of file diff --git a/src/blockheader.rs b/src/header.rs similarity index 100% rename from src/blockheader.rs rename to src/header.rs diff --git a/src/lib.rs b/src/lib.rs index 776deb3dc..071c3bf06 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,10 +84,13 @@ pub use util::hash::*; pub use util::uint::*; pub use util::bytes::*; +pub mod env_info; +pub mod engine; pub mod state; pub mod account; -pub mod blockheader; +pub mod header; pub mod transaction; +pub mod receipt; pub mod networkparams; pub mod denominations; diff --git a/src/receipt.rs b/src/receipt.rs new file mode 100644 index 000000000..e860970ac --- /dev/null +++ b/src/receipt.rs @@ -0,0 +1,6 @@ +use util::hash::*; + +pub struct Receipt { + // TODO + pub state_root: H256, +} diff --git a/src/state.rs b/src/state.rs index a2b7c16e9..dbe349d77 100644 --- a/src/state.rs +++ b/src/state.rs @@ -9,28 +9,13 @@ use util::bytes::*; use util::rlp::*; use util::uint::*; use account::Account; +use transaction::Transaction; +use receipt::Receipt; +use env_info::EnvInfo; +use engine::Engine; -/* -enum ValueOrRef<'self, 'db: 'self> { - Value(OverlayDB), - Ref(&'db mut OverlayDB) -} - -impl<'self, 'db> ValueOrRef<'self, 'db: 'self> { - pub fn get_mut(&mut self) -> &mut OverlayDB { - match self { - Value(ref mut x) => x, - Ref(x) => x, - } - } - pub fn get(&self) -> &OverlayDB { - match self { - Value(ref x) => x, - Ref(x) => x, - } - } -} -*/ +/// Information concerning the result of the `State::apply` operation. +pub struct ApplyResult; // TODO /// Representation of the entire state of all accounts in the system. pub struct State { @@ -146,9 +131,9 @@ impl State { /// Execute a given transaction. /// This will change the state accordingly. -/* pub fn execute(_env_info: EnvInfo, _seal_engine: SealEngine, _t: Transaction, _p: Permanence) -> (ExecutionResult, TransactionReceipt) { + pub fn apply(_env_info: &EnvInfo, _engine: &Engine, _t: &Transaction, _is_permanent: bool) -> (ApplyResult, Receipt) { unimplemented!(); - }*/ + } /// Convert into a JSON representation. pub fn as_json(&self) -> String { diff --git a/src/transaction.rs b/src/transaction.rs index 4fbd9588b..82fa9ccb6 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -3,20 +3,23 @@ use util::bytes::*; use util::uint::*; use util::rlp::*; +/// A set of information describing an externally-originating message call +/// or contract creation operation. pub struct Transaction { nonce: U256, gas_price: U256, gas: U256, - receive_address: Option
, + to: Option
, value: U256, data: Bytes, } impl Transaction { + /// Is this transaction meant to create a contract? pub fn is_contract_creation(&self) -> bool { - self.receive_address.is_none() + self.to.is_none() } - + /// Is this transaction meant to send a message? pub fn is_message_call(&self) -> bool { !self.is_contract_creation() } @@ -28,7 +31,7 @@ impl Encodable for Transaction { self.nonce.encode(e); self.gas_price.encode(e); self.gas.encode(e); - self.receive_address.encode(e); + self.to.encode(e); self.value.encode(e); self.data.encode(e); }) @@ -36,14 +39,14 @@ impl Encodable for Transaction { } impl Decodable for Transaction { - fn decode(decoder: &D) -> Result where D: Decoder { + fn decode(decoder: &D) -> Result where D: Decoder { let d = try!(decoder.as_list()); let transaction = Transaction { nonce: try!(Decodable::decode(&d[0])), gas_price: try!(Decodable::decode(&d[1])), gas: try!(Decodable::decode(&d[2])), - receive_address: try!(Decodable::decode(&d[3])), + to: try!(Decodable::decode(&d[3])), value: try!(Decodable::decode(&d[4])), data: try!(Decodable::decode(&d[5])), };