Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Mining #547

Merged
merged 22 commits into from
Mar 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion ethash/src/compute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ fn get_data_size(block_number: u64) -> usize {
}

#[inline]
fn get_seedhash(block_number: u64) -> H256 {
/// Given the `block_number`, determine the seed hash for Ethash.
pub fn get_seedhash(block_number: u64) -> H256 {
let epochs = block_number / ETHASH_EPOCH_LENGTH;
let mut ret: H256 = [0u8; 32];
for _ in 0..epochs {
Expand Down
4 changes: 2 additions & 2 deletions ethash/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ mod compute;

use std::mem;
use compute::Light;
pub use compute::{quick_get_difficulty, H256, ProofOfWork, ETHASH_EPOCH_LENGTH};
pub use compute::{get_seedhash, quick_get_difficulty, H256, ProofOfWork, ETHASH_EPOCH_LENGTH};

use std::sync::{Arc, Mutex};

Expand All @@ -35,7 +35,7 @@ struct LightCache {
prev: Option<Arc<Light>>,
}

/// Lighy/Full cache manager
/// Light/Full cache manager.
pub struct EthashManager {
cache: Mutex<LightCache>,
}
Expand Down
2 changes: 1 addition & 1 deletion ethcore/res/ethereum/tests
Submodule tests updated 31 files
+1 −12,522 BasicTests/difficulty.json
+240 −240 BasicTests/difficultyCustomHomestead.json
+5,520 −5,520 BasicTests/difficultyFrontier.json
+5,520 −5,520 BasicTests/difficultyHomestead.json
+5,520 −5,520 BasicTests/difficultyMorden.json
+5,520 −5,520 BasicTests/difficultyOlimpic.json
+246 −186 StateTests/Homestead/stCallCodes.json
+38 −38 StateTests/Homestead/stCallCreateCallCodeTest.json
+201 −151 StateTests/Homestead/stCallDelegateCodes.json
+203 −153 StateTests/Homestead/stCallDelegateCodesCallCode.json
+34 −34 StateTests/Homestead/stDelegatecallTest.json
+5 −5 StateTests/Homestead/stHomeSteadSpecific.json
+17 −17 StateTests/Homestead/stInitCodeTest.json
+46 −46 StateTests/Homestead/stLogTests.json
+9 −10 StateTests/Homestead/stMemoryStressTest.json
+65 −65 StateTests/Homestead/stMemoryTest.json
+89 −89 StateTests/Homestead/stPreCompiledContracts.json
+15 −15 StateTests/Homestead/stQuadraticComplexityTest.json
+2 −2 StateTests/Homestead/stRecursiveCreate.json
+17 −17 StateTests/Homestead/stRefundTest.json
+9 −9 StateTests/Homestead/stSpecialTest.json
+71 −64 StateTests/Homestead/stSystemOperationsTest.json
+40 −40 StateTests/Homestead/stTransactionTest.json
+85 −85 StateTests/Homestead/stWalletTest.json
+172 −112 StateTests/stCallCodes.json
+3 −4 StateTests/stMemoryStressTest.json
+9 −9 StateTests/stTransitionTest.json
+1 −1 TransactionTests/Homestead/tt10mbDataField.json
+57 −57 TransactionTests/Homestead/ttTransactionTest.json
+69 −69 TransactionTests/Homestead/ttWrongRLPTransaction.json
+3 −3 TransactionTests/tt10mbDataField.json
75 changes: 41 additions & 34 deletions ethcore/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
use common::*;
use engine::*;
use state::*;
use verification::PreVerifiedBlock;
use verification::PreverifiedBlock;

/// A block, encoded as it is on the block chain.
// TODO: rename to Block
Expand Down Expand Up @@ -155,9 +155,9 @@ pub struct OpenBlock<'x> {
/// Just like OpenBlock, except that we've applied `Engine::on_close_block`, finished up the non-seal header fields,
/// and collected the uncles.
///
/// There is no function available to push a transaction. If you want that you'll need to `reopen()` it.
pub struct ClosedBlock<'x> {
open_block: OpenBlock<'x>,
/// There is no function available to push a transaction.
pub struct ClosedBlock {
block: ExecutedBlock,
uncle_bytes: Bytes,
}

Expand All @@ -178,10 +178,12 @@ impl<'x> OpenBlock<'x> {
last_hashes: last_hashes,
};

r.block.base.header.set_number(parent.number() + 1);
r.block.base.header.set_author(author);
r.block.base.header.set_extra_data(extra_data);
r.block.base.header.set_timestamp_now();
r.block.base.header.parent_hash = parent.hash();
r.block.base.header.number = parent.number + 1;
r.block.base.header.author = author;
r.block.base.header.set_timestamp_now(parent.timestamp());
r.block.base.header.extra_data = extra_data;
r.block.base.header.note_dirty();

engine.populate_from_parent(&mut r.block.base.header, parent);
engine.on_new_block(&mut r.block);
Expand Down Expand Up @@ -259,7 +261,7 @@ impl<'x> OpenBlock<'x> {
}

/// Turn this into a `ClosedBlock`. A BlockChain must be provided in order to figure out the uncles.
pub fn close(self) -> ClosedBlock<'x> {
pub fn close(self) -> ClosedBlock {
let mut s = self;
s.engine.on_close_block(&mut s.block);
s.block.base.header.transactions_root = ordered_trie_root(s.block.base.transactions.iter().map(|ref e| e.rlp_bytes().to_vec()).collect());
Expand All @@ -271,46 +273,51 @@ impl<'x> OpenBlock<'x> {
s.block.base.header.gas_used = s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used);
s.block.base.header.note_dirty();

ClosedBlock::new(s, uncle_bytes)
ClosedBlock {
block: s.block,
uncle_bytes: uncle_bytes,
}
}
}

impl<'x> IsBlock for OpenBlock<'x> {
fn block(&self) -> &ExecutedBlock { &self.block }
}

impl<'x> IsBlock for ClosedBlock<'x> {
fn block(&self) -> &ExecutedBlock { &self.open_block.block }
impl<'x> IsBlock for ClosedBlock {
fn block(&self) -> &ExecutedBlock { &self.block }
}

impl<'x> ClosedBlock<'x> {
fn new(open_block: OpenBlock<'x>, uncle_bytes: Bytes) -> Self {
ClosedBlock {
open_block: open_block,
uncle_bytes: uncle_bytes,
}
}

impl ClosedBlock {
/// Get the hash of the header without seal arguments.
pub fn hash(&self) -> H256 { self.header().rlp_sha3(Seal::Without) }

/// Provide a valid seal in order to turn this into a `SealedBlock`.
///
/// NOTE: This does not check the validity of `seal` with the engine.
pub fn seal(self, seal: Vec<Bytes>) -> Result<SealedBlock, BlockError> {
pub fn seal(self, engine: &Engine, seal: Vec<Bytes>) -> Result<SealedBlock, BlockError> {
let mut s = self;
if seal.len() != s.open_block.engine.seal_fields() {
return Err(BlockError::InvalidSealArity(Mismatch{expected: s.open_block.engine.seal_fields(), found: seal.len()}));
if seal.len() != engine.seal_fields() {
return Err(BlockError::InvalidSealArity(Mismatch{expected: engine.seal_fields(), found: seal.len()}));
}
s.open_block.block.base.header.set_seal(seal);
Ok(SealedBlock { block: s.open_block.block, uncle_bytes: s.uncle_bytes })
s.block.base.header.set_seal(seal);
Ok(SealedBlock { block: s.block, uncle_bytes: s.uncle_bytes })
}

/// Turn this back into an `OpenBlock`.
pub fn reopen(self) -> OpenBlock<'x> { self.open_block }
/// Provide a valid seal in order to turn this into a `SealedBlock`.
/// This does check the validity of `seal` with the engine.
/// Returns the `ClosedBlock` back again if the seal is no good.
pub fn try_seal(self, engine: &Engine, seal: Vec<Bytes>) -> Result<SealedBlock, ClosedBlock> {
let mut s = self;
s.block.base.header.set_seal(seal);
match engine.verify_block_seal(&s.block.base.header) {
Err(_) => Err(s),
_ => Ok(SealedBlock { block: s.block, uncle_bytes: s.uncle_bytes }),
}
}

/// Drop this object and return the underlieing database.
pub fn drain(self) -> JournalDB { self.open_block.block.state.drop().1 }
pub fn drain(self) -> JournalDB { self.block.state.drop().1 }
}

impl SealedBlock {
Expand All @@ -332,7 +339,7 @@ impl IsBlock for SealedBlock {
}

/// Enact the block given by block header, transactions and uncles
pub fn enact<'x>(header: &Header, transactions: &[SignedTransaction], uncles: &[Header], engine: &'x Engine, db: JournalDB, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock<'x>, Error> {
pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Header], engine: &Engine, db: JournalDB, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
{
if ::log::max_log_level() >= ::log::LogLevel::Trace {
let s = State::from_existing(db.clone(), parent.state_root().clone(), engine.account_start_nonce());
Expand All @@ -350,22 +357,22 @@ pub fn enact<'x>(header: &Header, transactions: &[SignedTransaction], uncles: &[
}

/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
pub fn enact_bytes<'x>(block_bytes: &[u8], engine: &'x Engine, db: JournalDB, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock<'x>, Error> {
pub fn enact_bytes(block_bytes: &[u8], engine: &Engine, db: JournalDB, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
let block = BlockView::new(block_bytes);
let header = block.header();
enact(&header, &block.transactions(), &block.uncles(), engine, db, parent, last_hashes)
}

/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
pub fn enact_verified<'x>(block: &PreVerifiedBlock, engine: &'x Engine, db: JournalDB, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock<'x>, Error> {
pub fn enact_verified(block: &PreverifiedBlock, engine: &Engine, db: JournalDB, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
let view = BlockView::new(&block.bytes);
enact(&block.header, &block.transactions, &view.uncles(), engine, db, parent, last_hashes)
}

/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards
pub fn enact_and_seal(block_bytes: &[u8], engine: &Engine, db: JournalDB, parent: &Header, last_hashes: LastHashes) -> Result<SealedBlock, Error> {
let header = BlockView::new(block_bytes).header_view();
Ok(try!(try!(enact_bytes(block_bytes, engine, db, parent, last_hashes)).seal(header.seal())))
Ok(try!(try!(enact_bytes(block_bytes, engine, db, parent, last_hashes)).seal(engine, header.seal())))
}

#[cfg(test)]
Expand All @@ -386,7 +393,7 @@ mod tests {
let last_hashes = vec![genesis_header.hash()];
let b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), vec![]);
let b = b.close();
let _ = b.seal(vec![]);
let _ = b.seal(engine.deref(), vec![]);
}

#[test]
Expand All @@ -398,7 +405,7 @@ mod tests {
let mut db_result = get_temp_journal_db();
let mut db = db_result.take();
engine.spec().ensure_db_good(&mut db);
let b = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()], Address::zero(), vec![]).close().seal(vec![]).unwrap();
let b = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()], Address::zero(), vec![]).close().seal(engine.deref(), vec![]).unwrap();
let orig_bytes = b.rlp_bytes();
let orig_db = b.drain();

Expand Down
26 changes: 13 additions & 13 deletions ethcore/src/block_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use service::*;
use client::BlockStatus;
use util::panics::*;

known_heap_size!(0, UnVerifiedBlock, VerifyingBlock, PreVerifiedBlock);
known_heap_size!(0, UnverifiedBlock, VerifyingBlock, PreverifiedBlock);

const MIN_MEM_LIMIT: usize = 16384;
const MIN_QUEUE_LIMIT: usize = 512;
Expand Down Expand Up @@ -105,14 +105,14 @@ pub struct BlockQueue {
max_mem_use: usize,
}

struct UnVerifiedBlock {
struct UnverifiedBlock {
header: Header,
bytes: Bytes,
}

struct VerifyingBlock {
hash: H256,
block: Option<PreVerifiedBlock>,
block: Option<PreverifiedBlock>,
}

struct QueueSignal {
Expand All @@ -134,8 +134,8 @@ impl QueueSignal {

#[derive(Default)]
struct Verification {
unverified: VecDeque<UnVerifiedBlock>,
verified: VecDeque<PreVerifiedBlock>,
unverified: VecDeque<UnverifiedBlock>,
verified: VecDeque<PreverifiedBlock>,
verifying: VecDeque<VerifyingBlock>,
bad: HashSet<H256>,
}
Expand Down Expand Up @@ -244,7 +244,7 @@ impl BlockQueue {
}
}

fn drain_verifying(verifying: &mut VecDeque<VerifyingBlock>, verified: &mut VecDeque<PreVerifiedBlock>, bad: &mut HashSet<H256>) {
fn drain_verifying(verifying: &mut VecDeque<VerifyingBlock>, verified: &mut VecDeque<PreverifiedBlock>, bad: &mut HashSet<H256>) {
while !verifying.is_empty() && verifying.front().unwrap().block.is_some() {
let block = verifying.pop_front().unwrap().block.unwrap();
if bad.contains(&block.header.parent_hash) {
Expand Down Expand Up @@ -289,31 +289,31 @@ impl BlockQueue {
let header = BlockView::new(&bytes).header();
let h = header.hash();
if self.processing.read().unwrap().contains(&h) {
return Err(ImportError::AlreadyQueued);
return Err(x!(ImportError::AlreadyQueued));
}
{
let mut verification = self.verification.lock().unwrap();
if verification.bad.contains(&h) {
return Err(ImportError::Bad(None));
return Err(x!(ImportError::KnownBad));
}

if verification.bad.contains(&header.parent_hash) {
verification.bad.insert(h.clone());
return Err(ImportError::Bad(None));
return Err(x!(ImportError::KnownBad));
}
}

match verify_block_basic(&header, &bytes, self.engine.deref().deref()) {
Ok(()) => {
self.processing.write().unwrap().insert(h.clone());
self.verification.lock().unwrap().unverified.push_back(UnVerifiedBlock { header: header, bytes: bytes });
self.verification.lock().unwrap().unverified.push_back(UnverifiedBlock { header: header, bytes: bytes });
self.more_to_verify.notify_all();
Ok(h)
},
Err(err) => {
warn!(target: "client", "Stage 1 block verification failed for {}\nError: {:?}", BlockView::new(&bytes).header_view().sha3(), err);
self.verification.lock().unwrap().bad.insert(h.clone());
Err(From::from(err))
Err(err)
}
}
}
Expand Down Expand Up @@ -352,7 +352,7 @@ impl BlockQueue {
}

/// Removes up to `max` verified blocks from the queue
pub fn drain(&mut self, max: usize) -> Vec<PreVerifiedBlock> {
pub fn drain(&mut self, max: usize) -> Vec<PreverifiedBlock> {
let mut verification = self.verification.lock().unwrap();
let count = min(max, verification.verified.len());
let mut result = Vec::with_capacity(count);
Expand Down Expand Up @@ -455,7 +455,7 @@ mod tests {
match duplicate_import {
Err(e) => {
match e {
ImportError::AlreadyQueued => {},
Error::Import(ImportError::AlreadyQueued) => {},
_ => { panic!("must return AlreadyQueued error"); }
}
}
Expand Down
6 changes: 6 additions & 0 deletions ethcore/src/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,12 @@ impl BlockChain {
self.extras_db.write(batch).unwrap();
}

/// Given a block's `parent`, find every block header which represents a valid uncle.
pub fn find_uncle_headers(&self, _parent: &H256) -> Vec<Header> {
// TODO
Vec::new()
}

/// Get inserted block info which is critical to preapre extras updates.
fn block_info(&self, block_bytes: &[u8]) -> BlockInfo {
let block = BlockView::new(block_bytes);
Expand Down